From e35b5a53d31ed076926cd67e5badf5dbc4f9baa1 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 6 Apr 2021 14:46:38 -0400 Subject: [PATCH 01/57] ENH: add tf view and model classes --- libraries/disp/disp.pro | 4 ++ .../viewers/helpers/timefrequencymodel.cpp | 40 +++++++++++++++++ .../disp/viewers/helpers/timefrequencymodel.h | 45 +++++++++++++++++++ libraries/disp/viewers/timefrequencyview.cpp | 40 +++++++++++++++++ libraries/disp/viewers/timefrequencyview.h | 45 +++++++++++++++++++ 5 files changed, 174 insertions(+) create mode 100644 libraries/disp/viewers/helpers/timefrequencymodel.cpp create mode 100644 libraries/disp/viewers/helpers/timefrequencymodel.h create mode 100644 libraries/disp/viewers/timefrequencyview.cpp create mode 100644 libraries/disp/viewers/timefrequencyview.h diff --git a/libraries/disp/disp.pro b/libraries/disp/disp.pro index e02f9599908..09ee245b786 100644 --- a/libraries/disp/disp.pro +++ b/libraries/disp/disp.pro @@ -106,6 +106,7 @@ SOURCES += \ viewers/averagelayoutview.cpp \ viewers/fwdsettingsview.cpp \ viewers/helpers/scalecontrol.cpp \ + viewers/helpers/timefrequencymodel.cpp \ viewers/progressview.cpp \ viewers/spectrumview.cpp \ viewers/modalityselectionview.cpp \ @@ -119,6 +120,7 @@ SOURCES += \ viewers/spharasettingsview.cpp \ viewers/fiffrawviewsettings.cpp \ viewers/averageselectionview.cpp \ + viewers/timefrequencyview.cpp \ viewers/triggerdetectionview.cpp \ viewers/quickcontrolview.cpp \ viewers/connectivitysettingsview.cpp \ @@ -165,6 +167,7 @@ HEADERS += \ viewers/averagelayoutview.h \ viewers/fwdsettingsview.h \ viewers/helpers/scalecontrol.h \ + viewers/helpers/timefrequencymodel.h \ viewers/progressview.h \ viewers/spectrumview.h \ viewers/modalityselectionview.h \ @@ -178,6 +181,7 @@ HEADERS += \ viewers/spharasettingsview.h \ viewers/fiffrawviewsettings.h \ viewers/averageselectionview.h \ + viewers/timefrequencyview.h \ viewers/triggerdetectionview.h \ viewers/quickcontrolview.h \ viewers/connectivitysettingsview.h \ diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp new file mode 100644 index 00000000000..151b07eb6a1 --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -0,0 +1,40 @@ +//============================================================================================================= +/** + * @file timefrequencymodel.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencyModel Class. + * + */ + +#include "timefrequencymodel.h" + +TimeFrequencyModel::TimeFrequencyModel() +{ + +} diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h new file mode 100644 index 00000000000..bc1916595b6 --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -0,0 +1,45 @@ +//============================================================================================================= +/** + * @file timefrequencymodel.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencyModel Class. + * + */ + +#ifndef TIMEFREQUENCYMODEL_H +#define TIMEFREQUENCYMODEL_H + + +class TimeFrequencyModel +{ +public: + TimeFrequencyModel(); +}; + +#endif // TIMEFREQUENCYMODEL_H diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp new file mode 100644 index 00000000000..1d1da2228f9 --- /dev/null +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -0,0 +1,40 @@ +//============================================================================================================= +/** + * @file timefrequencyview.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencyView Class. + * + */ + +#include "timefrequencyview.h" + +TimeFrequencyView::TimeFrequencyView() +{ + +} diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h new file mode 100644 index 00000000000..d7db3bc3fd4 --- /dev/null +++ b/libraries/disp/viewers/timefrequencyview.h @@ -0,0 +1,45 @@ +//============================================================================================================= +/** + * @file timefrequencyview.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencyView Class. + * + */ + +#ifndef TIMEFREQUENCYVIEW_H +#define TIMEFREQUENCYVIEW_H + + +class TimeFrequencyView +{ +public: + TimeFrequencyView(); +}; + +#endif // TIMEFREQUENCYVIEW_H From bc55890d857c61907149477ae9f7d447183fe46a Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 6 Apr 2021 15:12:30 -0400 Subject: [PATCH 02/57] ENH: skeleton for timefrequency plugin in mneanalyze --- .../plugins/dataloader/dataloader.h | 6 - applications/mne_analyze/plugins/plugins.pro | 1 + .../plugins/timefrequency/timefrequency.cpp | 153 ++++++++++++++++++ .../plugins/timefrequency/timefrequency.h | 144 +++++++++++++++++ .../plugins/timefrequency/timefrequency.json | 0 .../plugins/timefrequency/timefrequency.pro | 111 +++++++++++++ .../timefrequency/timefrequency_global.h | 54 +++++++ .../viewers/helpers/timefrequencymodel.cpp | 2 +- .../disp/viewers/helpers/timefrequencymodel.h | 2 +- libraries/disp/viewers/timefrequencyview.cpp | 2 +- libraries/disp/viewers/timefrequencyview.h | 2 +- 11 files changed, 467 insertions(+), 10 deletions(-) create mode 100644 applications/mne_analyze/plugins/timefrequency/timefrequency.cpp create mode 100644 applications/mne_analyze/plugins/timefrequency/timefrequency.h create mode 100644 applications/mne_analyze/plugins/timefrequency/timefrequency.json create mode 100644 applications/mne_analyze/plugins/timefrequency/timefrequency.pro create mode 100644 applications/mne_analyze/plugins/timefrequency/timefrequency_global.h diff --git a/applications/mne_analyze/plugins/dataloader/dataloader.h b/applications/mne_analyze/plugins/dataloader/dataloader.h index 7c10578a8a9..9ff8f91a320 100644 --- a/applications/mne_analyze/plugins/dataloader/dataloader.h +++ b/applications/mne_analyze/plugins/dataloader/dataloader.h @@ -75,12 +75,6 @@ namespace DISPLIB { namespace DATALOADERPLUGIN { -//============================================================================================================= -// DATALOADERPLUGIN FORWARD DECLARATIONS -//============================================================================================================= - -class DataLoaderControl; - //============================================================================================================= /** * DataLoader Plugin diff --git a/applications/mne_analyze/plugins/plugins.pro b/applications/mne_analyze/plugins/plugins.pro index 0d151f6d920..df049c41f53 100644 --- a/applications/mne_analyze/plugins/plugins.pro +++ b/applications/mne_analyze/plugins/plugins.pro @@ -49,6 +49,7 @@ SUBDIRS += \ controlmanager \ coregistration \ dipolefit \ + timefrequency \ # sampleplugin \ # Exclude plugins which rely on the Qt3D module. Note: The Qt3D module is not yet supported by Wasm diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp new file mode 100644 index 00000000000..50a21b86921 --- /dev/null +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -0,0 +1,153 @@ +//============================================================================================================= +/** + * @file timefrequency.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequency class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequency.h" + +#include +#include +#include +#include +#include + +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace TIMEFREQUENCYPLUGIN; +using namespace ANSHAREDLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequency::TimeFrequency() +: m_sSettingsPath("MNEANALYZE/TimeFrequency") +{ + loadSettings(); +} + +//============================================================================================================= + +TimeFrequency::~TimeFrequency() +{ + +} + +//============================================================================================================= + +QSharedPointer TimeFrequency::clone() const +{ + QSharedPointer pTimeFrequencyClone(new TimeFrequency); + return pTimeFrequencyClone; +} + +//============================================================================================================= + +void TimeFrequency::init() +{ + m_pCommu = new Communicator(this); +} + +//============================================================================================================= + +void TimeFrequency::unload() +{ + +} + +//============================================================================================================= + +QString TimeFrequency::getName() const +{ + return "Data Loader"; +} + +//============================================================================================================= + +QMenu *TimeFrequency::getMenu() +{ + return Q_NULLPTR; +} + +//============================================================================================================= + +QDockWidget *TimeFrequency::getControl() +{ + return Q_NULLPTR; +} + +//============================================================================================================= + +QWidget *TimeFrequency::getView() +{ + return Q_NULLPTR; +} + +//============================================================================================================= + +void TimeFrequency::handleEvent(QSharedPointer e) +{ + +} + +//============================================================================================================= + +QVector TimeFrequency::getEventSubscriptions(void) const +{ + QVector temp = {SELECTED_MODEL_CHANGED}; + + return temp; +} + +//============================================================================================================= + +void TimeFrequency::saveSettings() +{ + QSettings settings("MNECPP"); + settings.beginGroup(m_sSettingsPath); +} + +//============================================================================================================= + +void TimeFrequency::loadSettings() +{ + QSettings settings("MNECPP"); + settings.beginGroup(m_sSettingsPath); +} diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h new file mode 100644 index 00000000000..8f8a5bdd02b --- /dev/null +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -0,0 +1,144 @@ +//============================================================================================================= +/** + * @file timefrequency.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the TimeFrequency class. + * + */ + +#ifndef TIMEFREQUENCY_H +#define TIMEFREQUENCY_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequency_global.h" + +#include +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include +#include +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace ANSHAREDLIB { + class Communicator; + class AbstractModel; +} + +namespace DISPLIB { + class ProgressView; +} + +//============================================================================================================= +// DEFINE NAMESPACE TIMEFREQUENCYPLUGIN +//============================================================================================================= + +namespace TIMEFREQUENCYPLUGIN +{ + +//============================================================================================================= +// TIMEFREQUENCYPLUGIN FORWARD DECLARATIONS +//============================================================================================================= + +class TimeFrequencyControl; + +//============================================================================================================= +/** + * TimeFrequency Plugin + * + * @brief The TimeFrequency class provides input and output capabilities for the fiff file format. + */ +class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "ansharedlib/1.0" FILE "timefrequency.json") //New Qt5 Plugin system replaces Q_EXPORT_PLUGIN2 macro + // Use the Q_INTERFACES() macro to tell Qt's meta-object system about the interfaces + Q_INTERFACES(ANSHAREDLIB::AbstractPlugin) +public: + //========================================================================================================= + /** + * Constructs a TimeFrequency. + */ + TimeFrequency(); + + //========================================================================================================= + /** + * Destroys the TimeFrequency. + */ + ~TimeFrequency() override; + + // AbstractPlugin functions + virtual QSharedPointer clone() const override; + virtual void init() override; + virtual void unload() override; + virtual QString getName() const override; + + virtual QMenu* getMenu() override; + virtual QDockWidget* getControl() override; + virtual QWidget* getView() override; + + virtual void handleEvent(QSharedPointer e) override; + virtual QVector getEventSubscriptions() const override; + +private: + //========================================================================================================= + /** + * Loads settings from the system. + */ + void loadSettings(); + + //========================================================================================================= + /** + * Save the settings in the register/file/mechanism for lon-term storage. + */ + void saveSettings(); + + QPointer m_pCommu; /**< Used for sending events */ + QString m_sSettingsPath; /**< Variable that stores the key where to store settings for this plugin.*/ +}; + +//============================================================================================================= +// INLINE DEFINITIONS +//============================================================================================================= + +} // NAMESPACE + +#endif // TIMEFREQUENCY_H diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.json b/applications/mne_analyze/plugins/timefrequency/timefrequency.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.pro b/applications/mne_analyze/plugins/timefrequency/timefrequency.pro new file mode 100644 index 00000000000..ba4831ba16a --- /dev/null +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.pro @@ -0,0 +1,111 @@ +#============================================================================================================== +# +# @file timefrequency.pro +# @author Gabriel Motta +# @since 0.1.9 +# @date April, 2021 +# +# @section LICENSE +# +# Copyright (C) 2021, Gabriel Motta. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted provided that +# the following conditions are met: +# * Redistributions of source code must retain the above copyright notice, this list of conditions and the +# following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and +# the following disclaimer in the documentation and/or other materials provided with the distribution. +# * Neither the name of MNE-CPP authors nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# +# @brief This project file generates the makefile for the timefrequency plugin. +# +#============================================================================================================== + +include(../../../../mne-cpp.pri) + +TEMPLATE = lib + +QT += gui widgets + +CONFIG += skip_target_version_ext plugin + +DEFINES += TIMEFREQUENCY_PLUGIN + +DESTDIR = $${MNE_BINARY_DIR}/mne_analyze_plugins + +contains(MNECPP_CONFIG, wasm) { + DEFINES += WASMBUILD +} + +TARGET = timefrequency +CONFIG(debug, debug|release) { + TARGET = $$join(TARGET,,,d) +} + +contains(MNECPP_CONFIG, static) { + CONFIG += staticlib + DEFINES += STATICBUILD +} else { + CONFIG += shared +} + +LIBS += -L$${MNE_LIBRARY_DIR} +CONFIG(debug, debug|release) { + LIBS += -lanSharedd \ + -lmnecppDispd \ + -lmnecppFiffd \ + -lmnecppUtilsd \ +} else { + LIBS += -lanShared \ + -lmnecppDisp \ + -lmnecppFiff \ + -lmnecppUtils \ +} + +SOURCES += \ + timefrequency.cpp \ + +HEADERS += \ + timefrequency_global.h \ + timefrequency.h \ + +OTHER_FILES += timefrequency.json + +INCLUDEPATH += $${EIGEN_INCLUDE_DIR} +INCLUDEPATH += $${MNE_INCLUDE_DIR} +INCLUDEPATH += $${MNE_ANALYZE_INCLUDE_DIR} + +unix:!macx { + QMAKE_RPATHDIR += $ORIGIN/../../lib +} + +# Activate FFTW backend in Eigen for non-static builds only +contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { + DEFINES += EIGEN_FFTW_DEFAULT + INCLUDEPATH += $$shell_path($${FFTW_DIR_INCLUDE}) + LIBS += -L$$shell_path($${FFTW_DIR_LIBS}) + + win32 { + # On Windows + LIBS += -llibfftw3-3 \ + -llibfftw3f-3 \ + -llibfftw3l-3 \ + } + + unix:!macx { + # On Linux + LIBS += -lfftw3 \ + -lfftw3_threads \ + } +} diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency_global.h b/applications/mne_analyze/plugins/timefrequency/timefrequency_global.h new file mode 100644 index 00000000000..87ff35cdb55 --- /dev/null +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency_global.h @@ -0,0 +1,54 @@ +//============================================================================================================= +/** + * @file timefrequency_global.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the FiffIO library export/import macros. + * + */ + +#ifndef TIMEFREQUENCY_GLOBAL_H +#define TIMEFREQUENCY_GLOBAL_H + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// PREPROCESSOR DEFINES +//============================================================================================================= + +#if defined(TIMEFREQUENCY_PLUGIN) +# define TIMEFREQUENCYSHARED_EXPORT Q_DECL_EXPORT /**< Q_DECL_EXPORT must be added to the declarations of symbols used when compiling a shared library. */ +#else +# define TIMEFREQUENCYSHARED_EXPORT Q_DECL_IMPORT /**< Q_DECL_IMPORT must be added to the declarations of symbols used when compiling a client that uses the shared library. */ +#endif + +#endif // TIMEFREQUENCY_GLOBAL_H diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index 151b07eb6a1..4693f12f7be 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -1,7 +1,7 @@ //============================================================================================================= /** * @file timefrequencymodel.cpp - * @author Gabriel Motta + * @author Gabriel Motta * @since 0.1.9 * @date April, 2021 * diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h index bc1916595b6..2a2cb1d4a72 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.h +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -1,7 +1,7 @@ //============================================================================================================= /** * @file timefrequencymodel.h - * @author Gabriel Motta + * @author Gabriel Motta * @since 0.1.9 * @date April, 2021 * diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 1d1da2228f9..65b12b6161e 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -1,7 +1,7 @@ //============================================================================================================= /** * @file timefrequencyview.cpp - * @author Gabriel Motta + * @author Gabriel Motta * @since 0.1.9 * @date April, 2021 * diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index d7db3bc3fd4..294f23d70b9 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -1,7 +1,7 @@ //============================================================================================================= /** * @file timefrequencyview.h - * @author Gabriel Motta + * @author Gabriel Motta * @since 0.1.9 * @date April, 2021 * From d9c0c79b3e00d6f9a96adfc371fc42da74b6fe0f Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 6 Apr 2021 15:58:28 -0400 Subject: [PATCH 03/57] ENH: scene and items for layout view --- libraries/disp/disp.pro | 4 ++++ libraries/disp/viewers/helpers/timefrequencyscene.cpp | 6 ++++++ libraries/disp/viewers/helpers/timefrequencyscene.h | 11 +++++++++++ .../disp/viewers/helpers/timefrequencysceneitem.cpp | 6 ++++++ .../disp/viewers/helpers/timefrequencysceneitem.h | 11 +++++++++++ 5 files changed, 38 insertions(+) create mode 100644 libraries/disp/viewers/helpers/timefrequencyscene.cpp create mode 100644 libraries/disp/viewers/helpers/timefrequencyscene.h create mode 100644 libraries/disp/viewers/helpers/timefrequencysceneitem.cpp create mode 100644 libraries/disp/viewers/helpers/timefrequencysceneitem.h diff --git a/libraries/disp/disp.pro b/libraries/disp/disp.pro index 09ee245b786..565e965b6b4 100644 --- a/libraries/disp/disp.pro +++ b/libraries/disp/disp.pro @@ -107,6 +107,8 @@ SOURCES += \ viewers/fwdsettingsview.cpp \ viewers/helpers/scalecontrol.cpp \ viewers/helpers/timefrequencymodel.cpp \ + viewers/helpers/timefrequencyscene.cpp \ + viewers/helpers/timefrequencysceneitem.cpp \ viewers/progressview.cpp \ viewers/spectrumview.cpp \ viewers/modalityselectionview.cpp \ @@ -168,6 +170,8 @@ HEADERS += \ viewers/fwdsettingsview.h \ viewers/helpers/scalecontrol.h \ viewers/helpers/timefrequencymodel.h \ + viewers/helpers/timefrequencyscene.h \ + viewers/helpers/timefrequencysceneitem.h \ viewers/progressview.h \ viewers/spectrumview.h \ viewers/modalityselectionview.h \ diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.cpp b/libraries/disp/viewers/helpers/timefrequencyscene.cpp new file mode 100644 index 00000000000..06c2c1e9681 --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencyscene.cpp @@ -0,0 +1,6 @@ +#include "timefrequencyscene.h" + +TimeFrequencyScene::TimeFrequencyScene() +{ + +} diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.h b/libraries/disp/viewers/helpers/timefrequencyscene.h new file mode 100644 index 00000000000..6f68f415f28 --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencyscene.h @@ -0,0 +1,11 @@ +#ifndef TIMEFREQUENCYSCENE_H +#define TIMEFREQUENCYSCENE_H + + +class TimeFrequencyScene +{ +public: + TimeFrequencyScene(); +}; + +#endif // TIMEFREQUENCYSCENE_H diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp new file mode 100644 index 00000000000..c2c4c2945af --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp @@ -0,0 +1,6 @@ +#include "timefrequencysceneitem.h" + +TimeFrequencySceneItem::TimeFrequencySceneItem() +{ + +} diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.h b/libraries/disp/viewers/helpers/timefrequencysceneitem.h new file mode 100644 index 00000000000..c46a8e5721b --- /dev/null +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.h @@ -0,0 +1,11 @@ +#ifndef TIMEFREQUENCYSCENEITEM_H +#define TIMEFREQUENCYSCENEITEM_H + + +class TimeFrequencySceneItem +{ +public: + TimeFrequencySceneItem(); +}; + +#endif // TIMEFREQUENCYSCENEITEM_H From 7642ad6de241110c4dc0582510e5bd526866dd73 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Wed, 7 Apr 2021 10:14:38 -0400 Subject: [PATCH 04/57] ENH: subclassing abstractview --- libraries/disp/viewers/timefrequencyview.cpp | 56 +++++++++++++++++ libraries/disp/viewers/timefrequencyview.h | 64 +++++++++++++++++++- 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 65b12b6161e..54512164695 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -32,9 +32,65 @@ * */ +//============================================================================================================= +// INCLUDES +//============================================================================================================= + #include "timefrequencyview.h" +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + TimeFrequencyView::TimeFrequencyView() { } + +//============================================================================================================= + +void TimeFrequencyView::updateGuiMode(GuiMode mode) +{ + switch(mode) { + case GuiMode::Clinical: + break; + default: // default is research mode + break; + } +} + +//============================================================================================================= + +void TimeFrequencyView::updateProcessingMode(ProcessingMode mode) +{ + switch(mode) { + case ProcessingMode::Offline: + break; + default: // default is realtime mode + break; + } +} + +//============================================================================================================= + +void TimeFrequencyView::saveSettings() +{ + +} + +//============================================================================================================= + +void TimeFrequencyView::loadSettings() +{ + +} diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index 294f23d70b9..c2b5b209ee6 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -35,11 +35,73 @@ #ifndef TIMEFREQUENCYVIEW_H #define TIMEFREQUENCYVIEW_H +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../disp_global.h" +#include "abstractview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ -class TimeFrequencyView +//============================================================================================================= +/** + * @brief The TimeFrequencyView class + */ +class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView { public: TimeFrequencyView(); + + //========================================================================================================= + /** + * Update the views GUI based on the set GuiMode (Clinical=0, Research=1). + * + * @param mode The new mode (Clinical=0, Research=1). + */ + void updateGuiMode(GuiMode mode); + + //========================================================================================================= + /** + * Update the views GUI based on the set ProcessingMode (RealTime=0, Offline=1). + * + * @param mode The new mode (RealTime=0, Offline=1). + */ + void updateProcessingMode(ProcessingMode mode); + + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + */ + void saveSettings(); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + */ + void loadSettings(); + + //========================================================================================================= + /** + * Clears the view + */ + void clearView(); }; +} //namespace #endif // TIMEFREQUENCYVIEW_H From dd01477355a4945f1bda41c6e3ace0dc95280689 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Wed, 7 Apr 2021 14:36:09 -0400 Subject: [PATCH 05/57] ENH: setting up plugin --- applications/mne_analyze/mne_analyze/main.cpp | 1 + .../plugins/timefrequency/timefrequency.cpp | 6 ++++-- .../plugins/timefrequency/timefrequency.h | 4 ++++ .../plugins/timefrequency/timefrequency.pro | 12 ++++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/applications/mne_analyze/mne_analyze/main.cpp b/applications/mne_analyze/mne_analyze/main.cpp index d2a5a6221e6..ec80bbe0cd8 100644 --- a/applications/mne_analyze/mne_analyze/main.cpp +++ b/applications/mne_analyze/mne_analyze/main.cpp @@ -78,6 +78,7 @@ Q_IMPORT_PLUGIN(SourceLocalization) Q_IMPORT_PLUGIN(ControlManager) Q_IMPORT_PLUGIN(ChannelSelection) Q_IMPORT_PLUGIN(CoRegistration) +Q_IMPORT_PLUGIN(TimeFrequency) #ifndef WASMBUILD Q_IMPORT_PLUGIN(View3D) #endif diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 50a21b86921..9152e09fd2a 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -45,6 +45,7 @@ #include #include +#include //============================================================================================================= // USED NAMESPACES @@ -96,7 +97,7 @@ void TimeFrequency::unload() QString TimeFrequency::getName() const { - return "Data Loader"; + return "Time-Frequency"; } //============================================================================================================= @@ -117,7 +118,8 @@ QDockWidget *TimeFrequency::getControl() QWidget *TimeFrequency::getView() { - return Q_NULLPTR; + m_pTimeFreqView = new DISPLIB::TimeFrequencyView(); + return m_pTimeFreqView; } //============================================================================================================= diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h index 8f8a5bdd02b..cdf84987349 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.h +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -65,6 +65,7 @@ namespace ANSHAREDLIB { namespace DISPLIB { class ProgressView; + class TimeFrequencyView; } //============================================================================================================= @@ -133,6 +134,9 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlu QPointer m_pCommu; /**< Used for sending events */ QString m_sSettingsPath; /**< Variable that stores the key where to store settings for this plugin.*/ + + QPointer m_pTimeFreqView; + }; //============================================================================================================= diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.pro b/applications/mne_analyze/plugins/timefrequency/timefrequency.pro index ba4831ba16a..1ba9ac22c3f 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.pro +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.pro @@ -64,12 +64,24 @@ LIBS += -L$${MNE_LIBRARY_DIR} CONFIG(debug, debug|release) { LIBS += -lanSharedd \ -lmnecppDispd \ + -lmnecppConnectivityd \ + -lmnecppRtProcessingd \ + -lmnecppInversed \ + -lmnecppFwdd \ + -lmnecppMned \ -lmnecppFiffd \ + -lmnecppFsd \ -lmnecppUtilsd \ } else { LIBS += -lanShared \ -lmnecppDisp \ + -lmnecppConnectivity \ + -lmnecppRtProcessing \ + -lmnecppInverse \ + -lmnecppFwd \ + -lmnecppMne \ -lmnecppFiff \ + -lmnecppFs \ -lmnecppUtils \ } From 48e4a2a25fc7fe233f38712bc4ac27e45e6666de Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Wed, 7 Apr 2021 14:36:37 -0400 Subject: [PATCH 06/57] ENH: setting up views --- libraries/disp/disp.pro | 2 + .../disp/viewers/helpers/timefrequencymodel.h | 4 + .../viewers/helpers/timefrequencyscene.cpp | 52 ++++++++ .../disp/viewers/helpers/timefrequencyscene.h | 60 ++++++++- .../disp/viewers/timefrequencylayoutview.cpp | 104 ++++++++++++++++ .../disp/viewers/timefrequencylayoutview.h | 116 ++++++++++++++++++ libraries/disp/viewers/timefrequencyview.cpp | 15 +++ libraries/disp/viewers/timefrequencyview.h | 4 + 8 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 libraries/disp/viewers/timefrequencylayoutview.cpp create mode 100644 libraries/disp/viewers/timefrequencylayoutview.h diff --git a/libraries/disp/disp.pro b/libraries/disp/disp.pro index 565e965b6b4..1d676c7571e 100644 --- a/libraries/disp/disp.pro +++ b/libraries/disp/disp.pro @@ -122,6 +122,7 @@ SOURCES += \ viewers/spharasettingsview.cpp \ viewers/fiffrawviewsettings.cpp \ viewers/averageselectionview.cpp \ + viewers/timefrequencylayoutview.cpp \ viewers/timefrequencyview.cpp \ viewers/triggerdetectionview.cpp \ viewers/quickcontrolview.cpp \ @@ -185,6 +186,7 @@ HEADERS += \ viewers/spharasettingsview.h \ viewers/fiffrawviewsettings.h \ viewers/averageselectionview.h \ + viewers/timefrequencylayoutview.h \ viewers/timefrequencyview.h \ viewers/triggerdetectionview.h \ viewers/quickcontrolview.h \ diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h index 2a2cb1d4a72..8b3d928c814 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.h +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -40,6 +40,10 @@ class TimeFrequencyModel { public: TimeFrequencyModel(); + + +private: +// QSharedPointer m_pChannelInfoModel; }; #endif // TIMEFREQUENCYMODEL_H diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.cpp b/libraries/disp/viewers/helpers/timefrequencyscene.cpp index 06c2c1e9681..404c759ba1e 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.cpp +++ b/libraries/disp/viewers/helpers/timefrequencyscene.cpp @@ -1,5 +1,57 @@ +//============================================================================================================= +/** + * @file timefrequencyscene.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencyScene Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + #include "timefrequencyscene.h" +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + TimeFrequencyScene::TimeFrequencyScene() { diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.h b/libraries/disp/viewers/helpers/timefrequencyscene.h index 6f68f415f28..83526ad297b 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.h +++ b/libraries/disp/viewers/helpers/timefrequencyscene.h @@ -1,11 +1,67 @@ +//============================================================================================================= +/** + * @file timefrequencyscene.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencyScene Class. + * + */ + #ifndef TIMEFREQUENCYSCENE_H #define TIMEFREQUENCYSCENE_H +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../../disp_global.h" + +#include "layoutscene.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= -class TimeFrequencyScene +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +class TimeFrequencyScene : public LayoutScene { public: TimeFrequencyScene(); }; - +}//namespace #endif // TIMEFREQUENCYSCENE_H diff --git a/libraries/disp/viewers/timefrequencylayoutview.cpp b/libraries/disp/viewers/timefrequencylayoutview.cpp new file mode 100644 index 00000000000..83196e58727 --- /dev/null +++ b/libraries/disp/viewers/timefrequencylayoutview.cpp @@ -0,0 +1,104 @@ +//============================================================================================================= +/** + * @file timefrequencylaoutview.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencyLayoutView Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequencylayoutview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencyLayoutView::TimeFrequencyLayoutView() +{ + +} + +//============================================================================================================= + +void TimeFrequencyLayoutView::updateGuiMode(GuiMode mode) +{ + switch(mode) { + case GuiMode::Clinical: + break; + default: // default is research mode + break; + } +} + +//============================================================================================================= + +void TimeFrequencyLayoutView::updateProcessingMode(ProcessingMode mode) +{ + switch(mode) { + case ProcessingMode::Offline: + break; + default: // default is realtime mode + break; + } +} + +//============================================================================================================= + +void TimeFrequencyLayoutView::saveSettings() +{ + +} + +//============================================================================================================= + +void TimeFrequencyLayoutView::loadSettings() +{ + +} + + +//============================================================================================================= + +void TimeFrequencyLayoutView::clearView() +{ + +} diff --git a/libraries/disp/viewers/timefrequencylayoutview.h b/libraries/disp/viewers/timefrequencylayoutview.h new file mode 100644 index 00000000000..f662f077a03 --- /dev/null +++ b/libraries/disp/viewers/timefrequencylayoutview.h @@ -0,0 +1,116 @@ +//============================================================================================================= +/** + * @file timefrequencylayoutview.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencyLayoutView Class. + * + */ + +#ifndef TIMEFREQUENCYLAYOUTVIEW_H +#define TIMEFREQUENCYLAYOUTVIEW_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../disp_global.h" +#include "abstractview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +// DISPLIB FORWARD DECLARATIONS +//============================================================================================================= + +class TimeFrequencyScene; + +//============================================================================================================= +class TimeFrequencyLayoutView : public AbstractView +{ +public: + TimeFrequencyLayoutView(); + + //========================================================================================================= + /** + * Update the views GUI based on the set GuiMode (Clinical=0, Research=1). + * + * @param mode The new mode (Clinical=0, Research=1). + */ + void updateGuiMode(GuiMode mode); + + //========================================================================================================= + /** + * Update the views GUI based on the set ProcessingMode (RealTime=0, Offline=1). + * + * @param mode The new mode (RealTime=0, Offline=1). + */ + void updateProcessingMode(ProcessingMode mode); + + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + */ + void saveSettings(); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + */ + void loadSettings(); + + //========================================================================================================= + /** + * Clears the view + */ + void clearView(); + +protected: + QScopedPointer m_pAverageScene; + QScopedPointer m_pTimeFrequencyLayoutView; +}; +}//namespace + +#endif // TIMEFREQUENCYLAYOUTVIEW_H diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 54512164695..f8028736ed1 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -94,3 +94,18 @@ void TimeFrequencyView::loadSettings() { } + + +//============================================================================================================= + +void TimeFrequencyView::clearView() +{ + +} + +//============================================================================================================= + +void TimeFrequencyView::paintEvent(QPaintEvent *event) +{ + return AbstractView::paintEvent(event); +} diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index c2b5b209ee6..adc9cae7085 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -101,6 +101,10 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView * Clears the view */ void clearView(); + +protected: + + virtual void paintEvent(QPaintEvent *event); }; } //namespace From fff0e7f3a40d499bc79b1d5ed35fc660222651c5 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Thu, 8 Apr 2021 13:26:54 -0400 Subject: [PATCH 07/57] ENH: init layout view, tabs in plugin --- .../plugins/timefrequency/timefrequency.cpp | 9 +++ .../plugins/timefrequency/timefrequency.h | 2 + .../viewers/helpers/timefrequencyscene.cpp | 4 +- .../disp/viewers/helpers/timefrequencyscene.h | 6 +- .../helpers/timefrequencysceneitem.cpp | 56 +++++++++++++++++ .../viewers/helpers/timefrequencysceneitem.h | 62 ++++++++++++++++++- .../disp/viewers/timefrequencylayoutview.cpp | 39 ++++++++++++ .../disp/viewers/timefrequencylayoutview.h | 11 +++- libraries/disp/viewers/timefrequencyview.cpp | 11 ++++ libraries/disp/viewers/timefrequencyview.h | 5 ++ 10 files changed, 197 insertions(+), 8 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 9152e09fd2a..f1cbb6e5d2c 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -46,6 +46,7 @@ #include #include +#include //============================================================================================================= // USED NAMESPACES @@ -118,7 +119,15 @@ QDockWidget *TimeFrequency::getControl() QWidget *TimeFrequency::getView() { + QWidget* pTimeFreqViewWidget = new QWidget(); + QTabWidget* pTabView = new QTabWidget(pTimeFreqViewWidget); + m_pTimeFreqView = new DISPLIB::TimeFrequencyView(); + m_pTimeFreqLayoutView = new DISPLIB::TimeFrequencyLayoutView(); + + pTabView->addTab(m_pTimeFreqView, "Average View"); + pTabView->addTab(m_pTimeFreqLayoutView, "Layout View"); + return m_pTimeFreqView; } diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h index cdf84987349..3d8b9d540bd 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.h +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -66,6 +66,7 @@ namespace ANSHAREDLIB { namespace DISPLIB { class ProgressView; class TimeFrequencyView; + class TimeFrequencyLayoutView; } //============================================================================================================= @@ -136,6 +137,7 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlu QString m_sSettingsPath; /**< Variable that stores the key where to store settings for this plugin.*/ QPointer m_pTimeFreqView; + QPointer m_pTimeFreqLayoutView; }; diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.cpp b/libraries/disp/viewers/helpers/timefrequencyscene.cpp index 404c759ba1e..ed5dbf854ce 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.cpp +++ b/libraries/disp/viewers/helpers/timefrequencyscene.cpp @@ -52,7 +52,9 @@ using namespace DISPLIB; // DEFINE MEMBER METHODS //============================================================================================================= -TimeFrequencyScene::TimeFrequencyScene() +TimeFrequencyScene::TimeFrequencyScene(QGraphicsView* view, + QObject* parent) +: LayoutScene(view, parent) { } diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.h b/libraries/disp/viewers/helpers/timefrequencyscene.h index 83526ad297b..d5dc6e82460 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.h +++ b/libraries/disp/viewers/helpers/timefrequencyscene.h @@ -58,10 +58,12 @@ namespace DISPLIB { -class TimeFrequencyScene : public LayoutScene +class DISPSHARED_EXPORT TimeFrequencyScene : public LayoutScene { + Q_OBJECT public: - TimeFrequencyScene(); + TimeFrequencyScene(QGraphicsView* view, + QObject *parent = 0); }; }//namespace #endif // TIMEFREQUENCYSCENE_H diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp index c2c4c2945af..474581d3146 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp @@ -1,5 +1,61 @@ +//============================================================================================================= +/** + * @file timefrequencysceneitem.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencySceneItem Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + #include "timefrequencysceneitem.h" +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + TimeFrequencySceneItem::TimeFrequencySceneItem() { diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.h b/libraries/disp/viewers/helpers/timefrequencysceneitem.h index c46a8e5721b..cbe364ab1a5 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.h +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.h @@ -1,11 +1,69 @@ +//============================================================================================================= +/** + * @file timefrequencysceneitem.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencySceneItem Class. + * + */ + #ifndef TIMEFREQUENCYSCENEITEM_H #define TIMEFREQUENCYSCENEITEM_H +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../../disp_global.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= -class TimeFrequencySceneItem +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +class DISPSHARED_EXPORT TimeFrequencySceneItem : public QGraphicsObject { + Q_OBJECT public: TimeFrequencySceneItem(); }; - +}//namespace #endif // TIMEFREQUENCYSCENEITEM_H diff --git a/libraries/disp/viewers/timefrequencylayoutview.cpp b/libraries/disp/viewers/timefrequencylayoutview.cpp index 83196e58727..c3b671f0b2c 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.cpp +++ b/libraries/disp/viewers/timefrequencylayoutview.cpp @@ -37,11 +37,18 @@ //============================================================================================================= #include "timefrequencylayoutview.h" +#include "helpers/timefrequencyscene.h" +#include "helpers/timefrequencysceneitem.h" //============================================================================================================= // QT INCLUDES //============================================================================================================= +#include +#if !defined(NO_QOPENGLWIDGET) + #include +#endif + //============================================================================================================= // USED NAMESPACES //============================================================================================================= @@ -53,12 +60,44 @@ using namespace DISPLIB; //============================================================================================================= TimeFrequencyLayoutView::TimeFrequencyLayoutView() +: TimeFrequencyLayoutView("", Q_NULLPTR) { } //============================================================================================================= + +TimeFrequencyLayoutView::TimeFrequencyLayoutView(const QString& sSettingsPath, + QWidget *parent, + Qt::WindowFlags f) +: AbstractView(parent, f) +{ + m_sSettingsPath = sSettingsPath; + this->setWindowTitle("Time-Frequency Layout"); + + m_pTimeFreqGraphicsView = new QGraphicsView(); + +#if !defined(NO_QOPENGLWIDGET) + m_pTimeFreqGraphicsView->setViewport(new QOpenGLWidget); +#endif + + m_pTimeFreqGraphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_pTimeFreqGraphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + m_pTimeFreqScene = new TimeFrequencyScene(m_pTimeFreqGraphicsView, this); + m_pTimeFreqScene->setBackgroundBrush(QBrush(Qt::white)); + + m_pTimeFreqGraphicsView->setScene(m_pTimeFreqScene); + + QVBoxLayout *neLayout = new QVBoxLayout(this); + neLayout->setContentsMargins(0,0,0,0); + neLayout->addWidget(m_pTimeFreqGraphicsView); + this->setLayout(neLayout); +} + +//============================================================================================================= + void TimeFrequencyLayoutView::updateGuiMode(GuiMode mode) { switch(mode) { diff --git a/libraries/disp/viewers/timefrequencylayoutview.h b/libraries/disp/viewers/timefrequencylayoutview.h index f662f077a03..369844fe036 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.h +++ b/libraries/disp/viewers/timefrequencylayoutview.h @@ -68,11 +68,16 @@ namespace DISPLIB class TimeFrequencyScene; //============================================================================================================= -class TimeFrequencyLayoutView : public AbstractView +class DISPSHARED_EXPORT TimeFrequencyLayoutView : public AbstractView { + Q_OBJECT public: TimeFrequencyLayoutView(); + TimeFrequencyLayoutView(const QString& sSettingsPath, + QWidget* parent, + Qt::WindowFlags f = Qt::Widget); + //========================================================================================================= /** * Update the views GUI based on the set GuiMode (Clinical=0, Research=1). @@ -108,8 +113,8 @@ class TimeFrequencyLayoutView : public AbstractView void clearView(); protected: - QScopedPointer m_pAverageScene; - QScopedPointer m_pTimeFrequencyLayoutView; + QPointer m_pTimeFreqScene; + QPointer m_pTimeFreqGraphicsView; }; }//namespace diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index f8028736ed1..31ca81b6f71 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -53,12 +53,23 @@ using namespace DISPLIB; //============================================================================================================= TimeFrequencyView::TimeFrequencyView() +: TimeFrequencyView("", Q_NULLPTR) { } //============================================================================================================= +TimeFrequencyView::TimeFrequencyView(const QString& sSettingsPath, + QWidget *parent, + Qt::WindowFlags f) +: AbstractView(parent, f) +{ + m_sSettingsPath = sSettingsPath; +} + +//============================================================================================================= + void TimeFrequencyView::updateGuiMode(GuiMode mode) { switch(mode) { diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index adc9cae7085..bc3660be8ee 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -65,9 +65,14 @@ namespace DISPLIB */ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView { + Q_OBJECT public: TimeFrequencyView(); + TimeFrequencyView(const QString& sSettingsPath, + QWidget* parent, + Qt::WindowFlags f = Qt::Widget); + //========================================================================================================= /** * Update the views GUI based on the set GuiMode (Clinical=0, Research=1). From af26eb5657235ff97a61021689350857e6d174df Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Fri, 9 Apr 2021 11:23:35 -0400 Subject: [PATCH 08/57] ENh: timefrequency in lib layer, raw data and events to plugin --- .../plugins/timefrequency/timefrequency.cpp | 30 ++++++++++++++- .../plugins/timefrequency/timefrequency.h | 5 +++ libraries/rtprocessing/rtprocessing.pro | 2 + libraries/rtprocessing/timefrequency.cpp | 6 +++ libraries/rtprocessing/timefrequency.h | 38 +++++++++++++++++++ 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 libraries/rtprocessing/timefrequency.cpp create mode 100644 libraries/rtprocessing/timefrequency.h diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index f1cbb6e5d2c..5a2639cb1d8 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -121,6 +121,7 @@ QWidget *TimeFrequency::getView() { QWidget* pTimeFreqViewWidget = new QWidget(); QTabWidget* pTabView = new QTabWidget(pTimeFreqViewWidget); + QVBoxLayout* pViewLayout = new QVBoxLayout(); m_pTimeFreqView = new DISPLIB::TimeFrequencyView(); m_pTimeFreqLayoutView = new DISPLIB::TimeFrequencyLayoutView(); @@ -128,14 +129,24 @@ QWidget *TimeFrequency::getView() pTabView->addTab(m_pTimeFreqView, "Average View"); pTabView->addTab(m_pTimeFreqLayoutView, "Layout View"); - return m_pTimeFreqView; + pViewLayout->addWidget(pTabView); + pTimeFreqViewWidget->setLayout(pViewLayout); + + return pTimeFreqViewWidget; } //============================================================================================================= void TimeFrequency::handleEvent(QSharedPointer e) { - + switch (e->getType()) { + case EVENT_TYPE::SELECTED_MODEL_CHANGED:{ + onModelChanged(e->getData().value >()); + break; + } + default: + qWarning() << "[Averaging::handleEvent] Received an Event that is not handled by switch cases."; + } } //============================================================================================================= @@ -162,3 +173,18 @@ void TimeFrequency::loadSettings() QSettings settings("MNECPP"); settings.beginGroup(m_sSettingsPath); } + +//============================================================================================================= + +void TimeFrequency::onModelChanged(QSharedPointer pNewModel) +{ + if(pNewModel->getType() == MODEL_TYPE::ANSHAREDLIB_FIFFRAW_MODEL) { + if(m_pFiffRawModel) { + if(m_pFiffRawModel == pNewModel) { + qInfo() << "[Averaging::onModelChanged] New model is the same as old model"; + return; + } + } + m_pFiffRawModel = qSharedPointerCast(pNewModel); + } +} diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h index 3d8b9d540bd..04897429d69 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.h +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -133,12 +133,17 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlu */ void saveSettings(); + //========================================================================================================= + void onModelChanged(QSharedPointer pNewModel); + QPointer m_pCommu; /**< Used for sending events */ QString m_sSettingsPath; /**< Variable that stores the key where to store settings for this plugin.*/ QPointer m_pTimeFreqView; QPointer m_pTimeFreqLayoutView; + QSharedPointer m_pFiffRawModel; /**< Pointer to currently loaded FiffRawView Model */ + }; //============================================================================================================= diff --git a/libraries/rtprocessing/rtprocessing.pro b/libraries/rtprocessing/rtprocessing.pro index 9dae3b7da9b..d165b63956d 100644 --- a/libraries/rtprocessing/rtprocessing.pro +++ b/libraries/rtprocessing/rtprocessing.pro @@ -94,6 +94,7 @@ SOURCES += \ helpers/parksmcclellan.cpp \ helpers/filterkernel.cpp \ helpers/filterio.cpp \ + timefrequency.cpp HEADERS += \ icp.h \ @@ -112,6 +113,7 @@ HEADERS += \ helpers/parksmcclellan.h \ helpers/filterkernel.h \ helpers/filterio.h \ + timefrequency.h INCLUDEPATH += $${EIGEN_INCLUDE_DIR} INCLUDEPATH += $${MNE_INCLUDE_DIR} diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp new file mode 100644 index 00000000000..fefd9c62c4e --- /dev/null +++ b/libraries/rtprocessing/timefrequency.cpp @@ -0,0 +1,6 @@ +#include "timefrequency.h" + +TimeFrequency::TimeFrequency() +{ + +} diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h new file mode 100644 index 00000000000..84076f2f3c1 --- /dev/null +++ b/libraries/rtprocessing/timefrequency.h @@ -0,0 +1,38 @@ +#ifndef TIMEFREQUENCY_RTPROCESSING_H +#define TIMEFREQUENCY_RTPROCESSING_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "rtprocessing_global.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace FIFFLIB { + class FiffRawData; +} + +class TimeFrequency +{ +public: + TimeFrequency(); +}; + +#endif // TIMEFREQUENCY_RTPROCESSING_H From 42e7eeeeab93694b8d7837a80bede327d4149b8b Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Fri, 9 Apr 2021 13:06:30 -0400 Subject: [PATCH 09/57] ENH: trying qml for view --- libraries/disp/disp.pro | 15 + libraries/disp/viewers/qml/Data.qml | 1571 ++++++++++++++++++ libraries/disp/viewers/qml/NewButton.qml | 63 + libraries/disp/viewers/qml/tfview.qml | 275 +++ libraries/disp/viewers/timefrequencyview.cpp | 20 + libraries/disp/viewers/timefrequencyview.h | 1 + 6 files changed, 1945 insertions(+) create mode 100644 libraries/disp/viewers/qml/Data.qml create mode 100644 libraries/disp/viewers/qml/NewButton.qml create mode 100644 libraries/disp/viewers/qml/tfview.qml diff --git a/libraries/disp/disp.pro b/libraries/disp/disp.pro index 1d676c7571e..9fa0ea79bb4 100644 --- a/libraries/disp/disp.pro +++ b/libraries/disp/disp.pro @@ -44,6 +44,11 @@ QT += core widgets svg concurrent opengl qtHaveModule(printsupport): QT += printsupport qtHaveModule(charts): QT += charts +qtHaveModule(datavisualization){ +QT += qml quick datavisualization quickwidgets +} + + DEFINES += DISP_LIBRARY DESTDIR = $${MNE_LIBRARY_DIR} @@ -255,6 +260,16 @@ FORMS += \ viewers/formfiles/applytoview.ui \ viewers/formfiles/bidsview.ui \ +qtHaveModule(datavisualization) { + +DEFINES += QML_VIEWS_ON + +DISTFILES += \ + viewers/qml/tfview.qml \ + viewers/qml/Data.qml \ + viewers/qml/NewButton.qml \ +} + INCLUDEPATH += $${EIGEN_INCLUDE_DIR} INCLUDEPATH += $${MNE_INCLUDE_DIR} diff --git a/libraries/disp/viewers/qml/Data.qml b/libraries/disp/viewers/qml/Data.qml new file mode 100644 index 00000000000..ed9913b36ae --- /dev/null +++ b/libraries/disp/viewers/qml/Data.qml @@ -0,0 +1,1571 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Data Visualization module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 + +Item { + property alias model: dataModel + + ListModel { + id: dataModel + ListElement{ radius: "0"; angle: "0"; value: "50"; } + ListElement{ radius: "0"; angle: "5"; value: "54.3578"; } + ListElement{ radius: "0"; angle: "10"; value: "58.6824"; } + ListElement{ radius: "0"; angle: "15"; value: "62.941"; } + ListElement{ radius: "0"; angle: "20"; value: "67.101"; } + ListElement{ radius: "0"; angle: "25"; value: "71.1309"; } + ListElement{ radius: "0"; angle: "30"; value: "75"; } + ListElement{ radius: "0"; angle: "35"; value: "78.6788"; } + ListElement{ radius: "0"; angle: "40"; value: "82.1394"; } + ListElement{ radius: "0"; angle: "45"; value: "85.3553"; } + ListElement{ radius: "0"; angle: "50"; value: "88.3022"; } + ListElement{ radius: "0"; angle: "55"; value: "90.9576"; } + ListElement{ radius: "0"; angle: "60"; value: "93.3013"; } + ListElement{ radius: "0"; angle: "65"; value: "95.3154"; } + ListElement{ radius: "0"; angle: "70"; value: "96.9846"; } + ListElement{ radius: "0"; angle: "75"; value: "98.2963"; } + ListElement{ radius: "0"; angle: "80"; value: "99.2404"; } + ListElement{ radius: "0"; angle: "85"; value: "99.8097"; } + ListElement{ radius: "0"; angle: "90"; value: "100"; } + ListElement{ radius: "0"; angle: "95"; value: "99.8097"; } + ListElement{ radius: "0"; angle: "100"; value: "99.2404"; } + ListElement{ radius: "0"; angle: "105"; value: "98.2963"; } + ListElement{ radius: "0"; angle: "110"; value: "96.9846"; } + ListElement{ radius: "0"; angle: "115"; value: "95.3154"; } + ListElement{ radius: "0"; angle: "120"; value: "93.3013"; } + ListElement{ radius: "0"; angle: "125"; value: "90.9576"; } + ListElement{ radius: "0"; angle: "130"; value: "88.3022"; } + ListElement{ radius: "0"; angle: "135"; value: "85.3553"; } + ListElement{ radius: "0"; angle: "140"; value: "82.1394"; } + ListElement{ radius: "0"; angle: "145"; value: "78.6788"; } + ListElement{ radius: "0"; angle: "150"; value: "75"; } + ListElement{ radius: "0"; angle: "155"; value: "71.1309"; } + ListElement{ radius: "0"; angle: "160"; value: "67.101"; } + ListElement{ radius: "0"; angle: "165"; value: "62.941"; } + ListElement{ radius: "0"; angle: "170"; value: "58.6824"; } + ListElement{ radius: "0"; angle: "175"; value: "54.3578"; } + ListElement{ radius: "0"; angle: "180"; value: "50"; } + ListElement{ radius: "0"; angle: "185"; value: "45.6422"; } + ListElement{ radius: "0"; angle: "190"; value: "41.3176"; } + ListElement{ radius: "0"; angle: "195"; value: "37.059"; } + ListElement{ radius: "0"; angle: "200"; value: "32.899"; } + ListElement{ radius: "0"; angle: "205"; value: "28.8691"; } + ListElement{ radius: "0"; angle: "210"; value: "25"; } + ListElement{ radius: "0"; angle: "215"; value: "21.3212"; } + ListElement{ radius: "0"; angle: "220"; value: "17.8606"; } + ListElement{ radius: "0"; angle: "225"; value: "14.6447"; } + ListElement{ radius: "0"; angle: "230"; value: "11.6978"; } + ListElement{ radius: "0"; angle: "235"; value: "9.0424"; } + ListElement{ radius: "0"; angle: "240"; value: "6.69873"; } + ListElement{ radius: "0"; angle: "245"; value: "4.68461"; } + ListElement{ radius: "0"; angle: "250"; value: "3.01537"; } + ListElement{ radius: "0"; angle: "255"; value: "1.70371"; } + ListElement{ radius: "0"; angle: "260"; value: "0.759612"; } + ListElement{ radius: "0"; angle: "265"; value: "0.190265"; } + ListElement{ radius: "0"; angle: "270"; value: "0"; } + ListElement{ radius: "0"; angle: "275"; value: "0.190265"; } + ListElement{ radius: "0"; angle: "280"; value: "0.759612"; } + ListElement{ radius: "0"; angle: "285"; value: "1.70371"; } + ListElement{ radius: "0"; angle: "290"; value: "3.01537"; } + ListElement{ radius: "0"; angle: "295"; value: "4.68461"; } + ListElement{ radius: "0"; angle: "300"; value: "6.69873"; } + ListElement{ radius: "0"; angle: "305"; value: "9.0424"; } + ListElement{ radius: "0"; angle: "310"; value: "11.6978"; } + ListElement{ radius: "0"; angle: "315"; value: "14.6447"; } + ListElement{ radius: "0"; angle: "320"; value: "17.8606"; } + ListElement{ radius: "0"; angle: "325"; value: "21.3212"; } + ListElement{ radius: "0"; angle: "330"; value: "25"; } + ListElement{ radius: "0"; angle: "335"; value: "28.8691"; } + ListElement{ radius: "0"; angle: "340"; value: "32.899"; } + ListElement{ radius: "0"; angle: "345"; value: "37.059"; } + ListElement{ radius: "0"; angle: "350"; value: "41.3176"; } + ListElement{ radius: "0"; angle: "355"; value: "45.6422"; } + ListElement{ radius: "0"; angle: "360"; value: "50"; } + ListElement{ radius: "5"; angle: "0"; value: "49.3844"; } + ListElement{ radius: "5"; angle: "5"; value: "53.7422"; } + ListElement{ radius: "5"; angle: "10"; value: "58.0668"; } + ListElement{ radius: "5"; angle: "15"; value: "62.3254"; } + ListElement{ radius: "5"; angle: "20"; value: "66.4854"; } + ListElement{ radius: "5"; angle: "25"; value: "70.5153"; } + ListElement{ radius: "5"; angle: "30"; value: "74.3844"; } + ListElement{ radius: "5"; angle: "35"; value: "78.0632"; } + ListElement{ radius: "5"; angle: "40"; value: "81.5238"; } + ListElement{ radius: "5"; angle: "45"; value: "84.7398"; } + ListElement{ radius: "5"; angle: "50"; value: "87.6866"; } + ListElement{ radius: "5"; angle: "55"; value: "90.342"; } + ListElement{ radius: "5"; angle: "60"; value: "92.6857"; } + ListElement{ radius: "5"; angle: "65"; value: "94.6998"; } + ListElement{ radius: "5"; angle: "70"; value: "96.369"; } + ListElement{ radius: "5"; angle: "75"; value: "97.6807"; } + ListElement{ radius: "5"; angle: "80"; value: "98.6248"; } + ListElement{ radius: "5"; angle: "85"; value: "99.1942"; } + ListElement{ radius: "5"; angle: "90"; value: "99.3844"; } + ListElement{ radius: "5"; angle: "95"; value: "99.1942"; } + ListElement{ radius: "5"; angle: "100"; value: "98.6248"; } + ListElement{ radius: "5"; angle: "105"; value: "97.6807"; } + ListElement{ radius: "5"; angle: "110"; value: "96.369"; } + ListElement{ radius: "5"; angle: "115"; value: "94.6998"; } + ListElement{ radius: "5"; angle: "120"; value: "92.6857"; } + ListElement{ radius: "5"; angle: "125"; value: "90.342"; } + ListElement{ radius: "5"; angle: "130"; value: "87.6866"; } + ListElement{ radius: "5"; angle: "135"; value: "84.7398"; } + ListElement{ radius: "5"; angle: "140"; value: "81.5238"; } + ListElement{ radius: "5"; angle: "145"; value: "78.0632"; } + ListElement{ radius: "5"; angle: "150"; value: "74.3844"; } + ListElement{ radius: "5"; angle: "155"; value: "70.5153"; } + ListElement{ radius: "5"; angle: "160"; value: "66.4854"; } + ListElement{ radius: "5"; angle: "165"; value: "62.3254"; } + ListElement{ radius: "5"; angle: "170"; value: "58.0668"; } + ListElement{ radius: "5"; angle: "175"; value: "53.7422"; } + ListElement{ radius: "5"; angle: "180"; value: "49.3844"; } + ListElement{ radius: "5"; angle: "185"; value: "45.0266"; } + ListElement{ radius: "5"; angle: "190"; value: "40.702"; } + ListElement{ radius: "5"; angle: "195"; value: "36.4435"; } + ListElement{ radius: "5"; angle: "200"; value: "32.2834"; } + ListElement{ radius: "5"; angle: "205"; value: "28.2535"; } + ListElement{ radius: "5"; angle: "210"; value: "24.3844"; } + ListElement{ radius: "5"; angle: "215"; value: "20.7056"; } + ListElement{ radius: "5"; angle: "220"; value: "17.245"; } + ListElement{ radius: "5"; angle: "225"; value: "14.0291"; } + ListElement{ radius: "5"; angle: "230"; value: "11.0822"; } + ListElement{ radius: "5"; angle: "235"; value: "8.42681"; } + ListElement{ radius: "5"; angle: "240"; value: "6.08315"; } + ListElement{ radius: "5"; angle: "245"; value: "4.06903"; } + ListElement{ radius: "5"; angle: "250"; value: "2.39979"; } + ListElement{ radius: "5"; angle: "255"; value: "1.08813"; } + ListElement{ radius: "5"; angle: "260"; value: "0.144029"; } + ListElement{ radius: "5"; angle: "265"; value: "-0.425318"; } + ListElement{ radius: "5"; angle: "270"; value: "-0.615583"; } + ListElement{ radius: "5"; angle: "275"; value: "-0.425318"; } + ListElement{ radius: "5"; angle: "280"; value: "0.144029"; } + ListElement{ radius: "5"; angle: "285"; value: "1.08813"; } + ListElement{ radius: "5"; angle: "290"; value: "2.39979"; } + ListElement{ radius: "5"; angle: "295"; value: "4.06903"; } + ListElement{ radius: "5"; angle: "300"; value: "6.08315"; } + ListElement{ radius: "5"; angle: "305"; value: "8.42681"; } + ListElement{ radius: "5"; angle: "310"; value: "11.0822"; } + ListElement{ radius: "5"; angle: "315"; value: "14.0291"; } + ListElement{ radius: "5"; angle: "320"; value: "17.245"; } + ListElement{ radius: "5"; angle: "325"; value: "20.7056"; } + ListElement{ radius: "5"; angle: "330"; value: "24.3844"; } + ListElement{ radius: "5"; angle: "335"; value: "28.2535"; } + ListElement{ radius: "5"; angle: "340"; value: "32.2834"; } + ListElement{ radius: "5"; angle: "345"; value: "36.4435"; } + ListElement{ radius: "5"; angle: "350"; value: "40.702"; } + ListElement{ radius: "5"; angle: "355"; value: "45.0266"; } + ListElement{ radius: "5"; angle: "360"; value: "49.3844"; } + ListElement{ radius: "10"; angle: "0"; value: "47.5528"; } + ListElement{ radius: "10"; angle: "5"; value: "51.9106"; } + ListElement{ radius: "10"; angle: "10"; value: "56.2352"; } + ListElement{ radius: "10"; angle: "15"; value: "60.4938"; } + ListElement{ radius: "10"; angle: "20"; value: "64.6538"; } + ListElement{ radius: "10"; angle: "25"; value: "68.6837"; } + ListElement{ radius: "10"; angle: "30"; value: "72.5528"; } + ListElement{ radius: "10"; angle: "35"; value: "76.2316"; } + ListElement{ radius: "10"; angle: "40"; value: "79.6922"; } + ListElement{ radius: "10"; angle: "45"; value: "82.9082"; } + ListElement{ radius: "10"; angle: "50"; value: "85.855"; } + ListElement{ radius: "10"; angle: "55"; value: "88.5104"; } + ListElement{ radius: "10"; angle: "60"; value: "90.8541"; } + ListElement{ radius: "10"; angle: "65"; value: "92.8682"; } + ListElement{ radius: "10"; angle: "70"; value: "94.5375"; } + ListElement{ radius: "10"; angle: "75"; value: "95.8491"; } + ListElement{ radius: "10"; angle: "80"; value: "96.7932"; } + ListElement{ radius: "10"; angle: "85"; value: "97.3626"; } + ListElement{ radius: "10"; angle: "90"; value: "97.5528"; } + ListElement{ radius: "10"; angle: "95"; value: "97.3626"; } + ListElement{ radius: "10"; angle: "100"; value: "96.7932"; } + ListElement{ radius: "10"; angle: "105"; value: "95.8491"; } + ListElement{ radius: "10"; angle: "110"; value: "94.5375"; } + ListElement{ radius: "10"; angle: "115"; value: "92.8682"; } + ListElement{ radius: "10"; angle: "120"; value: "90.8541"; } + ListElement{ radius: "10"; angle: "125"; value: "88.5104"; } + ListElement{ radius: "10"; angle: "130"; value: "85.855"; } + ListElement{ radius: "10"; angle: "135"; value: "82.9082"; } + ListElement{ radius: "10"; angle: "140"; value: "79.6922"; } + ListElement{ radius: "10"; angle: "145"; value: "76.2316"; } + ListElement{ radius: "10"; angle: "150"; value: "72.5528"; } + ListElement{ radius: "10"; angle: "155"; value: "68.6837"; } + ListElement{ radius: "10"; angle: "160"; value: "64.6538"; } + ListElement{ radius: "10"; angle: "165"; value: "60.4938"; } + ListElement{ radius: "10"; angle: "170"; value: "56.2352"; } + ListElement{ radius: "10"; angle: "175"; value: "51.9106"; } + ListElement{ radius: "10"; angle: "180"; value: "47.5528"; } + ListElement{ radius: "10"; angle: "185"; value: "43.195"; } + ListElement{ radius: "10"; angle: "190"; value: "38.8704"; } + ListElement{ radius: "10"; angle: "195"; value: "34.6119"; } + ListElement{ radius: "10"; angle: "200"; value: "30.4518"; } + ListElement{ radius: "10"; angle: "205"; value: "26.4219"; } + ListElement{ radius: "10"; angle: "210"; value: "22.5528"; } + ListElement{ radius: "10"; angle: "215"; value: "18.874"; } + ListElement{ radius: "10"; angle: "220"; value: "15.4134"; } + ListElement{ radius: "10"; angle: "225"; value: "12.1975"; } + ListElement{ radius: "10"; angle: "230"; value: "9.2506"; } + ListElement{ radius: "10"; angle: "235"; value: "6.59522"; } + ListElement{ radius: "10"; angle: "240"; value: "4.25156"; } + ListElement{ radius: "10"; angle: "245"; value: "2.23744"; } + ListElement{ radius: "10"; angle: "250"; value: "0.568195"; } + ListElement{ radius: "10"; angle: "255"; value: "-0.743465"; } + ListElement{ radius: "10"; angle: "260"; value: "-1.68756"; } + ListElement{ radius: "10"; angle: "265"; value: "-2.25691"; } + ListElement{ radius: "10"; angle: "270"; value: "-2.44717"; } + ListElement{ radius: "10"; angle: "275"; value: "-2.25691"; } + ListElement{ radius: "10"; angle: "280"; value: "-1.68756"; } + ListElement{ radius: "10"; angle: "285"; value: "-0.743465"; } + ListElement{ radius: "10"; angle: "290"; value: "0.568195"; } + ListElement{ radius: "10"; angle: "295"; value: "2.23744"; } + ListElement{ radius: "10"; angle: "300"; value: "4.25156"; } + ListElement{ radius: "10"; angle: "305"; value: "6.59522"; } + ListElement{ radius: "10"; angle: "310"; value: "9.2506"; } + ListElement{ radius: "10"; angle: "315"; value: "12.1975"; } + ListElement{ radius: "10"; angle: "320"; value: "15.4134"; } + ListElement{ radius: "10"; angle: "325"; value: "18.874"; } + ListElement{ radius: "10"; angle: "330"; value: "22.5528"; } + ListElement{ radius: "10"; angle: "335"; value: "26.4219"; } + ListElement{ radius: "10"; angle: "340"; value: "30.4518"; } + ListElement{ radius: "10"; angle: "345"; value: "34.6119"; } + ListElement{ radius: "10"; angle: "350"; value: "38.8704"; } + ListElement{ radius: "10"; angle: "355"; value: "43.195"; } + ListElement{ radius: "10"; angle: "360"; value: "47.5528"; } + ListElement{ radius: "15"; angle: "0"; value: "44.5503"; } + ListElement{ radius: "15"; angle: "5"; value: "48.9081"; } + ListElement{ radius: "15"; angle: "10"; value: "53.2327"; } + ListElement{ radius: "15"; angle: "15"; value: "57.4913"; } + ListElement{ radius: "15"; angle: "20"; value: "61.6513"; } + ListElement{ radius: "15"; angle: "25"; value: "65.6812"; } + ListElement{ radius: "15"; angle: "30"; value: "69.5503"; } + ListElement{ radius: "15"; angle: "35"; value: "73.2291"; } + ListElement{ radius: "15"; angle: "40"; value: "76.6897"; } + ListElement{ radius: "15"; angle: "45"; value: "79.9057"; } + ListElement{ radius: "15"; angle: "50"; value: "82.8525"; } + ListElement{ radius: "15"; angle: "55"; value: "85.5079"; } + ListElement{ radius: "15"; angle: "60"; value: "87.8516"; } + ListElement{ radius: "15"; angle: "65"; value: "89.8657"; } + ListElement{ radius: "15"; angle: "70"; value: "91.535"; } + ListElement{ radius: "15"; angle: "75"; value: "92.8466"; } + ListElement{ radius: "15"; angle: "80"; value: "93.7907"; } + ListElement{ radius: "15"; angle: "85"; value: "94.3601"; } + ListElement{ radius: "15"; angle: "90"; value: "94.5503"; } + ListElement{ radius: "15"; angle: "95"; value: "94.3601"; } + ListElement{ radius: "15"; angle: "100"; value: "93.7907"; } + ListElement{ radius: "15"; angle: "105"; value: "92.8466"; } + ListElement{ radius: "15"; angle: "110"; value: "91.535"; } + ListElement{ radius: "15"; angle: "115"; value: "89.8657"; } + ListElement{ radius: "15"; angle: "120"; value: "87.8516"; } + ListElement{ radius: "15"; angle: "125"; value: "85.5079"; } + ListElement{ radius: "15"; angle: "130"; value: "82.8525"; } + ListElement{ radius: "15"; angle: "135"; value: "79.9057"; } + ListElement{ radius: "15"; angle: "140"; value: "76.6897"; } + ListElement{ radius: "15"; angle: "145"; value: "73.2291"; } + ListElement{ radius: "15"; angle: "150"; value: "69.5503"; } + ListElement{ radius: "15"; angle: "155"; value: "65.6812"; } + ListElement{ radius: "15"; angle: "160"; value: "61.6513"; } + ListElement{ radius: "15"; angle: "165"; value: "57.4913"; } + ListElement{ radius: "15"; angle: "170"; value: "53.2327"; } + ListElement{ radius: "15"; angle: "175"; value: "48.9081"; } + ListElement{ radius: "15"; angle: "180"; value: "44.5503"; } + ListElement{ radius: "15"; angle: "185"; value: "40.1925"; } + ListElement{ radius: "15"; angle: "190"; value: "35.8679"; } + ListElement{ radius: "15"; angle: "195"; value: "31.6094"; } + ListElement{ radius: "15"; angle: "200"; value: "27.4493"; } + ListElement{ radius: "15"; angle: "205"; value: "23.4194"; } + ListElement{ radius: "15"; angle: "210"; value: "19.5503"; } + ListElement{ radius: "15"; angle: "215"; value: "15.8715"; } + ListElement{ radius: "15"; angle: "220"; value: "12.4109"; } + ListElement{ radius: "15"; angle: "225"; value: "9.19499"; } + ListElement{ radius: "15"; angle: "230"; value: "6.2481"; } + ListElement{ radius: "15"; angle: "235"; value: "3.59272"; } + ListElement{ radius: "15"; angle: "240"; value: "1.24906"; } + ListElement{ radius: "15"; angle: "245"; value: "-0.765063"; } + ListElement{ radius: "15"; angle: "250"; value: "-2.4343"; } + ListElement{ radius: "15"; angle: "255"; value: "-3.74597"; } + ListElement{ radius: "15"; angle: "260"; value: "-4.69006"; } + ListElement{ radius: "15"; angle: "265"; value: "-5.25941"; } + ListElement{ radius: "15"; angle: "270"; value: "-5.44967"; } + ListElement{ radius: "15"; angle: "275"; value: "-5.25941"; } + ListElement{ radius: "15"; angle: "280"; value: "-4.69006"; } + ListElement{ radius: "15"; angle: "285"; value: "-3.74597"; } + ListElement{ radius: "15"; angle: "290"; value: "-2.4343"; } + ListElement{ radius: "15"; angle: "295"; value: "-0.765063"; } + ListElement{ radius: "15"; angle: "300"; value: "1.24906"; } + ListElement{ radius: "15"; angle: "305"; value: "3.59272"; } + ListElement{ radius: "15"; angle: "310"; value: "6.2481"; } + ListElement{ radius: "15"; angle: "315"; value: "9.19499"; } + ListElement{ radius: "15"; angle: "320"; value: "12.4109"; } + ListElement{ radius: "15"; angle: "325"; value: "15.8715"; } + ListElement{ radius: "15"; angle: "330"; value: "19.5503"; } + ListElement{ radius: "15"; angle: "335"; value: "23.4194"; } + ListElement{ radius: "15"; angle: "340"; value: "27.4493"; } + ListElement{ radius: "15"; angle: "345"; value: "31.6094"; } + ListElement{ radius: "15"; angle: "350"; value: "35.8679"; } + ListElement{ radius: "15"; angle: "355"; value: "40.1925"; } + ListElement{ radius: "15"; angle: "360"; value: "44.5503"; } + ListElement{ radius: "20"; angle: "0"; value: "40.4508"; } + ListElement{ radius: "20"; angle: "5"; value: "44.8086"; } + ListElement{ radius: "20"; angle: "10"; value: "49.1333"; } + ListElement{ radius: "20"; angle: "15"; value: "53.3918"; } + ListElement{ radius: "20"; angle: "20"; value: "57.5519"; } + ListElement{ radius: "20"; angle: "25"; value: "61.5818"; } + ListElement{ radius: "20"; angle: "30"; value: "65.4508"; } + ListElement{ radius: "20"; angle: "35"; value: "69.1297"; } + ListElement{ radius: "20"; angle: "40"; value: "72.5902"; } + ListElement{ radius: "20"; angle: "45"; value: "75.8062"; } + ListElement{ radius: "20"; angle: "50"; value: "78.7531"; } + ListElement{ radius: "20"; angle: "55"; value: "81.4085"; } + ListElement{ radius: "20"; angle: "60"; value: "83.7521"; } + ListElement{ radius: "20"; angle: "65"; value: "85.7662"; } + ListElement{ radius: "20"; angle: "70"; value: "87.4355"; } + ListElement{ radius: "20"; angle: "75"; value: "88.7471"; } + ListElement{ radius: "20"; angle: "80"; value: "89.6912"; } + ListElement{ radius: "20"; angle: "85"; value: "90.2606"; } + ListElement{ radius: "20"; angle: "90"; value: "90.4508"; } + ListElement{ radius: "20"; angle: "95"; value: "90.2606"; } + ListElement{ radius: "20"; angle: "100"; value: "89.6912"; } + ListElement{ radius: "20"; angle: "105"; value: "88.7471"; } + ListElement{ radius: "20"; angle: "110"; value: "87.4355"; } + ListElement{ radius: "20"; angle: "115"; value: "85.7662"; } + ListElement{ radius: "20"; angle: "120"; value: "83.7521"; } + ListElement{ radius: "20"; angle: "125"; value: "81.4085"; } + ListElement{ radius: "20"; angle: "130"; value: "78.7531"; } + ListElement{ radius: "20"; angle: "135"; value: "75.8062"; } + ListElement{ radius: "20"; angle: "140"; value: "72.5902"; } + ListElement{ radius: "20"; angle: "145"; value: "69.1297"; } + ListElement{ radius: "20"; angle: "150"; value: "65.4508"; } + ListElement{ radius: "20"; angle: "155"; value: "61.5818"; } + ListElement{ radius: "20"; angle: "160"; value: "57.5519"; } + ListElement{ radius: "20"; angle: "165"; value: "53.3918"; } + ListElement{ radius: "20"; angle: "170"; value: "49.1333"; } + ListElement{ radius: "20"; angle: "175"; value: "44.8086"; } + ListElement{ radius: "20"; angle: "180"; value: "40.4508"; } + ListElement{ radius: "20"; angle: "185"; value: "36.0931"; } + ListElement{ radius: "20"; angle: "190"; value: "31.7684"; } + ListElement{ radius: "20"; angle: "195"; value: "27.5099"; } + ListElement{ radius: "20"; angle: "200"; value: "23.3498"; } + ListElement{ radius: "20"; angle: "205"; value: "19.3199"; } + ListElement{ radius: "20"; angle: "210"; value: "15.4508"; } + ListElement{ radius: "20"; angle: "215"; value: "11.772"; } + ListElement{ radius: "20"; angle: "220"; value: "8.31147"; } + ListElement{ radius: "20"; angle: "225"; value: "5.09551"; } + ListElement{ radius: "20"; angle: "230"; value: "2.14863"; } + ListElement{ radius: "20"; angle: "235"; value: "-0.506752"; } + ListElement{ radius: "20"; angle: "240"; value: "-2.85042"; } + ListElement{ radius: "20"; angle: "245"; value: "-4.86454"; } + ListElement{ radius: "20"; angle: "250"; value: "-6.53378"; } + ListElement{ radius: "20"; angle: "255"; value: "-7.84544"; } + ListElement{ radius: "20"; angle: "260"; value: "-8.78954"; } + ListElement{ radius: "20"; angle: "265"; value: "-9.35889"; } + ListElement{ radius: "20"; angle: "270"; value: "-9.54915"; } + ListElement{ radius: "20"; angle: "275"; value: "-9.35889"; } + ListElement{ radius: "20"; angle: "280"; value: "-8.78954"; } + ListElement{ radius: "20"; angle: "285"; value: "-7.84544"; } + ListElement{ radius: "20"; angle: "290"; value: "-6.53378"; } + ListElement{ radius: "20"; angle: "295"; value: "-4.86454"; } + ListElement{ radius: "20"; angle: "300"; value: "-2.85042"; } + ListElement{ radius: "20"; angle: "305"; value: "-0.506752"; } + ListElement{ radius: "20"; angle: "310"; value: "2.14863"; } + ListElement{ radius: "20"; angle: "315"; value: "5.09551"; } + ListElement{ radius: "20"; angle: "320"; value: "8.31147"; } + ListElement{ radius: "20"; angle: "325"; value: "11.772"; } + ListElement{ radius: "20"; angle: "330"; value: "15.4508"; } + ListElement{ radius: "20"; angle: "335"; value: "19.3199"; } + ListElement{ radius: "20"; angle: "340"; value: "23.3498"; } + ListElement{ radius: "20"; angle: "345"; value: "27.5099"; } + ListElement{ radius: "20"; angle: "350"; value: "31.7684"; } + ListElement{ radius: "20"; angle: "355"; value: "36.0931"; } + ListElement{ radius: "20"; angle: "360"; value: "40.4508"; } + ListElement{ radius: "25"; angle: "0"; value: "35.3553"; } + ListElement{ radius: "25"; angle: "5"; value: "39.7131"; } + ListElement{ radius: "25"; angle: "10"; value: "44.0377"; } + ListElement{ radius: "25"; angle: "15"; value: "48.2963"; } + ListElement{ radius: "25"; angle: "20"; value: "52.4563"; } + ListElement{ radius: "25"; angle: "25"; value: "56.4863"; } + ListElement{ radius: "25"; angle: "30"; value: "60.3553"; } + ListElement{ radius: "25"; angle: "35"; value: "64.0342"; } + ListElement{ radius: "25"; angle: "40"; value: "67.4947"; } + ListElement{ radius: "25"; angle: "45"; value: "70.7107"; } + ListElement{ radius: "25"; angle: "50"; value: "73.6576"; } + ListElement{ radius: "25"; angle: "55"; value: "76.3129"; } + ListElement{ radius: "25"; angle: "60"; value: "78.6566"; } + ListElement{ radius: "25"; angle: "65"; value: "80.6707"; } + ListElement{ radius: "25"; angle: "70"; value: "82.34"; } + ListElement{ radius: "25"; angle: "75"; value: "83.6516"; } + ListElement{ radius: "25"; angle: "80"; value: "84.5957"; } + ListElement{ radius: "25"; angle: "85"; value: "85.1651"; } + ListElement{ radius: "25"; angle: "90"; value: "85.3553"; } + ListElement{ radius: "25"; angle: "95"; value: "85.1651"; } + ListElement{ radius: "25"; angle: "100"; value: "84.5957"; } + ListElement{ radius: "25"; angle: "105"; value: "83.6516"; } + ListElement{ radius: "25"; angle: "110"; value: "82.34"; } + ListElement{ radius: "25"; angle: "115"; value: "80.6707"; } + ListElement{ radius: "25"; angle: "120"; value: "78.6566"; } + ListElement{ radius: "25"; angle: "125"; value: "76.3129"; } + ListElement{ radius: "25"; angle: "130"; value: "73.6576"; } + ListElement{ radius: "25"; angle: "135"; value: "70.7107"; } + ListElement{ radius: "25"; angle: "140"; value: "67.4947"; } + ListElement{ radius: "25"; angle: "145"; value: "64.0342"; } + ListElement{ radius: "25"; angle: "150"; value: "60.3553"; } + ListElement{ radius: "25"; angle: "155"; value: "56.4863"; } + ListElement{ radius: "25"; angle: "160"; value: "52.4563"; } + ListElement{ radius: "25"; angle: "165"; value: "48.2963"; } + ListElement{ radius: "25"; angle: "170"; value: "44.0377"; } + ListElement{ radius: "25"; angle: "175"; value: "39.7131"; } + ListElement{ radius: "25"; angle: "180"; value: "35.3553"; } + ListElement{ radius: "25"; angle: "185"; value: "30.9976"; } + ListElement{ radius: "25"; angle: "190"; value: "26.6729"; } + ListElement{ radius: "25"; angle: "195"; value: "22.4144"; } + ListElement{ radius: "25"; angle: "200"; value: "18.2543"; } + ListElement{ radius: "25"; angle: "205"; value: "14.2244"; } + ListElement{ radius: "25"; angle: "210"; value: "10.3553"; } + ListElement{ radius: "25"; angle: "215"; value: "6.67652"; } + ListElement{ radius: "25"; angle: "220"; value: "3.21596"; } + ListElement{ radius: "25"; angle: "225"; value: "5.55112e-15"; } + ListElement{ radius: "25"; angle: "230"; value: "-2.94688"; } + ListElement{ radius: "25"; angle: "235"; value: "-5.60226"; } + ListElement{ radius: "25"; angle: "240"; value: "-7.94593"; } + ListElement{ radius: "25"; angle: "245"; value: "-9.96005"; } + ListElement{ radius: "25"; angle: "250"; value: "-11.6293"; } + ListElement{ radius: "25"; angle: "255"; value: "-12.941"; } + ListElement{ radius: "25"; angle: "260"; value: "-13.885"; } + ListElement{ radius: "25"; angle: "265"; value: "-14.4544"; } + ListElement{ radius: "25"; angle: "270"; value: "-14.6447"; } + ListElement{ radius: "25"; angle: "275"; value: "-14.4544"; } + ListElement{ radius: "25"; angle: "280"; value: "-13.885"; } + ListElement{ radius: "25"; angle: "285"; value: "-12.941"; } + ListElement{ radius: "25"; angle: "290"; value: "-11.6293"; } + ListElement{ radius: "25"; angle: "295"; value: "-9.96005"; } + ListElement{ radius: "25"; angle: "300"; value: "-7.94593"; } + ListElement{ radius: "25"; angle: "305"; value: "-5.60226"; } + ListElement{ radius: "25"; angle: "310"; value: "-2.94688"; } + ListElement{ radius: "25"; angle: "315"; value: "-5.55112e-15"; } + ListElement{ radius: "25"; angle: "320"; value: "3.21596"; } + ListElement{ radius: "25"; angle: "325"; value: "6.67652"; } + ListElement{ radius: "25"; angle: "330"; value: "10.3553"; } + ListElement{ radius: "25"; angle: "335"; value: "14.2244"; } + ListElement{ radius: "25"; angle: "340"; value: "18.2543"; } + ListElement{ radius: "25"; angle: "345"; value: "22.4144"; } + ListElement{ radius: "25"; angle: "350"; value: "26.6729"; } + ListElement{ radius: "25"; angle: "355"; value: "30.9976"; } + ListElement{ radius: "25"; angle: "360"; value: "35.3553"; } + ListElement{ radius: "30"; angle: "0"; value: "29.3893"; } + ListElement{ radius: "30"; angle: "5"; value: "33.747"; } + ListElement{ radius: "30"; angle: "10"; value: "38.0717"; } + ListElement{ radius: "30"; angle: "15"; value: "42.3302"; } + ListElement{ radius: "30"; angle: "20"; value: "46.4903"; } + ListElement{ radius: "30"; angle: "25"; value: "50.5202"; } + ListElement{ radius: "30"; angle: "30"; value: "54.3893"; } + ListElement{ radius: "30"; angle: "35"; value: "58.0681"; } + ListElement{ radius: "30"; angle: "40"; value: "61.5286"; } + ListElement{ radius: "30"; angle: "45"; value: "64.7446"; } + ListElement{ radius: "30"; angle: "50"; value: "67.6915"; } + ListElement{ radius: "30"; angle: "55"; value: "70.3469"; } + ListElement{ radius: "30"; angle: "60"; value: "72.6905"; } + ListElement{ radius: "30"; angle: "65"; value: "74.7047"; } + ListElement{ radius: "30"; angle: "70"; value: "76.3739"; } + ListElement{ radius: "30"; angle: "75"; value: "77.6856"; } + ListElement{ radius: "30"; angle: "80"; value: "78.6297"; } + ListElement{ radius: "30"; angle: "85"; value: "79.199"; } + ListElement{ radius: "30"; angle: "90"; value: "79.3893"; } + ListElement{ radius: "30"; angle: "95"; value: "79.199"; } + ListElement{ radius: "30"; angle: "100"; value: "78.6297"; } + ListElement{ radius: "30"; angle: "105"; value: "77.6856"; } + ListElement{ radius: "30"; angle: "110"; value: "76.3739"; } + ListElement{ radius: "30"; angle: "115"; value: "74.7047"; } + ListElement{ radius: "30"; angle: "120"; value: "72.6905"; } + ListElement{ radius: "30"; angle: "125"; value: "70.3469"; } + ListElement{ radius: "30"; angle: "130"; value: "67.6915"; } + ListElement{ radius: "30"; angle: "135"; value: "64.7446"; } + ListElement{ radius: "30"; angle: "140"; value: "61.5286"; } + ListElement{ radius: "30"; angle: "145"; value: "58.0681"; } + ListElement{ radius: "30"; angle: "150"; value: "54.3893"; } + ListElement{ radius: "30"; angle: "155"; value: "50.5202"; } + ListElement{ radius: "30"; angle: "160"; value: "46.4903"; } + ListElement{ radius: "30"; angle: "165"; value: "42.3302"; } + ListElement{ radius: "30"; angle: "170"; value: "38.0717"; } + ListElement{ radius: "30"; angle: "175"; value: "33.747"; } + ListElement{ radius: "30"; angle: "180"; value: "29.3893"; } + ListElement{ radius: "30"; angle: "185"; value: "25.0315"; } + ListElement{ radius: "30"; angle: "190"; value: "20.7069"; } + ListElement{ radius: "30"; angle: "195"; value: "16.4483"; } + ListElement{ radius: "30"; angle: "200"; value: "12.2883"; } + ListElement{ radius: "30"; angle: "205"; value: "8.25835"; } + ListElement{ radius: "30"; angle: "210"; value: "4.38926"; } + ListElement{ radius: "30"; angle: "215"; value: "0.710441"; } + ListElement{ radius: "30"; angle: "220"; value: "-2.75012"; } + ListElement{ radius: "30"; angle: "225"; value: "-5.96608"; } + ListElement{ radius: "30"; angle: "230"; value: "-8.91296"; } + ListElement{ radius: "30"; angle: "235"; value: "-11.5683"; } + ListElement{ radius: "30"; angle: "240"; value: "-13.912"; } + ListElement{ radius: "30"; angle: "245"; value: "-15.9261"; } + ListElement{ radius: "30"; angle: "250"; value: "-17.5954"; } + ListElement{ radius: "30"; angle: "255"; value: "-18.907"; } + ListElement{ radius: "30"; angle: "260"; value: "-19.8511"; } + ListElement{ radius: "30"; angle: "265"; value: "-20.4205"; } + ListElement{ radius: "30"; angle: "270"; value: "-20.6107"; } + ListElement{ radius: "30"; angle: "275"; value: "-20.4205"; } + ListElement{ radius: "30"; angle: "280"; value: "-19.8511"; } + ListElement{ radius: "30"; angle: "285"; value: "-18.907"; } + ListElement{ radius: "30"; angle: "290"; value: "-17.5954"; } + ListElement{ radius: "30"; angle: "295"; value: "-15.9261"; } + ListElement{ radius: "30"; angle: "300"; value: "-13.912"; } + ListElement{ radius: "30"; angle: "305"; value: "-11.5683"; } + ListElement{ radius: "30"; angle: "310"; value: "-8.91296"; } + ListElement{ radius: "30"; angle: "315"; value: "-5.96608"; } + ListElement{ radius: "30"; angle: "320"; value: "-2.75012"; } + ListElement{ radius: "30"; angle: "325"; value: "0.710441"; } + ListElement{ radius: "30"; angle: "330"; value: "4.38926"; } + ListElement{ radius: "30"; angle: "335"; value: "8.25835"; } + ListElement{ radius: "30"; angle: "340"; value: "12.2883"; } + ListElement{ radius: "30"; angle: "345"; value: "16.4483"; } + ListElement{ radius: "30"; angle: "350"; value: "20.7069"; } + ListElement{ radius: "30"; angle: "355"; value: "25.0315"; } + ListElement{ radius: "30"; angle: "360"; value: "29.3893"; } + ListElement{ radius: "35"; angle: "0"; value: "22.6995"; } + ListElement{ radius: "35"; angle: "5"; value: "27.0573"; } + ListElement{ radius: "35"; angle: "10"; value: "31.3819"; } + ListElement{ radius: "35"; angle: "15"; value: "35.6405"; } + ListElement{ radius: "35"; angle: "20"; value: "39.8005"; } + ListElement{ radius: "35"; angle: "25"; value: "43.8304"; } + ListElement{ radius: "35"; angle: "30"; value: "47.6995"; } + ListElement{ radius: "35"; angle: "35"; value: "51.3783"; } + ListElement{ radius: "35"; angle: "40"; value: "54.8389"; } + ListElement{ radius: "35"; angle: "45"; value: "58.0549"; } + ListElement{ radius: "35"; angle: "50"; value: "61.0017"; } + ListElement{ radius: "35"; angle: "55"; value: "63.6571"; } + ListElement{ radius: "35"; angle: "60"; value: "66.0008"; } + ListElement{ radius: "35"; angle: "65"; value: "68.0149"; } + ListElement{ radius: "35"; angle: "70"; value: "69.6842"; } + ListElement{ radius: "35"; angle: "75"; value: "70.9958"; } + ListElement{ radius: "35"; angle: "80"; value: "71.9399"; } + ListElement{ radius: "35"; angle: "85"; value: "72.5093"; } + ListElement{ radius: "35"; angle: "90"; value: "72.6995"; } + ListElement{ radius: "35"; angle: "95"; value: "72.5093"; } + ListElement{ radius: "35"; angle: "100"; value: "71.9399"; } + ListElement{ radius: "35"; angle: "105"; value: "70.9958"; } + ListElement{ radius: "35"; angle: "110"; value: "69.6842"; } + ListElement{ radius: "35"; angle: "115"; value: "68.0149"; } + ListElement{ radius: "35"; angle: "120"; value: "66.0008"; } + ListElement{ radius: "35"; angle: "125"; value: "63.6571"; } + ListElement{ radius: "35"; angle: "130"; value: "61.0017"; } + ListElement{ radius: "35"; angle: "135"; value: "58.0549"; } + ListElement{ radius: "35"; angle: "140"; value: "54.8389"; } + ListElement{ radius: "35"; angle: "145"; value: "51.3783"; } + ListElement{ radius: "35"; angle: "150"; value: "47.6995"; } + ListElement{ radius: "35"; angle: "155"; value: "43.8304"; } + ListElement{ radius: "35"; angle: "160"; value: "39.8005"; } + ListElement{ radius: "35"; angle: "165"; value: "35.6405"; } + ListElement{ radius: "35"; angle: "170"; value: "31.3819"; } + ListElement{ radius: "35"; angle: "175"; value: "27.0573"; } + ListElement{ radius: "35"; angle: "180"; value: "22.6995"; } + ListElement{ radius: "35"; angle: "185"; value: "18.3417"; } + ListElement{ radius: "35"; angle: "190"; value: "14.0171"; } + ListElement{ radius: "35"; angle: "195"; value: "9.75857"; } + ListElement{ radius: "35"; angle: "200"; value: "5.59852"; } + ListElement{ radius: "35"; angle: "205"; value: "1.56861"; } + ListElement{ radius: "35"; angle: "210"; value: "-2.30048"; } + ListElement{ radius: "35"; angle: "215"; value: "-5.9793"; } + ListElement{ radius: "35"; angle: "220"; value: "-9.43986"; } + ListElement{ radius: "35"; angle: "225"; value: "-12.6558"; } + ListElement{ radius: "35"; angle: "230"; value: "-15.6027"; } + ListElement{ radius: "35"; angle: "235"; value: "-18.2581"; } + ListElement{ radius: "35"; angle: "240"; value: "-20.6017"; } + ListElement{ radius: "35"; angle: "245"; value: "-22.6159"; } + ListElement{ radius: "35"; angle: "250"; value: "-24.2851"; } + ListElement{ radius: "35"; angle: "255"; value: "-25.5968"; } + ListElement{ radius: "35"; angle: "260"; value: "-26.5409"; } + ListElement{ radius: "35"; angle: "265"; value: "-27.1102"; } + ListElement{ radius: "35"; angle: "270"; value: "-27.3005"; } + ListElement{ radius: "35"; angle: "275"; value: "-27.1102"; } + ListElement{ radius: "35"; angle: "280"; value: "-26.5409"; } + ListElement{ radius: "35"; angle: "285"; value: "-25.5968"; } + ListElement{ radius: "35"; angle: "290"; value: "-24.2851"; } + ListElement{ radius: "35"; angle: "295"; value: "-22.6159"; } + ListElement{ radius: "35"; angle: "300"; value: "-20.6017"; } + ListElement{ radius: "35"; angle: "305"; value: "-18.2581"; } + ListElement{ radius: "35"; angle: "310"; value: "-15.6027"; } + ListElement{ radius: "35"; angle: "315"; value: "-12.6558"; } + ListElement{ radius: "35"; angle: "320"; value: "-9.43986"; } + ListElement{ radius: "35"; angle: "325"; value: "-5.9793"; } + ListElement{ radius: "35"; angle: "330"; value: "-2.30048"; } + ListElement{ radius: "35"; angle: "335"; value: "1.56861"; } + ListElement{ radius: "35"; angle: "340"; value: "5.59852"; } + ListElement{ radius: "35"; angle: "345"; value: "9.75857"; } + ListElement{ radius: "35"; angle: "350"; value: "14.0171"; } + ListElement{ radius: "35"; angle: "355"; value: "18.3417"; } + ListElement{ radius: "35"; angle: "360"; value: "22.6995"; } + ListElement{ radius: "40"; angle: "0"; value: "15.4508"; } + ListElement{ radius: "40"; angle: "5"; value: "19.8086"; } + ListElement{ radius: "40"; angle: "10"; value: "24.1333"; } + ListElement{ radius: "40"; angle: "15"; value: "28.3918"; } + ListElement{ radius: "40"; angle: "20"; value: "32.5519"; } + ListElement{ radius: "40"; angle: "25"; value: "36.5818"; } + ListElement{ radius: "40"; angle: "30"; value: "40.4508"; } + ListElement{ radius: "40"; angle: "35"; value: "44.1297"; } + ListElement{ radius: "40"; angle: "40"; value: "47.5902"; } + ListElement{ radius: "40"; angle: "45"; value: "50.8062"; } + ListElement{ radius: "40"; angle: "50"; value: "53.7531"; } + ListElement{ radius: "40"; angle: "55"; value: "56.4085"; } + ListElement{ radius: "40"; angle: "60"; value: "58.7521"; } + ListElement{ radius: "40"; angle: "65"; value: "60.7662"; } + ListElement{ radius: "40"; angle: "70"; value: "62.4355"; } + ListElement{ radius: "40"; angle: "75"; value: "63.7471"; } + ListElement{ radius: "40"; angle: "80"; value: "64.6912"; } + ListElement{ radius: "40"; angle: "85"; value: "65.2606"; } + ListElement{ radius: "40"; angle: "90"; value: "65.4508"; } + ListElement{ radius: "40"; angle: "95"; value: "65.2606"; } + ListElement{ radius: "40"; angle: "100"; value: "64.6912"; } + ListElement{ radius: "40"; angle: "105"; value: "63.7471"; } + ListElement{ radius: "40"; angle: "110"; value: "62.4355"; } + ListElement{ radius: "40"; angle: "115"; value: "60.7662"; } + ListElement{ radius: "40"; angle: "120"; value: "58.7521"; } + ListElement{ radius: "40"; angle: "125"; value: "56.4085"; } + ListElement{ radius: "40"; angle: "130"; value: "53.7531"; } + ListElement{ radius: "40"; angle: "135"; value: "50.8062"; } + ListElement{ radius: "40"; angle: "140"; value: "47.5902"; } + ListElement{ radius: "40"; angle: "145"; value: "44.1297"; } + ListElement{ radius: "40"; angle: "150"; value: "40.4508"; } + ListElement{ radius: "40"; angle: "155"; value: "36.5818"; } + ListElement{ radius: "40"; angle: "160"; value: "32.5519"; } + ListElement{ radius: "40"; angle: "165"; value: "28.3918"; } + ListElement{ radius: "40"; angle: "170"; value: "24.1333"; } + ListElement{ radius: "40"; angle: "175"; value: "19.8086"; } + ListElement{ radius: "40"; angle: "180"; value: "15.4508"; } + ListElement{ radius: "40"; angle: "185"; value: "11.0931"; } + ListElement{ radius: "40"; angle: "190"; value: "6.76844"; } + ListElement{ radius: "40"; angle: "195"; value: "2.5099"; } + ListElement{ radius: "40"; angle: "200"; value: "-1.65016"; } + ListElement{ radius: "40"; angle: "205"; value: "-5.68006"; } + ListElement{ radius: "40"; angle: "210"; value: "-9.54915"; } + ListElement{ radius: "40"; angle: "215"; value: "-13.228"; } + ListElement{ radius: "40"; angle: "220"; value: "-16.6885"; } + ListElement{ radius: "40"; angle: "225"; value: "-19.9045"; } + ListElement{ radius: "40"; angle: "230"; value: "-22.8514"; } + ListElement{ radius: "40"; angle: "235"; value: "-25.5068"; } + ListElement{ radius: "40"; angle: "240"; value: "-27.8504"; } + ListElement{ radius: "40"; angle: "245"; value: "-29.8645"; } + ListElement{ radius: "40"; angle: "250"; value: "-31.5338"; } + ListElement{ radius: "40"; angle: "255"; value: "-32.8454"; } + ListElement{ radius: "40"; angle: "260"; value: "-33.7895"; } + ListElement{ radius: "40"; angle: "265"; value: "-34.3589"; } + ListElement{ radius: "40"; angle: "270"; value: "-34.5492"; } + ListElement{ radius: "40"; angle: "275"; value: "-34.3589"; } + ListElement{ radius: "40"; angle: "280"; value: "-33.7895"; } + ListElement{ radius: "40"; angle: "285"; value: "-32.8454"; } + ListElement{ radius: "40"; angle: "290"; value: "-31.5338"; } + ListElement{ radius: "40"; angle: "295"; value: "-29.8645"; } + ListElement{ radius: "40"; angle: "300"; value: "-27.8504"; } + ListElement{ radius: "40"; angle: "305"; value: "-25.5068"; } + ListElement{ radius: "40"; angle: "310"; value: "-22.8514"; } + ListElement{ radius: "40"; angle: "315"; value: "-19.9045"; } + ListElement{ radius: "40"; angle: "320"; value: "-16.6885"; } + ListElement{ radius: "40"; angle: "325"; value: "-13.228"; } + ListElement{ radius: "40"; angle: "330"; value: "-9.54915"; } + ListElement{ radius: "40"; angle: "335"; value: "-5.68006"; } + ListElement{ radius: "40"; angle: "340"; value: "-1.65016"; } + ListElement{ radius: "40"; angle: "345"; value: "2.5099"; } + ListElement{ radius: "40"; angle: "350"; value: "6.76844"; } + ListElement{ radius: "40"; angle: "355"; value: "11.0931"; } + ListElement{ radius: "40"; angle: "360"; value: "15.4508"; } + ListElement{ radius: "45"; angle: "0"; value: "7.82172"; } + ListElement{ radius: "45"; angle: "5"; value: "12.1795"; } + ListElement{ radius: "45"; angle: "10"; value: "16.5041"; } + ListElement{ radius: "45"; angle: "15"; value: "20.7627"; } + ListElement{ radius: "45"; angle: "20"; value: "24.9227"; } + ListElement{ radius: "45"; angle: "25"; value: "28.9526"; } + ListElement{ radius: "45"; angle: "30"; value: "32.8217"; } + ListElement{ radius: "45"; angle: "35"; value: "36.5005"; } + ListElement{ radius: "45"; angle: "40"; value: "39.9611"; } + ListElement{ radius: "45"; angle: "45"; value: "43.1771"; } + ListElement{ radius: "45"; angle: "50"; value: "46.1239"; } + ListElement{ radius: "45"; angle: "55"; value: "48.7793"; } + ListElement{ radius: "45"; angle: "60"; value: "51.123"; } + ListElement{ radius: "45"; angle: "65"; value: "53.1371"; } + ListElement{ radius: "45"; angle: "70"; value: "54.8064"; } + ListElement{ radius: "45"; angle: "75"; value: "56.118"; } + ListElement{ radius: "45"; angle: "80"; value: "57.0621"; } + ListElement{ radius: "45"; angle: "85"; value: "57.6315"; } + ListElement{ radius: "45"; angle: "90"; value: "57.8217"; } + ListElement{ radius: "45"; angle: "95"; value: "57.6315"; } + ListElement{ radius: "45"; angle: "100"; value: "57.0621"; } + ListElement{ radius: "45"; angle: "105"; value: "56.118"; } + ListElement{ radius: "45"; angle: "110"; value: "54.8064"; } + ListElement{ radius: "45"; angle: "115"; value: "53.1371"; } + ListElement{ radius: "45"; angle: "120"; value: "51.123"; } + ListElement{ radius: "45"; angle: "125"; value: "48.7793"; } + ListElement{ radius: "45"; angle: "130"; value: "46.1239"; } + ListElement{ radius: "45"; angle: "135"; value: "43.1771"; } + ListElement{ radius: "45"; angle: "140"; value: "39.9611"; } + ListElement{ radius: "45"; angle: "145"; value: "36.5005"; } + ListElement{ radius: "45"; angle: "150"; value: "32.8217"; } + ListElement{ radius: "45"; angle: "155"; value: "28.9526"; } + ListElement{ radius: "45"; angle: "160"; value: "24.9227"; } + ListElement{ radius: "45"; angle: "165"; value: "20.7627"; } + ListElement{ radius: "45"; angle: "170"; value: "16.5041"; } + ListElement{ radius: "45"; angle: "175"; value: "12.1795"; } + ListElement{ radius: "45"; angle: "180"; value: "7.82172"; } + ListElement{ radius: "45"; angle: "185"; value: "3.46394"; } + ListElement{ radius: "45"; angle: "190"; value: "-0.860686"; } + ListElement{ radius: "45"; angle: "195"; value: "-5.11923"; } + ListElement{ radius: "45"; angle: "200"; value: "-9.27928"; } + ListElement{ radius: "45"; angle: "205"; value: "-13.3092"; } + ListElement{ radius: "45"; angle: "210"; value: "-17.1783"; } + ListElement{ radius: "45"; angle: "215"; value: "-20.8571"; } + ListElement{ radius: "45"; angle: "220"; value: "-24.3177"; } + ListElement{ radius: "45"; angle: "225"; value: "-27.5336"; } + ListElement{ radius: "45"; angle: "230"; value: "-30.4805"; } + ListElement{ radius: "45"; angle: "235"; value: "-33.1359"; } + ListElement{ radius: "45"; angle: "240"; value: "-35.4795"; } + ListElement{ radius: "45"; angle: "245"; value: "-37.4937"; } + ListElement{ radius: "45"; angle: "250"; value: "-39.1629"; } + ListElement{ radius: "45"; angle: "255"; value: "-40.4746"; } + ListElement{ radius: "45"; angle: "260"; value: "-41.4187"; } + ListElement{ radius: "45"; angle: "265"; value: "-41.988"; } + ListElement{ radius: "45"; angle: "270"; value: "-42.1783"; } + ListElement{ radius: "45"; angle: "275"; value: "-41.988"; } + ListElement{ radius: "45"; angle: "280"; value: "-41.4187"; } + ListElement{ radius: "45"; angle: "285"; value: "-40.4746"; } + ListElement{ radius: "45"; angle: "290"; value: "-39.1629"; } + ListElement{ radius: "45"; angle: "295"; value: "-37.4937"; } + ListElement{ radius: "45"; angle: "300"; value: "-35.4795"; } + ListElement{ radius: "45"; angle: "305"; value: "-33.1359"; } + ListElement{ radius: "45"; angle: "310"; value: "-30.4805"; } + ListElement{ radius: "45"; angle: "315"; value: "-27.5336"; } + ListElement{ radius: "45"; angle: "320"; value: "-24.3177"; } + ListElement{ radius: "45"; angle: "325"; value: "-20.8571"; } + ListElement{ radius: "45"; angle: "330"; value: "-17.1783"; } + ListElement{ radius: "45"; angle: "335"; value: "-13.3092"; } + ListElement{ radius: "45"; angle: "340"; value: "-9.27928"; } + ListElement{ radius: "45"; angle: "345"; value: "-5.11923"; } + ListElement{ radius: "45"; angle: "350"; value: "-0.860686"; } + ListElement{ radius: "45"; angle: "355"; value: "3.46394"; } + ListElement{ radius: "45"; angle: "360"; value: "7.82172"; } + ListElement{ radius: "50"; angle: "0"; value: "3.06162e-15"; } + ListElement{ radius: "50"; angle: "5"; value: "4.35779"; } + ListElement{ radius: "50"; angle: "10"; value: "8.68241"; } + ListElement{ radius: "50"; angle: "15"; value: "12.941"; } + ListElement{ radius: "50"; angle: "20"; value: "17.101"; } + ListElement{ radius: "50"; angle: "25"; value: "21.1309"; } + ListElement{ radius: "50"; angle: "30"; value: "25"; } + ListElement{ radius: "50"; angle: "35"; value: "28.6788"; } + ListElement{ radius: "50"; angle: "40"; value: "32.1394"; } + ListElement{ radius: "50"; angle: "45"; value: "35.3553"; } + ListElement{ radius: "50"; angle: "50"; value: "38.3022"; } + ListElement{ radius: "50"; angle: "55"; value: "40.9576"; } + ListElement{ radius: "50"; angle: "60"; value: "43.3013"; } + ListElement{ radius: "50"; angle: "65"; value: "45.3154"; } + ListElement{ radius: "50"; angle: "70"; value: "46.9846"; } + ListElement{ radius: "50"; angle: "75"; value: "48.2963"; } + ListElement{ radius: "50"; angle: "80"; value: "49.2404"; } + ListElement{ radius: "50"; angle: "85"; value: "49.8097"; } + ListElement{ radius: "50"; angle: "90"; value: "50"; } + ListElement{ radius: "50"; angle: "95"; value: "49.8097"; } + ListElement{ radius: "50"; angle: "100"; value: "49.2404"; } + ListElement{ radius: "50"; angle: "105"; value: "48.2963"; } + ListElement{ radius: "50"; angle: "110"; value: "46.9846"; } + ListElement{ radius: "50"; angle: "115"; value: "45.3154"; } + ListElement{ radius: "50"; angle: "120"; value: "43.3013"; } + ListElement{ radius: "50"; angle: "125"; value: "40.9576"; } + ListElement{ radius: "50"; angle: "130"; value: "38.3022"; } + ListElement{ radius: "50"; angle: "135"; value: "35.3553"; } + ListElement{ radius: "50"; angle: "140"; value: "32.1394"; } + ListElement{ radius: "50"; angle: "145"; value: "28.6788"; } + ListElement{ radius: "50"; angle: "150"; value: "25"; } + ListElement{ radius: "50"; angle: "155"; value: "21.1309"; } + ListElement{ radius: "50"; angle: "160"; value: "17.101"; } + ListElement{ radius: "50"; angle: "165"; value: "12.941"; } + ListElement{ radius: "50"; angle: "170"; value: "8.68241"; } + ListElement{ radius: "50"; angle: "175"; value: "4.35779"; } + ListElement{ radius: "50"; angle: "180"; value: "9.18485e-15"; } + ListElement{ radius: "50"; angle: "185"; value: "-4.35779"; } + ListElement{ radius: "50"; angle: "190"; value: "-8.68241"; } + ListElement{ radius: "50"; angle: "195"; value: "-12.941"; } + ListElement{ radius: "50"; angle: "200"; value: "-17.101"; } + ListElement{ radius: "50"; angle: "205"; value: "-21.1309"; } + ListElement{ radius: "50"; angle: "210"; value: "-25"; } + ListElement{ radius: "50"; angle: "215"; value: "-28.6788"; } + ListElement{ radius: "50"; angle: "220"; value: "-32.1394"; } + ListElement{ radius: "50"; angle: "225"; value: "-35.3553"; } + ListElement{ radius: "50"; angle: "230"; value: "-38.3022"; } + ListElement{ radius: "50"; angle: "235"; value: "-40.9576"; } + ListElement{ radius: "50"; angle: "240"; value: "-43.3013"; } + ListElement{ radius: "50"; angle: "245"; value: "-45.3154"; } + ListElement{ radius: "50"; angle: "250"; value: "-46.9846"; } + ListElement{ radius: "50"; angle: "255"; value: "-48.2963"; } + ListElement{ radius: "50"; angle: "260"; value: "-49.2404"; } + ListElement{ radius: "50"; angle: "265"; value: "-49.8097"; } + ListElement{ radius: "50"; angle: "270"; value: "-50"; } + ListElement{ radius: "50"; angle: "275"; value: "-49.8097"; } + ListElement{ radius: "50"; angle: "280"; value: "-49.2404"; } + ListElement{ radius: "50"; angle: "285"; value: "-48.2963"; } + ListElement{ radius: "50"; angle: "290"; value: "-46.9846"; } + ListElement{ radius: "50"; angle: "295"; value: "-45.3154"; } + ListElement{ radius: "50"; angle: "300"; value: "-43.3013"; } + ListElement{ radius: "50"; angle: "305"; value: "-40.9576"; } + ListElement{ radius: "50"; angle: "310"; value: "-38.3022"; } + ListElement{ radius: "50"; angle: "315"; value: "-35.3553"; } + ListElement{ radius: "50"; angle: "320"; value: "-32.1394"; } + ListElement{ radius: "50"; angle: "325"; value: "-28.6788"; } + ListElement{ radius: "50"; angle: "330"; value: "-25"; } + ListElement{ radius: "50"; angle: "335"; value: "-21.1309"; } + ListElement{ radius: "50"; angle: "340"; value: "-17.101"; } + ListElement{ radius: "50"; angle: "345"; value: "-12.941"; } + ListElement{ radius: "50"; angle: "350"; value: "-8.68241"; } + ListElement{ radius: "50"; angle: "355"; value: "-4.35779"; } + ListElement{ radius: "50"; angle: "360"; value: "-9.18485e-15"; } + ListElement{ radius: "55"; angle: "0"; value: "-7.82172"; } + ListElement{ radius: "55"; angle: "5"; value: "-3.46394"; } + ListElement{ radius: "55"; angle: "10"; value: "0.860686"; } + ListElement{ radius: "55"; angle: "15"; value: "5.11923"; } + ListElement{ radius: "55"; angle: "20"; value: "9.27928"; } + ListElement{ radius: "55"; angle: "25"; value: "13.3092"; } + ListElement{ radius: "55"; angle: "30"; value: "17.1783"; } + ListElement{ radius: "55"; angle: "35"; value: "20.8571"; } + ListElement{ radius: "55"; angle: "40"; value: "24.3177"; } + ListElement{ radius: "55"; angle: "45"; value: "27.5336"; } + ListElement{ radius: "55"; angle: "50"; value: "30.4805"; } + ListElement{ radius: "55"; angle: "55"; value: "33.1359"; } + ListElement{ radius: "55"; angle: "60"; value: "35.4795"; } + ListElement{ radius: "55"; angle: "65"; value: "37.4937"; } + ListElement{ radius: "55"; angle: "70"; value: "39.1629"; } + ListElement{ radius: "55"; angle: "75"; value: "40.4746"; } + ListElement{ radius: "55"; angle: "80"; value: "41.4187"; } + ListElement{ radius: "55"; angle: "85"; value: "41.988"; } + ListElement{ radius: "55"; angle: "90"; value: "42.1783"; } + ListElement{ radius: "55"; angle: "95"; value: "41.988"; } + ListElement{ radius: "55"; angle: "100"; value: "41.4187"; } + ListElement{ radius: "55"; angle: "105"; value: "40.4746"; } + ListElement{ radius: "55"; angle: "110"; value: "39.1629"; } + ListElement{ radius: "55"; angle: "115"; value: "37.4937"; } + ListElement{ radius: "55"; angle: "120"; value: "35.4795"; } + ListElement{ radius: "55"; angle: "125"; value: "33.1359"; } + ListElement{ radius: "55"; angle: "130"; value: "30.4805"; } + ListElement{ radius: "55"; angle: "135"; value: "27.5336"; } + ListElement{ radius: "55"; angle: "140"; value: "24.3177"; } + ListElement{ radius: "55"; angle: "145"; value: "20.8571"; } + ListElement{ radius: "55"; angle: "150"; value: "17.1783"; } + ListElement{ radius: "55"; angle: "155"; value: "13.3092"; } + ListElement{ radius: "55"; angle: "160"; value: "9.27928"; } + ListElement{ radius: "55"; angle: "165"; value: "5.11923"; } + ListElement{ radius: "55"; angle: "170"; value: "0.860686"; } + ListElement{ radius: "55"; angle: "175"; value: "-3.46394"; } + ListElement{ radius: "55"; angle: "180"; value: "-7.82172"; } + ListElement{ radius: "55"; angle: "185"; value: "-12.1795"; } + ListElement{ radius: "55"; angle: "190"; value: "-16.5041"; } + ListElement{ radius: "55"; angle: "195"; value: "-20.7627"; } + ListElement{ radius: "55"; angle: "200"; value: "-24.9227"; } + ListElement{ radius: "55"; angle: "205"; value: "-28.9526"; } + ListElement{ radius: "55"; angle: "210"; value: "-32.8217"; } + ListElement{ radius: "55"; angle: "215"; value: "-36.5005"; } + ListElement{ radius: "55"; angle: "220"; value: "-39.9611"; } + ListElement{ radius: "55"; angle: "225"; value: "-43.1771"; } + ListElement{ radius: "55"; angle: "230"; value: "-46.1239"; } + ListElement{ radius: "55"; angle: "235"; value: "-48.7793"; } + ListElement{ radius: "55"; angle: "240"; value: "-51.123"; } + ListElement{ radius: "55"; angle: "245"; value: "-53.1371"; } + ListElement{ radius: "55"; angle: "250"; value: "-54.8064"; } + ListElement{ radius: "55"; angle: "255"; value: "-56.118"; } + ListElement{ radius: "55"; angle: "260"; value: "-57.0621"; } + ListElement{ radius: "55"; angle: "265"; value: "-57.6315"; } + ListElement{ radius: "55"; angle: "270"; value: "-57.8217"; } + ListElement{ radius: "55"; angle: "275"; value: "-57.6315"; } + ListElement{ radius: "55"; angle: "280"; value: "-57.0621"; } + ListElement{ radius: "55"; angle: "285"; value: "-56.118"; } + ListElement{ radius: "55"; angle: "290"; value: "-54.8064"; } + ListElement{ radius: "55"; angle: "295"; value: "-53.1371"; } + ListElement{ radius: "55"; angle: "300"; value: "-51.123"; } + ListElement{ radius: "55"; angle: "305"; value: "-48.7793"; } + ListElement{ radius: "55"; angle: "310"; value: "-46.1239"; } + ListElement{ radius: "55"; angle: "315"; value: "-43.1771"; } + ListElement{ radius: "55"; angle: "320"; value: "-39.9611"; } + ListElement{ radius: "55"; angle: "325"; value: "-36.5005"; } + ListElement{ radius: "55"; angle: "330"; value: "-32.8217"; } + ListElement{ radius: "55"; angle: "335"; value: "-28.9526"; } + ListElement{ radius: "55"; angle: "340"; value: "-24.9227"; } + ListElement{ radius: "55"; angle: "345"; value: "-20.7627"; } + ListElement{ radius: "55"; angle: "350"; value: "-16.5041"; } + ListElement{ radius: "55"; angle: "355"; value: "-12.1795"; } + ListElement{ radius: "55"; angle: "360"; value: "-7.82172"; } + ListElement{ radius: "60"; angle: "0"; value: "-15.4508"; } + ListElement{ radius: "60"; angle: "5"; value: "-11.0931"; } + ListElement{ radius: "60"; angle: "10"; value: "-6.76844"; } + ListElement{ radius: "60"; angle: "15"; value: "-2.5099"; } + ListElement{ radius: "60"; angle: "20"; value: "1.65016"; } + ListElement{ radius: "60"; angle: "25"; value: "5.68006"; } + ListElement{ radius: "60"; angle: "30"; value: "9.54915"; } + ListElement{ radius: "60"; angle: "35"; value: "13.228"; } + ListElement{ radius: "60"; angle: "40"; value: "16.6885"; } + ListElement{ radius: "60"; angle: "45"; value: "19.9045"; } + ListElement{ radius: "60"; angle: "50"; value: "22.8514"; } + ListElement{ radius: "60"; angle: "55"; value: "25.5068"; } + ListElement{ radius: "60"; angle: "60"; value: "27.8504"; } + ListElement{ radius: "60"; angle: "65"; value: "29.8645"; } + ListElement{ radius: "60"; angle: "70"; value: "31.5338"; } + ListElement{ radius: "60"; angle: "75"; value: "32.8454"; } + ListElement{ radius: "60"; angle: "80"; value: "33.7895"; } + ListElement{ radius: "60"; angle: "85"; value: "34.3589"; } + ListElement{ radius: "60"; angle: "90"; value: "34.5492"; } + ListElement{ radius: "60"; angle: "95"; value: "34.3589"; } + ListElement{ radius: "60"; angle: "100"; value: "33.7895"; } + ListElement{ radius: "60"; angle: "105"; value: "32.8454"; } + ListElement{ radius: "60"; angle: "110"; value: "31.5338"; } + ListElement{ radius: "60"; angle: "115"; value: "29.8645"; } + ListElement{ radius: "60"; angle: "120"; value: "27.8504"; } + ListElement{ radius: "60"; angle: "125"; value: "25.5068"; } + ListElement{ radius: "60"; angle: "130"; value: "22.8514"; } + ListElement{ radius: "60"; angle: "135"; value: "19.9045"; } + ListElement{ radius: "60"; angle: "140"; value: "16.6885"; } + ListElement{ radius: "60"; angle: "145"; value: "13.228"; } + ListElement{ radius: "60"; angle: "150"; value: "9.54915"; } + ListElement{ radius: "60"; angle: "155"; value: "5.68006"; } + ListElement{ radius: "60"; angle: "160"; value: "1.65016"; } + ListElement{ radius: "60"; angle: "165"; value: "-2.5099"; } + ListElement{ radius: "60"; angle: "170"; value: "-6.76844"; } + ListElement{ radius: "60"; angle: "175"; value: "-11.0931"; } + ListElement{ radius: "60"; angle: "180"; value: "-15.4508"; } + ListElement{ radius: "60"; angle: "185"; value: "-19.8086"; } + ListElement{ radius: "60"; angle: "190"; value: "-24.1333"; } + ListElement{ radius: "60"; angle: "195"; value: "-28.3918"; } + ListElement{ radius: "60"; angle: "200"; value: "-32.5519"; } + ListElement{ radius: "60"; angle: "205"; value: "-36.5818"; } + ListElement{ radius: "60"; angle: "210"; value: "-40.4508"; } + ListElement{ radius: "60"; angle: "215"; value: "-44.1297"; } + ListElement{ radius: "60"; angle: "220"; value: "-47.5902"; } + ListElement{ radius: "60"; angle: "225"; value: "-50.8062"; } + ListElement{ radius: "60"; angle: "230"; value: "-53.7531"; } + ListElement{ radius: "60"; angle: "235"; value: "-56.4085"; } + ListElement{ radius: "60"; angle: "240"; value: "-58.7521"; } + ListElement{ radius: "60"; angle: "245"; value: "-60.7662"; } + ListElement{ radius: "60"; angle: "250"; value: "-62.4355"; } + ListElement{ radius: "60"; angle: "255"; value: "-63.7471"; } + ListElement{ radius: "60"; angle: "260"; value: "-64.6912"; } + ListElement{ radius: "60"; angle: "265"; value: "-65.2606"; } + ListElement{ radius: "60"; angle: "270"; value: "-65.4508"; } + ListElement{ radius: "60"; angle: "275"; value: "-65.2606"; } + ListElement{ radius: "60"; angle: "280"; value: "-64.6912"; } + ListElement{ radius: "60"; angle: "285"; value: "-63.7471"; } + ListElement{ radius: "60"; angle: "290"; value: "-62.4355"; } + ListElement{ radius: "60"; angle: "295"; value: "-60.7662"; } + ListElement{ radius: "60"; angle: "300"; value: "-58.7521"; } + ListElement{ radius: "60"; angle: "305"; value: "-56.4085"; } + ListElement{ radius: "60"; angle: "310"; value: "-53.7531"; } + ListElement{ radius: "60"; angle: "315"; value: "-50.8062"; } + ListElement{ radius: "60"; angle: "320"; value: "-47.5902"; } + ListElement{ radius: "60"; angle: "325"; value: "-44.1297"; } + ListElement{ radius: "60"; angle: "330"; value: "-40.4508"; } + ListElement{ radius: "60"; angle: "335"; value: "-36.5818"; } + ListElement{ radius: "60"; angle: "340"; value: "-32.5519"; } + ListElement{ radius: "60"; angle: "345"; value: "-28.3918"; } + ListElement{ radius: "60"; angle: "350"; value: "-24.1333"; } + ListElement{ radius: "60"; angle: "355"; value: "-19.8086"; } + ListElement{ radius: "60"; angle: "360"; value: "-15.4508"; } + ListElement{ radius: "65"; angle: "0"; value: "-22.6995"; } + ListElement{ radius: "65"; angle: "5"; value: "-18.3417"; } + ListElement{ radius: "65"; angle: "10"; value: "-14.0171"; } + ListElement{ radius: "65"; angle: "15"; value: "-9.75857"; } + ListElement{ radius: "65"; angle: "20"; value: "-5.59852"; } + ListElement{ radius: "65"; angle: "25"; value: "-1.56861"; } + ListElement{ radius: "65"; angle: "30"; value: "2.30048"; } + ListElement{ radius: "65"; angle: "35"; value: "5.9793"; } + ListElement{ radius: "65"; angle: "40"; value: "9.43986"; } + ListElement{ radius: "65"; angle: "45"; value: "12.6558"; } + ListElement{ radius: "65"; angle: "50"; value: "15.6027"; } + ListElement{ radius: "65"; angle: "55"; value: "18.2581"; } + ListElement{ radius: "65"; angle: "60"; value: "20.6017"; } + ListElement{ radius: "65"; angle: "65"; value: "22.6159"; } + ListElement{ radius: "65"; angle: "70"; value: "24.2851"; } + ListElement{ radius: "65"; angle: "75"; value: "25.5968"; } + ListElement{ radius: "65"; angle: "80"; value: "26.5409"; } + ListElement{ radius: "65"; angle: "85"; value: "27.1102"; } + ListElement{ radius: "65"; angle: "90"; value: "27.3005"; } + ListElement{ radius: "65"; angle: "95"; value: "27.1102"; } + ListElement{ radius: "65"; angle: "100"; value: "26.5409"; } + ListElement{ radius: "65"; angle: "105"; value: "25.5968"; } + ListElement{ radius: "65"; angle: "110"; value: "24.2851"; } + ListElement{ radius: "65"; angle: "115"; value: "22.6159"; } + ListElement{ radius: "65"; angle: "120"; value: "20.6017"; } + ListElement{ radius: "65"; angle: "125"; value: "18.2581"; } + ListElement{ radius: "65"; angle: "130"; value: "15.6027"; } + ListElement{ radius: "65"; angle: "135"; value: "12.6558"; } + ListElement{ radius: "65"; angle: "140"; value: "9.43986"; } + ListElement{ radius: "65"; angle: "145"; value: "5.9793"; } + ListElement{ radius: "65"; angle: "150"; value: "2.30048"; } + ListElement{ radius: "65"; angle: "155"; value: "-1.56861"; } + ListElement{ radius: "65"; angle: "160"; value: "-5.59852"; } + ListElement{ radius: "65"; angle: "165"; value: "-9.75857"; } + ListElement{ radius: "65"; angle: "170"; value: "-14.0171"; } + ListElement{ radius: "65"; angle: "175"; value: "-18.3417"; } + ListElement{ radius: "65"; angle: "180"; value: "-22.6995"; } + ListElement{ radius: "65"; angle: "185"; value: "-27.0573"; } + ListElement{ radius: "65"; angle: "190"; value: "-31.3819"; } + ListElement{ radius: "65"; angle: "195"; value: "-35.6405"; } + ListElement{ radius: "65"; angle: "200"; value: "-39.8005"; } + ListElement{ radius: "65"; angle: "205"; value: "-43.8304"; } + ListElement{ radius: "65"; angle: "210"; value: "-47.6995"; } + ListElement{ radius: "65"; angle: "215"; value: "-51.3783"; } + ListElement{ radius: "65"; angle: "220"; value: "-54.8389"; } + ListElement{ radius: "65"; angle: "225"; value: "-58.0549"; } + ListElement{ radius: "65"; angle: "230"; value: "-61.0017"; } + ListElement{ radius: "65"; angle: "235"; value: "-63.6571"; } + ListElement{ radius: "65"; angle: "240"; value: "-66.0008"; } + ListElement{ radius: "65"; angle: "245"; value: "-68.0149"; } + ListElement{ radius: "65"; angle: "250"; value: "-69.6842"; } + ListElement{ radius: "65"; angle: "255"; value: "-70.9958"; } + ListElement{ radius: "65"; angle: "260"; value: "-71.9399"; } + ListElement{ radius: "65"; angle: "265"; value: "-72.5093"; } + ListElement{ radius: "65"; angle: "270"; value: "-72.6995"; } + ListElement{ radius: "65"; angle: "275"; value: "-72.5093"; } + ListElement{ radius: "65"; angle: "280"; value: "-71.9399"; } + ListElement{ radius: "65"; angle: "285"; value: "-70.9958"; } + ListElement{ radius: "65"; angle: "290"; value: "-69.6842"; } + ListElement{ radius: "65"; angle: "295"; value: "-68.0149"; } + ListElement{ radius: "65"; angle: "300"; value: "-66.0008"; } + ListElement{ radius: "65"; angle: "305"; value: "-63.6571"; } + ListElement{ radius: "65"; angle: "310"; value: "-61.0017"; } + ListElement{ radius: "65"; angle: "315"; value: "-58.0549"; } + ListElement{ radius: "65"; angle: "320"; value: "-54.8389"; } + ListElement{ radius: "65"; angle: "325"; value: "-51.3783"; } + ListElement{ radius: "65"; angle: "330"; value: "-47.6995"; } + ListElement{ radius: "65"; angle: "335"; value: "-43.8304"; } + ListElement{ radius: "65"; angle: "340"; value: "-39.8005"; } + ListElement{ radius: "65"; angle: "345"; value: "-35.6405"; } + ListElement{ radius: "65"; angle: "350"; value: "-31.3819"; } + ListElement{ radius: "65"; angle: "355"; value: "-27.0573"; } + ListElement{ radius: "65"; angle: "360"; value: "-22.6995"; } + ListElement{ radius: "70"; angle: "0"; value: "-29.3893"; } + ListElement{ radius: "70"; angle: "5"; value: "-25.0315"; } + ListElement{ radius: "70"; angle: "10"; value: "-20.7069"; } + ListElement{ radius: "70"; angle: "15"; value: "-16.4483"; } + ListElement{ radius: "70"; angle: "20"; value: "-12.2883"; } + ListElement{ radius: "70"; angle: "25"; value: "-8.25835"; } + ListElement{ radius: "70"; angle: "30"; value: "-4.38926"; } + ListElement{ radius: "70"; angle: "35"; value: "-0.710441"; } + ListElement{ radius: "70"; angle: "40"; value: "2.75012"; } + ListElement{ radius: "70"; angle: "45"; value: "5.96608"; } + ListElement{ radius: "70"; angle: "50"; value: "8.91296"; } + ListElement{ radius: "70"; angle: "55"; value: "11.5683"; } + ListElement{ radius: "70"; angle: "60"; value: "13.912"; } + ListElement{ radius: "70"; angle: "65"; value: "15.9261"; } + ListElement{ radius: "70"; angle: "70"; value: "17.5954"; } + ListElement{ radius: "70"; angle: "75"; value: "18.907"; } + ListElement{ radius: "70"; angle: "80"; value: "19.8511"; } + ListElement{ radius: "70"; angle: "85"; value: "20.4205"; } + ListElement{ radius: "70"; angle: "90"; value: "20.6107"; } + ListElement{ radius: "70"; angle: "95"; value: "20.4205"; } + ListElement{ radius: "70"; angle: "100"; value: "19.8511"; } + ListElement{ radius: "70"; angle: "105"; value: "18.907"; } + ListElement{ radius: "70"; angle: "110"; value: "17.5954"; } + ListElement{ radius: "70"; angle: "115"; value: "15.9261"; } + ListElement{ radius: "70"; angle: "120"; value: "13.912"; } + ListElement{ radius: "70"; angle: "125"; value: "11.5683"; } + ListElement{ radius: "70"; angle: "130"; value: "8.91296"; } + ListElement{ radius: "70"; angle: "135"; value: "5.96608"; } + ListElement{ radius: "70"; angle: "140"; value: "2.75012"; } + ListElement{ radius: "70"; angle: "145"; value: "-0.710441"; } + ListElement{ radius: "70"; angle: "150"; value: "-4.38926"; } + ListElement{ radius: "70"; angle: "155"; value: "-8.25835"; } + ListElement{ radius: "70"; angle: "160"; value: "-12.2883"; } + ListElement{ radius: "70"; angle: "165"; value: "-16.4483"; } + ListElement{ radius: "70"; angle: "170"; value: "-20.7069"; } + ListElement{ radius: "70"; angle: "175"; value: "-25.0315"; } + ListElement{ radius: "70"; angle: "180"; value: "-29.3893"; } + ListElement{ radius: "70"; angle: "185"; value: "-33.747"; } + ListElement{ radius: "70"; angle: "190"; value: "-38.0717"; } + ListElement{ radius: "70"; angle: "195"; value: "-42.3302"; } + ListElement{ radius: "70"; angle: "200"; value: "-46.4903"; } + ListElement{ radius: "70"; angle: "205"; value: "-50.5202"; } + ListElement{ radius: "70"; angle: "210"; value: "-54.3893"; } + ListElement{ radius: "70"; angle: "215"; value: "-58.0681"; } + ListElement{ radius: "70"; angle: "220"; value: "-61.5286"; } + ListElement{ radius: "70"; angle: "225"; value: "-64.7446"; } + ListElement{ radius: "70"; angle: "230"; value: "-67.6915"; } + ListElement{ radius: "70"; angle: "235"; value: "-70.3469"; } + ListElement{ radius: "70"; angle: "240"; value: "-72.6905"; } + ListElement{ radius: "70"; angle: "245"; value: "-74.7047"; } + ListElement{ radius: "70"; angle: "250"; value: "-76.3739"; } + ListElement{ radius: "70"; angle: "255"; value: "-77.6856"; } + ListElement{ radius: "70"; angle: "260"; value: "-78.6297"; } + ListElement{ radius: "70"; angle: "265"; value: "-79.199"; } + ListElement{ radius: "70"; angle: "270"; value: "-79.3893"; } + ListElement{ radius: "70"; angle: "275"; value: "-79.199"; } + ListElement{ radius: "70"; angle: "280"; value: "-78.6297"; } + ListElement{ radius: "70"; angle: "285"; value: "-77.6856"; } + ListElement{ radius: "70"; angle: "290"; value: "-76.3739"; } + ListElement{ radius: "70"; angle: "295"; value: "-74.7047"; } + ListElement{ radius: "70"; angle: "300"; value: "-72.6905"; } + ListElement{ radius: "70"; angle: "305"; value: "-70.3469"; } + ListElement{ radius: "70"; angle: "310"; value: "-67.6915"; } + ListElement{ radius: "70"; angle: "315"; value: "-64.7446"; } + ListElement{ radius: "70"; angle: "320"; value: "-61.5286"; } + ListElement{ radius: "70"; angle: "325"; value: "-58.0681"; } + ListElement{ radius: "70"; angle: "330"; value: "-54.3893"; } + ListElement{ radius: "70"; angle: "335"; value: "-50.5202"; } + ListElement{ radius: "70"; angle: "340"; value: "-46.4903"; } + ListElement{ radius: "70"; angle: "345"; value: "-42.3302"; } + ListElement{ radius: "70"; angle: "350"; value: "-38.0717"; } + ListElement{ radius: "70"; angle: "355"; value: "-33.747"; } + ListElement{ radius: "70"; angle: "360"; value: "-29.3893"; } + ListElement{ radius: "75"; angle: "0"; value: "-35.3553"; } + ListElement{ radius: "75"; angle: "5"; value: "-30.9976"; } + ListElement{ radius: "75"; angle: "10"; value: "-26.6729"; } + ListElement{ radius: "75"; angle: "15"; value: "-22.4144"; } + ListElement{ radius: "75"; angle: "20"; value: "-18.2543"; } + ListElement{ radius: "75"; angle: "25"; value: "-14.2244"; } + ListElement{ radius: "75"; angle: "30"; value: "-10.3553"; } + ListElement{ radius: "75"; angle: "35"; value: "-6.67652"; } + ListElement{ radius: "75"; angle: "40"; value: "-3.21596"; } + ListElement{ radius: "75"; angle: "45"; value: "5.55112e-15"; } + ListElement{ radius: "75"; angle: "50"; value: "2.94688"; } + ListElement{ radius: "75"; angle: "55"; value: "5.60226"; } + ListElement{ radius: "75"; angle: "60"; value: "7.94593"; } + ListElement{ radius: "75"; angle: "65"; value: "9.96005"; } + ListElement{ radius: "75"; angle: "70"; value: "11.6293"; } + ListElement{ radius: "75"; angle: "75"; value: "12.941"; } + ListElement{ radius: "75"; angle: "80"; value: "13.885"; } + ListElement{ radius: "75"; angle: "85"; value: "14.4544"; } + ListElement{ radius: "75"; angle: "90"; value: "14.6447"; } + ListElement{ radius: "75"; angle: "95"; value: "14.4544"; } + ListElement{ radius: "75"; angle: "100"; value: "13.885"; } + ListElement{ radius: "75"; angle: "105"; value: "12.941"; } + ListElement{ radius: "75"; angle: "110"; value: "11.6293"; } + ListElement{ radius: "75"; angle: "115"; value: "9.96005"; } + ListElement{ radius: "75"; angle: "120"; value: "7.94593"; } + ListElement{ radius: "75"; angle: "125"; value: "5.60226"; } + ListElement{ radius: "75"; angle: "130"; value: "2.94688"; } + ListElement{ radius: "75"; angle: "135"; value: "5.55112e-15"; } + ListElement{ radius: "75"; angle: "140"; value: "-3.21596"; } + ListElement{ radius: "75"; angle: "145"; value: "-6.67652"; } + ListElement{ radius: "75"; angle: "150"; value: "-10.3553"; } + ListElement{ radius: "75"; angle: "155"; value: "-14.2244"; } + ListElement{ radius: "75"; angle: "160"; value: "-18.2543"; } + ListElement{ radius: "75"; angle: "165"; value: "-22.4144"; } + ListElement{ radius: "75"; angle: "170"; value: "-26.6729"; } + ListElement{ radius: "75"; angle: "175"; value: "-30.9976"; } + ListElement{ radius: "75"; angle: "180"; value: "-35.3553"; } + ListElement{ radius: "75"; angle: "185"; value: "-39.7131"; } + ListElement{ radius: "75"; angle: "190"; value: "-44.0377"; } + ListElement{ radius: "75"; angle: "195"; value: "-48.2963"; } + ListElement{ radius: "75"; angle: "200"; value: "-52.4563"; } + ListElement{ radius: "75"; angle: "205"; value: "-56.4863"; } + ListElement{ radius: "75"; angle: "210"; value: "-60.3553"; } + ListElement{ radius: "75"; angle: "215"; value: "-64.0342"; } + ListElement{ radius: "75"; angle: "220"; value: "-67.4947"; } + ListElement{ radius: "75"; angle: "225"; value: "-70.7107"; } + ListElement{ radius: "75"; angle: "230"; value: "-73.6576"; } + ListElement{ radius: "75"; angle: "235"; value: "-76.3129"; } + ListElement{ radius: "75"; angle: "240"; value: "-78.6566"; } + ListElement{ radius: "75"; angle: "245"; value: "-80.6707"; } + ListElement{ radius: "75"; angle: "250"; value: "-82.34"; } + ListElement{ radius: "75"; angle: "255"; value: "-83.6516"; } + ListElement{ radius: "75"; angle: "260"; value: "-84.5957"; } + ListElement{ radius: "75"; angle: "265"; value: "-85.1651"; } + ListElement{ radius: "75"; angle: "270"; value: "-85.3553"; } + ListElement{ radius: "75"; angle: "275"; value: "-85.1651"; } + ListElement{ radius: "75"; angle: "280"; value: "-84.5957"; } + ListElement{ radius: "75"; angle: "285"; value: "-83.6516"; } + ListElement{ radius: "75"; angle: "290"; value: "-82.34"; } + ListElement{ radius: "75"; angle: "295"; value: "-80.6707"; } + ListElement{ radius: "75"; angle: "300"; value: "-78.6566"; } + ListElement{ radius: "75"; angle: "305"; value: "-76.3129"; } + ListElement{ radius: "75"; angle: "310"; value: "-73.6576"; } + ListElement{ radius: "75"; angle: "315"; value: "-70.7107"; } + ListElement{ radius: "75"; angle: "320"; value: "-67.4947"; } + ListElement{ radius: "75"; angle: "325"; value: "-64.0342"; } + ListElement{ radius: "75"; angle: "330"; value: "-60.3553"; } + ListElement{ radius: "75"; angle: "335"; value: "-56.4863"; } + ListElement{ radius: "75"; angle: "340"; value: "-52.4563"; } + ListElement{ radius: "75"; angle: "345"; value: "-48.2963"; } + ListElement{ radius: "75"; angle: "350"; value: "-44.0377"; } + ListElement{ radius: "75"; angle: "355"; value: "-39.7131"; } + ListElement{ radius: "75"; angle: "360"; value: "-35.3553"; } + ListElement{ radius: "80"; angle: "0"; value: "-40.4508"; } + ListElement{ radius: "80"; angle: "5"; value: "-36.0931"; } + ListElement{ radius: "80"; angle: "10"; value: "-31.7684"; } + ListElement{ radius: "80"; angle: "15"; value: "-27.5099"; } + ListElement{ radius: "80"; angle: "20"; value: "-23.3498"; } + ListElement{ radius: "80"; angle: "25"; value: "-19.3199"; } + ListElement{ radius: "80"; angle: "30"; value: "-15.4508"; } + ListElement{ radius: "80"; angle: "35"; value: "-11.772"; } + ListElement{ radius: "80"; angle: "40"; value: "-8.31147"; } + ListElement{ radius: "80"; angle: "45"; value: "-5.09551"; } + ListElement{ radius: "80"; angle: "50"; value: "-2.14863"; } + ListElement{ radius: "80"; angle: "55"; value: "0.506752"; } + ListElement{ radius: "80"; angle: "60"; value: "2.85042"; } + ListElement{ radius: "80"; angle: "65"; value: "4.86454"; } + ListElement{ radius: "80"; angle: "70"; value: "6.53378"; } + ListElement{ radius: "80"; angle: "75"; value: "7.84544"; } + ListElement{ radius: "80"; angle: "80"; value: "8.78954"; } + ListElement{ radius: "80"; angle: "85"; value: "9.35889"; } + ListElement{ radius: "80"; angle: "90"; value: "9.54915"; } + ListElement{ radius: "80"; angle: "95"; value: "9.35889"; } + ListElement{ radius: "80"; angle: "100"; value: "8.78954"; } + ListElement{ radius: "80"; angle: "105"; value: "7.84544"; } + ListElement{ radius: "80"; angle: "110"; value: "6.53378"; } + ListElement{ radius: "80"; angle: "115"; value: "4.86454"; } + ListElement{ radius: "80"; angle: "120"; value: "2.85042"; } + ListElement{ radius: "80"; angle: "125"; value: "0.506752"; } + ListElement{ radius: "80"; angle: "130"; value: "-2.14863"; } + ListElement{ radius: "80"; angle: "135"; value: "-5.09551"; } + ListElement{ radius: "80"; angle: "140"; value: "-8.31147"; } + ListElement{ radius: "80"; angle: "145"; value: "-11.772"; } + ListElement{ radius: "80"; angle: "150"; value: "-15.4508"; } + ListElement{ radius: "80"; angle: "155"; value: "-19.3199"; } + ListElement{ radius: "80"; angle: "160"; value: "-23.3498"; } + ListElement{ radius: "80"; angle: "165"; value: "-27.5099"; } + ListElement{ radius: "80"; angle: "170"; value: "-31.7684"; } + ListElement{ radius: "80"; angle: "175"; value: "-36.0931"; } + ListElement{ radius: "80"; angle: "180"; value: "-40.4508"; } + ListElement{ radius: "80"; angle: "185"; value: "-44.8086"; } + ListElement{ radius: "80"; angle: "190"; value: "-49.1333"; } + ListElement{ radius: "80"; angle: "195"; value: "-53.3918"; } + ListElement{ radius: "80"; angle: "200"; value: "-57.5519"; } + ListElement{ radius: "80"; angle: "205"; value: "-61.5818"; } + ListElement{ radius: "80"; angle: "210"; value: "-65.4508"; } + ListElement{ radius: "80"; angle: "215"; value: "-69.1297"; } + ListElement{ radius: "80"; angle: "220"; value: "-72.5902"; } + ListElement{ radius: "80"; angle: "225"; value: "-75.8062"; } + ListElement{ radius: "80"; angle: "230"; value: "-78.7531"; } + ListElement{ radius: "80"; angle: "235"; value: "-81.4085"; } + ListElement{ radius: "80"; angle: "240"; value: "-83.7521"; } + ListElement{ radius: "80"; angle: "245"; value: "-85.7662"; } + ListElement{ radius: "80"; angle: "250"; value: "-87.4355"; } + ListElement{ radius: "80"; angle: "255"; value: "-88.7471"; } + ListElement{ radius: "80"; angle: "260"; value: "-89.6912"; } + ListElement{ radius: "80"; angle: "265"; value: "-90.2606"; } + ListElement{ radius: "80"; angle: "270"; value: "-90.4508"; } + ListElement{ radius: "80"; angle: "275"; value: "-90.2606"; } + ListElement{ radius: "80"; angle: "280"; value: "-89.6912"; } + ListElement{ radius: "80"; angle: "285"; value: "-88.7471"; } + ListElement{ radius: "80"; angle: "290"; value: "-87.4355"; } + ListElement{ radius: "80"; angle: "295"; value: "-85.7662"; } + ListElement{ radius: "80"; angle: "300"; value: "-83.7521"; } + ListElement{ radius: "80"; angle: "305"; value: "-81.4085"; } + ListElement{ radius: "80"; angle: "310"; value: "-78.7531"; } + ListElement{ radius: "80"; angle: "315"; value: "-75.8062"; } + ListElement{ radius: "80"; angle: "320"; value: "-72.5902"; } + ListElement{ radius: "80"; angle: "325"; value: "-69.1297"; } + ListElement{ radius: "80"; angle: "330"; value: "-65.4508"; } + ListElement{ radius: "80"; angle: "335"; value: "-61.5818"; } + ListElement{ radius: "80"; angle: "340"; value: "-57.5519"; } + ListElement{ radius: "80"; angle: "345"; value: "-53.3918"; } + ListElement{ radius: "80"; angle: "350"; value: "-49.1333"; } + ListElement{ radius: "80"; angle: "355"; value: "-44.8086"; } + ListElement{ radius: "80"; angle: "360"; value: "-40.4508"; } + ListElement{ radius: "85"; angle: "0"; value: "-44.5503"; } + ListElement{ radius: "85"; angle: "5"; value: "-40.1925"; } + ListElement{ radius: "85"; angle: "10"; value: "-35.8679"; } + ListElement{ radius: "85"; angle: "15"; value: "-31.6094"; } + ListElement{ radius: "85"; angle: "20"; value: "-27.4493"; } + ListElement{ radius: "85"; angle: "25"; value: "-23.4194"; } + ListElement{ radius: "85"; angle: "30"; value: "-19.5503"; } + ListElement{ radius: "85"; angle: "35"; value: "-15.8715"; } + ListElement{ radius: "85"; angle: "40"; value: "-12.4109"; } + ListElement{ radius: "85"; angle: "45"; value: "-9.19499"; } + ListElement{ radius: "85"; angle: "50"; value: "-6.2481"; } + ListElement{ radius: "85"; angle: "55"; value: "-3.59272"; } + ListElement{ radius: "85"; angle: "60"; value: "-1.24906"; } + ListElement{ radius: "85"; angle: "65"; value: "0.765063"; } + ListElement{ radius: "85"; angle: "70"; value: "2.4343"; } + ListElement{ radius: "85"; angle: "75"; value: "3.74597"; } + ListElement{ radius: "85"; angle: "80"; value: "4.69006"; } + ListElement{ radius: "85"; angle: "85"; value: "5.25941"; } + ListElement{ radius: "85"; angle: "90"; value: "5.44967"; } + ListElement{ radius: "85"; angle: "95"; value: "5.25941"; } + ListElement{ radius: "85"; angle: "100"; value: "4.69006"; } + ListElement{ radius: "85"; angle: "105"; value: "3.74597"; } + ListElement{ radius: "85"; angle: "110"; value: "2.4343"; } + ListElement{ radius: "85"; angle: "115"; value: "0.765063"; } + ListElement{ radius: "85"; angle: "120"; value: "-1.24906"; } + ListElement{ radius: "85"; angle: "125"; value: "-3.59272"; } + ListElement{ radius: "85"; angle: "130"; value: "-6.2481"; } + ListElement{ radius: "85"; angle: "135"; value: "-9.19499"; } + ListElement{ radius: "85"; angle: "140"; value: "-12.4109"; } + ListElement{ radius: "85"; angle: "145"; value: "-15.8715"; } + ListElement{ radius: "85"; angle: "150"; value: "-19.5503"; } + ListElement{ radius: "85"; angle: "155"; value: "-23.4194"; } + ListElement{ radius: "85"; angle: "160"; value: "-27.4493"; } + ListElement{ radius: "85"; angle: "165"; value: "-31.6094"; } + ListElement{ radius: "85"; angle: "170"; value: "-35.8679"; } + ListElement{ radius: "85"; angle: "175"; value: "-40.1925"; } + ListElement{ radius: "85"; angle: "180"; value: "-44.5503"; } + ListElement{ radius: "85"; angle: "185"; value: "-48.9081"; } + ListElement{ radius: "85"; angle: "190"; value: "-53.2327"; } + ListElement{ radius: "85"; angle: "195"; value: "-57.4913"; } + ListElement{ radius: "85"; angle: "200"; value: "-61.6513"; } + ListElement{ radius: "85"; angle: "205"; value: "-65.6812"; } + ListElement{ radius: "85"; angle: "210"; value: "-69.5503"; } + ListElement{ radius: "85"; angle: "215"; value: "-73.2291"; } + ListElement{ radius: "85"; angle: "220"; value: "-76.6897"; } + ListElement{ radius: "85"; angle: "225"; value: "-79.9057"; } + ListElement{ radius: "85"; angle: "230"; value: "-82.8525"; } + ListElement{ radius: "85"; angle: "235"; value: "-85.5079"; } + ListElement{ radius: "85"; angle: "240"; value: "-87.8516"; } + ListElement{ radius: "85"; angle: "245"; value: "-89.8657"; } + ListElement{ radius: "85"; angle: "250"; value: "-91.535"; } + ListElement{ radius: "85"; angle: "255"; value: "-92.8466"; } + ListElement{ radius: "85"; angle: "260"; value: "-93.7907"; } + ListElement{ radius: "85"; angle: "265"; value: "-94.3601"; } + ListElement{ radius: "85"; angle: "270"; value: "-94.5503"; } + ListElement{ radius: "85"; angle: "275"; value: "-94.3601"; } + ListElement{ radius: "85"; angle: "280"; value: "-93.7907"; } + ListElement{ radius: "85"; angle: "285"; value: "-92.8466"; } + ListElement{ radius: "85"; angle: "290"; value: "-91.535"; } + ListElement{ radius: "85"; angle: "295"; value: "-89.8657"; } + ListElement{ radius: "85"; angle: "300"; value: "-87.8516"; } + ListElement{ radius: "85"; angle: "305"; value: "-85.5079"; } + ListElement{ radius: "85"; angle: "310"; value: "-82.8525"; } + ListElement{ radius: "85"; angle: "315"; value: "-79.9057"; } + ListElement{ radius: "85"; angle: "320"; value: "-76.6897"; } + ListElement{ radius: "85"; angle: "325"; value: "-73.2291"; } + ListElement{ radius: "85"; angle: "330"; value: "-69.5503"; } + ListElement{ radius: "85"; angle: "335"; value: "-65.6812"; } + ListElement{ radius: "85"; angle: "340"; value: "-61.6513"; } + ListElement{ radius: "85"; angle: "345"; value: "-57.4913"; } + ListElement{ radius: "85"; angle: "350"; value: "-53.2327"; } + ListElement{ radius: "85"; angle: "355"; value: "-48.9081"; } + ListElement{ radius: "85"; angle: "360"; value: "-44.5503"; } + ListElement{ radius: "90"; angle: "0"; value: "-47.5528"; } + ListElement{ radius: "90"; angle: "5"; value: "-43.195"; } + ListElement{ radius: "90"; angle: "10"; value: "-38.8704"; } + ListElement{ radius: "90"; angle: "15"; value: "-34.6119"; } + ListElement{ radius: "90"; angle: "20"; value: "-30.4518"; } + ListElement{ radius: "90"; angle: "25"; value: "-26.4219"; } + ListElement{ radius: "90"; angle: "30"; value: "-22.5528"; } + ListElement{ radius: "90"; angle: "35"; value: "-18.874"; } + ListElement{ radius: "90"; angle: "40"; value: "-15.4134"; } + ListElement{ radius: "90"; angle: "45"; value: "-12.1975"; } + ListElement{ radius: "90"; angle: "50"; value: "-9.2506"; } + ListElement{ radius: "90"; angle: "55"; value: "-6.59522"; } + ListElement{ radius: "90"; angle: "60"; value: "-4.25156"; } + ListElement{ radius: "90"; angle: "65"; value: "-2.23744"; } + ListElement{ radius: "90"; angle: "70"; value: "-0.568195"; } + ListElement{ radius: "90"; angle: "75"; value: "0.743465"; } + ListElement{ radius: "90"; angle: "80"; value: "1.68756"; } + ListElement{ radius: "90"; angle: "85"; value: "2.25691"; } + ListElement{ radius: "90"; angle: "90"; value: "2.44717"; } + ListElement{ radius: "90"; angle: "95"; value: "2.25691"; } + ListElement{ radius: "90"; angle: "100"; value: "1.68756"; } + ListElement{ radius: "90"; angle: "105"; value: "0.743465"; } + ListElement{ radius: "90"; angle: "110"; value: "-0.568195"; } + ListElement{ radius: "90"; angle: "115"; value: "-2.23744"; } + ListElement{ radius: "90"; angle: "120"; value: "-4.25156"; } + ListElement{ radius: "90"; angle: "125"; value: "-6.59522"; } + ListElement{ radius: "90"; angle: "130"; value: "-9.2506"; } + ListElement{ radius: "90"; angle: "135"; value: "-12.1975"; } + ListElement{ radius: "90"; angle: "140"; value: "-15.4134"; } + ListElement{ radius: "90"; angle: "145"; value: "-18.874"; } + ListElement{ radius: "90"; angle: "150"; value: "-22.5528"; } + ListElement{ radius: "90"; angle: "155"; value: "-26.4219"; } + ListElement{ radius: "90"; angle: "160"; value: "-30.4518"; } + ListElement{ radius: "90"; angle: "165"; value: "-34.6119"; } + ListElement{ radius: "90"; angle: "170"; value: "-38.8704"; } + ListElement{ radius: "90"; angle: "175"; value: "-43.195"; } + ListElement{ radius: "90"; angle: "180"; value: "-47.5528"; } + ListElement{ radius: "90"; angle: "185"; value: "-51.9106"; } + ListElement{ radius: "90"; angle: "190"; value: "-56.2352"; } + ListElement{ radius: "90"; angle: "195"; value: "-60.4938"; } + ListElement{ radius: "90"; angle: "200"; value: "-64.6538"; } + ListElement{ radius: "90"; angle: "205"; value: "-68.6837"; } + ListElement{ radius: "90"; angle: "210"; value: "-72.5528"; } + ListElement{ radius: "90"; angle: "215"; value: "-76.2316"; } + ListElement{ radius: "90"; angle: "220"; value: "-79.6922"; } + ListElement{ radius: "90"; angle: "225"; value: "-82.9082"; } + ListElement{ radius: "90"; angle: "230"; value: "-85.855"; } + ListElement{ radius: "90"; angle: "235"; value: "-88.5104"; } + ListElement{ radius: "90"; angle: "240"; value: "-90.8541"; } + ListElement{ radius: "90"; angle: "245"; value: "-92.8682"; } + ListElement{ radius: "90"; angle: "250"; value: "-94.5375"; } + ListElement{ radius: "90"; angle: "255"; value: "-95.8491"; } + ListElement{ radius: "90"; angle: "260"; value: "-96.7932"; } + ListElement{ radius: "90"; angle: "265"; value: "-97.3626"; } + ListElement{ radius: "90"; angle: "270"; value: "-97.5528"; } + ListElement{ radius: "90"; angle: "275"; value: "-97.3626"; } + ListElement{ radius: "90"; angle: "280"; value: "-96.7932"; } + ListElement{ radius: "90"; angle: "285"; value: "-95.8491"; } + ListElement{ radius: "90"; angle: "290"; value: "-94.5375"; } + ListElement{ radius: "90"; angle: "295"; value: "-92.8682"; } + ListElement{ radius: "90"; angle: "300"; value: "-90.8541"; } + ListElement{ radius: "90"; angle: "305"; value: "-88.5104"; } + ListElement{ radius: "90"; angle: "310"; value: "-85.855"; } + ListElement{ radius: "90"; angle: "315"; value: "-82.9082"; } + ListElement{ radius: "90"; angle: "320"; value: "-79.6922"; } + ListElement{ radius: "90"; angle: "325"; value: "-76.2316"; } + ListElement{ radius: "90"; angle: "330"; value: "-72.5528"; } + ListElement{ radius: "90"; angle: "335"; value: "-68.6837"; } + ListElement{ radius: "90"; angle: "340"; value: "-64.6538"; } + ListElement{ radius: "90"; angle: "345"; value: "-60.4938"; } + ListElement{ radius: "90"; angle: "350"; value: "-56.2352"; } + ListElement{ radius: "90"; angle: "355"; value: "-51.9106"; } + ListElement{ radius: "90"; angle: "360"; value: "-47.5528"; } + ListElement{ radius: "95"; angle: "0"; value: "-49.3844"; } + ListElement{ radius: "95"; angle: "5"; value: "-45.0266"; } + ListElement{ radius: "95"; angle: "10"; value: "-40.702"; } + ListElement{ radius: "95"; angle: "15"; value: "-36.4435"; } + ListElement{ radius: "95"; angle: "20"; value: "-32.2834"; } + ListElement{ radius: "95"; angle: "25"; value: "-28.2535"; } + ListElement{ radius: "95"; angle: "30"; value: "-24.3844"; } + ListElement{ radius: "95"; angle: "35"; value: "-20.7056"; } + ListElement{ radius: "95"; angle: "40"; value: "-17.245"; } + ListElement{ radius: "95"; angle: "45"; value: "-14.0291"; } + ListElement{ radius: "95"; angle: "50"; value: "-11.0822"; } + ListElement{ radius: "95"; angle: "55"; value: "-8.42681"; } + ListElement{ radius: "95"; angle: "60"; value: "-6.08315"; } + ListElement{ radius: "95"; angle: "65"; value: "-4.06903"; } + ListElement{ radius: "95"; angle: "70"; value: "-2.39979"; } + ListElement{ radius: "95"; angle: "75"; value: "-1.08813"; } + ListElement{ radius: "95"; angle: "80"; value: "-0.144029"; } + ListElement{ radius: "95"; angle: "85"; value: "0.425318"; } + ListElement{ radius: "95"; angle: "90"; value: "0.615583"; } + ListElement{ radius: "95"; angle: "95"; value: "0.425318"; } + ListElement{ radius: "95"; angle: "100"; value: "-0.144029"; } + ListElement{ radius: "95"; angle: "105"; value: "-1.08813"; } + ListElement{ radius: "95"; angle: "110"; value: "-2.39979"; } + ListElement{ radius: "95"; angle: "115"; value: "-4.06903"; } + ListElement{ radius: "95"; angle: "120"; value: "-6.08315"; } + ListElement{ radius: "95"; angle: "125"; value: "-8.42681"; } + ListElement{ radius: "95"; angle: "130"; value: "-11.0822"; } + ListElement{ radius: "95"; angle: "135"; value: "-14.0291"; } + ListElement{ radius: "95"; angle: "140"; value: "-17.245"; } + ListElement{ radius: "95"; angle: "145"; value: "-20.7056"; } + ListElement{ radius: "95"; angle: "150"; value: "-24.3844"; } + ListElement{ radius: "95"; angle: "155"; value: "-28.2535"; } + ListElement{ radius: "95"; angle: "160"; value: "-32.2834"; } + ListElement{ radius: "95"; angle: "165"; value: "-36.4435"; } + ListElement{ radius: "95"; angle: "170"; value: "-40.702"; } + ListElement{ radius: "95"; angle: "175"; value: "-45.0266"; } + ListElement{ radius: "95"; angle: "180"; value: "-49.3844"; } + ListElement{ radius: "95"; angle: "185"; value: "-53.7422"; } + ListElement{ radius: "95"; angle: "190"; value: "-58.0668"; } + ListElement{ radius: "95"; angle: "195"; value: "-62.3254"; } + ListElement{ radius: "95"; angle: "200"; value: "-66.4854"; } + ListElement{ radius: "95"; angle: "205"; value: "-70.5153"; } + ListElement{ radius: "95"; angle: "210"; value: "-74.3844"; } + ListElement{ radius: "95"; angle: "215"; value: "-78.0632"; } + ListElement{ radius: "95"; angle: "220"; value: "-81.5238"; } + ListElement{ radius: "95"; angle: "225"; value: "-84.7398"; } + ListElement{ radius: "95"; angle: "230"; value: "-87.6866"; } + ListElement{ radius: "95"; angle: "235"; value: "-90.342"; } + ListElement{ radius: "95"; angle: "240"; value: "-92.6857"; } + ListElement{ radius: "95"; angle: "245"; value: "-94.6998"; } + ListElement{ radius: "95"; angle: "250"; value: "-96.369"; } + ListElement{ radius: "95"; angle: "255"; value: "-97.6807"; } + ListElement{ radius: "95"; angle: "260"; value: "-98.6248"; } + ListElement{ radius: "95"; angle: "265"; value: "-99.1942"; } + ListElement{ radius: "95"; angle: "270"; value: "-99.3844"; } + ListElement{ radius: "95"; angle: "275"; value: "-99.1942"; } + ListElement{ radius: "95"; angle: "280"; value: "-98.6248"; } + ListElement{ radius: "95"; angle: "285"; value: "-97.6807"; } + ListElement{ radius: "95"; angle: "290"; value: "-96.369"; } + ListElement{ radius: "95"; angle: "295"; value: "-94.6998"; } + ListElement{ radius: "95"; angle: "300"; value: "-92.6857"; } + ListElement{ radius: "95"; angle: "305"; value: "-90.342"; } + ListElement{ radius: "95"; angle: "310"; value: "-87.6866"; } + ListElement{ radius: "95"; angle: "315"; value: "-84.7398"; } + ListElement{ radius: "95"; angle: "320"; value: "-81.5238"; } + ListElement{ radius: "95"; angle: "325"; value: "-78.0632"; } + ListElement{ radius: "95"; angle: "330"; value: "-74.3844"; } + ListElement{ radius: "95"; angle: "335"; value: "-70.5153"; } + ListElement{ radius: "95"; angle: "340"; value: "-66.4854"; } + ListElement{ radius: "95"; angle: "345"; value: "-62.3254"; } + ListElement{ radius: "95"; angle: "350"; value: "-58.0668"; } + ListElement{ radius: "95"; angle: "355"; value: "-53.7422"; } + ListElement{ radius: "95"; angle: "360"; value: "-49.3844"; } + ListElement{ radius: "100"; angle: "0"; value: "-50"; } + ListElement{ radius: "100"; angle: "5"; value: "-45.6422"; } + ListElement{ radius: "100"; angle: "10"; value: "-41.3176"; } + ListElement{ radius: "100"; angle: "15"; value: "-37.059"; } + ListElement{ radius: "100"; angle: "20"; value: "-32.899"; } + ListElement{ radius: "100"; angle: "25"; value: "-28.8691"; } + ListElement{ radius: "100"; angle: "30"; value: "-25"; } + ListElement{ radius: "100"; angle: "35"; value: "-21.3212"; } + ListElement{ radius: "100"; angle: "40"; value: "-17.8606"; } + ListElement{ radius: "100"; angle: "45"; value: "-14.6447"; } + ListElement{ radius: "100"; angle: "50"; value: "-11.6978"; } + ListElement{ radius: "100"; angle: "55"; value: "-9.0424"; } + ListElement{ radius: "100"; angle: "60"; value: "-6.69873"; } + ListElement{ radius: "100"; angle: "65"; value: "-4.68461"; } + ListElement{ radius: "100"; angle: "70"; value: "-3.01537"; } + ListElement{ radius: "100"; angle: "75"; value: "-1.70371"; } + ListElement{ radius: "100"; angle: "80"; value: "-0.759612"; } + ListElement{ radius: "100"; angle: "85"; value: "-0.190265"; } + ListElement{ radius: "100"; angle: "90"; value: "0"; } + ListElement{ radius: "100"; angle: "95"; value: "-0.190265"; } + ListElement{ radius: "100"; angle: "100"; value: "-0.759612"; } + ListElement{ radius: "100"; angle: "105"; value: "-1.70371"; } + ListElement{ radius: "100"; angle: "110"; value: "-3.01537"; } + ListElement{ radius: "100"; angle: "115"; value: "-4.68461"; } + ListElement{ radius: "100"; angle: "120"; value: "-6.69873"; } + ListElement{ radius: "100"; angle: "125"; value: "-9.0424"; } + ListElement{ radius: "100"; angle: "130"; value: "-11.6978"; } + ListElement{ radius: "100"; angle: "135"; value: "-14.6447"; } + ListElement{ radius: "100"; angle: "140"; value: "-17.8606"; } + ListElement{ radius: "100"; angle: "145"; value: "-21.3212"; } + ListElement{ radius: "100"; angle: "150"; value: "-25"; } + ListElement{ radius: "100"; angle: "155"; value: "-28.8691"; } + ListElement{ radius: "100"; angle: "160"; value: "-32.899"; } + ListElement{ radius: "100"; angle: "165"; value: "-37.059"; } + ListElement{ radius: "100"; angle: "170"; value: "-41.3176"; } + ListElement{ radius: "100"; angle: "175"; value: "-45.6422"; } + ListElement{ radius: "100"; angle: "180"; value: "-50"; } + ListElement{ radius: "100"; angle: "185"; value: "-54.3578"; } + ListElement{ radius: "100"; angle: "190"; value: "-58.6824"; } + ListElement{ radius: "100"; angle: "195"; value: "-62.941"; } + ListElement{ radius: "100"; angle: "200"; value: "-67.101"; } + ListElement{ radius: "100"; angle: "205"; value: "-71.1309"; } + ListElement{ radius: "100"; angle: "210"; value: "-75"; } + ListElement{ radius: "100"; angle: "215"; value: "-78.6788"; } + ListElement{ radius: "100"; angle: "220"; value: "-82.1394"; } + ListElement{ radius: "100"; angle: "225"; value: "-85.3553"; } + ListElement{ radius: "100"; angle: "230"; value: "-88.3022"; } + ListElement{ radius: "100"; angle: "235"; value: "-90.9576"; } + ListElement{ radius: "100"; angle: "240"; value: "-93.3013"; } + ListElement{ radius: "100"; angle: "245"; value: "-95.3154"; } + ListElement{ radius: "100"; angle: "250"; value: "-96.9846"; } + ListElement{ radius: "100"; angle: "255"; value: "-98.2963"; } + ListElement{ radius: "100"; angle: "260"; value: "-99.2404"; } + ListElement{ radius: "100"; angle: "265"; value: "-99.8097"; } + ListElement{ radius: "100"; angle: "270"; value: "-100"; } + ListElement{ radius: "100"; angle: "275"; value: "-99.8097"; } + ListElement{ radius: "100"; angle: "280"; value: "-99.2404"; } + ListElement{ radius: "100"; angle: "285"; value: "-98.2963"; } + ListElement{ radius: "100"; angle: "290"; value: "-96.9846"; } + ListElement{ radius: "100"; angle: "295"; value: "-95.3154"; } + ListElement{ radius: "100"; angle: "300"; value: "-93.3013"; } + ListElement{ radius: "100"; angle: "305"; value: "-90.9576"; } + ListElement{ radius: "100"; angle: "310"; value: "-88.3022"; } + ListElement{ radius: "100"; angle: "315"; value: "-85.3553"; } + ListElement{ radius: "100"; angle: "320"; value: "-82.1394"; } + ListElement{ radius: "100"; angle: "325"; value: "-78.6788"; } + ListElement{ radius: "100"; angle: "330"; value: "-75"; } + ListElement{ radius: "100"; angle: "335"; value: "-71.1309"; } + ListElement{ radius: "100"; angle: "340"; value: "-67.101"; } + ListElement{ radius: "100"; angle: "345"; value: "-62.941"; } + ListElement{ radius: "100"; angle: "350"; value: "-58.6824"; } + ListElement{ radius: "100"; angle: "355"; value: "-54.3578"; } + ListElement{ radius: "100"; angle: "360"; value: "-50"; } + } +} diff --git a/libraries/disp/viewers/qml/NewButton.qml b/libraries/disp/viewers/qml/NewButton.qml new file mode 100644 index 00000000000..19309cca237 --- /dev/null +++ b/libraries/disp/viewers/qml/NewButton.qml @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Data Visualization module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Styles 1.0 + +Item { + id: newbutton + + property alias text: buttonText.text + + signal clicked + + implicitWidth: buttonText.implicitWidth + 5 + implicitHeight: buttonText.implicitHeight + 10 + + Button { + id: buttonText + width: parent.width + height: parent.height + + style: ButtonStyle { + label: Component { + Text { + text: buttonText.text + clip: true + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors.fill: parent + } + } + } + onClicked: newbutton.clicked() + } +} diff --git a/libraries/disp/viewers/qml/tfview.qml b/libraries/disp/viewers/qml/tfview.qml new file mode 100644 index 00000000000..c6bb34a35a2 --- /dev/null +++ b/libraries/disp/viewers/qml/tfview.qml @@ -0,0 +1,275 @@ +import QtQuick 2.1 +import QtQuick.Layouts 1.0 +import QtQuick.Window 2.1 +import QtDataVisualization 1.2 +import "." + +Window { + id: mainview + title: "Qt Quick 2 Spectrogram Example" + visible: true + width: 1024 + height: 768 + color: surfaceGraph.theme.windowColor + + Data { + id: surfaceData + } + + Item { + id: surfaceView + width: mainview.width + height: mainview.height + anchors.top: mainview.top + anchors.left: mainview.left + + ColorGradient { + id: surfaceGradient + ColorGradientStop { position: 0.0; color: "black" } + ColorGradientStop { position: 0.2; color: "red" } + ColorGradientStop { position: 0.5; color: "blue" } + ColorGradientStop { position: 0.8; color: "yellow" } + ColorGradientStop { position: 1.0; color: "white" } + } + + ValueAxis3D { + id: xAxis + segmentCount: 8 + labelFormat: "%i\u00B0" + title: "Angle" + titleVisible: true + titleFixed: false + } + + ValueAxis3D { + id: yAxis + segmentCount: 8 + labelFormat: "%i \%" + title: "Value" + titleVisible: true + labelAutoRotation: 0 + titleFixed: false + } + + ValueAxis3D { + id: zAxis + segmentCount: 5 + labelFormat: "%i nm" + title: "Radius" + titleVisible: true + titleFixed: false + } + + Theme3D { + id: customTheme + type: Theme3D.ThemeQt + // Don't show specular spotlight as we don't want it to distort the colors + lightStrength: 0.0 + ambientLightStrength: 1.0 + backgroundEnabled: false + gridLineColor: "#AAAAAA" + windowColor: "#EEEEEE" + } + + + //! [5] + TouchInputHandler3D { + id: customInputHandler + rotationEnabled: false + } + //! [5] + + //! [0] + //! [7] + Surface3D { + //! [7] + id: surfaceGraph + width: surfaceView.width + height: surfaceView.height + + shadowQuality: AbstractGraph3D.ShadowQualityNone + selectionMode: AbstractGraph3D.SelectionSlice | AbstractGraph3D.SelectionItemAndColumn + axisX: xAxis + axisY: yAxis + axisZ: zAxis + + theme: customTheme + //! [6] + inputHandler: customInputHandler + //! [6] + + // Remove the perspective and view the graph from top down to achieve 2D effect + //! [1] + orthoProjection: true + scene.activeCamera.cameraPreset: Camera3D.CameraPresetDirectlyAbove + //! [1] + + //! [2] + flipHorizontalGrid: true + //! [2] + + //! [4] + radialLabelOffset: 0.01 + //! [4] + + horizontalAspectRatio: 1 + scene.activeCamera.zoomLevel: 85 + + Surface3DSeries { + id: surfaceSeries + flatShadingEnabled: false + drawMode: Surface3DSeries.DrawSurface + baseGradient: surfaceGradient + colorStyle: Theme3D.ColorStyleRangeGradient + itemLabelFormat: "(@xLabel, @zLabel): @yLabel" + + ItemModelSurfaceDataProxy { + itemModel: surfaceData.model + rowRole: "radius" + columnRole: "angle" + yPosRole: "value" + } + } + } + //! [0] + } + + RowLayout { + id: buttonLayout + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + opacity: 0.5 + + //! [3] + NewButton { + id: polarToggle + Layout.fillWidth: true + Layout.fillHeight: true + text: "Switch to polar" + onClicked: { + if (surfaceGraph.polar === false) { + surfaceGraph.polar = true + text = "Switch to cartesian" + } else { + surfaceGraph.polar = false + text = "Switch to polar" + } + } + } + //! [3] + + NewButton { + id: orthoToggle + Layout.fillWidth: true + Layout.fillHeight: true + text: "Switch to perspective" + onClicked: { + if (surfaceGraph.orthoProjection === true) { + surfaceGraph.orthoProjection = false; + xAxis.labelAutoRotation = 30 + yAxis.labelAutoRotation = 30 + zAxis.labelAutoRotation = 30 + customInputHandler.rotationEnabled = true + text = "Switch to orthographic" + } else { + surfaceGraph.orthoProjection = true; + surfaceGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetDirectlyAbove + surfaceSeries.drawMode &= ~Surface3DSeries.DrawWireframe; + xAxis.labelAutoRotation = 0 + yAxis.labelAutoRotation = 0 + zAxis.labelAutoRotation = 0 + customInputHandler.rotationEnabled = false + text = "Switch to perspective" + } + } + } + + NewButton { + id: flipGridToggle + Layout.fillWidth: true + Layout.fillHeight: true + text: "Toggle axis grid on top" + onClicked: { + onClicked: { + if (surfaceGraph.flipHorizontalGrid === true) { + surfaceGraph.flipHorizontalGrid = false; + } else { + surfaceGraph.flipHorizontalGrid = true; + } + } + } + } + + NewButton { + id: labelOffsetToggle + Layout.fillWidth: true + Layout.fillHeight: true + text: "Toggle radial label position" + visible: surfaceGraph.polar + onClicked: { + if (surfaceGraph.radialLabelOffset >= 1.0) { + surfaceGraph.radialLabelOffset = 0.01 + } else { + surfaceGraph.radialLabelOffset = 1.0 + } + } + } + + NewButton { + id: surfaceGridToggle + Layout.fillWidth: true + Layout.fillHeight: true + text: "Toggle surface grid" + visible: !surfaceGraph.orthoProjection + onClicked: { + if (surfaceSeries.drawMode & Surface3DSeries.DrawWireframe) { + surfaceSeries.drawMode &= ~Surface3DSeries.DrawWireframe; + } else { + surfaceSeries.drawMode |= Surface3DSeries.DrawWireframe; + } + } + } + + } + + Rectangle { + id: legend + anchors.margins: 20 + anchors.bottom: parent.bottom + anchors.top: buttonLayout.bottom + anchors.right: parent.right + border.color: "black" + border.width: 1 + width: 50 + rotation: 180 + gradient: Gradient { + GradientStop { position: 0.0; color: "black" } + GradientStop { position: 0.2; color: "red" } + GradientStop { position: 0.5; color: "blue" } + GradientStop { position: 0.8; color: "yellow" } + GradientStop { position: 1.0; color: "white" } + } + } + + Text { + anchors.verticalCenter: legend.bottom + anchors.right: legend.left + anchors.margins: 2 + text: surfaceGraph.axisY.min + "%" + } + + Text { + anchors.verticalCenter: legend.verticalCenter + anchors.right: legend.left + anchors.margins: 2 + text: (surfaceGraph.axisY.max + surfaceGraph.axisY.min) / 2 + "%" + } + + Text { + anchors.verticalCenter: legend.top + anchors.right: legend.left + anchors.margins: 2 + text: surfaceGraph.axisY.max + "%" + } +} diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 31ca81b6f71..f8c2a58ae38 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -42,6 +42,10 @@ // QT INCLUDES //============================================================================================================= +#include +#include +#include + //============================================================================================================= // USED NAMESPACES //============================================================================================================= @@ -66,6 +70,7 @@ TimeFrequencyView::TimeFrequencyView(const QString& sSettingsPath, : AbstractView(parent, f) { m_sSettingsPath = sSettingsPath; + initQMLView(); } //============================================================================================================= @@ -116,6 +121,21 @@ void TimeFrequencyView::clearView() //============================================================================================================= +void TimeFrequencyView::initQMLView() +{ + QUrl source("qml/tfview.qml"); + QQuickWidget* widget = new QQuickWidget(); + widget->setSource(source); + + QVBoxLayout* layout = new QVBoxLayout(); + layout->addWidget(widget); + + + this->setLayout(layout); +} + +//============================================================================================================= + void TimeFrequencyView::paintEvent(QPaintEvent *event) { return AbstractView::paintEvent(event); diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index bc3660be8ee..37441d555b4 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -108,6 +108,7 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView void clearView(); protected: + void initQMLView(); virtual void paintEvent(QPaintEvent *event); }; From b8aa1d1fbaf8ac596fe7d137dd607d64218d0cb5 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Fri, 9 Apr 2021 13:53:38 -0400 Subject: [PATCH 10/57] ENH: embedding qml --- libraries/disp/viewers/qml/tfview.qml | 30 +++++++++----------- libraries/disp/viewers/timefrequencyview.cpp | 13 +++++---- libraries/disp/viewers/timefrequencyview.h | 2 +- libraries/rtprocessing/timefrequency.h | 1 - 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/libraries/disp/viewers/qml/tfview.qml b/libraries/disp/viewers/qml/tfview.qml index c6bb34a35a2..2c0e5f956ae 100644 --- a/libraries/disp/viewers/qml/tfview.qml +++ b/libraries/disp/viewers/qml/tfview.qml @@ -4,13 +4,11 @@ import QtQuick.Window 2.1 import QtDataVisualization 1.2 import "." -Window { +Item { id: mainview - title: "Qt Quick 2 Spectrogram Example" visible: true - width: 1024 - height: 768 - color: surfaceGraph.theme.windowColor + width: parent.width + height: parent.height Data { id: surfaceData @@ -25,18 +23,17 @@ Window { ColorGradient { id: surfaceGradient - ColorGradientStop { position: 0.0; color: "black" } - ColorGradientStop { position: 0.2; color: "red" } - ColorGradientStop { position: 0.5; color: "blue" } - ColorGradientStop { position: 0.8; color: "yellow" } - ColorGradientStop { position: 1.0; color: "white" } + ColorGradientStop { position: 0.0; color: "red" } + ColorGradientStop { position: 0.3; color: "yellow" } + ColorGradientStop { position: 0.7; color: "cyan" } + ColorGradientStop { position: 1.0; color: "blue" } } ValueAxis3D { id: xAxis segmentCount: 8 labelFormat: "%i\u00B0" - title: "Angle" + title: "Time" titleVisible: true titleFixed: false } @@ -55,7 +52,7 @@ Window { id: zAxis segmentCount: 5 labelFormat: "%i nm" - title: "Radius" + title: "Frequency" titleVisible: true titleFixed: false } @@ -244,11 +241,10 @@ Window { width: 50 rotation: 180 gradient: Gradient { - GradientStop { position: 0.0; color: "black" } - GradientStop { position: 0.2; color: "red" } - GradientStop { position: 0.5; color: "blue" } - GradientStop { position: 0.8; color: "yellow" } - GradientStop { position: 1.0; color: "white" } + GradientStop { position: 0.0; color: "red" } + GradientStop { position: 0.3; color: "yellow" } + GradientStop { position: 0.7; color: "cyan" } + GradientStop { position: 1.0; color: "blue" } } } diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index f8c2a58ae38..25a3cfcd015 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -123,9 +123,10 @@ void TimeFrequencyView::clearView() void TimeFrequencyView::initQMLView() { - QUrl source("qml/tfview.qml"); + QUrl source = QUrl::fromLocalFile("../libraries/disp/viewers/qml/tfview.qml"); QQuickWidget* widget = new QQuickWidget(); widget->setSource(source); + widget->setResizeMode(QQuickWidget::SizeRootObjectToView); QVBoxLayout* layout = new QVBoxLayout(); layout->addWidget(widget); @@ -134,9 +135,9 @@ void TimeFrequencyView::initQMLView() this->setLayout(layout); } -//============================================================================================================= +////============================================================================================================= -void TimeFrequencyView::paintEvent(QPaintEvent *event) -{ - return AbstractView::paintEvent(event); -} +//void TimeFrequencyView::paintEvent(QPaintEvent *event) +//{ +// return AbstractView::paintEvent(event); +//} diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index 37441d555b4..6166a5ac654 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -110,7 +110,7 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView protected: void initQMLView(); - virtual void paintEvent(QPaintEvent *event); +// virtual void paintEvent(QPaintEvent *event); }; } //namespace diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index 84076f2f3c1..cc58eae6409 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -13,7 +13,6 @@ // QT INCLUDES //============================================================================================================= -#include //============================================================================================================= // EIGEN INCLUDES From d9b38b0d06fa86a4fcf5f5a8d68c520c2f2de623 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Mon, 12 Apr 2021 11:01:56 -0400 Subject: [PATCH 11/57] ENH: functions for redrawing layout. catching avg model in analyze --- .../plugins/timefrequency/timefrequency.cpp | 10 ++----- .../plugins/timefrequency/timefrequency.h | 3 ++- .../viewers/helpers/timefrequencyscene.cpp | 27 +++++++++++++++++++ .../disp/viewers/helpers/timefrequencyscene.h | 16 +++++++++++ .../helpers/timefrequencysceneitem.cpp | 2 +- .../viewers/helpers/timefrequencysceneitem.h | 7 ++++- libraries/disp/viewers/timefrequencyview.h | 4 ++- libraries/rtprocessing/timefrequency.cpp | 10 +++++++ libraries/rtprocessing/timefrequency.h | 11 ++++++++ 9 files changed, 78 insertions(+), 12 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 5a2639cb1d8..ca59896fcb6 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -178,13 +178,7 @@ void TimeFrequency::loadSettings() void TimeFrequency::onModelChanged(QSharedPointer pNewModel) { - if(pNewModel->getType() == MODEL_TYPE::ANSHAREDLIB_FIFFRAW_MODEL) { - if(m_pFiffRawModel) { - if(m_pFiffRawModel == pNewModel) { - qInfo() << "[Averaging::onModelChanged] New model is the same as old model"; - return; - } - } - m_pFiffRawModel = qSharedPointerCast(pNewModel); + if(pNewModel->getType() == MODEL_TYPE::ANSHAREDLIB_AVERAGING_MODEL) { + m_pAvgModel = qSharedPointerCast(pNewModel); } } diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h index 04897429d69..9e15843f751 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.h +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -61,6 +61,7 @@ namespace ANSHAREDLIB { class Communicator; class AbstractModel; + class AveragingDataModel; } namespace DISPLIB { @@ -142,7 +143,7 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlu QPointer m_pTimeFreqView; QPointer m_pTimeFreqLayoutView; - QSharedPointer m_pFiffRawModel; /**< Pointer to currently loaded FiffRawView Model */ + QSharedPointer m_pAvgModel; /**< Pointer to currently loaded FiffRawView Model */ }; diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.cpp b/libraries/disp/viewers/helpers/timefrequencyscene.cpp index ed5dbf854ce..6584eda8914 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.cpp +++ b/libraries/disp/viewers/helpers/timefrequencyscene.cpp @@ -38,6 +38,9 @@ #include "timefrequencyscene.h" +#include "timefrequencysceneitem.h" +#include "selectionsceneitem.h" + //============================================================================================================= // QT INCLUDES //============================================================================================================= @@ -58,3 +61,27 @@ TimeFrequencyScene::TimeFrequencyScene(QGraphicsView* view, { } + +//============================================================================================================= + +void TimeFrequencyScene::repaintItems(const QList &selectedChannelItems) +{ +// this->clear(); + +// QListIterator i(selectedChannelItems); + +// while (i.hasNext()) { +// SelectionSceneItem* selectionSceneItemTemp = static_cast(i.next()); +// TimeFrequencySceneItem* averageSceneItemTemp = new TimeFrequencySceneItem(); + +// this->addItem(averageSceneItemTemp); +// } +} + +//============================================================================================================= + +void TimeFrequencyScene::updateScene() +{ + this->update(); +} + diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.h b/libraries/disp/viewers/helpers/timefrequencyscene.h index d5dc6e82460..11d93164cb6 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.h +++ b/libraries/disp/viewers/helpers/timefrequencyscene.h @@ -62,8 +62,24 @@ class DISPSHARED_EXPORT TimeFrequencyScene : public LayoutScene { Q_OBJECT public: + //========================================================================================================= TimeFrequencyScene(QGraphicsView* view, QObject *parent = 0); + + //========================================================================================================= + /** + * Repaints all items from the layout data in the scene. + * + * @param [in] selectedChannelItems items which are to painted to the average scene + */ + void repaintItems(const QList &selectedChannelItems); + + //========================================================================================================= + /** + * Updates and repaints the scene + */ + void updateScene(); + }; }//namespace #endif // TIMEFREQUENCYSCENE_H diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp index 474581d3146..eefb4a40aaf 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp @@ -56,7 +56,7 @@ using namespace DISPLIB; // DEFINE MEMBER METHODS //============================================================================================================= -TimeFrequencySceneItem::TimeFrequencySceneItem() +TimeFrequencySceneItem::TimeFrequencySceneItem(const QPointF& channelPosition) { } diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.h b/libraries/disp/viewers/helpers/timefrequencysceneitem.h index cbe364ab1a5..a6f265cc0b9 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.h +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.h @@ -63,7 +63,12 @@ class DISPSHARED_EXPORT TimeFrequencySceneItem : public QGraphicsObject { Q_OBJECT public: - TimeFrequencySceneItem(); + TimeFrequencySceneItem(const QPointF& channelPosition); + +private: + + QPointF m_qpChannelPosition; /**< The channels 2D position in the scene.*/ + }; }//namespace #endif // TIMEFREQUENCYSCENEITEM_H diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index 6166a5ac654..1ce7688f5e2 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -67,8 +67,10 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView { Q_OBJECT public: - TimeFrequencyView(); + //========================================================================================================= + TimeFrequencyView(); + //========================================================================================================= TimeFrequencyView(const QString& sSettingsPath, QWidget* parent, Qt::WindowFlags f = Qt::Widget); diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index fefd9c62c4e..8a60d27b2a5 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -1,6 +1,16 @@ +//============================================================================================================= +// INCLUDES +//============================================================================================================= + #include "timefrequency.h" +#include +#include + TimeFrequency::TimeFrequency() { } + +void computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); + diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index cc58eae6409..4d054c03896 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -26,12 +26,23 @@ namespace FIFFLIB { class FiffRawData; + class FiffEvokedSet; } +//============================================================================================================= +// DEFINE NAMESPACE RTPROCESSINGLIB +//============================================================================================================= + +namespace RTPROCESSINGLIB +{ + class TimeFrequency { public: TimeFrequency(); }; +RTPROCESINGSHARED_EXPORT void computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); + +}//namespace #endif // TIMEFREQUENCY_RTPROCESSING_H From 8f3645d5f246f1275979c2fab1f6399f1c8dc310 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Mon, 12 Apr 2021 16:15:10 -0400 Subject: [PATCH 12/57] ENH: graphics layout formatting and plotting --- .../viewers/helpers/timefrequencyscene.cpp | 21 +++++++++++++++ .../disp/viewers/helpers/timefrequencyscene.h | 15 +++++++++++ .../helpers/timefrequencysceneitem.cpp | 26 ++++++++++++++++++- .../viewers/helpers/timefrequencysceneitem.h | 25 +++++++++++++++--- .../disp/viewers/timefrequencylayoutview.cpp | 23 ++++++++++++++++ .../disp/viewers/timefrequencylayoutview.h | 14 ++++++++++ 6 files changed, 120 insertions(+), 4 deletions(-) diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.cpp b/libraries/disp/viewers/helpers/timefrequencyscene.cpp index 6584eda8914..d338f465c14 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.cpp +++ b/libraries/disp/viewers/helpers/timefrequencyscene.cpp @@ -45,6 +45,8 @@ // QT INCLUDES //============================================================================================================= +#include + //============================================================================================================= // USED NAMESPACES //============================================================================================================= @@ -80,6 +82,25 @@ void TimeFrequencyScene::repaintItems(const QList &selectedChan //============================================================================================================= +void TimeFrequencyScene::repaintSelectionItems(const DISPLIB::SelectionItem &selectedChannelItems) +{ + this->clear(); + + for (int i = 0; i < selectedChannelItems.m_iChannelKind.size(); i++){ + TimeFrequencySceneItem* averageSceneItemTemp = new TimeFrequencySceneItem(selectedChannelItems.m_sChannelName[i], + selectedChannelItems.m_iChannelNumber[i], + selectedChannelItems.m_qpChannelPosition[i], + selectedChannelItems.m_iChannelKind[i], + selectedChannelItems.m_iChannelUnit[i]); + + QGraphicsProxyWidget* pWidget = this->addWidget(averageSceneItemTemp); + + pWidget->setPos(selectedChannelItems.m_qpChannelPosition[i]); + } +} + +//============================================================================================================= + void TimeFrequencyScene::updateScene() { this->update(); diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.h b/libraries/disp/viewers/helpers/timefrequencyscene.h index 11d93164cb6..e15dc723135 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.h +++ b/libraries/disp/viewers/helpers/timefrequencyscene.h @@ -58,6 +58,13 @@ namespace DISPLIB { +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +class SelectionSceneItem; +class SelectionItem; + class DISPSHARED_EXPORT TimeFrequencyScene : public LayoutScene { Q_OBJECT @@ -74,6 +81,14 @@ class DISPSHARED_EXPORT TimeFrequencyScene : public LayoutScene */ void repaintItems(const QList &selectedChannelItems); + //========================================================================================================= + /** + * Repaints all items from the layout data in the scene from a SelectionItem object + * + * @param [in] selectedChannelItems data about items which are to be painted + */ + void repaintSelectionItems(const DISPLIB::SelectionItem &selectedChannelItems); + //========================================================================================================= /** * Updates and repaints the scene diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp index eefb4a40aaf..9a9f5e1caf7 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp @@ -42,6 +42,10 @@ // QT INCLUDES //============================================================================================================= +#include +#include +#include + //============================================================================================================= // EIGEN INCLUDES //============================================================================================================= @@ -56,7 +60,27 @@ using namespace DISPLIB; // DEFINE MEMBER METHODS //============================================================================================================= -TimeFrequencySceneItem::TimeFrequencySceneItem(const QPointF& channelPosition) +TimeFrequencySceneItem::TimeFrequencySceneItem(const QString& channelName, + int channelNumber, + const QPointF& channelPosition, + int channelKind, + int channelUnit) { } + +//============================================================================================================= + +void TimeFrequencySceneItem::initQMLView() +{ + QUrl source = QUrl::fromLocalFile("../libraries/disp/viewers/qml/tfview.qml"); + QQuickWidget* widget = new QQuickWidget(); + widget->setSource(source); + widget->setResizeMode(QQuickWidget::SizeRootObjectToView); + + QVBoxLayout* layout = new QVBoxLayout(); + layout->addWidget(widget); + + + this->setLayout(layout); +} diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.h b/libraries/disp/viewers/helpers/timefrequencysceneitem.h index a6f265cc0b9..09e4bce5698 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.h +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.h @@ -45,7 +45,8 @@ // QT INCLUDES //============================================================================================================= -#include +#include +#include //============================================================================================================= // EIGEN INCLUDES @@ -59,14 +60,32 @@ namespace DISPLIB { //============================================================================================================= -class DISPSHARED_EXPORT TimeFrequencySceneItem : public QGraphicsObject +class DISPSHARED_EXPORT TimeFrequencySceneItem : public QWidget { Q_OBJECT public: - TimeFrequencySceneItem(const QPointF& channelPosition); + TimeFrequencySceneItem(const QString& channelName, + int channelNumber, + const QPointF& channelPosition, + int channelKind, + int channelUnit); + +protected: + void initQMLView(); private: + QString m_sChannelName; /**< The channel name.*/ + int m_iChannelNumber; /**< The channel number.*/ + int m_iChannelKind; /**< The channel kind.*/ + int m_iChannelUnit; /**< The channel unit.*/ + int m_iTotalNumberChannels; /**< The total number of channels loaded in the curent evoked data set.*/ + int m_iFontTextSize; /**< The font text size of the electrode names.*/ + int m_iMaxWidth; /**< The max width. */ + int m_iMaxHeigth; /**< The max heigth. */ + + bool m_bIsBad; /**< Whether this channel is bad. */ + QPointF m_qpChannelPosition; /**< The channels 2D position in the scene.*/ }; diff --git a/libraries/disp/viewers/timefrequencylayoutview.cpp b/libraries/disp/viewers/timefrequencylayoutview.cpp index c3b671f0b2c..a827cc07142 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.cpp +++ b/libraries/disp/viewers/timefrequencylayoutview.cpp @@ -39,12 +39,14 @@ #include "timefrequencylayoutview.h" #include "helpers/timefrequencyscene.h" #include "helpers/timefrequencysceneitem.h" +#include "helpers/selectionsceneitem.h" //============================================================================================================= // QT INCLUDES //============================================================================================================= #include +#include #if !defined(NO_QOPENGLWIDGET) #include #endif @@ -141,3 +143,24 @@ void TimeFrequencyLayoutView::clearView() { } + +//============================================================================================================= + +void TimeFrequencyLayoutView::channelSelectionChanged(const QVariant &data) +{ + if(!m_pTimeFreqScene) { + qDebug() << "AverageLayoutView::channelSelectionManagerChanged - m_pAverageScene is NULL. Returning. "; + return; + } + + SelectionItem* pSelectionItem = data.value(); + + //Repaint the average items in the average scene based on the input parameter selectedChannelItems and update them with current data + m_pTimeFreqScene->repaintSelectionItems(*pSelectionItem); +} +//============================================================================================================= + +void TimeFrequencyLayoutView::updateData() +{ + +} diff --git a/libraries/disp/viewers/timefrequencylayoutview.h b/libraries/disp/viewers/timefrequencylayoutview.h index 369844fe036..fbcf8a4a649 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.h +++ b/libraries/disp/viewers/timefrequencylayoutview.h @@ -94,6 +94,14 @@ class DISPSHARED_EXPORT TimeFrequencyLayoutView : public AbstractView */ void updateProcessingMode(ProcessingMode mode); + //========================================================================================================= + /** + * Sets the currently viewable channels using the corrent name and location parameters + * + * @param [in] data QVariant containing a SelectionItem object with selected channel information + */ + void channelSelectionChanged(const QVariant &data); + //========================================================================================================= /** * Saves all important settings of this view via QSettings. @@ -112,6 +120,12 @@ class DISPSHARED_EXPORT TimeFrequencyLayoutView : public AbstractView */ void clearView(); + //========================================================================================================= + /** + * call this function whenever the items' data needs to be updated + */ + void updateData(); + protected: QPointer m_pTimeFreqScene; QPointer m_pTimeFreqGraphicsView; From a35d842a8d01d1718e80ac9b46dfb274fe29366a Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 13 Apr 2021 15:39:35 -0400 Subject: [PATCH 13/57] ENH: passing channel select data to plot layout --- .../plugins/timefrequency/timefrequency.cpp | 28 ++++++++- .../plugins/timefrequency/timefrequency.h | 8 +++ .../helpers/timefrequencysceneitem.cpp | 13 ++-- .../disp/viewers/timefrequencylayoutview.h | 4 ++ libraries/disp/viewers/timefrequencyview.cpp | 23 +++++-- libraries/disp/viewers/timefrequencyview.h | 11 +++- libraries/rtprocessing/timefrequency.cpp | 62 ++++++++++++++++++- libraries/rtprocessing/timefrequency.h | 44 +++++++++++-- 8 files changed, 170 insertions(+), 23 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index ca59896fcb6..3d309958707 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -40,13 +40,12 @@ #include #include -#include -#include #include #include #include #include +#include //============================================================================================================= // USED NAMESPACES @@ -144,6 +143,9 @@ void TimeFrequency::handleEvent(QSharedPointer e) onModelChanged(e->getData().value >()); break; } + case EVENT_TYPE::CHANNEL_SELECTION_ITEMS:{ + setChannelSelection(e->getData()); + } default: qWarning() << "[Averaging::handleEvent] Received an Event that is not handled by switch cases."; } @@ -153,7 +155,9 @@ void TimeFrequency::handleEvent(QSharedPointer e) QVector TimeFrequency::getEventSubscriptions(void) const { - QVector temp = {SELECTED_MODEL_CHANGED}; + QVector temp; + temp.push_back(SELECTED_MODEL_CHANGED); + temp.push_back(CHANNEL_SELECTION_ITEMS); return temp; } @@ -182,3 +186,21 @@ void TimeFrequency::onModelChanged(QSharedPointer pN m_pAvgModel = qSharedPointerCast(pNewModel); } } + +//============================================================================================================= + +void TimeFrequency::setChannelSelection(const QVariant &data) +{ + if(data.value()->m_sViewsToApply.contains("layoutview")){ + if(m_pTimeFreqLayoutView){ + m_pTimeFreqLayoutView->channelSelectionChanged(data); + } + } + if(data.value()->m_sViewsToApply.contains("butterflyview")){ +// if(data.value()->m_bShowAll){ +// emit showAllChannels(); +// } else { +// emit showSelectedChannels(data.value()->m_iChannelNumber); +// } + } +} diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h index 9e15843f751..e38e3fa8c29 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.h +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -137,6 +137,14 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlu //========================================================================================================= void onModelChanged(QSharedPointer pNewModel); + //========================================================================================================= + /** + * Sets channel selection for views based on QVariant with a SelectionItem object + * + * @param [in] data QVariant with a SelectionItem object with channel selection information + */ + void setChannelSelection(const QVariant &data); + QPointer m_pCommu; /**< Used for sending events */ QString m_sSettingsPath; /**< Variable that stores the key where to store settings for this plugin.*/ diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp index 9a9f5e1caf7..22a9b5bac5c 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp @@ -45,6 +45,7 @@ #include #include #include +#include //============================================================================================================= // EIGEN INCLUDES @@ -66,17 +67,19 @@ TimeFrequencySceneItem::TimeFrequencySceneItem(const QString& channelName, int channelKind, int channelUnit) { - + initQMLView(); } //============================================================================================================= void TimeFrequencySceneItem::initQMLView() { - QUrl source = QUrl::fromLocalFile("../libraries/disp/viewers/qml/tfview.qml"); - QQuickWidget* widget = new QQuickWidget(); - widget->setSource(source); - widget->setResizeMode(QQuickWidget::SizeRootObjectToView); +// QUrl source = QUrl::fromLocalFile("../libraries/disp/viewers/qml/tfview.qml"); +// QQuickWidget* widget = new QQuickWidget(); +// widget->setSource(source); +// widget->setResizeMode(QQuickWidget::SizeRootObjectToView); + + QLabel* widget = new QLabel("Test"); QVBoxLayout* layout = new QVBoxLayout(); layout->addWidget(widget); diff --git a/libraries/disp/viewers/timefrequencylayoutview.h b/libraries/disp/viewers/timefrequencylayoutview.h index fbcf8a4a649..ab5dfc5b68c 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.h +++ b/libraries/disp/viewers/timefrequencylayoutview.h @@ -65,6 +65,7 @@ namespace DISPLIB // DISPLIB FORWARD DECLARATIONS //============================================================================================================= +class EvokedSetModel; class TimeFrequencyScene; //============================================================================================================= @@ -129,6 +130,9 @@ class DISPSHARED_EXPORT TimeFrequencyLayoutView : public AbstractView protected: QPointer m_pTimeFreqScene; QPointer m_pTimeFreqGraphicsView; + + QSharedPointer m_pEvokedSetModel; /**< The evoked model */ + }; }//namespace diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 25a3cfcd015..8ff95bbb174 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -38,6 +38,8 @@ #include "timefrequencyview.h" +#include "helpers/evokedsetmodel.h" + //============================================================================================================= // QT INCLUDES //============================================================================================================= @@ -45,6 +47,8 @@ #include #include #include +#include +#include //============================================================================================================= // USED NAMESPACES @@ -70,7 +74,7 @@ TimeFrequencyView::TimeFrequencyView(const QString& sSettingsPath, : AbstractView(parent, f) { m_sSettingsPath = sSettingsPath; - initQMLView(); + //initQMLView(); } //============================================================================================================= @@ -135,9 +139,16 @@ void TimeFrequencyView::initQMLView() this->setLayout(layout); } -////============================================================================================================= +//============================================================================================================= + +void TimeFrequencyView::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + + painter.save(); + painter.setBrush(QBrush()); + painter.drawRect(QRect(-1,-1,this->width()+2,this->height()+2)); + painter.restore(); -//void TimeFrequencyView::paintEvent(QPaintEvent *event) -//{ -// return AbstractView::paintEvent(event); -//} + return AbstractView::paintEvent(event); +} diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index 1ce7688f5e2..c9170092d1a 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -59,6 +59,12 @@ namespace DISPLIB { +//============================================================================================================= +// DISPLIB FORWARD DECLARATIONS +//============================================================================================================= + +class EvokedSetModel; + //============================================================================================================= /** * @brief The TimeFrequencyView class @@ -112,7 +118,10 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView protected: void initQMLView(); -// virtual void paintEvent(QPaintEvent *event); + virtual void paintEvent(QPaintEvent *event); + + QSharedPointer m_pEvokedSetModel; /**< The evoked model */ + }; } //namespace diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 8a60d27b2a5..b8cd84f69ed 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -1,3 +1,37 @@ +//============================================================================================================= +/** + * @file timefrequency.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of TimeFrequency functions + * + */ + //============================================================================================================= // INCLUDES //============================================================================================================= @@ -7,10 +41,32 @@ #include #include -TimeFrequency::TimeFrequency() +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace RTPROCESSINGLIB; + + +//TimeFrequency::TimeFrequency() +//{ + +//} + +//============================================================================================================= +// DEFINE GLOBAL RTPROCESSINGLIB METHODS +//============================================================================================================= + +void computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { } -void computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); - diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index 4d054c03896..5c22541e693 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -1,3 +1,37 @@ +//============================================================================================================= +/** + * @file timefrequency.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of TimeFrequency functions + * + */ + #ifndef TIMEFREQUENCY_RTPROCESSING_H #define TIMEFREQUENCY_RTPROCESSING_H @@ -36,11 +70,11 @@ namespace FIFFLIB { namespace RTPROCESSINGLIB { -class TimeFrequency -{ -public: - TimeFrequency(); -}; +//class TimeFrequency +//{ +//public: +// TimeFrequency(); +//}; RTPROCESINGSHARED_EXPORT void computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); From 0bcacfabbc9c364f56c25e79d2b384bd0cc9f856 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 13 Apr 2021 16:28:15 -0400 Subject: [PATCH 14/57] MAINT: testing drawing by had with paintEvent function --- .../plugins/timefrequency/timefrequency.cpp | 7 ++++ .../plugins/timefrequency/timefrequency.h | 2 + libraries/disp/viewers/timefrequencyview.cpp | 42 ++++++++++++++++++- libraries/disp/viewers/timefrequencyview.h | 8 ++++ 4 files changed, 58 insertions(+), 1 deletion(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 3d309958707..1e772025f0d 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -46,6 +46,10 @@ #include #include #include +#include + +#include +#include //============================================================================================================= // USED NAMESPACES @@ -61,6 +65,7 @@ using namespace ANSHAREDLIB; TimeFrequency::TimeFrequency() : m_sSettingsPath("MNEANALYZE/TimeFrequency") { + m_pEvokedModel = QSharedPointer(new DISPLIB::EvokedSetModel()); loadSettings(); } @@ -184,6 +189,8 @@ void TimeFrequency::onModelChanged(QSharedPointer pN { if(pNewModel->getType() == MODEL_TYPE::ANSHAREDLIB_AVERAGING_MODEL) { m_pAvgModel = qSharedPointerCast(pNewModel); + m_pEvokedModel->setEvokedSet(m_pAvgModel->data(QModelIndex()).value>()); + m_pTimeFreqView->setEvokedSetModel(m_pEvokedModel); } } diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h index e38e3fa8c29..52f95c750bf 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.h +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -68,6 +68,7 @@ namespace DISPLIB { class ProgressView; class TimeFrequencyView; class TimeFrequencyLayoutView; + class EvokedSetModel; } //============================================================================================================= @@ -151,6 +152,7 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlu QPointer m_pTimeFreqView; QPointer m_pTimeFreqLayoutView; + QSharedPointer m_pEvokedModel; /**< Pointer to model used to display averaging data from m_pFiffEvokedSet and m_pFiffEvoked */ QSharedPointer m_pAvgModel; /**< Pointer to currently loaded FiffRawView Model */ }; diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 8ff95bbb174..b9c5d147996 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -143,6 +143,8 @@ void TimeFrequencyView::initQMLView() void TimeFrequencyView::paintEvent(QPaintEvent *event) { + if (m_pEvokedSetModel){ + QPainter painter(this); painter.save(); @@ -150,5 +152,43 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) painter.drawRect(QRect(-1,-1,this->width()+2,this->height()+2)); painter.restore(); - return AbstractView::paintEvent(event); + + + + //paint chart + + + + + //paint axis labels + + + //test + if(m_pEvokedSetModel->getNumSamples() > 0) { + painter.save(); + painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); + + float fDx = (float)(this->width()) / ((float)m_pEvokedSetModel->getNumSamples()); + float posX = fDx * ((float)m_pEvokedSetModel->getNumPreStimSamples()); + painter.drawLine(posX, 1, posX, this->height()); + + painter.drawText(QPointF(posX+5,this->rect().bottomRight().y()-5), QString("0ms / Stimulus")); + + + painter.restore(); + } + + } + + return QWidget::paintEvent(event); +} + +//============================================================================================================= + +void TimeFrequencyView::setEvokedSetModel(QSharedPointer model) +{ + m_pEvokedSetModel = model; + +// connect(m_pEvokedSetModel.data(), &EvokedSetModel::dataChanged, +// this, &ButterflyView::dataUpdate, Qt::UniqueConnection); } diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index c9170092d1a..bdf51f1748a 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -115,6 +115,14 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView */ void clearView(); + //========================================================================================================= + /** + * Set the evoked set model. + * + * @param [in] model The new evoked set model. + */ + void setEvokedSetModel(QSharedPointer model); + protected: void initQMLView(); From e0415cdb0026bae41ec8ec80bca46804ac0bbea5 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Wed, 14 Apr 2021 11:52:52 -0400 Subject: [PATCH 15/57] ENH: drawing tf chart --- .../viewers/helpers/timefrequencymodel.cpp | 19 ++++ .../disp/viewers/helpers/timefrequencymodel.h | 28 +++++- libraries/disp/viewers/timefrequencyview.cpp | 87 +++++++++++++++---- 3 files changed, 114 insertions(+), 20 deletions(-) diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index 4693f12f7be..b858c294d6f 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -32,8 +32,27 @@ * */ +//============================================================================================================= +// INCLUDES +//============================================================================================================= + #include "timefrequencymodel.h" +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + + TimeFrequencyModel::TimeFrequencyModel() { diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h index 8b3d928c814..6551bcb0339 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.h +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -35,6 +35,29 @@ #ifndef TIMEFREQUENCYMODEL_H #define TIMEFREQUENCYMODEL_H +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../../disp_global.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ class TimeFrequencyModel { @@ -44,6 +67,9 @@ class TimeFrequencyModel private: // QSharedPointer m_pChannelInfoModel; -}; + QLinearGradient m_Gradient; + +}; +}//namespace #endif // TIMEFREQUENCYMODEL_H diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index b9c5d147996..3ea0eeded7d 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -145,38 +145,87 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) { if (m_pEvokedSetModel){ - QPainter painter(this); + int chartBorders = 30; - painter.save(); - painter.setBrush(QBrush()); - painter.drawRect(QRect(-1,-1,this->width()+2,this->height()+2)); - painter.restore(); + QPainter painter(this); - - - - //paint chart + painter.save(); + painter.setBrush(QBrush()); + painter.drawRect(QRect(-1,-1,this->width()+2,this->height()+2)); + painter.restore(); - //paint axis labels + //paint chart + painter.save(); + painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); + QRect chartBound(chartBorders,chartBorders,this->width()-chartBorders * 4 ,this->height()- chartBorders * 2); + painter.drawRect(chartBound); + painter.restore(); + //paint gradient bar - //test - if(m_pEvokedSetModel->getNumSamples() > 0) { painter.save(); - painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); - float fDx = (float)(this->width()) / ((float)m_pEvokedSetModel->getNumSamples()); - float posX = fDx * ((float)m_pEvokedSetModel->getNumPreStimSamples()); - painter.drawLine(posX, 1, posX, this->height()); + QLinearGradient linGrad(this->width() - chartBorders * 1.5f, chartBound.topRight().y(), this->width() - chartBorders * 1.5f, chartBound.bottomRight().y()); + painter.save(); + painter.setBrush(linGrad); + painter.drawRect(chartBound.topRight().x() + chartBorders, chartBound.topRight().y(), chartBorders, chartBound.height()); - painter.drawText(QPointF(posX+5,this->rect().bottomRight().y()-5), QString("0ms / Stimulus")); + painter.restore(); - painter.restore(); - } + //paint axis labels + //test + if(m_pEvokedSetModel->getNumSamples() > 0) { + painter.save(); + painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); + + float fDx = (float)(chartBound.width()) / ((float)m_pEvokedSetModel->getNumSamples()); + float posX = fDx * ((float)m_pEvokedSetModel->getNumPreStimSamples()); + painter.drawLine(chartBound.bottomLeft().x()+posX, chartBound.bottomRight().y(), chartBound.bottomLeft().x() + posX, chartBound.topRight().y()); + + painter.drawText(QPointF(posX+chartBound.bottomLeft().x(),chartBound.bottomRight().y()-5), QString("0ms / Stimulus")); + + painter.restore(); + + painter.save(); + QColor colorTimeSpacer = Qt::black; + colorTimeSpacer.setAlphaF(0.5); + painter.setPen(QPen(colorTimeSpacer, 1, Qt::DashLine)); + + float yStart = chartBound.topLeft().y(); + float yEnd = chartBound.bottomRight().y(); + + float sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); + int counter = 1; + float timeDistanceMSec = 50.0; + float timeDistanceSamples = (timeDistanceMSec/1000.0)*m_pEvokedSetModel->getSamplingFrequency(); //time distance corresponding to sampling frequency + + //spacers before stim + while(sampleCounter-timeDistanceSamples>0) { + sampleCounter-=timeDistanceSamples; + float x = fDx*sampleCounter; + painter.drawLine(x, yStart, x, yEnd); + painter.drawText(QPointF(x+5,yEnd-5), QString("-%1ms").arg(timeDistanceMSec*counter)); + counter++; + } + + //spacers after stim + counter = 1; + sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); + while(sampleCounter+timeDistanceSamplesgetNumSamples()) { + sampleCounter+=timeDistanceSamples; + float x = fDx*sampleCounter; + painter.drawLine(x, yStart, x, yEnd); + painter.drawText(QPointF(x+5,yEnd-5), QString("%1ms").arg(timeDistanceMSec*counter)); + counter++; + } + + painter.restore(); + + } } From 46a62732c856cdcdc489b165973d679ed0c3acf9 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Thu, 15 Apr 2021 09:46:15 -0400 Subject: [PATCH 16/57] MAINT: separate draw functionality --- libraries/disp/viewers/timefrequencyview.cpp | 24 ++++++++++++++++---- libraries/disp/viewers/timefrequencyview.h | 6 +++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 3ea0eeded7d..4698379ff43 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -206,9 +206,9 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) //spacers before stim while(sampleCounter-timeDistanceSamples>0) { sampleCounter-=timeDistanceSamples; - float x = fDx*sampleCounter; + float x = chartBound.bottomLeft().x() + fDx*sampleCounter; painter.drawLine(x, yStart, x, yEnd); - painter.drawText(QPointF(x+5,yEnd-5), QString("-%1ms").arg(timeDistanceMSec*counter)); + painter.drawText(QPointF(x - chartBorders/3, yEnd + chartBorders/2), QString("-%1ms").arg(timeDistanceMSec*counter)); counter++; } @@ -217,9 +217,9 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); while(sampleCounter+timeDistanceSamplesgetNumSamples()) { sampleCounter+=timeDistanceSamples; - float x = fDx*sampleCounter; + float x = chartBound.bottomLeft().x() + fDx*sampleCounter; painter.drawLine(x, yStart, x, yEnd); - painter.drawText(QPointF(x+5,yEnd-5), QString("%1ms").arg(timeDistanceMSec*counter)); + painter.drawText(QPointF(x - chartBorders/3, yEnd + chartBorders/2), QString("%1ms").arg(timeDistanceMSec*counter)); counter++; } @@ -241,3 +241,19 @@ void TimeFrequencyView::setEvokedSetModel(QSharedPointer model) // connect(m_pEvokedSetModel.data(), &EvokedSetModel::dataChanged, // this, &ButterflyView::dataUpdate, Qt::UniqueConnection); } + +//============================================================================================================= + +void TimeFrequencyView::paintChart(QPainter& painter, + const QRect chartRect) +{ + +} + +//============================================================================================================= + +void TimeFrequencyView::paintAxes(QPainter& painter, + const QRect chartRect) +{ + +} diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index bdf51f1748a..3ef789bc19e 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -128,6 +128,12 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView virtual void paintEvent(QPaintEvent *event); + void paintChart(QPainter& painter, + const QRect chartRect); + + void paintAxes(QPainter& painter, + const QRect chartRect); + QSharedPointer m_pEvokedSetModel; /**< The evoked model */ }; From e3f1d526a11202e9a60e3f82bee2a02d29cd3633 Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Thu, 15 Apr 2021 12:52:58 -0400 Subject: [PATCH 17/57] ENH: class for creating color gradient --- libraries/disp/disp.pro | 2 + .../disp/viewers/helpers/colorgradient.cpp | 45 ++++++++++++++++ .../disp/viewers/helpers/colorgradient.h | 53 +++++++++++++++++++ libraries/disp/viewers/timefrequencyview.cpp | 34 ++++++------ libraries/disp/viewers/timefrequencyview.h | 19 +++++-- 5 files changed, 129 insertions(+), 24 deletions(-) create mode 100644 libraries/disp/viewers/helpers/colorgradient.cpp create mode 100644 libraries/disp/viewers/helpers/colorgradient.h diff --git a/libraries/disp/disp.pro b/libraries/disp/disp.pro index 9fa0ea79bb4..f0102b63f60 100644 --- a/libraries/disp/disp.pro +++ b/libraries/disp/disp.pro @@ -110,6 +110,7 @@ SOURCES += \ viewers/filterdesignview.cpp \ viewers/averagelayoutview.cpp \ viewers/fwdsettingsview.cpp \ + viewers/helpers/colorgradient.cpp \ viewers/helpers/scalecontrol.cpp \ viewers/helpers/timefrequencymodel.cpp \ viewers/helpers/timefrequencyscene.cpp \ @@ -174,6 +175,7 @@ HEADERS += \ viewers/filterdesignview.h \ viewers/averagelayoutview.h \ viewers/fwdsettingsview.h \ + viewers/helpers/colorgradient.h \ viewers/helpers/scalecontrol.h \ viewers/helpers/timefrequencymodel.h \ viewers/helpers/timefrequencyscene.h \ diff --git a/libraries/disp/viewers/helpers/colorgradient.cpp b/libraries/disp/viewers/helpers/colorgradient.cpp new file mode 100644 index 00000000000..29c91db0b75 --- /dev/null +++ b/libraries/disp/viewers/helpers/colorgradient.cpp @@ -0,0 +1,45 @@ +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "colorgradient.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +ColorGradient::ColorGradient() +{ + +} + +//============================================================================================================= + +void ColorGradient::getColor(int value, + int &r, + int &g, + int &b) +{ + if(!m_vecColors.size()){ + return; + } + + for (int i = 0; i< m_vecColors.size(); i++){ + ColorPoint& currentColor = m_vecColors[i]; + if(value < currentColor.val){ + ColorPoint& prevColor = m_vecColors[std::max(0, i - 1)]; + } + } +} diff --git a/libraries/disp/viewers/helpers/colorgradient.h b/libraries/disp/viewers/helpers/colorgradient.h new file mode 100644 index 00000000000..0c0c47c64ad --- /dev/null +++ b/libraries/disp/viewers/helpers/colorgradient.h @@ -0,0 +1,53 @@ +#ifndef COLORGRADIENT_H +#define COLORGRADIENT_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../../disp_global.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +class ColorGradient +{ +public: + ColorGradient(); + + void getColor(int value, + int& r, + int& g, + int& b); + +private: + struct ColorPoint + { + ColorPoint(int red, + int green, + int blue): r(red), g(green), b(blue) {} + int r; + int g; + int b; + int val; + }; + + std::vector m_vecColors; +}; +}//namespace + +#endif // COLORGRADIENT_H diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 4698379ff43..6432651e167 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -44,8 +44,6 @@ // QT INCLUDES //============================================================================================================= -#include -#include #include #include #include @@ -72,6 +70,7 @@ TimeFrequencyView::TimeFrequencyView(const QString& sSettingsPath, QWidget *parent, Qt::WindowFlags f) : AbstractView(parent, f) +, m_iChartBorderSpacing(30) { m_sSettingsPath = sSettingsPath; //initQMLView(); @@ -127,16 +126,16 @@ void TimeFrequencyView::clearView() void TimeFrequencyView::initQMLView() { - QUrl source = QUrl::fromLocalFile("../libraries/disp/viewers/qml/tfview.qml"); - QQuickWidget* widget = new QQuickWidget(); - widget->setSource(source); - widget->setResizeMode(QQuickWidget::SizeRootObjectToView); +// QUrl source = QUrl::fromLocalFile("../libraries/disp/viewers/qml/tfview.qml"); +// QQuickWidget* widget = new QQuickWidget(); +// widget->setSource(source); +// widget->setResizeMode(QQuickWidget::SizeRootObjectToView); - QVBoxLayout* layout = new QVBoxLayout(); - layout->addWidget(widget); +// QVBoxLayout* layout = new QVBoxLayout(); +// layout->addWidget(widget); - this->setLayout(layout); +// this->setLayout(layout); } //============================================================================================================= @@ -144,9 +143,6 @@ void TimeFrequencyView::initQMLView() void TimeFrequencyView::paintEvent(QPaintEvent *event) { if (m_pEvokedSetModel){ - - int chartBorders = 30; - QPainter painter(this); painter.save(); @@ -160,7 +156,7 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) //paint chart painter.save(); painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); - QRect chartBound(chartBorders,chartBorders,this->width()-chartBorders * 4 ,this->height()- chartBorders * 2); + QRect chartBound(m_iChartBorderSpacing,m_iChartBorderSpacing,this->width()-m_iChartBorderSpacing * 4 ,this->height()- m_iChartBorderSpacing * 2); painter.drawRect(chartBound); painter.restore(); @@ -168,10 +164,10 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) painter.save(); - QLinearGradient linGrad(this->width() - chartBorders * 1.5f, chartBound.topRight().y(), this->width() - chartBorders * 1.5f, chartBound.bottomRight().y()); + QLinearGradient linGrad(this->width() - m_iChartBorderSpacing * 1.5f, chartBound.topRight().y(), this->width() - m_iChartBorderSpacing * 1.5f, chartBound.bottomRight().y()); painter.save(); painter.setBrush(linGrad); - painter.drawRect(chartBound.topRight().x() + chartBorders, chartBound.topRight().y(), chartBorders, chartBound.height()); + painter.drawRect(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); painter.restore(); @@ -208,7 +204,7 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) sampleCounter-=timeDistanceSamples; float x = chartBound.bottomLeft().x() + fDx*sampleCounter; painter.drawLine(x, yStart, x, yEnd); - painter.drawText(QPointF(x - chartBorders/3, yEnd + chartBorders/2), QString("-%1ms").arg(timeDistanceMSec*counter)); + painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("-%1ms").arg(timeDistanceMSec*counter)); counter++; } @@ -219,7 +215,7 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) sampleCounter+=timeDistanceSamples; float x = chartBound.bottomLeft().x() + fDx*sampleCounter; painter.drawLine(x, yStart, x, yEnd); - painter.drawText(QPointF(x - chartBorders/3, yEnd + chartBorders/2), QString("%1ms").arg(timeDistanceMSec*counter)); + painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("%1ms").arg(timeDistanceMSec*counter)); counter++; } @@ -245,7 +241,7 @@ void TimeFrequencyView::setEvokedSetModel(QSharedPointer model) //============================================================================================================= void TimeFrequencyView::paintChart(QPainter& painter, - const QRect chartRect) + const QRect chartBound) { } @@ -253,7 +249,7 @@ void TimeFrequencyView::paintChart(QPainter& painter, //============================================================================================================= void TimeFrequencyView::paintAxes(QPainter& painter, - const QRect chartRect) + const QRect chartBound) { } diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index 3ef789bc19e..7d5378a3649 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -85,7 +85,7 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView /** * Update the views GUI based on the set GuiMode (Clinical=0, Research=1). * - * @param mode The new mode (Clinical=0, Research=1). + * @param[in] mode The new mode (Clinical=0, Research=1). */ void updateGuiMode(GuiMode mode); @@ -93,7 +93,7 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView /** * Update the views GUI based on the set ProcessingMode (RealTime=0, Offline=1). * - * @param mode The new mode (RealTime=0, Offline=1). + * @param[in] mode The new mode (RealTime=0, Offline=1). */ void updateProcessingMode(ProcessingMode mode); @@ -119,22 +119,31 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView /** * Set the evoked set model. * - * @param [in] model The new evoked set model. + * @param[in] model The new evoked set model. */ void setEvokedSetModel(QSharedPointer model); + //========================================================================================================= + /** + * Sets spacing for time frequency chart + * + * @param[in] iSpacing Spacing value in pixels + */ + void setChartBorderSpacing(int iSpacing); + protected: void initQMLView(); virtual void paintEvent(QPaintEvent *event); void paintChart(QPainter& painter, - const QRect chartRect); + const QRect chartBound); void paintAxes(QPainter& painter, - const QRect chartRect); + const QRect chartBound); QSharedPointer m_pEvokedSetModel; /**< The evoked model */ + int m_iChartBorderSpacing; }; From b3c1572517239ef5abc4aaaebd5b6c087d59fc37 Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Thu, 15 Apr 2021 17:29:05 -0400 Subject: [PATCH 18/57] ENH: color library --- libraries/disp/disp.pro | 4 +- .../disp/viewers/helpers/colorgradient.cpp | 45 ------- .../disp/viewers/helpers/colorgradient.h | 53 -------- libraries/disp/viewers/helpers/colorlib.cpp | 89 ++++++++++++ libraries/disp/viewers/helpers/colorlib.h | 127 ++++++++++++++++++ 5 files changed, 218 insertions(+), 100 deletions(-) delete mode 100644 libraries/disp/viewers/helpers/colorgradient.cpp delete mode 100644 libraries/disp/viewers/helpers/colorgradient.h create mode 100644 libraries/disp/viewers/helpers/colorlib.cpp create mode 100644 libraries/disp/viewers/helpers/colorlib.h diff --git a/libraries/disp/disp.pro b/libraries/disp/disp.pro index f0102b63f60..db68e5bc2ec 100644 --- a/libraries/disp/disp.pro +++ b/libraries/disp/disp.pro @@ -110,7 +110,7 @@ SOURCES += \ viewers/filterdesignview.cpp \ viewers/averagelayoutview.cpp \ viewers/fwdsettingsview.cpp \ - viewers/helpers/colorgradient.cpp \ + viewers/helpers/colorlib.cpp \ viewers/helpers/scalecontrol.cpp \ viewers/helpers/timefrequencymodel.cpp \ viewers/helpers/timefrequencyscene.cpp \ @@ -175,7 +175,7 @@ HEADERS += \ viewers/filterdesignview.h \ viewers/averagelayoutview.h \ viewers/fwdsettingsview.h \ - viewers/helpers/colorgradient.h \ + viewers/helpers/colorlib.h \ viewers/helpers/scalecontrol.h \ viewers/helpers/timefrequencymodel.h \ viewers/helpers/timefrequencyscene.h \ diff --git a/libraries/disp/viewers/helpers/colorgradient.cpp b/libraries/disp/viewers/helpers/colorgradient.cpp deleted file mode 100644 index 29c91db0b75..00000000000 --- a/libraries/disp/viewers/helpers/colorgradient.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//============================================================================================================= -// INCLUDES -//============================================================================================================= - -#include "colorgradient.h" - -#include - -//============================================================================================================= -// QT INCLUDES -//============================================================================================================= - -//============================================================================================================= -// USED NAMESPACES -//============================================================================================================= - -using namespace DISPLIB; - -//============================================================================================================= -// DEFINE MEMBER METHODS -//============================================================================================================= - -ColorGradient::ColorGradient() -{ - -} - -//============================================================================================================= - -void ColorGradient::getColor(int value, - int &r, - int &g, - int &b) -{ - if(!m_vecColors.size()){ - return; - } - - for (int i = 0; i< m_vecColors.size(); i++){ - ColorPoint& currentColor = m_vecColors[i]; - if(value < currentColor.val){ - ColorPoint& prevColor = m_vecColors[std::max(0, i - 1)]; - } - } -} diff --git a/libraries/disp/viewers/helpers/colorgradient.h b/libraries/disp/viewers/helpers/colorgradient.h deleted file mode 100644 index 0c0c47c64ad..00000000000 --- a/libraries/disp/viewers/helpers/colorgradient.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef COLORGRADIENT_H -#define COLORGRADIENT_H - -//============================================================================================================= -// INCLUDES -//============================================================================================================= - -#include "../../disp_global.h" - -#include - -//============================================================================================================= -// QT INCLUDES -//============================================================================================================= - -//============================================================================================================= -// EIGEN INCLUDES -//============================================================================================================= - -//============================================================================================================= -// DEFINE NAMESPACE DISPLIB -//============================================================================================================= - -namespace DISPLIB -{ - -class ColorGradient -{ -public: - ColorGradient(); - - void getColor(int value, - int& r, - int& g, - int& b); - -private: - struct ColorPoint - { - ColorPoint(int red, - int green, - int blue): r(red), g(green), b(blue) {} - int r; - int g; - int b; - int val; - }; - - std::vector m_vecColors; -}; -}//namespace - -#endif // COLORGRADIENT_H diff --git a/libraries/disp/viewers/helpers/colorlib.cpp b/libraries/disp/viewers/helpers/colorlib.cpp new file mode 100644 index 00000000000..33579213c12 --- /dev/null +++ b/libraries/disp/viewers/helpers/colorlib.cpp @@ -0,0 +1,89 @@ +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "colorlib.h" + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE STATIC METHODS +//============================================================================================================= + +ColorMap ColorMap::fromGradient(const ColorGradient &gradient, + int resolution) +{ + ColorMap map; + map.m_iResolution = resolution; + + for (int i = 0 ; i < resolution; i++){ + float value = static_cast(i) / static_cast(resolution); + map.m_vColors.push_back(gradient.getColor(value)); + } + + return map; +} + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +ColorGradient::ColorGradient(std::initializer_list list) +{ + for (ColorPoint color : list){ + m_vecColors.push_back(color); + } +} + +//============================================================================================================= + +Color ColorGradient::getColor(float value) const +{ + if(!m_vecColors.size()){ + return Color(0,0,0); + } + + Color color(0,0,0); + + for (int i = 0; i< m_vecColors.size(); i++){ + const ColorPoint& currentColor = m_vecColors[i]; + if(value < currentColor.val){ + int index = ((i-1) > 0) ? i-1 : 0; + const ColorPoint& prevColor = m_vecColors[index]; + + float fDifference = currentColor.val - prevColor.val; + float fRatio = (fDifference) ? ((value - currentColor.val)/fDifference) : 0; + + color.r = (fRatio * (currentColor.r() - prevColor.r())) + currentColor.r(); + color.g = (fRatio * (currentColor.g() - prevColor.g())) + currentColor.g(); + color.b = (fRatio * (currentColor.b() - prevColor.b())) + currentColor.b(); + + return color; + } + } + return color; +} + +//============================================================================================================= + +#ifdef QT_CORE_LIB +QLinearGradient ColorGradient::getQGradient(QPoint from, QPoint to) const +{ + QLinearGradient gradient(from, to); + for(const ColorPoint& color : m_vecColors){ + gradient.setColorAt(color.val, color.getQColor()); + } + + return gradient; +} +#endif diff --git a/libraries/disp/viewers/helpers/colorlib.h b/libraries/disp/viewers/helpers/colorlib.h new file mode 100644 index 00000000000..f898e64b8d1 --- /dev/null +++ b/libraries/disp/viewers/helpers/colorlib.h @@ -0,0 +1,127 @@ +#ifndef COLORLIB_H +#define COLORLIB_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../../disp_global.h" + +#include +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#ifdef QT_CORE_LIB +#include +#include +#endif + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +struct Color; +struct ColorPoint; +class ColorMap; +class ColorGradient; + + +//============================================================================================================= +/** + * Holds data on an RBG Color + */ +struct Color{ + float r; + float g; + float b; + Color() : Color(0,0,0) {} + Color(float red, + float green, + float blue) : r(red), g(green), b(blue) {} +#ifdef QT_CORE_LIB + QColor getQColor() const {return QColor(r, g, b);} +#endif +}; + +//============================================================================================================= +/** + * Holds data on an RGB Color associated with a value between 0-1 + */ +struct ColorPoint +{ + ColorPoint(float red, + float green, + float blue, + float value): m_color(red, green, blue), val(value) {} + ColorPoint(Color color, + int value): m_color(color), val(value) {} + Color m_color; + float val; + float r() const {return m_color.r;} + float g() const {return m_color.g;} + float b() const {return m_color.b;} +#ifdef QT_CORE_LIB + QColor getQColor() const {return m_color.getQColor();} +#endif +}; + +//============================================================================================================= +/** + * Holds a colormap + */ +class ColorMap +{ +public: + uint size() const {return m_vColors.size();} + + int resolution() const {return m_iResolution;} + + static ColorMap fromGradient(const ColorGradient& gradient, + int resolution = 256); +private: + ColorMap(); + + int m_iResolution; + std::vector m_vColors; +}; + +//============================================================================================================= +/** + * A Gradient between multiple colors + */ +class ColorGradient +{ +public: + ColorGradient() = delete; + ColorGradient(std::initializer_list list); + + Color getColor(float value) const; + +#ifdef QT_CORE_LIB + QLinearGradient getQGradient(QPoint from, QPoint to) const; +#endif + ColorMap getColorMap(); + +private: + + std::vector m_vecColors; +}; + + +}//namespace + +#endif // COLORGRADIENT_H From d311df71f25f99e1485cbc454d9834367468a09b Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Fri, 16 Apr 2021 09:30:03 -0400 Subject: [PATCH 19/57] MAINT: remove qml files --- libraries/disp/disp.pro | 10 - libraries/disp/viewers/qml/Data.qml | 1571 ---------------------- libraries/disp/viewers/qml/NewButton.qml | 63 - libraries/disp/viewers/qml/tfview.qml | 271 ---- 4 files changed, 1915 deletions(-) delete mode 100644 libraries/disp/viewers/qml/Data.qml delete mode 100644 libraries/disp/viewers/qml/NewButton.qml delete mode 100644 libraries/disp/viewers/qml/tfview.qml diff --git a/libraries/disp/disp.pro b/libraries/disp/disp.pro index db68e5bc2ec..43e1f128b17 100644 --- a/libraries/disp/disp.pro +++ b/libraries/disp/disp.pro @@ -262,16 +262,6 @@ FORMS += \ viewers/formfiles/applytoview.ui \ viewers/formfiles/bidsview.ui \ -qtHaveModule(datavisualization) { - -DEFINES += QML_VIEWS_ON - -DISTFILES += \ - viewers/qml/tfview.qml \ - viewers/qml/Data.qml \ - viewers/qml/NewButton.qml \ -} - INCLUDEPATH += $${EIGEN_INCLUDE_DIR} INCLUDEPATH += $${MNE_INCLUDE_DIR} diff --git a/libraries/disp/viewers/qml/Data.qml b/libraries/disp/viewers/qml/Data.qml deleted file mode 100644 index ed9913b36ae..00000000000 --- a/libraries/disp/viewers/qml/Data.qml +++ /dev/null @@ -1,1571 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 or (at your option) any later version -** approved by the KDE Free Qt Foundation. The licenses are as published by -** the Free Software Foundation and appearing in the file LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.1 - -Item { - property alias model: dataModel - - ListModel { - id: dataModel - ListElement{ radius: "0"; angle: "0"; value: "50"; } - ListElement{ radius: "0"; angle: "5"; value: "54.3578"; } - ListElement{ radius: "0"; angle: "10"; value: "58.6824"; } - ListElement{ radius: "0"; angle: "15"; value: "62.941"; } - ListElement{ radius: "0"; angle: "20"; value: "67.101"; } - ListElement{ radius: "0"; angle: "25"; value: "71.1309"; } - ListElement{ radius: "0"; angle: "30"; value: "75"; } - ListElement{ radius: "0"; angle: "35"; value: "78.6788"; } - ListElement{ radius: "0"; angle: "40"; value: "82.1394"; } - ListElement{ radius: "0"; angle: "45"; value: "85.3553"; } - ListElement{ radius: "0"; angle: "50"; value: "88.3022"; } - ListElement{ radius: "0"; angle: "55"; value: "90.9576"; } - ListElement{ radius: "0"; angle: "60"; value: "93.3013"; } - ListElement{ radius: "0"; angle: "65"; value: "95.3154"; } - ListElement{ radius: "0"; angle: "70"; value: "96.9846"; } - ListElement{ radius: "0"; angle: "75"; value: "98.2963"; } - ListElement{ radius: "0"; angle: "80"; value: "99.2404"; } - ListElement{ radius: "0"; angle: "85"; value: "99.8097"; } - ListElement{ radius: "0"; angle: "90"; value: "100"; } - ListElement{ radius: "0"; angle: "95"; value: "99.8097"; } - ListElement{ radius: "0"; angle: "100"; value: "99.2404"; } - ListElement{ radius: "0"; angle: "105"; value: "98.2963"; } - ListElement{ radius: "0"; angle: "110"; value: "96.9846"; } - ListElement{ radius: "0"; angle: "115"; value: "95.3154"; } - ListElement{ radius: "0"; angle: "120"; value: "93.3013"; } - ListElement{ radius: "0"; angle: "125"; value: "90.9576"; } - ListElement{ radius: "0"; angle: "130"; value: "88.3022"; } - ListElement{ radius: "0"; angle: "135"; value: "85.3553"; } - ListElement{ radius: "0"; angle: "140"; value: "82.1394"; } - ListElement{ radius: "0"; angle: "145"; value: "78.6788"; } - ListElement{ radius: "0"; angle: "150"; value: "75"; } - ListElement{ radius: "0"; angle: "155"; value: "71.1309"; } - ListElement{ radius: "0"; angle: "160"; value: "67.101"; } - ListElement{ radius: "0"; angle: "165"; value: "62.941"; } - ListElement{ radius: "0"; angle: "170"; value: "58.6824"; } - ListElement{ radius: "0"; angle: "175"; value: "54.3578"; } - ListElement{ radius: "0"; angle: "180"; value: "50"; } - ListElement{ radius: "0"; angle: "185"; value: "45.6422"; } - ListElement{ radius: "0"; angle: "190"; value: "41.3176"; } - ListElement{ radius: "0"; angle: "195"; value: "37.059"; } - ListElement{ radius: "0"; angle: "200"; value: "32.899"; } - ListElement{ radius: "0"; angle: "205"; value: "28.8691"; } - ListElement{ radius: "0"; angle: "210"; value: "25"; } - ListElement{ radius: "0"; angle: "215"; value: "21.3212"; } - ListElement{ radius: "0"; angle: "220"; value: "17.8606"; } - ListElement{ radius: "0"; angle: "225"; value: "14.6447"; } - ListElement{ radius: "0"; angle: "230"; value: "11.6978"; } - ListElement{ radius: "0"; angle: "235"; value: "9.0424"; } - ListElement{ radius: "0"; angle: "240"; value: "6.69873"; } - ListElement{ radius: "0"; angle: "245"; value: "4.68461"; } - ListElement{ radius: "0"; angle: "250"; value: "3.01537"; } - ListElement{ radius: "0"; angle: "255"; value: "1.70371"; } - ListElement{ radius: "0"; angle: "260"; value: "0.759612"; } - ListElement{ radius: "0"; angle: "265"; value: "0.190265"; } - ListElement{ radius: "0"; angle: "270"; value: "0"; } - ListElement{ radius: "0"; angle: "275"; value: "0.190265"; } - ListElement{ radius: "0"; angle: "280"; value: "0.759612"; } - ListElement{ radius: "0"; angle: "285"; value: "1.70371"; } - ListElement{ radius: "0"; angle: "290"; value: "3.01537"; } - ListElement{ radius: "0"; angle: "295"; value: "4.68461"; } - ListElement{ radius: "0"; angle: "300"; value: "6.69873"; } - ListElement{ radius: "0"; angle: "305"; value: "9.0424"; } - ListElement{ radius: "0"; angle: "310"; value: "11.6978"; } - ListElement{ radius: "0"; angle: "315"; value: "14.6447"; } - ListElement{ radius: "0"; angle: "320"; value: "17.8606"; } - ListElement{ radius: "0"; angle: "325"; value: "21.3212"; } - ListElement{ radius: "0"; angle: "330"; value: "25"; } - ListElement{ radius: "0"; angle: "335"; value: "28.8691"; } - ListElement{ radius: "0"; angle: "340"; value: "32.899"; } - ListElement{ radius: "0"; angle: "345"; value: "37.059"; } - ListElement{ radius: "0"; angle: "350"; value: "41.3176"; } - ListElement{ radius: "0"; angle: "355"; value: "45.6422"; } - ListElement{ radius: "0"; angle: "360"; value: "50"; } - ListElement{ radius: "5"; angle: "0"; value: "49.3844"; } - ListElement{ radius: "5"; angle: "5"; value: "53.7422"; } - ListElement{ radius: "5"; angle: "10"; value: "58.0668"; } - ListElement{ radius: "5"; angle: "15"; value: "62.3254"; } - ListElement{ radius: "5"; angle: "20"; value: "66.4854"; } - ListElement{ radius: "5"; angle: "25"; value: "70.5153"; } - ListElement{ radius: "5"; angle: "30"; value: "74.3844"; } - ListElement{ radius: "5"; angle: "35"; value: "78.0632"; } - ListElement{ radius: "5"; angle: "40"; value: "81.5238"; } - ListElement{ radius: "5"; angle: "45"; value: "84.7398"; } - ListElement{ radius: "5"; angle: "50"; value: "87.6866"; } - ListElement{ radius: "5"; angle: "55"; value: "90.342"; } - ListElement{ radius: "5"; angle: "60"; value: "92.6857"; } - ListElement{ radius: "5"; angle: "65"; value: "94.6998"; } - ListElement{ radius: "5"; angle: "70"; value: "96.369"; } - ListElement{ radius: "5"; angle: "75"; value: "97.6807"; } - ListElement{ radius: "5"; angle: "80"; value: "98.6248"; } - ListElement{ radius: "5"; angle: "85"; value: "99.1942"; } - ListElement{ radius: "5"; angle: "90"; value: "99.3844"; } - ListElement{ radius: "5"; angle: "95"; value: "99.1942"; } - ListElement{ radius: "5"; angle: "100"; value: "98.6248"; } - ListElement{ radius: "5"; angle: "105"; value: "97.6807"; } - ListElement{ radius: "5"; angle: "110"; value: "96.369"; } - ListElement{ radius: "5"; angle: "115"; value: "94.6998"; } - ListElement{ radius: "5"; angle: "120"; value: "92.6857"; } - ListElement{ radius: "5"; angle: "125"; value: "90.342"; } - ListElement{ radius: "5"; angle: "130"; value: "87.6866"; } - ListElement{ radius: "5"; angle: "135"; value: "84.7398"; } - ListElement{ radius: "5"; angle: "140"; value: "81.5238"; } - ListElement{ radius: "5"; angle: "145"; value: "78.0632"; } - ListElement{ radius: "5"; angle: "150"; value: "74.3844"; } - ListElement{ radius: "5"; angle: "155"; value: "70.5153"; } - ListElement{ radius: "5"; angle: "160"; value: "66.4854"; } - ListElement{ radius: "5"; angle: "165"; value: "62.3254"; } - ListElement{ radius: "5"; angle: "170"; value: "58.0668"; } - ListElement{ radius: "5"; angle: "175"; value: "53.7422"; } - ListElement{ radius: "5"; angle: "180"; value: "49.3844"; } - ListElement{ radius: "5"; angle: "185"; value: "45.0266"; } - ListElement{ radius: "5"; angle: "190"; value: "40.702"; } - ListElement{ radius: "5"; angle: "195"; value: "36.4435"; } - ListElement{ radius: "5"; angle: "200"; value: "32.2834"; } - ListElement{ radius: "5"; angle: "205"; value: "28.2535"; } - ListElement{ radius: "5"; angle: "210"; value: "24.3844"; } - ListElement{ radius: "5"; angle: "215"; value: "20.7056"; } - ListElement{ radius: "5"; angle: "220"; value: "17.245"; } - ListElement{ radius: "5"; angle: "225"; value: "14.0291"; } - ListElement{ radius: "5"; angle: "230"; value: "11.0822"; } - ListElement{ radius: "5"; angle: "235"; value: "8.42681"; } - ListElement{ radius: "5"; angle: "240"; value: "6.08315"; } - ListElement{ radius: "5"; angle: "245"; value: "4.06903"; } - ListElement{ radius: "5"; angle: "250"; value: "2.39979"; } - ListElement{ radius: "5"; angle: "255"; value: "1.08813"; } - ListElement{ radius: "5"; angle: "260"; value: "0.144029"; } - ListElement{ radius: "5"; angle: "265"; value: "-0.425318"; } - ListElement{ radius: "5"; angle: "270"; value: "-0.615583"; } - ListElement{ radius: "5"; angle: "275"; value: "-0.425318"; } - ListElement{ radius: "5"; angle: "280"; value: "0.144029"; } - ListElement{ radius: "5"; angle: "285"; value: "1.08813"; } - ListElement{ radius: "5"; angle: "290"; value: "2.39979"; } - ListElement{ radius: "5"; angle: "295"; value: "4.06903"; } - ListElement{ radius: "5"; angle: "300"; value: "6.08315"; } - ListElement{ radius: "5"; angle: "305"; value: "8.42681"; } - ListElement{ radius: "5"; angle: "310"; value: "11.0822"; } - ListElement{ radius: "5"; angle: "315"; value: "14.0291"; } - ListElement{ radius: "5"; angle: "320"; value: "17.245"; } - ListElement{ radius: "5"; angle: "325"; value: "20.7056"; } - ListElement{ radius: "5"; angle: "330"; value: "24.3844"; } - ListElement{ radius: "5"; angle: "335"; value: "28.2535"; } - ListElement{ radius: "5"; angle: "340"; value: "32.2834"; } - ListElement{ radius: "5"; angle: "345"; value: "36.4435"; } - ListElement{ radius: "5"; angle: "350"; value: "40.702"; } - ListElement{ radius: "5"; angle: "355"; value: "45.0266"; } - ListElement{ radius: "5"; angle: "360"; value: "49.3844"; } - ListElement{ radius: "10"; angle: "0"; value: "47.5528"; } - ListElement{ radius: "10"; angle: "5"; value: "51.9106"; } - ListElement{ radius: "10"; angle: "10"; value: "56.2352"; } - ListElement{ radius: "10"; angle: "15"; value: "60.4938"; } - ListElement{ radius: "10"; angle: "20"; value: "64.6538"; } - ListElement{ radius: "10"; angle: "25"; value: "68.6837"; } - ListElement{ radius: "10"; angle: "30"; value: "72.5528"; } - ListElement{ radius: "10"; angle: "35"; value: "76.2316"; } - ListElement{ radius: "10"; angle: "40"; value: "79.6922"; } - ListElement{ radius: "10"; angle: "45"; value: "82.9082"; } - ListElement{ radius: "10"; angle: "50"; value: "85.855"; } - ListElement{ radius: "10"; angle: "55"; value: "88.5104"; } - ListElement{ radius: "10"; angle: "60"; value: "90.8541"; } - ListElement{ radius: "10"; angle: "65"; value: "92.8682"; } - ListElement{ radius: "10"; angle: "70"; value: "94.5375"; } - ListElement{ radius: "10"; angle: "75"; value: "95.8491"; } - ListElement{ radius: "10"; angle: "80"; value: "96.7932"; } - ListElement{ radius: "10"; angle: "85"; value: "97.3626"; } - ListElement{ radius: "10"; angle: "90"; value: "97.5528"; } - ListElement{ radius: "10"; angle: "95"; value: "97.3626"; } - ListElement{ radius: "10"; angle: "100"; value: "96.7932"; } - ListElement{ radius: "10"; angle: "105"; value: "95.8491"; } - ListElement{ radius: "10"; angle: "110"; value: "94.5375"; } - ListElement{ radius: "10"; angle: "115"; value: "92.8682"; } - ListElement{ radius: "10"; angle: "120"; value: "90.8541"; } - ListElement{ radius: "10"; angle: "125"; value: "88.5104"; } - ListElement{ radius: "10"; angle: "130"; value: "85.855"; } - ListElement{ radius: "10"; angle: "135"; value: "82.9082"; } - ListElement{ radius: "10"; angle: "140"; value: "79.6922"; } - ListElement{ radius: "10"; angle: "145"; value: "76.2316"; } - ListElement{ radius: "10"; angle: "150"; value: "72.5528"; } - ListElement{ radius: "10"; angle: "155"; value: "68.6837"; } - ListElement{ radius: "10"; angle: "160"; value: "64.6538"; } - ListElement{ radius: "10"; angle: "165"; value: "60.4938"; } - ListElement{ radius: "10"; angle: "170"; value: "56.2352"; } - ListElement{ radius: "10"; angle: "175"; value: "51.9106"; } - ListElement{ radius: "10"; angle: "180"; value: "47.5528"; } - ListElement{ radius: "10"; angle: "185"; value: "43.195"; } - ListElement{ radius: "10"; angle: "190"; value: "38.8704"; } - ListElement{ radius: "10"; angle: "195"; value: "34.6119"; } - ListElement{ radius: "10"; angle: "200"; value: "30.4518"; } - ListElement{ radius: "10"; angle: "205"; value: "26.4219"; } - ListElement{ radius: "10"; angle: "210"; value: "22.5528"; } - ListElement{ radius: "10"; angle: "215"; value: "18.874"; } - ListElement{ radius: "10"; angle: "220"; value: "15.4134"; } - ListElement{ radius: "10"; angle: "225"; value: "12.1975"; } - ListElement{ radius: "10"; angle: "230"; value: "9.2506"; } - ListElement{ radius: "10"; angle: "235"; value: "6.59522"; } - ListElement{ radius: "10"; angle: "240"; value: "4.25156"; } - ListElement{ radius: "10"; angle: "245"; value: "2.23744"; } - ListElement{ radius: "10"; angle: "250"; value: "0.568195"; } - ListElement{ radius: "10"; angle: "255"; value: "-0.743465"; } - ListElement{ radius: "10"; angle: "260"; value: "-1.68756"; } - ListElement{ radius: "10"; angle: "265"; value: "-2.25691"; } - ListElement{ radius: "10"; angle: "270"; value: "-2.44717"; } - ListElement{ radius: "10"; angle: "275"; value: "-2.25691"; } - ListElement{ radius: "10"; angle: "280"; value: "-1.68756"; } - ListElement{ radius: "10"; angle: "285"; value: "-0.743465"; } - ListElement{ radius: "10"; angle: "290"; value: "0.568195"; } - ListElement{ radius: "10"; angle: "295"; value: "2.23744"; } - ListElement{ radius: "10"; angle: "300"; value: "4.25156"; } - ListElement{ radius: "10"; angle: "305"; value: "6.59522"; } - ListElement{ radius: "10"; angle: "310"; value: "9.2506"; } - ListElement{ radius: "10"; angle: "315"; value: "12.1975"; } - ListElement{ radius: "10"; angle: "320"; value: "15.4134"; } - ListElement{ radius: "10"; angle: "325"; value: "18.874"; } - ListElement{ radius: "10"; angle: "330"; value: "22.5528"; } - ListElement{ radius: "10"; angle: "335"; value: "26.4219"; } - ListElement{ radius: "10"; angle: "340"; value: "30.4518"; } - ListElement{ radius: "10"; angle: "345"; value: "34.6119"; } - ListElement{ radius: "10"; angle: "350"; value: "38.8704"; } - ListElement{ radius: "10"; angle: "355"; value: "43.195"; } - ListElement{ radius: "10"; angle: "360"; value: "47.5528"; } - ListElement{ radius: "15"; angle: "0"; value: "44.5503"; } - ListElement{ radius: "15"; angle: "5"; value: "48.9081"; } - ListElement{ radius: "15"; angle: "10"; value: "53.2327"; } - ListElement{ radius: "15"; angle: "15"; value: "57.4913"; } - ListElement{ radius: "15"; angle: "20"; value: "61.6513"; } - ListElement{ radius: "15"; angle: "25"; value: "65.6812"; } - ListElement{ radius: "15"; angle: "30"; value: "69.5503"; } - ListElement{ radius: "15"; angle: "35"; value: "73.2291"; } - ListElement{ radius: "15"; angle: "40"; value: "76.6897"; } - ListElement{ radius: "15"; angle: "45"; value: "79.9057"; } - ListElement{ radius: "15"; angle: "50"; value: "82.8525"; } - ListElement{ radius: "15"; angle: "55"; value: "85.5079"; } - ListElement{ radius: "15"; angle: "60"; value: "87.8516"; } - ListElement{ radius: "15"; angle: "65"; value: "89.8657"; } - ListElement{ radius: "15"; angle: "70"; value: "91.535"; } - ListElement{ radius: "15"; angle: "75"; value: "92.8466"; } - ListElement{ radius: "15"; angle: "80"; value: "93.7907"; } - ListElement{ radius: "15"; angle: "85"; value: "94.3601"; } - ListElement{ radius: "15"; angle: "90"; value: "94.5503"; } - ListElement{ radius: "15"; angle: "95"; value: "94.3601"; } - ListElement{ radius: "15"; angle: "100"; value: "93.7907"; } - ListElement{ radius: "15"; angle: "105"; value: "92.8466"; } - ListElement{ radius: "15"; angle: "110"; value: "91.535"; } - ListElement{ radius: "15"; angle: "115"; value: "89.8657"; } - ListElement{ radius: "15"; angle: "120"; value: "87.8516"; } - ListElement{ radius: "15"; angle: "125"; value: "85.5079"; } - ListElement{ radius: "15"; angle: "130"; value: "82.8525"; } - ListElement{ radius: "15"; angle: "135"; value: "79.9057"; } - ListElement{ radius: "15"; angle: "140"; value: "76.6897"; } - ListElement{ radius: "15"; angle: "145"; value: "73.2291"; } - ListElement{ radius: "15"; angle: "150"; value: "69.5503"; } - ListElement{ radius: "15"; angle: "155"; value: "65.6812"; } - ListElement{ radius: "15"; angle: "160"; value: "61.6513"; } - ListElement{ radius: "15"; angle: "165"; value: "57.4913"; } - ListElement{ radius: "15"; angle: "170"; value: "53.2327"; } - ListElement{ radius: "15"; angle: "175"; value: "48.9081"; } - ListElement{ radius: "15"; angle: "180"; value: "44.5503"; } - ListElement{ radius: "15"; angle: "185"; value: "40.1925"; } - ListElement{ radius: "15"; angle: "190"; value: "35.8679"; } - ListElement{ radius: "15"; angle: "195"; value: "31.6094"; } - ListElement{ radius: "15"; angle: "200"; value: "27.4493"; } - ListElement{ radius: "15"; angle: "205"; value: "23.4194"; } - ListElement{ radius: "15"; angle: "210"; value: "19.5503"; } - ListElement{ radius: "15"; angle: "215"; value: "15.8715"; } - ListElement{ radius: "15"; angle: "220"; value: "12.4109"; } - ListElement{ radius: "15"; angle: "225"; value: "9.19499"; } - ListElement{ radius: "15"; angle: "230"; value: "6.2481"; } - ListElement{ radius: "15"; angle: "235"; value: "3.59272"; } - ListElement{ radius: "15"; angle: "240"; value: "1.24906"; } - ListElement{ radius: "15"; angle: "245"; value: "-0.765063"; } - ListElement{ radius: "15"; angle: "250"; value: "-2.4343"; } - ListElement{ radius: "15"; angle: "255"; value: "-3.74597"; } - ListElement{ radius: "15"; angle: "260"; value: "-4.69006"; } - ListElement{ radius: "15"; angle: "265"; value: "-5.25941"; } - ListElement{ radius: "15"; angle: "270"; value: "-5.44967"; } - ListElement{ radius: "15"; angle: "275"; value: "-5.25941"; } - ListElement{ radius: "15"; angle: "280"; value: "-4.69006"; } - ListElement{ radius: "15"; angle: "285"; value: "-3.74597"; } - ListElement{ radius: "15"; angle: "290"; value: "-2.4343"; } - ListElement{ radius: "15"; angle: "295"; value: "-0.765063"; } - ListElement{ radius: "15"; angle: "300"; value: "1.24906"; } - ListElement{ radius: "15"; angle: "305"; value: "3.59272"; } - ListElement{ radius: "15"; angle: "310"; value: "6.2481"; } - ListElement{ radius: "15"; angle: "315"; value: "9.19499"; } - ListElement{ radius: "15"; angle: "320"; value: "12.4109"; } - ListElement{ radius: "15"; angle: "325"; value: "15.8715"; } - ListElement{ radius: "15"; angle: "330"; value: "19.5503"; } - ListElement{ radius: "15"; angle: "335"; value: "23.4194"; } - ListElement{ radius: "15"; angle: "340"; value: "27.4493"; } - ListElement{ radius: "15"; angle: "345"; value: "31.6094"; } - ListElement{ radius: "15"; angle: "350"; value: "35.8679"; } - ListElement{ radius: "15"; angle: "355"; value: "40.1925"; } - ListElement{ radius: "15"; angle: "360"; value: "44.5503"; } - ListElement{ radius: "20"; angle: "0"; value: "40.4508"; } - ListElement{ radius: "20"; angle: "5"; value: "44.8086"; } - ListElement{ radius: "20"; angle: "10"; value: "49.1333"; } - ListElement{ radius: "20"; angle: "15"; value: "53.3918"; } - ListElement{ radius: "20"; angle: "20"; value: "57.5519"; } - ListElement{ radius: "20"; angle: "25"; value: "61.5818"; } - ListElement{ radius: "20"; angle: "30"; value: "65.4508"; } - ListElement{ radius: "20"; angle: "35"; value: "69.1297"; } - ListElement{ radius: "20"; angle: "40"; value: "72.5902"; } - ListElement{ radius: "20"; angle: "45"; value: "75.8062"; } - ListElement{ radius: "20"; angle: "50"; value: "78.7531"; } - ListElement{ radius: "20"; angle: "55"; value: "81.4085"; } - ListElement{ radius: "20"; angle: "60"; value: "83.7521"; } - ListElement{ radius: "20"; angle: "65"; value: "85.7662"; } - ListElement{ radius: "20"; angle: "70"; value: "87.4355"; } - ListElement{ radius: "20"; angle: "75"; value: "88.7471"; } - ListElement{ radius: "20"; angle: "80"; value: "89.6912"; } - ListElement{ radius: "20"; angle: "85"; value: "90.2606"; } - ListElement{ radius: "20"; angle: "90"; value: "90.4508"; } - ListElement{ radius: "20"; angle: "95"; value: "90.2606"; } - ListElement{ radius: "20"; angle: "100"; value: "89.6912"; } - ListElement{ radius: "20"; angle: "105"; value: "88.7471"; } - ListElement{ radius: "20"; angle: "110"; value: "87.4355"; } - ListElement{ radius: "20"; angle: "115"; value: "85.7662"; } - ListElement{ radius: "20"; angle: "120"; value: "83.7521"; } - ListElement{ radius: "20"; angle: "125"; value: "81.4085"; } - ListElement{ radius: "20"; angle: "130"; value: "78.7531"; } - ListElement{ radius: "20"; angle: "135"; value: "75.8062"; } - ListElement{ radius: "20"; angle: "140"; value: "72.5902"; } - ListElement{ radius: "20"; angle: "145"; value: "69.1297"; } - ListElement{ radius: "20"; angle: "150"; value: "65.4508"; } - ListElement{ radius: "20"; angle: "155"; value: "61.5818"; } - ListElement{ radius: "20"; angle: "160"; value: "57.5519"; } - ListElement{ radius: "20"; angle: "165"; value: "53.3918"; } - ListElement{ radius: "20"; angle: "170"; value: "49.1333"; } - ListElement{ radius: "20"; angle: "175"; value: "44.8086"; } - ListElement{ radius: "20"; angle: "180"; value: "40.4508"; } - ListElement{ radius: "20"; angle: "185"; value: "36.0931"; } - ListElement{ radius: "20"; angle: "190"; value: "31.7684"; } - ListElement{ radius: "20"; angle: "195"; value: "27.5099"; } - ListElement{ radius: "20"; angle: "200"; value: "23.3498"; } - ListElement{ radius: "20"; angle: "205"; value: "19.3199"; } - ListElement{ radius: "20"; angle: "210"; value: "15.4508"; } - ListElement{ radius: "20"; angle: "215"; value: "11.772"; } - ListElement{ radius: "20"; angle: "220"; value: "8.31147"; } - ListElement{ radius: "20"; angle: "225"; value: "5.09551"; } - ListElement{ radius: "20"; angle: "230"; value: "2.14863"; } - ListElement{ radius: "20"; angle: "235"; value: "-0.506752"; } - ListElement{ radius: "20"; angle: "240"; value: "-2.85042"; } - ListElement{ radius: "20"; angle: "245"; value: "-4.86454"; } - ListElement{ radius: "20"; angle: "250"; value: "-6.53378"; } - ListElement{ radius: "20"; angle: "255"; value: "-7.84544"; } - ListElement{ radius: "20"; angle: "260"; value: "-8.78954"; } - ListElement{ radius: "20"; angle: "265"; value: "-9.35889"; } - ListElement{ radius: "20"; angle: "270"; value: "-9.54915"; } - ListElement{ radius: "20"; angle: "275"; value: "-9.35889"; } - ListElement{ radius: "20"; angle: "280"; value: "-8.78954"; } - ListElement{ radius: "20"; angle: "285"; value: "-7.84544"; } - ListElement{ radius: "20"; angle: "290"; value: "-6.53378"; } - ListElement{ radius: "20"; angle: "295"; value: "-4.86454"; } - ListElement{ radius: "20"; angle: "300"; value: "-2.85042"; } - ListElement{ radius: "20"; angle: "305"; value: "-0.506752"; } - ListElement{ radius: "20"; angle: "310"; value: "2.14863"; } - ListElement{ radius: "20"; angle: "315"; value: "5.09551"; } - ListElement{ radius: "20"; angle: "320"; value: "8.31147"; } - ListElement{ radius: "20"; angle: "325"; value: "11.772"; } - ListElement{ radius: "20"; angle: "330"; value: "15.4508"; } - ListElement{ radius: "20"; angle: "335"; value: "19.3199"; } - ListElement{ radius: "20"; angle: "340"; value: "23.3498"; } - ListElement{ radius: "20"; angle: "345"; value: "27.5099"; } - ListElement{ radius: "20"; angle: "350"; value: "31.7684"; } - ListElement{ radius: "20"; angle: "355"; value: "36.0931"; } - ListElement{ radius: "20"; angle: "360"; value: "40.4508"; } - ListElement{ radius: "25"; angle: "0"; value: "35.3553"; } - ListElement{ radius: "25"; angle: "5"; value: "39.7131"; } - ListElement{ radius: "25"; angle: "10"; value: "44.0377"; } - ListElement{ radius: "25"; angle: "15"; value: "48.2963"; } - ListElement{ radius: "25"; angle: "20"; value: "52.4563"; } - ListElement{ radius: "25"; angle: "25"; value: "56.4863"; } - ListElement{ radius: "25"; angle: "30"; value: "60.3553"; } - ListElement{ radius: "25"; angle: "35"; value: "64.0342"; } - ListElement{ radius: "25"; angle: "40"; value: "67.4947"; } - ListElement{ radius: "25"; angle: "45"; value: "70.7107"; } - ListElement{ radius: "25"; angle: "50"; value: "73.6576"; } - ListElement{ radius: "25"; angle: "55"; value: "76.3129"; } - ListElement{ radius: "25"; angle: "60"; value: "78.6566"; } - ListElement{ radius: "25"; angle: "65"; value: "80.6707"; } - ListElement{ radius: "25"; angle: "70"; value: "82.34"; } - ListElement{ radius: "25"; angle: "75"; value: "83.6516"; } - ListElement{ radius: "25"; angle: "80"; value: "84.5957"; } - ListElement{ radius: "25"; angle: "85"; value: "85.1651"; } - ListElement{ radius: "25"; angle: "90"; value: "85.3553"; } - ListElement{ radius: "25"; angle: "95"; value: "85.1651"; } - ListElement{ radius: "25"; angle: "100"; value: "84.5957"; } - ListElement{ radius: "25"; angle: "105"; value: "83.6516"; } - ListElement{ radius: "25"; angle: "110"; value: "82.34"; } - ListElement{ radius: "25"; angle: "115"; value: "80.6707"; } - ListElement{ radius: "25"; angle: "120"; value: "78.6566"; } - ListElement{ radius: "25"; angle: "125"; value: "76.3129"; } - ListElement{ radius: "25"; angle: "130"; value: "73.6576"; } - ListElement{ radius: "25"; angle: "135"; value: "70.7107"; } - ListElement{ radius: "25"; angle: "140"; value: "67.4947"; } - ListElement{ radius: "25"; angle: "145"; value: "64.0342"; } - ListElement{ radius: "25"; angle: "150"; value: "60.3553"; } - ListElement{ radius: "25"; angle: "155"; value: "56.4863"; } - ListElement{ radius: "25"; angle: "160"; value: "52.4563"; } - ListElement{ radius: "25"; angle: "165"; value: "48.2963"; } - ListElement{ radius: "25"; angle: "170"; value: "44.0377"; } - ListElement{ radius: "25"; angle: "175"; value: "39.7131"; } - ListElement{ radius: "25"; angle: "180"; value: "35.3553"; } - ListElement{ radius: "25"; angle: "185"; value: "30.9976"; } - ListElement{ radius: "25"; angle: "190"; value: "26.6729"; } - ListElement{ radius: "25"; angle: "195"; value: "22.4144"; } - ListElement{ radius: "25"; angle: "200"; value: "18.2543"; } - ListElement{ radius: "25"; angle: "205"; value: "14.2244"; } - ListElement{ radius: "25"; angle: "210"; value: "10.3553"; } - ListElement{ radius: "25"; angle: "215"; value: "6.67652"; } - ListElement{ radius: "25"; angle: "220"; value: "3.21596"; } - ListElement{ radius: "25"; angle: "225"; value: "5.55112e-15"; } - ListElement{ radius: "25"; angle: "230"; value: "-2.94688"; } - ListElement{ radius: "25"; angle: "235"; value: "-5.60226"; } - ListElement{ radius: "25"; angle: "240"; value: "-7.94593"; } - ListElement{ radius: "25"; angle: "245"; value: "-9.96005"; } - ListElement{ radius: "25"; angle: "250"; value: "-11.6293"; } - ListElement{ radius: "25"; angle: "255"; value: "-12.941"; } - ListElement{ radius: "25"; angle: "260"; value: "-13.885"; } - ListElement{ radius: "25"; angle: "265"; value: "-14.4544"; } - ListElement{ radius: "25"; angle: "270"; value: "-14.6447"; } - ListElement{ radius: "25"; angle: "275"; value: "-14.4544"; } - ListElement{ radius: "25"; angle: "280"; value: "-13.885"; } - ListElement{ radius: "25"; angle: "285"; value: "-12.941"; } - ListElement{ radius: "25"; angle: "290"; value: "-11.6293"; } - ListElement{ radius: "25"; angle: "295"; value: "-9.96005"; } - ListElement{ radius: "25"; angle: "300"; value: "-7.94593"; } - ListElement{ radius: "25"; angle: "305"; value: "-5.60226"; } - ListElement{ radius: "25"; angle: "310"; value: "-2.94688"; } - ListElement{ radius: "25"; angle: "315"; value: "-5.55112e-15"; } - ListElement{ radius: "25"; angle: "320"; value: "3.21596"; } - ListElement{ radius: "25"; angle: "325"; value: "6.67652"; } - ListElement{ radius: "25"; angle: "330"; value: "10.3553"; } - ListElement{ radius: "25"; angle: "335"; value: "14.2244"; } - ListElement{ radius: "25"; angle: "340"; value: "18.2543"; } - ListElement{ radius: "25"; angle: "345"; value: "22.4144"; } - ListElement{ radius: "25"; angle: "350"; value: "26.6729"; } - ListElement{ radius: "25"; angle: "355"; value: "30.9976"; } - ListElement{ radius: "25"; angle: "360"; value: "35.3553"; } - ListElement{ radius: "30"; angle: "0"; value: "29.3893"; } - ListElement{ radius: "30"; angle: "5"; value: "33.747"; } - ListElement{ radius: "30"; angle: "10"; value: "38.0717"; } - ListElement{ radius: "30"; angle: "15"; value: "42.3302"; } - ListElement{ radius: "30"; angle: "20"; value: "46.4903"; } - ListElement{ radius: "30"; angle: "25"; value: "50.5202"; } - ListElement{ radius: "30"; angle: "30"; value: "54.3893"; } - ListElement{ radius: "30"; angle: "35"; value: "58.0681"; } - ListElement{ radius: "30"; angle: "40"; value: "61.5286"; } - ListElement{ radius: "30"; angle: "45"; value: "64.7446"; } - ListElement{ radius: "30"; angle: "50"; value: "67.6915"; } - ListElement{ radius: "30"; angle: "55"; value: "70.3469"; } - ListElement{ radius: "30"; angle: "60"; value: "72.6905"; } - ListElement{ radius: "30"; angle: "65"; value: "74.7047"; } - ListElement{ radius: "30"; angle: "70"; value: "76.3739"; } - ListElement{ radius: "30"; angle: "75"; value: "77.6856"; } - ListElement{ radius: "30"; angle: "80"; value: "78.6297"; } - ListElement{ radius: "30"; angle: "85"; value: "79.199"; } - ListElement{ radius: "30"; angle: "90"; value: "79.3893"; } - ListElement{ radius: "30"; angle: "95"; value: "79.199"; } - ListElement{ radius: "30"; angle: "100"; value: "78.6297"; } - ListElement{ radius: "30"; angle: "105"; value: "77.6856"; } - ListElement{ radius: "30"; angle: "110"; value: "76.3739"; } - ListElement{ radius: "30"; angle: "115"; value: "74.7047"; } - ListElement{ radius: "30"; angle: "120"; value: "72.6905"; } - ListElement{ radius: "30"; angle: "125"; value: "70.3469"; } - ListElement{ radius: "30"; angle: "130"; value: "67.6915"; } - ListElement{ radius: "30"; angle: "135"; value: "64.7446"; } - ListElement{ radius: "30"; angle: "140"; value: "61.5286"; } - ListElement{ radius: "30"; angle: "145"; value: "58.0681"; } - ListElement{ radius: "30"; angle: "150"; value: "54.3893"; } - ListElement{ radius: "30"; angle: "155"; value: "50.5202"; } - ListElement{ radius: "30"; angle: "160"; value: "46.4903"; } - ListElement{ radius: "30"; angle: "165"; value: "42.3302"; } - ListElement{ radius: "30"; angle: "170"; value: "38.0717"; } - ListElement{ radius: "30"; angle: "175"; value: "33.747"; } - ListElement{ radius: "30"; angle: "180"; value: "29.3893"; } - ListElement{ radius: "30"; angle: "185"; value: "25.0315"; } - ListElement{ radius: "30"; angle: "190"; value: "20.7069"; } - ListElement{ radius: "30"; angle: "195"; value: "16.4483"; } - ListElement{ radius: "30"; angle: "200"; value: "12.2883"; } - ListElement{ radius: "30"; angle: "205"; value: "8.25835"; } - ListElement{ radius: "30"; angle: "210"; value: "4.38926"; } - ListElement{ radius: "30"; angle: "215"; value: "0.710441"; } - ListElement{ radius: "30"; angle: "220"; value: "-2.75012"; } - ListElement{ radius: "30"; angle: "225"; value: "-5.96608"; } - ListElement{ radius: "30"; angle: "230"; value: "-8.91296"; } - ListElement{ radius: "30"; angle: "235"; value: "-11.5683"; } - ListElement{ radius: "30"; angle: "240"; value: "-13.912"; } - ListElement{ radius: "30"; angle: "245"; value: "-15.9261"; } - ListElement{ radius: "30"; angle: "250"; value: "-17.5954"; } - ListElement{ radius: "30"; angle: "255"; value: "-18.907"; } - ListElement{ radius: "30"; angle: "260"; value: "-19.8511"; } - ListElement{ radius: "30"; angle: "265"; value: "-20.4205"; } - ListElement{ radius: "30"; angle: "270"; value: "-20.6107"; } - ListElement{ radius: "30"; angle: "275"; value: "-20.4205"; } - ListElement{ radius: "30"; angle: "280"; value: "-19.8511"; } - ListElement{ radius: "30"; angle: "285"; value: "-18.907"; } - ListElement{ radius: "30"; angle: "290"; value: "-17.5954"; } - ListElement{ radius: "30"; angle: "295"; value: "-15.9261"; } - ListElement{ radius: "30"; angle: "300"; value: "-13.912"; } - ListElement{ radius: "30"; angle: "305"; value: "-11.5683"; } - ListElement{ radius: "30"; angle: "310"; value: "-8.91296"; } - ListElement{ radius: "30"; angle: "315"; value: "-5.96608"; } - ListElement{ radius: "30"; angle: "320"; value: "-2.75012"; } - ListElement{ radius: "30"; angle: "325"; value: "0.710441"; } - ListElement{ radius: "30"; angle: "330"; value: "4.38926"; } - ListElement{ radius: "30"; angle: "335"; value: "8.25835"; } - ListElement{ radius: "30"; angle: "340"; value: "12.2883"; } - ListElement{ radius: "30"; angle: "345"; value: "16.4483"; } - ListElement{ radius: "30"; angle: "350"; value: "20.7069"; } - ListElement{ radius: "30"; angle: "355"; value: "25.0315"; } - ListElement{ radius: "30"; angle: "360"; value: "29.3893"; } - ListElement{ radius: "35"; angle: "0"; value: "22.6995"; } - ListElement{ radius: "35"; angle: "5"; value: "27.0573"; } - ListElement{ radius: "35"; angle: "10"; value: "31.3819"; } - ListElement{ radius: "35"; angle: "15"; value: "35.6405"; } - ListElement{ radius: "35"; angle: "20"; value: "39.8005"; } - ListElement{ radius: "35"; angle: "25"; value: "43.8304"; } - ListElement{ radius: "35"; angle: "30"; value: "47.6995"; } - ListElement{ radius: "35"; angle: "35"; value: "51.3783"; } - ListElement{ radius: "35"; angle: "40"; value: "54.8389"; } - ListElement{ radius: "35"; angle: "45"; value: "58.0549"; } - ListElement{ radius: "35"; angle: "50"; value: "61.0017"; } - ListElement{ radius: "35"; angle: "55"; value: "63.6571"; } - ListElement{ radius: "35"; angle: "60"; value: "66.0008"; } - ListElement{ radius: "35"; angle: "65"; value: "68.0149"; } - ListElement{ radius: "35"; angle: "70"; value: "69.6842"; } - ListElement{ radius: "35"; angle: "75"; value: "70.9958"; } - ListElement{ radius: "35"; angle: "80"; value: "71.9399"; } - ListElement{ radius: "35"; angle: "85"; value: "72.5093"; } - ListElement{ radius: "35"; angle: "90"; value: "72.6995"; } - ListElement{ radius: "35"; angle: "95"; value: "72.5093"; } - ListElement{ radius: "35"; angle: "100"; value: "71.9399"; } - ListElement{ radius: "35"; angle: "105"; value: "70.9958"; } - ListElement{ radius: "35"; angle: "110"; value: "69.6842"; } - ListElement{ radius: "35"; angle: "115"; value: "68.0149"; } - ListElement{ radius: "35"; angle: "120"; value: "66.0008"; } - ListElement{ radius: "35"; angle: "125"; value: "63.6571"; } - ListElement{ radius: "35"; angle: "130"; value: "61.0017"; } - ListElement{ radius: "35"; angle: "135"; value: "58.0549"; } - ListElement{ radius: "35"; angle: "140"; value: "54.8389"; } - ListElement{ radius: "35"; angle: "145"; value: "51.3783"; } - ListElement{ radius: "35"; angle: "150"; value: "47.6995"; } - ListElement{ radius: "35"; angle: "155"; value: "43.8304"; } - ListElement{ radius: "35"; angle: "160"; value: "39.8005"; } - ListElement{ radius: "35"; angle: "165"; value: "35.6405"; } - ListElement{ radius: "35"; angle: "170"; value: "31.3819"; } - ListElement{ radius: "35"; angle: "175"; value: "27.0573"; } - ListElement{ radius: "35"; angle: "180"; value: "22.6995"; } - ListElement{ radius: "35"; angle: "185"; value: "18.3417"; } - ListElement{ radius: "35"; angle: "190"; value: "14.0171"; } - ListElement{ radius: "35"; angle: "195"; value: "9.75857"; } - ListElement{ radius: "35"; angle: "200"; value: "5.59852"; } - ListElement{ radius: "35"; angle: "205"; value: "1.56861"; } - ListElement{ radius: "35"; angle: "210"; value: "-2.30048"; } - ListElement{ radius: "35"; angle: "215"; value: "-5.9793"; } - ListElement{ radius: "35"; angle: "220"; value: "-9.43986"; } - ListElement{ radius: "35"; angle: "225"; value: "-12.6558"; } - ListElement{ radius: "35"; angle: "230"; value: "-15.6027"; } - ListElement{ radius: "35"; angle: "235"; value: "-18.2581"; } - ListElement{ radius: "35"; angle: "240"; value: "-20.6017"; } - ListElement{ radius: "35"; angle: "245"; value: "-22.6159"; } - ListElement{ radius: "35"; angle: "250"; value: "-24.2851"; } - ListElement{ radius: "35"; angle: "255"; value: "-25.5968"; } - ListElement{ radius: "35"; angle: "260"; value: "-26.5409"; } - ListElement{ radius: "35"; angle: "265"; value: "-27.1102"; } - ListElement{ radius: "35"; angle: "270"; value: "-27.3005"; } - ListElement{ radius: "35"; angle: "275"; value: "-27.1102"; } - ListElement{ radius: "35"; angle: "280"; value: "-26.5409"; } - ListElement{ radius: "35"; angle: "285"; value: "-25.5968"; } - ListElement{ radius: "35"; angle: "290"; value: "-24.2851"; } - ListElement{ radius: "35"; angle: "295"; value: "-22.6159"; } - ListElement{ radius: "35"; angle: "300"; value: "-20.6017"; } - ListElement{ radius: "35"; angle: "305"; value: "-18.2581"; } - ListElement{ radius: "35"; angle: "310"; value: "-15.6027"; } - ListElement{ radius: "35"; angle: "315"; value: "-12.6558"; } - ListElement{ radius: "35"; angle: "320"; value: "-9.43986"; } - ListElement{ radius: "35"; angle: "325"; value: "-5.9793"; } - ListElement{ radius: "35"; angle: "330"; value: "-2.30048"; } - ListElement{ radius: "35"; angle: "335"; value: "1.56861"; } - ListElement{ radius: "35"; angle: "340"; value: "5.59852"; } - ListElement{ radius: "35"; angle: "345"; value: "9.75857"; } - ListElement{ radius: "35"; angle: "350"; value: "14.0171"; } - ListElement{ radius: "35"; angle: "355"; value: "18.3417"; } - ListElement{ radius: "35"; angle: "360"; value: "22.6995"; } - ListElement{ radius: "40"; angle: "0"; value: "15.4508"; } - ListElement{ radius: "40"; angle: "5"; value: "19.8086"; } - ListElement{ radius: "40"; angle: "10"; value: "24.1333"; } - ListElement{ radius: "40"; angle: "15"; value: "28.3918"; } - ListElement{ radius: "40"; angle: "20"; value: "32.5519"; } - ListElement{ radius: "40"; angle: "25"; value: "36.5818"; } - ListElement{ radius: "40"; angle: "30"; value: "40.4508"; } - ListElement{ radius: "40"; angle: "35"; value: "44.1297"; } - ListElement{ radius: "40"; angle: "40"; value: "47.5902"; } - ListElement{ radius: "40"; angle: "45"; value: "50.8062"; } - ListElement{ radius: "40"; angle: "50"; value: "53.7531"; } - ListElement{ radius: "40"; angle: "55"; value: "56.4085"; } - ListElement{ radius: "40"; angle: "60"; value: "58.7521"; } - ListElement{ radius: "40"; angle: "65"; value: "60.7662"; } - ListElement{ radius: "40"; angle: "70"; value: "62.4355"; } - ListElement{ radius: "40"; angle: "75"; value: "63.7471"; } - ListElement{ radius: "40"; angle: "80"; value: "64.6912"; } - ListElement{ radius: "40"; angle: "85"; value: "65.2606"; } - ListElement{ radius: "40"; angle: "90"; value: "65.4508"; } - ListElement{ radius: "40"; angle: "95"; value: "65.2606"; } - ListElement{ radius: "40"; angle: "100"; value: "64.6912"; } - ListElement{ radius: "40"; angle: "105"; value: "63.7471"; } - ListElement{ radius: "40"; angle: "110"; value: "62.4355"; } - ListElement{ radius: "40"; angle: "115"; value: "60.7662"; } - ListElement{ radius: "40"; angle: "120"; value: "58.7521"; } - ListElement{ radius: "40"; angle: "125"; value: "56.4085"; } - ListElement{ radius: "40"; angle: "130"; value: "53.7531"; } - ListElement{ radius: "40"; angle: "135"; value: "50.8062"; } - ListElement{ radius: "40"; angle: "140"; value: "47.5902"; } - ListElement{ radius: "40"; angle: "145"; value: "44.1297"; } - ListElement{ radius: "40"; angle: "150"; value: "40.4508"; } - ListElement{ radius: "40"; angle: "155"; value: "36.5818"; } - ListElement{ radius: "40"; angle: "160"; value: "32.5519"; } - ListElement{ radius: "40"; angle: "165"; value: "28.3918"; } - ListElement{ radius: "40"; angle: "170"; value: "24.1333"; } - ListElement{ radius: "40"; angle: "175"; value: "19.8086"; } - ListElement{ radius: "40"; angle: "180"; value: "15.4508"; } - ListElement{ radius: "40"; angle: "185"; value: "11.0931"; } - ListElement{ radius: "40"; angle: "190"; value: "6.76844"; } - ListElement{ radius: "40"; angle: "195"; value: "2.5099"; } - ListElement{ radius: "40"; angle: "200"; value: "-1.65016"; } - ListElement{ radius: "40"; angle: "205"; value: "-5.68006"; } - ListElement{ radius: "40"; angle: "210"; value: "-9.54915"; } - ListElement{ radius: "40"; angle: "215"; value: "-13.228"; } - ListElement{ radius: "40"; angle: "220"; value: "-16.6885"; } - ListElement{ radius: "40"; angle: "225"; value: "-19.9045"; } - ListElement{ radius: "40"; angle: "230"; value: "-22.8514"; } - ListElement{ radius: "40"; angle: "235"; value: "-25.5068"; } - ListElement{ radius: "40"; angle: "240"; value: "-27.8504"; } - ListElement{ radius: "40"; angle: "245"; value: "-29.8645"; } - ListElement{ radius: "40"; angle: "250"; value: "-31.5338"; } - ListElement{ radius: "40"; angle: "255"; value: "-32.8454"; } - ListElement{ radius: "40"; angle: "260"; value: "-33.7895"; } - ListElement{ radius: "40"; angle: "265"; value: "-34.3589"; } - ListElement{ radius: "40"; angle: "270"; value: "-34.5492"; } - ListElement{ radius: "40"; angle: "275"; value: "-34.3589"; } - ListElement{ radius: "40"; angle: "280"; value: "-33.7895"; } - ListElement{ radius: "40"; angle: "285"; value: "-32.8454"; } - ListElement{ radius: "40"; angle: "290"; value: "-31.5338"; } - ListElement{ radius: "40"; angle: "295"; value: "-29.8645"; } - ListElement{ radius: "40"; angle: "300"; value: "-27.8504"; } - ListElement{ radius: "40"; angle: "305"; value: "-25.5068"; } - ListElement{ radius: "40"; angle: "310"; value: "-22.8514"; } - ListElement{ radius: "40"; angle: "315"; value: "-19.9045"; } - ListElement{ radius: "40"; angle: "320"; value: "-16.6885"; } - ListElement{ radius: "40"; angle: "325"; value: "-13.228"; } - ListElement{ radius: "40"; angle: "330"; value: "-9.54915"; } - ListElement{ radius: "40"; angle: "335"; value: "-5.68006"; } - ListElement{ radius: "40"; angle: "340"; value: "-1.65016"; } - ListElement{ radius: "40"; angle: "345"; value: "2.5099"; } - ListElement{ radius: "40"; angle: "350"; value: "6.76844"; } - ListElement{ radius: "40"; angle: "355"; value: "11.0931"; } - ListElement{ radius: "40"; angle: "360"; value: "15.4508"; } - ListElement{ radius: "45"; angle: "0"; value: "7.82172"; } - ListElement{ radius: "45"; angle: "5"; value: "12.1795"; } - ListElement{ radius: "45"; angle: "10"; value: "16.5041"; } - ListElement{ radius: "45"; angle: "15"; value: "20.7627"; } - ListElement{ radius: "45"; angle: "20"; value: "24.9227"; } - ListElement{ radius: "45"; angle: "25"; value: "28.9526"; } - ListElement{ radius: "45"; angle: "30"; value: "32.8217"; } - ListElement{ radius: "45"; angle: "35"; value: "36.5005"; } - ListElement{ radius: "45"; angle: "40"; value: "39.9611"; } - ListElement{ radius: "45"; angle: "45"; value: "43.1771"; } - ListElement{ radius: "45"; angle: "50"; value: "46.1239"; } - ListElement{ radius: "45"; angle: "55"; value: "48.7793"; } - ListElement{ radius: "45"; angle: "60"; value: "51.123"; } - ListElement{ radius: "45"; angle: "65"; value: "53.1371"; } - ListElement{ radius: "45"; angle: "70"; value: "54.8064"; } - ListElement{ radius: "45"; angle: "75"; value: "56.118"; } - ListElement{ radius: "45"; angle: "80"; value: "57.0621"; } - ListElement{ radius: "45"; angle: "85"; value: "57.6315"; } - ListElement{ radius: "45"; angle: "90"; value: "57.8217"; } - ListElement{ radius: "45"; angle: "95"; value: "57.6315"; } - ListElement{ radius: "45"; angle: "100"; value: "57.0621"; } - ListElement{ radius: "45"; angle: "105"; value: "56.118"; } - ListElement{ radius: "45"; angle: "110"; value: "54.8064"; } - ListElement{ radius: "45"; angle: "115"; value: "53.1371"; } - ListElement{ radius: "45"; angle: "120"; value: "51.123"; } - ListElement{ radius: "45"; angle: "125"; value: "48.7793"; } - ListElement{ radius: "45"; angle: "130"; value: "46.1239"; } - ListElement{ radius: "45"; angle: "135"; value: "43.1771"; } - ListElement{ radius: "45"; angle: "140"; value: "39.9611"; } - ListElement{ radius: "45"; angle: "145"; value: "36.5005"; } - ListElement{ radius: "45"; angle: "150"; value: "32.8217"; } - ListElement{ radius: "45"; angle: "155"; value: "28.9526"; } - ListElement{ radius: "45"; angle: "160"; value: "24.9227"; } - ListElement{ radius: "45"; angle: "165"; value: "20.7627"; } - ListElement{ radius: "45"; angle: "170"; value: "16.5041"; } - ListElement{ radius: "45"; angle: "175"; value: "12.1795"; } - ListElement{ radius: "45"; angle: "180"; value: "7.82172"; } - ListElement{ radius: "45"; angle: "185"; value: "3.46394"; } - ListElement{ radius: "45"; angle: "190"; value: "-0.860686"; } - ListElement{ radius: "45"; angle: "195"; value: "-5.11923"; } - ListElement{ radius: "45"; angle: "200"; value: "-9.27928"; } - ListElement{ radius: "45"; angle: "205"; value: "-13.3092"; } - ListElement{ radius: "45"; angle: "210"; value: "-17.1783"; } - ListElement{ radius: "45"; angle: "215"; value: "-20.8571"; } - ListElement{ radius: "45"; angle: "220"; value: "-24.3177"; } - ListElement{ radius: "45"; angle: "225"; value: "-27.5336"; } - ListElement{ radius: "45"; angle: "230"; value: "-30.4805"; } - ListElement{ radius: "45"; angle: "235"; value: "-33.1359"; } - ListElement{ radius: "45"; angle: "240"; value: "-35.4795"; } - ListElement{ radius: "45"; angle: "245"; value: "-37.4937"; } - ListElement{ radius: "45"; angle: "250"; value: "-39.1629"; } - ListElement{ radius: "45"; angle: "255"; value: "-40.4746"; } - ListElement{ radius: "45"; angle: "260"; value: "-41.4187"; } - ListElement{ radius: "45"; angle: "265"; value: "-41.988"; } - ListElement{ radius: "45"; angle: "270"; value: "-42.1783"; } - ListElement{ radius: "45"; angle: "275"; value: "-41.988"; } - ListElement{ radius: "45"; angle: "280"; value: "-41.4187"; } - ListElement{ radius: "45"; angle: "285"; value: "-40.4746"; } - ListElement{ radius: "45"; angle: "290"; value: "-39.1629"; } - ListElement{ radius: "45"; angle: "295"; value: "-37.4937"; } - ListElement{ radius: "45"; angle: "300"; value: "-35.4795"; } - ListElement{ radius: "45"; angle: "305"; value: "-33.1359"; } - ListElement{ radius: "45"; angle: "310"; value: "-30.4805"; } - ListElement{ radius: "45"; angle: "315"; value: "-27.5336"; } - ListElement{ radius: "45"; angle: "320"; value: "-24.3177"; } - ListElement{ radius: "45"; angle: "325"; value: "-20.8571"; } - ListElement{ radius: "45"; angle: "330"; value: "-17.1783"; } - ListElement{ radius: "45"; angle: "335"; value: "-13.3092"; } - ListElement{ radius: "45"; angle: "340"; value: "-9.27928"; } - ListElement{ radius: "45"; angle: "345"; value: "-5.11923"; } - ListElement{ radius: "45"; angle: "350"; value: "-0.860686"; } - ListElement{ radius: "45"; angle: "355"; value: "3.46394"; } - ListElement{ radius: "45"; angle: "360"; value: "7.82172"; } - ListElement{ radius: "50"; angle: "0"; value: "3.06162e-15"; } - ListElement{ radius: "50"; angle: "5"; value: "4.35779"; } - ListElement{ radius: "50"; angle: "10"; value: "8.68241"; } - ListElement{ radius: "50"; angle: "15"; value: "12.941"; } - ListElement{ radius: "50"; angle: "20"; value: "17.101"; } - ListElement{ radius: "50"; angle: "25"; value: "21.1309"; } - ListElement{ radius: "50"; angle: "30"; value: "25"; } - ListElement{ radius: "50"; angle: "35"; value: "28.6788"; } - ListElement{ radius: "50"; angle: "40"; value: "32.1394"; } - ListElement{ radius: "50"; angle: "45"; value: "35.3553"; } - ListElement{ radius: "50"; angle: "50"; value: "38.3022"; } - ListElement{ radius: "50"; angle: "55"; value: "40.9576"; } - ListElement{ radius: "50"; angle: "60"; value: "43.3013"; } - ListElement{ radius: "50"; angle: "65"; value: "45.3154"; } - ListElement{ radius: "50"; angle: "70"; value: "46.9846"; } - ListElement{ radius: "50"; angle: "75"; value: "48.2963"; } - ListElement{ radius: "50"; angle: "80"; value: "49.2404"; } - ListElement{ radius: "50"; angle: "85"; value: "49.8097"; } - ListElement{ radius: "50"; angle: "90"; value: "50"; } - ListElement{ radius: "50"; angle: "95"; value: "49.8097"; } - ListElement{ radius: "50"; angle: "100"; value: "49.2404"; } - ListElement{ radius: "50"; angle: "105"; value: "48.2963"; } - ListElement{ radius: "50"; angle: "110"; value: "46.9846"; } - ListElement{ radius: "50"; angle: "115"; value: "45.3154"; } - ListElement{ radius: "50"; angle: "120"; value: "43.3013"; } - ListElement{ radius: "50"; angle: "125"; value: "40.9576"; } - ListElement{ radius: "50"; angle: "130"; value: "38.3022"; } - ListElement{ radius: "50"; angle: "135"; value: "35.3553"; } - ListElement{ radius: "50"; angle: "140"; value: "32.1394"; } - ListElement{ radius: "50"; angle: "145"; value: "28.6788"; } - ListElement{ radius: "50"; angle: "150"; value: "25"; } - ListElement{ radius: "50"; angle: "155"; value: "21.1309"; } - ListElement{ radius: "50"; angle: "160"; value: "17.101"; } - ListElement{ radius: "50"; angle: "165"; value: "12.941"; } - ListElement{ radius: "50"; angle: "170"; value: "8.68241"; } - ListElement{ radius: "50"; angle: "175"; value: "4.35779"; } - ListElement{ radius: "50"; angle: "180"; value: "9.18485e-15"; } - ListElement{ radius: "50"; angle: "185"; value: "-4.35779"; } - ListElement{ radius: "50"; angle: "190"; value: "-8.68241"; } - ListElement{ radius: "50"; angle: "195"; value: "-12.941"; } - ListElement{ radius: "50"; angle: "200"; value: "-17.101"; } - ListElement{ radius: "50"; angle: "205"; value: "-21.1309"; } - ListElement{ radius: "50"; angle: "210"; value: "-25"; } - ListElement{ radius: "50"; angle: "215"; value: "-28.6788"; } - ListElement{ radius: "50"; angle: "220"; value: "-32.1394"; } - ListElement{ radius: "50"; angle: "225"; value: "-35.3553"; } - ListElement{ radius: "50"; angle: "230"; value: "-38.3022"; } - ListElement{ radius: "50"; angle: "235"; value: "-40.9576"; } - ListElement{ radius: "50"; angle: "240"; value: "-43.3013"; } - ListElement{ radius: "50"; angle: "245"; value: "-45.3154"; } - ListElement{ radius: "50"; angle: "250"; value: "-46.9846"; } - ListElement{ radius: "50"; angle: "255"; value: "-48.2963"; } - ListElement{ radius: "50"; angle: "260"; value: "-49.2404"; } - ListElement{ radius: "50"; angle: "265"; value: "-49.8097"; } - ListElement{ radius: "50"; angle: "270"; value: "-50"; } - ListElement{ radius: "50"; angle: "275"; value: "-49.8097"; } - ListElement{ radius: "50"; angle: "280"; value: "-49.2404"; } - ListElement{ radius: "50"; angle: "285"; value: "-48.2963"; } - ListElement{ radius: "50"; angle: "290"; value: "-46.9846"; } - ListElement{ radius: "50"; angle: "295"; value: "-45.3154"; } - ListElement{ radius: "50"; angle: "300"; value: "-43.3013"; } - ListElement{ radius: "50"; angle: "305"; value: "-40.9576"; } - ListElement{ radius: "50"; angle: "310"; value: "-38.3022"; } - ListElement{ radius: "50"; angle: "315"; value: "-35.3553"; } - ListElement{ radius: "50"; angle: "320"; value: "-32.1394"; } - ListElement{ radius: "50"; angle: "325"; value: "-28.6788"; } - ListElement{ radius: "50"; angle: "330"; value: "-25"; } - ListElement{ radius: "50"; angle: "335"; value: "-21.1309"; } - ListElement{ radius: "50"; angle: "340"; value: "-17.101"; } - ListElement{ radius: "50"; angle: "345"; value: "-12.941"; } - ListElement{ radius: "50"; angle: "350"; value: "-8.68241"; } - ListElement{ radius: "50"; angle: "355"; value: "-4.35779"; } - ListElement{ radius: "50"; angle: "360"; value: "-9.18485e-15"; } - ListElement{ radius: "55"; angle: "0"; value: "-7.82172"; } - ListElement{ radius: "55"; angle: "5"; value: "-3.46394"; } - ListElement{ radius: "55"; angle: "10"; value: "0.860686"; } - ListElement{ radius: "55"; angle: "15"; value: "5.11923"; } - ListElement{ radius: "55"; angle: "20"; value: "9.27928"; } - ListElement{ radius: "55"; angle: "25"; value: "13.3092"; } - ListElement{ radius: "55"; angle: "30"; value: "17.1783"; } - ListElement{ radius: "55"; angle: "35"; value: "20.8571"; } - ListElement{ radius: "55"; angle: "40"; value: "24.3177"; } - ListElement{ radius: "55"; angle: "45"; value: "27.5336"; } - ListElement{ radius: "55"; angle: "50"; value: "30.4805"; } - ListElement{ radius: "55"; angle: "55"; value: "33.1359"; } - ListElement{ radius: "55"; angle: "60"; value: "35.4795"; } - ListElement{ radius: "55"; angle: "65"; value: "37.4937"; } - ListElement{ radius: "55"; angle: "70"; value: "39.1629"; } - ListElement{ radius: "55"; angle: "75"; value: "40.4746"; } - ListElement{ radius: "55"; angle: "80"; value: "41.4187"; } - ListElement{ radius: "55"; angle: "85"; value: "41.988"; } - ListElement{ radius: "55"; angle: "90"; value: "42.1783"; } - ListElement{ radius: "55"; angle: "95"; value: "41.988"; } - ListElement{ radius: "55"; angle: "100"; value: "41.4187"; } - ListElement{ radius: "55"; angle: "105"; value: "40.4746"; } - ListElement{ radius: "55"; angle: "110"; value: "39.1629"; } - ListElement{ radius: "55"; angle: "115"; value: "37.4937"; } - ListElement{ radius: "55"; angle: "120"; value: "35.4795"; } - ListElement{ radius: "55"; angle: "125"; value: "33.1359"; } - ListElement{ radius: "55"; angle: "130"; value: "30.4805"; } - ListElement{ radius: "55"; angle: "135"; value: "27.5336"; } - ListElement{ radius: "55"; angle: "140"; value: "24.3177"; } - ListElement{ radius: "55"; angle: "145"; value: "20.8571"; } - ListElement{ radius: "55"; angle: "150"; value: "17.1783"; } - ListElement{ radius: "55"; angle: "155"; value: "13.3092"; } - ListElement{ radius: "55"; angle: "160"; value: "9.27928"; } - ListElement{ radius: "55"; angle: "165"; value: "5.11923"; } - ListElement{ radius: "55"; angle: "170"; value: "0.860686"; } - ListElement{ radius: "55"; angle: "175"; value: "-3.46394"; } - ListElement{ radius: "55"; angle: "180"; value: "-7.82172"; } - ListElement{ radius: "55"; angle: "185"; value: "-12.1795"; } - ListElement{ radius: "55"; angle: "190"; value: "-16.5041"; } - ListElement{ radius: "55"; angle: "195"; value: "-20.7627"; } - ListElement{ radius: "55"; angle: "200"; value: "-24.9227"; } - ListElement{ radius: "55"; angle: "205"; value: "-28.9526"; } - ListElement{ radius: "55"; angle: "210"; value: "-32.8217"; } - ListElement{ radius: "55"; angle: "215"; value: "-36.5005"; } - ListElement{ radius: "55"; angle: "220"; value: "-39.9611"; } - ListElement{ radius: "55"; angle: "225"; value: "-43.1771"; } - ListElement{ radius: "55"; angle: "230"; value: "-46.1239"; } - ListElement{ radius: "55"; angle: "235"; value: "-48.7793"; } - ListElement{ radius: "55"; angle: "240"; value: "-51.123"; } - ListElement{ radius: "55"; angle: "245"; value: "-53.1371"; } - ListElement{ radius: "55"; angle: "250"; value: "-54.8064"; } - ListElement{ radius: "55"; angle: "255"; value: "-56.118"; } - ListElement{ radius: "55"; angle: "260"; value: "-57.0621"; } - ListElement{ radius: "55"; angle: "265"; value: "-57.6315"; } - ListElement{ radius: "55"; angle: "270"; value: "-57.8217"; } - ListElement{ radius: "55"; angle: "275"; value: "-57.6315"; } - ListElement{ radius: "55"; angle: "280"; value: "-57.0621"; } - ListElement{ radius: "55"; angle: "285"; value: "-56.118"; } - ListElement{ radius: "55"; angle: "290"; value: "-54.8064"; } - ListElement{ radius: "55"; angle: "295"; value: "-53.1371"; } - ListElement{ radius: "55"; angle: "300"; value: "-51.123"; } - ListElement{ radius: "55"; angle: "305"; value: "-48.7793"; } - ListElement{ radius: "55"; angle: "310"; value: "-46.1239"; } - ListElement{ radius: "55"; angle: "315"; value: "-43.1771"; } - ListElement{ radius: "55"; angle: "320"; value: "-39.9611"; } - ListElement{ radius: "55"; angle: "325"; value: "-36.5005"; } - ListElement{ radius: "55"; angle: "330"; value: "-32.8217"; } - ListElement{ radius: "55"; angle: "335"; value: "-28.9526"; } - ListElement{ radius: "55"; angle: "340"; value: "-24.9227"; } - ListElement{ radius: "55"; angle: "345"; value: "-20.7627"; } - ListElement{ radius: "55"; angle: "350"; value: "-16.5041"; } - ListElement{ radius: "55"; angle: "355"; value: "-12.1795"; } - ListElement{ radius: "55"; angle: "360"; value: "-7.82172"; } - ListElement{ radius: "60"; angle: "0"; value: "-15.4508"; } - ListElement{ radius: "60"; angle: "5"; value: "-11.0931"; } - ListElement{ radius: "60"; angle: "10"; value: "-6.76844"; } - ListElement{ radius: "60"; angle: "15"; value: "-2.5099"; } - ListElement{ radius: "60"; angle: "20"; value: "1.65016"; } - ListElement{ radius: "60"; angle: "25"; value: "5.68006"; } - ListElement{ radius: "60"; angle: "30"; value: "9.54915"; } - ListElement{ radius: "60"; angle: "35"; value: "13.228"; } - ListElement{ radius: "60"; angle: "40"; value: "16.6885"; } - ListElement{ radius: "60"; angle: "45"; value: "19.9045"; } - ListElement{ radius: "60"; angle: "50"; value: "22.8514"; } - ListElement{ radius: "60"; angle: "55"; value: "25.5068"; } - ListElement{ radius: "60"; angle: "60"; value: "27.8504"; } - ListElement{ radius: "60"; angle: "65"; value: "29.8645"; } - ListElement{ radius: "60"; angle: "70"; value: "31.5338"; } - ListElement{ radius: "60"; angle: "75"; value: "32.8454"; } - ListElement{ radius: "60"; angle: "80"; value: "33.7895"; } - ListElement{ radius: "60"; angle: "85"; value: "34.3589"; } - ListElement{ radius: "60"; angle: "90"; value: "34.5492"; } - ListElement{ radius: "60"; angle: "95"; value: "34.3589"; } - ListElement{ radius: "60"; angle: "100"; value: "33.7895"; } - ListElement{ radius: "60"; angle: "105"; value: "32.8454"; } - ListElement{ radius: "60"; angle: "110"; value: "31.5338"; } - ListElement{ radius: "60"; angle: "115"; value: "29.8645"; } - ListElement{ radius: "60"; angle: "120"; value: "27.8504"; } - ListElement{ radius: "60"; angle: "125"; value: "25.5068"; } - ListElement{ radius: "60"; angle: "130"; value: "22.8514"; } - ListElement{ radius: "60"; angle: "135"; value: "19.9045"; } - ListElement{ radius: "60"; angle: "140"; value: "16.6885"; } - ListElement{ radius: "60"; angle: "145"; value: "13.228"; } - ListElement{ radius: "60"; angle: "150"; value: "9.54915"; } - ListElement{ radius: "60"; angle: "155"; value: "5.68006"; } - ListElement{ radius: "60"; angle: "160"; value: "1.65016"; } - ListElement{ radius: "60"; angle: "165"; value: "-2.5099"; } - ListElement{ radius: "60"; angle: "170"; value: "-6.76844"; } - ListElement{ radius: "60"; angle: "175"; value: "-11.0931"; } - ListElement{ radius: "60"; angle: "180"; value: "-15.4508"; } - ListElement{ radius: "60"; angle: "185"; value: "-19.8086"; } - ListElement{ radius: "60"; angle: "190"; value: "-24.1333"; } - ListElement{ radius: "60"; angle: "195"; value: "-28.3918"; } - ListElement{ radius: "60"; angle: "200"; value: "-32.5519"; } - ListElement{ radius: "60"; angle: "205"; value: "-36.5818"; } - ListElement{ radius: "60"; angle: "210"; value: "-40.4508"; } - ListElement{ radius: "60"; angle: "215"; value: "-44.1297"; } - ListElement{ radius: "60"; angle: "220"; value: "-47.5902"; } - ListElement{ radius: "60"; angle: "225"; value: "-50.8062"; } - ListElement{ radius: "60"; angle: "230"; value: "-53.7531"; } - ListElement{ radius: "60"; angle: "235"; value: "-56.4085"; } - ListElement{ radius: "60"; angle: "240"; value: "-58.7521"; } - ListElement{ radius: "60"; angle: "245"; value: "-60.7662"; } - ListElement{ radius: "60"; angle: "250"; value: "-62.4355"; } - ListElement{ radius: "60"; angle: "255"; value: "-63.7471"; } - ListElement{ radius: "60"; angle: "260"; value: "-64.6912"; } - ListElement{ radius: "60"; angle: "265"; value: "-65.2606"; } - ListElement{ radius: "60"; angle: "270"; value: "-65.4508"; } - ListElement{ radius: "60"; angle: "275"; value: "-65.2606"; } - ListElement{ radius: "60"; angle: "280"; value: "-64.6912"; } - ListElement{ radius: "60"; angle: "285"; value: "-63.7471"; } - ListElement{ radius: "60"; angle: "290"; value: "-62.4355"; } - ListElement{ radius: "60"; angle: "295"; value: "-60.7662"; } - ListElement{ radius: "60"; angle: "300"; value: "-58.7521"; } - ListElement{ radius: "60"; angle: "305"; value: "-56.4085"; } - ListElement{ radius: "60"; angle: "310"; value: "-53.7531"; } - ListElement{ radius: "60"; angle: "315"; value: "-50.8062"; } - ListElement{ radius: "60"; angle: "320"; value: "-47.5902"; } - ListElement{ radius: "60"; angle: "325"; value: "-44.1297"; } - ListElement{ radius: "60"; angle: "330"; value: "-40.4508"; } - ListElement{ radius: "60"; angle: "335"; value: "-36.5818"; } - ListElement{ radius: "60"; angle: "340"; value: "-32.5519"; } - ListElement{ radius: "60"; angle: "345"; value: "-28.3918"; } - ListElement{ radius: "60"; angle: "350"; value: "-24.1333"; } - ListElement{ radius: "60"; angle: "355"; value: "-19.8086"; } - ListElement{ radius: "60"; angle: "360"; value: "-15.4508"; } - ListElement{ radius: "65"; angle: "0"; value: "-22.6995"; } - ListElement{ radius: "65"; angle: "5"; value: "-18.3417"; } - ListElement{ radius: "65"; angle: "10"; value: "-14.0171"; } - ListElement{ radius: "65"; angle: "15"; value: "-9.75857"; } - ListElement{ radius: "65"; angle: "20"; value: "-5.59852"; } - ListElement{ radius: "65"; angle: "25"; value: "-1.56861"; } - ListElement{ radius: "65"; angle: "30"; value: "2.30048"; } - ListElement{ radius: "65"; angle: "35"; value: "5.9793"; } - ListElement{ radius: "65"; angle: "40"; value: "9.43986"; } - ListElement{ radius: "65"; angle: "45"; value: "12.6558"; } - ListElement{ radius: "65"; angle: "50"; value: "15.6027"; } - ListElement{ radius: "65"; angle: "55"; value: "18.2581"; } - ListElement{ radius: "65"; angle: "60"; value: "20.6017"; } - ListElement{ radius: "65"; angle: "65"; value: "22.6159"; } - ListElement{ radius: "65"; angle: "70"; value: "24.2851"; } - ListElement{ radius: "65"; angle: "75"; value: "25.5968"; } - ListElement{ radius: "65"; angle: "80"; value: "26.5409"; } - ListElement{ radius: "65"; angle: "85"; value: "27.1102"; } - ListElement{ radius: "65"; angle: "90"; value: "27.3005"; } - ListElement{ radius: "65"; angle: "95"; value: "27.1102"; } - ListElement{ radius: "65"; angle: "100"; value: "26.5409"; } - ListElement{ radius: "65"; angle: "105"; value: "25.5968"; } - ListElement{ radius: "65"; angle: "110"; value: "24.2851"; } - ListElement{ radius: "65"; angle: "115"; value: "22.6159"; } - ListElement{ radius: "65"; angle: "120"; value: "20.6017"; } - ListElement{ radius: "65"; angle: "125"; value: "18.2581"; } - ListElement{ radius: "65"; angle: "130"; value: "15.6027"; } - ListElement{ radius: "65"; angle: "135"; value: "12.6558"; } - ListElement{ radius: "65"; angle: "140"; value: "9.43986"; } - ListElement{ radius: "65"; angle: "145"; value: "5.9793"; } - ListElement{ radius: "65"; angle: "150"; value: "2.30048"; } - ListElement{ radius: "65"; angle: "155"; value: "-1.56861"; } - ListElement{ radius: "65"; angle: "160"; value: "-5.59852"; } - ListElement{ radius: "65"; angle: "165"; value: "-9.75857"; } - ListElement{ radius: "65"; angle: "170"; value: "-14.0171"; } - ListElement{ radius: "65"; angle: "175"; value: "-18.3417"; } - ListElement{ radius: "65"; angle: "180"; value: "-22.6995"; } - ListElement{ radius: "65"; angle: "185"; value: "-27.0573"; } - ListElement{ radius: "65"; angle: "190"; value: "-31.3819"; } - ListElement{ radius: "65"; angle: "195"; value: "-35.6405"; } - ListElement{ radius: "65"; angle: "200"; value: "-39.8005"; } - ListElement{ radius: "65"; angle: "205"; value: "-43.8304"; } - ListElement{ radius: "65"; angle: "210"; value: "-47.6995"; } - ListElement{ radius: "65"; angle: "215"; value: "-51.3783"; } - ListElement{ radius: "65"; angle: "220"; value: "-54.8389"; } - ListElement{ radius: "65"; angle: "225"; value: "-58.0549"; } - ListElement{ radius: "65"; angle: "230"; value: "-61.0017"; } - ListElement{ radius: "65"; angle: "235"; value: "-63.6571"; } - ListElement{ radius: "65"; angle: "240"; value: "-66.0008"; } - ListElement{ radius: "65"; angle: "245"; value: "-68.0149"; } - ListElement{ radius: "65"; angle: "250"; value: "-69.6842"; } - ListElement{ radius: "65"; angle: "255"; value: "-70.9958"; } - ListElement{ radius: "65"; angle: "260"; value: "-71.9399"; } - ListElement{ radius: "65"; angle: "265"; value: "-72.5093"; } - ListElement{ radius: "65"; angle: "270"; value: "-72.6995"; } - ListElement{ radius: "65"; angle: "275"; value: "-72.5093"; } - ListElement{ radius: "65"; angle: "280"; value: "-71.9399"; } - ListElement{ radius: "65"; angle: "285"; value: "-70.9958"; } - ListElement{ radius: "65"; angle: "290"; value: "-69.6842"; } - ListElement{ radius: "65"; angle: "295"; value: "-68.0149"; } - ListElement{ radius: "65"; angle: "300"; value: "-66.0008"; } - ListElement{ radius: "65"; angle: "305"; value: "-63.6571"; } - ListElement{ radius: "65"; angle: "310"; value: "-61.0017"; } - ListElement{ radius: "65"; angle: "315"; value: "-58.0549"; } - ListElement{ radius: "65"; angle: "320"; value: "-54.8389"; } - ListElement{ radius: "65"; angle: "325"; value: "-51.3783"; } - ListElement{ radius: "65"; angle: "330"; value: "-47.6995"; } - ListElement{ radius: "65"; angle: "335"; value: "-43.8304"; } - ListElement{ radius: "65"; angle: "340"; value: "-39.8005"; } - ListElement{ radius: "65"; angle: "345"; value: "-35.6405"; } - ListElement{ radius: "65"; angle: "350"; value: "-31.3819"; } - ListElement{ radius: "65"; angle: "355"; value: "-27.0573"; } - ListElement{ radius: "65"; angle: "360"; value: "-22.6995"; } - ListElement{ radius: "70"; angle: "0"; value: "-29.3893"; } - ListElement{ radius: "70"; angle: "5"; value: "-25.0315"; } - ListElement{ radius: "70"; angle: "10"; value: "-20.7069"; } - ListElement{ radius: "70"; angle: "15"; value: "-16.4483"; } - ListElement{ radius: "70"; angle: "20"; value: "-12.2883"; } - ListElement{ radius: "70"; angle: "25"; value: "-8.25835"; } - ListElement{ radius: "70"; angle: "30"; value: "-4.38926"; } - ListElement{ radius: "70"; angle: "35"; value: "-0.710441"; } - ListElement{ radius: "70"; angle: "40"; value: "2.75012"; } - ListElement{ radius: "70"; angle: "45"; value: "5.96608"; } - ListElement{ radius: "70"; angle: "50"; value: "8.91296"; } - ListElement{ radius: "70"; angle: "55"; value: "11.5683"; } - ListElement{ radius: "70"; angle: "60"; value: "13.912"; } - ListElement{ radius: "70"; angle: "65"; value: "15.9261"; } - ListElement{ radius: "70"; angle: "70"; value: "17.5954"; } - ListElement{ radius: "70"; angle: "75"; value: "18.907"; } - ListElement{ radius: "70"; angle: "80"; value: "19.8511"; } - ListElement{ radius: "70"; angle: "85"; value: "20.4205"; } - ListElement{ radius: "70"; angle: "90"; value: "20.6107"; } - ListElement{ radius: "70"; angle: "95"; value: "20.4205"; } - ListElement{ radius: "70"; angle: "100"; value: "19.8511"; } - ListElement{ radius: "70"; angle: "105"; value: "18.907"; } - ListElement{ radius: "70"; angle: "110"; value: "17.5954"; } - ListElement{ radius: "70"; angle: "115"; value: "15.9261"; } - ListElement{ radius: "70"; angle: "120"; value: "13.912"; } - ListElement{ radius: "70"; angle: "125"; value: "11.5683"; } - ListElement{ radius: "70"; angle: "130"; value: "8.91296"; } - ListElement{ radius: "70"; angle: "135"; value: "5.96608"; } - ListElement{ radius: "70"; angle: "140"; value: "2.75012"; } - ListElement{ radius: "70"; angle: "145"; value: "-0.710441"; } - ListElement{ radius: "70"; angle: "150"; value: "-4.38926"; } - ListElement{ radius: "70"; angle: "155"; value: "-8.25835"; } - ListElement{ radius: "70"; angle: "160"; value: "-12.2883"; } - ListElement{ radius: "70"; angle: "165"; value: "-16.4483"; } - ListElement{ radius: "70"; angle: "170"; value: "-20.7069"; } - ListElement{ radius: "70"; angle: "175"; value: "-25.0315"; } - ListElement{ radius: "70"; angle: "180"; value: "-29.3893"; } - ListElement{ radius: "70"; angle: "185"; value: "-33.747"; } - ListElement{ radius: "70"; angle: "190"; value: "-38.0717"; } - ListElement{ radius: "70"; angle: "195"; value: "-42.3302"; } - ListElement{ radius: "70"; angle: "200"; value: "-46.4903"; } - ListElement{ radius: "70"; angle: "205"; value: "-50.5202"; } - ListElement{ radius: "70"; angle: "210"; value: "-54.3893"; } - ListElement{ radius: "70"; angle: "215"; value: "-58.0681"; } - ListElement{ radius: "70"; angle: "220"; value: "-61.5286"; } - ListElement{ radius: "70"; angle: "225"; value: "-64.7446"; } - ListElement{ radius: "70"; angle: "230"; value: "-67.6915"; } - ListElement{ radius: "70"; angle: "235"; value: "-70.3469"; } - ListElement{ radius: "70"; angle: "240"; value: "-72.6905"; } - ListElement{ radius: "70"; angle: "245"; value: "-74.7047"; } - ListElement{ radius: "70"; angle: "250"; value: "-76.3739"; } - ListElement{ radius: "70"; angle: "255"; value: "-77.6856"; } - ListElement{ radius: "70"; angle: "260"; value: "-78.6297"; } - ListElement{ radius: "70"; angle: "265"; value: "-79.199"; } - ListElement{ radius: "70"; angle: "270"; value: "-79.3893"; } - ListElement{ radius: "70"; angle: "275"; value: "-79.199"; } - ListElement{ radius: "70"; angle: "280"; value: "-78.6297"; } - ListElement{ radius: "70"; angle: "285"; value: "-77.6856"; } - ListElement{ radius: "70"; angle: "290"; value: "-76.3739"; } - ListElement{ radius: "70"; angle: "295"; value: "-74.7047"; } - ListElement{ radius: "70"; angle: "300"; value: "-72.6905"; } - ListElement{ radius: "70"; angle: "305"; value: "-70.3469"; } - ListElement{ radius: "70"; angle: "310"; value: "-67.6915"; } - ListElement{ radius: "70"; angle: "315"; value: "-64.7446"; } - ListElement{ radius: "70"; angle: "320"; value: "-61.5286"; } - ListElement{ radius: "70"; angle: "325"; value: "-58.0681"; } - ListElement{ radius: "70"; angle: "330"; value: "-54.3893"; } - ListElement{ radius: "70"; angle: "335"; value: "-50.5202"; } - ListElement{ radius: "70"; angle: "340"; value: "-46.4903"; } - ListElement{ radius: "70"; angle: "345"; value: "-42.3302"; } - ListElement{ radius: "70"; angle: "350"; value: "-38.0717"; } - ListElement{ radius: "70"; angle: "355"; value: "-33.747"; } - ListElement{ radius: "70"; angle: "360"; value: "-29.3893"; } - ListElement{ radius: "75"; angle: "0"; value: "-35.3553"; } - ListElement{ radius: "75"; angle: "5"; value: "-30.9976"; } - ListElement{ radius: "75"; angle: "10"; value: "-26.6729"; } - ListElement{ radius: "75"; angle: "15"; value: "-22.4144"; } - ListElement{ radius: "75"; angle: "20"; value: "-18.2543"; } - ListElement{ radius: "75"; angle: "25"; value: "-14.2244"; } - ListElement{ radius: "75"; angle: "30"; value: "-10.3553"; } - ListElement{ radius: "75"; angle: "35"; value: "-6.67652"; } - ListElement{ radius: "75"; angle: "40"; value: "-3.21596"; } - ListElement{ radius: "75"; angle: "45"; value: "5.55112e-15"; } - ListElement{ radius: "75"; angle: "50"; value: "2.94688"; } - ListElement{ radius: "75"; angle: "55"; value: "5.60226"; } - ListElement{ radius: "75"; angle: "60"; value: "7.94593"; } - ListElement{ radius: "75"; angle: "65"; value: "9.96005"; } - ListElement{ radius: "75"; angle: "70"; value: "11.6293"; } - ListElement{ radius: "75"; angle: "75"; value: "12.941"; } - ListElement{ radius: "75"; angle: "80"; value: "13.885"; } - ListElement{ radius: "75"; angle: "85"; value: "14.4544"; } - ListElement{ radius: "75"; angle: "90"; value: "14.6447"; } - ListElement{ radius: "75"; angle: "95"; value: "14.4544"; } - ListElement{ radius: "75"; angle: "100"; value: "13.885"; } - ListElement{ radius: "75"; angle: "105"; value: "12.941"; } - ListElement{ radius: "75"; angle: "110"; value: "11.6293"; } - ListElement{ radius: "75"; angle: "115"; value: "9.96005"; } - ListElement{ radius: "75"; angle: "120"; value: "7.94593"; } - ListElement{ radius: "75"; angle: "125"; value: "5.60226"; } - ListElement{ radius: "75"; angle: "130"; value: "2.94688"; } - ListElement{ radius: "75"; angle: "135"; value: "5.55112e-15"; } - ListElement{ radius: "75"; angle: "140"; value: "-3.21596"; } - ListElement{ radius: "75"; angle: "145"; value: "-6.67652"; } - ListElement{ radius: "75"; angle: "150"; value: "-10.3553"; } - ListElement{ radius: "75"; angle: "155"; value: "-14.2244"; } - ListElement{ radius: "75"; angle: "160"; value: "-18.2543"; } - ListElement{ radius: "75"; angle: "165"; value: "-22.4144"; } - ListElement{ radius: "75"; angle: "170"; value: "-26.6729"; } - ListElement{ radius: "75"; angle: "175"; value: "-30.9976"; } - ListElement{ radius: "75"; angle: "180"; value: "-35.3553"; } - ListElement{ radius: "75"; angle: "185"; value: "-39.7131"; } - ListElement{ radius: "75"; angle: "190"; value: "-44.0377"; } - ListElement{ radius: "75"; angle: "195"; value: "-48.2963"; } - ListElement{ radius: "75"; angle: "200"; value: "-52.4563"; } - ListElement{ radius: "75"; angle: "205"; value: "-56.4863"; } - ListElement{ radius: "75"; angle: "210"; value: "-60.3553"; } - ListElement{ radius: "75"; angle: "215"; value: "-64.0342"; } - ListElement{ radius: "75"; angle: "220"; value: "-67.4947"; } - ListElement{ radius: "75"; angle: "225"; value: "-70.7107"; } - ListElement{ radius: "75"; angle: "230"; value: "-73.6576"; } - ListElement{ radius: "75"; angle: "235"; value: "-76.3129"; } - ListElement{ radius: "75"; angle: "240"; value: "-78.6566"; } - ListElement{ radius: "75"; angle: "245"; value: "-80.6707"; } - ListElement{ radius: "75"; angle: "250"; value: "-82.34"; } - ListElement{ radius: "75"; angle: "255"; value: "-83.6516"; } - ListElement{ radius: "75"; angle: "260"; value: "-84.5957"; } - ListElement{ radius: "75"; angle: "265"; value: "-85.1651"; } - ListElement{ radius: "75"; angle: "270"; value: "-85.3553"; } - ListElement{ radius: "75"; angle: "275"; value: "-85.1651"; } - ListElement{ radius: "75"; angle: "280"; value: "-84.5957"; } - ListElement{ radius: "75"; angle: "285"; value: "-83.6516"; } - ListElement{ radius: "75"; angle: "290"; value: "-82.34"; } - ListElement{ radius: "75"; angle: "295"; value: "-80.6707"; } - ListElement{ radius: "75"; angle: "300"; value: "-78.6566"; } - ListElement{ radius: "75"; angle: "305"; value: "-76.3129"; } - ListElement{ radius: "75"; angle: "310"; value: "-73.6576"; } - ListElement{ radius: "75"; angle: "315"; value: "-70.7107"; } - ListElement{ radius: "75"; angle: "320"; value: "-67.4947"; } - ListElement{ radius: "75"; angle: "325"; value: "-64.0342"; } - ListElement{ radius: "75"; angle: "330"; value: "-60.3553"; } - ListElement{ radius: "75"; angle: "335"; value: "-56.4863"; } - ListElement{ radius: "75"; angle: "340"; value: "-52.4563"; } - ListElement{ radius: "75"; angle: "345"; value: "-48.2963"; } - ListElement{ radius: "75"; angle: "350"; value: "-44.0377"; } - ListElement{ radius: "75"; angle: "355"; value: "-39.7131"; } - ListElement{ radius: "75"; angle: "360"; value: "-35.3553"; } - ListElement{ radius: "80"; angle: "0"; value: "-40.4508"; } - ListElement{ radius: "80"; angle: "5"; value: "-36.0931"; } - ListElement{ radius: "80"; angle: "10"; value: "-31.7684"; } - ListElement{ radius: "80"; angle: "15"; value: "-27.5099"; } - ListElement{ radius: "80"; angle: "20"; value: "-23.3498"; } - ListElement{ radius: "80"; angle: "25"; value: "-19.3199"; } - ListElement{ radius: "80"; angle: "30"; value: "-15.4508"; } - ListElement{ radius: "80"; angle: "35"; value: "-11.772"; } - ListElement{ radius: "80"; angle: "40"; value: "-8.31147"; } - ListElement{ radius: "80"; angle: "45"; value: "-5.09551"; } - ListElement{ radius: "80"; angle: "50"; value: "-2.14863"; } - ListElement{ radius: "80"; angle: "55"; value: "0.506752"; } - ListElement{ radius: "80"; angle: "60"; value: "2.85042"; } - ListElement{ radius: "80"; angle: "65"; value: "4.86454"; } - ListElement{ radius: "80"; angle: "70"; value: "6.53378"; } - ListElement{ radius: "80"; angle: "75"; value: "7.84544"; } - ListElement{ radius: "80"; angle: "80"; value: "8.78954"; } - ListElement{ radius: "80"; angle: "85"; value: "9.35889"; } - ListElement{ radius: "80"; angle: "90"; value: "9.54915"; } - ListElement{ radius: "80"; angle: "95"; value: "9.35889"; } - ListElement{ radius: "80"; angle: "100"; value: "8.78954"; } - ListElement{ radius: "80"; angle: "105"; value: "7.84544"; } - ListElement{ radius: "80"; angle: "110"; value: "6.53378"; } - ListElement{ radius: "80"; angle: "115"; value: "4.86454"; } - ListElement{ radius: "80"; angle: "120"; value: "2.85042"; } - ListElement{ radius: "80"; angle: "125"; value: "0.506752"; } - ListElement{ radius: "80"; angle: "130"; value: "-2.14863"; } - ListElement{ radius: "80"; angle: "135"; value: "-5.09551"; } - ListElement{ radius: "80"; angle: "140"; value: "-8.31147"; } - ListElement{ radius: "80"; angle: "145"; value: "-11.772"; } - ListElement{ radius: "80"; angle: "150"; value: "-15.4508"; } - ListElement{ radius: "80"; angle: "155"; value: "-19.3199"; } - ListElement{ radius: "80"; angle: "160"; value: "-23.3498"; } - ListElement{ radius: "80"; angle: "165"; value: "-27.5099"; } - ListElement{ radius: "80"; angle: "170"; value: "-31.7684"; } - ListElement{ radius: "80"; angle: "175"; value: "-36.0931"; } - ListElement{ radius: "80"; angle: "180"; value: "-40.4508"; } - ListElement{ radius: "80"; angle: "185"; value: "-44.8086"; } - ListElement{ radius: "80"; angle: "190"; value: "-49.1333"; } - ListElement{ radius: "80"; angle: "195"; value: "-53.3918"; } - ListElement{ radius: "80"; angle: "200"; value: "-57.5519"; } - ListElement{ radius: "80"; angle: "205"; value: "-61.5818"; } - ListElement{ radius: "80"; angle: "210"; value: "-65.4508"; } - ListElement{ radius: "80"; angle: "215"; value: "-69.1297"; } - ListElement{ radius: "80"; angle: "220"; value: "-72.5902"; } - ListElement{ radius: "80"; angle: "225"; value: "-75.8062"; } - ListElement{ radius: "80"; angle: "230"; value: "-78.7531"; } - ListElement{ radius: "80"; angle: "235"; value: "-81.4085"; } - ListElement{ radius: "80"; angle: "240"; value: "-83.7521"; } - ListElement{ radius: "80"; angle: "245"; value: "-85.7662"; } - ListElement{ radius: "80"; angle: "250"; value: "-87.4355"; } - ListElement{ radius: "80"; angle: "255"; value: "-88.7471"; } - ListElement{ radius: "80"; angle: "260"; value: "-89.6912"; } - ListElement{ radius: "80"; angle: "265"; value: "-90.2606"; } - ListElement{ radius: "80"; angle: "270"; value: "-90.4508"; } - ListElement{ radius: "80"; angle: "275"; value: "-90.2606"; } - ListElement{ radius: "80"; angle: "280"; value: "-89.6912"; } - ListElement{ radius: "80"; angle: "285"; value: "-88.7471"; } - ListElement{ radius: "80"; angle: "290"; value: "-87.4355"; } - ListElement{ radius: "80"; angle: "295"; value: "-85.7662"; } - ListElement{ radius: "80"; angle: "300"; value: "-83.7521"; } - ListElement{ radius: "80"; angle: "305"; value: "-81.4085"; } - ListElement{ radius: "80"; angle: "310"; value: "-78.7531"; } - ListElement{ radius: "80"; angle: "315"; value: "-75.8062"; } - ListElement{ radius: "80"; angle: "320"; value: "-72.5902"; } - ListElement{ radius: "80"; angle: "325"; value: "-69.1297"; } - ListElement{ radius: "80"; angle: "330"; value: "-65.4508"; } - ListElement{ radius: "80"; angle: "335"; value: "-61.5818"; } - ListElement{ radius: "80"; angle: "340"; value: "-57.5519"; } - ListElement{ radius: "80"; angle: "345"; value: "-53.3918"; } - ListElement{ radius: "80"; angle: "350"; value: "-49.1333"; } - ListElement{ radius: "80"; angle: "355"; value: "-44.8086"; } - ListElement{ radius: "80"; angle: "360"; value: "-40.4508"; } - ListElement{ radius: "85"; angle: "0"; value: "-44.5503"; } - ListElement{ radius: "85"; angle: "5"; value: "-40.1925"; } - ListElement{ radius: "85"; angle: "10"; value: "-35.8679"; } - ListElement{ radius: "85"; angle: "15"; value: "-31.6094"; } - ListElement{ radius: "85"; angle: "20"; value: "-27.4493"; } - ListElement{ radius: "85"; angle: "25"; value: "-23.4194"; } - ListElement{ radius: "85"; angle: "30"; value: "-19.5503"; } - ListElement{ radius: "85"; angle: "35"; value: "-15.8715"; } - ListElement{ radius: "85"; angle: "40"; value: "-12.4109"; } - ListElement{ radius: "85"; angle: "45"; value: "-9.19499"; } - ListElement{ radius: "85"; angle: "50"; value: "-6.2481"; } - ListElement{ radius: "85"; angle: "55"; value: "-3.59272"; } - ListElement{ radius: "85"; angle: "60"; value: "-1.24906"; } - ListElement{ radius: "85"; angle: "65"; value: "0.765063"; } - ListElement{ radius: "85"; angle: "70"; value: "2.4343"; } - ListElement{ radius: "85"; angle: "75"; value: "3.74597"; } - ListElement{ radius: "85"; angle: "80"; value: "4.69006"; } - ListElement{ radius: "85"; angle: "85"; value: "5.25941"; } - ListElement{ radius: "85"; angle: "90"; value: "5.44967"; } - ListElement{ radius: "85"; angle: "95"; value: "5.25941"; } - ListElement{ radius: "85"; angle: "100"; value: "4.69006"; } - ListElement{ radius: "85"; angle: "105"; value: "3.74597"; } - ListElement{ radius: "85"; angle: "110"; value: "2.4343"; } - ListElement{ radius: "85"; angle: "115"; value: "0.765063"; } - ListElement{ radius: "85"; angle: "120"; value: "-1.24906"; } - ListElement{ radius: "85"; angle: "125"; value: "-3.59272"; } - ListElement{ radius: "85"; angle: "130"; value: "-6.2481"; } - ListElement{ radius: "85"; angle: "135"; value: "-9.19499"; } - ListElement{ radius: "85"; angle: "140"; value: "-12.4109"; } - ListElement{ radius: "85"; angle: "145"; value: "-15.8715"; } - ListElement{ radius: "85"; angle: "150"; value: "-19.5503"; } - ListElement{ radius: "85"; angle: "155"; value: "-23.4194"; } - ListElement{ radius: "85"; angle: "160"; value: "-27.4493"; } - ListElement{ radius: "85"; angle: "165"; value: "-31.6094"; } - ListElement{ radius: "85"; angle: "170"; value: "-35.8679"; } - ListElement{ radius: "85"; angle: "175"; value: "-40.1925"; } - ListElement{ radius: "85"; angle: "180"; value: "-44.5503"; } - ListElement{ radius: "85"; angle: "185"; value: "-48.9081"; } - ListElement{ radius: "85"; angle: "190"; value: "-53.2327"; } - ListElement{ radius: "85"; angle: "195"; value: "-57.4913"; } - ListElement{ radius: "85"; angle: "200"; value: "-61.6513"; } - ListElement{ radius: "85"; angle: "205"; value: "-65.6812"; } - ListElement{ radius: "85"; angle: "210"; value: "-69.5503"; } - ListElement{ radius: "85"; angle: "215"; value: "-73.2291"; } - ListElement{ radius: "85"; angle: "220"; value: "-76.6897"; } - ListElement{ radius: "85"; angle: "225"; value: "-79.9057"; } - ListElement{ radius: "85"; angle: "230"; value: "-82.8525"; } - ListElement{ radius: "85"; angle: "235"; value: "-85.5079"; } - ListElement{ radius: "85"; angle: "240"; value: "-87.8516"; } - ListElement{ radius: "85"; angle: "245"; value: "-89.8657"; } - ListElement{ radius: "85"; angle: "250"; value: "-91.535"; } - ListElement{ radius: "85"; angle: "255"; value: "-92.8466"; } - ListElement{ radius: "85"; angle: "260"; value: "-93.7907"; } - ListElement{ radius: "85"; angle: "265"; value: "-94.3601"; } - ListElement{ radius: "85"; angle: "270"; value: "-94.5503"; } - ListElement{ radius: "85"; angle: "275"; value: "-94.3601"; } - ListElement{ radius: "85"; angle: "280"; value: "-93.7907"; } - ListElement{ radius: "85"; angle: "285"; value: "-92.8466"; } - ListElement{ radius: "85"; angle: "290"; value: "-91.535"; } - ListElement{ radius: "85"; angle: "295"; value: "-89.8657"; } - ListElement{ radius: "85"; angle: "300"; value: "-87.8516"; } - ListElement{ radius: "85"; angle: "305"; value: "-85.5079"; } - ListElement{ radius: "85"; angle: "310"; value: "-82.8525"; } - ListElement{ radius: "85"; angle: "315"; value: "-79.9057"; } - ListElement{ radius: "85"; angle: "320"; value: "-76.6897"; } - ListElement{ radius: "85"; angle: "325"; value: "-73.2291"; } - ListElement{ radius: "85"; angle: "330"; value: "-69.5503"; } - ListElement{ radius: "85"; angle: "335"; value: "-65.6812"; } - ListElement{ radius: "85"; angle: "340"; value: "-61.6513"; } - ListElement{ radius: "85"; angle: "345"; value: "-57.4913"; } - ListElement{ radius: "85"; angle: "350"; value: "-53.2327"; } - ListElement{ radius: "85"; angle: "355"; value: "-48.9081"; } - ListElement{ radius: "85"; angle: "360"; value: "-44.5503"; } - ListElement{ radius: "90"; angle: "0"; value: "-47.5528"; } - ListElement{ radius: "90"; angle: "5"; value: "-43.195"; } - ListElement{ radius: "90"; angle: "10"; value: "-38.8704"; } - ListElement{ radius: "90"; angle: "15"; value: "-34.6119"; } - ListElement{ radius: "90"; angle: "20"; value: "-30.4518"; } - ListElement{ radius: "90"; angle: "25"; value: "-26.4219"; } - ListElement{ radius: "90"; angle: "30"; value: "-22.5528"; } - ListElement{ radius: "90"; angle: "35"; value: "-18.874"; } - ListElement{ radius: "90"; angle: "40"; value: "-15.4134"; } - ListElement{ radius: "90"; angle: "45"; value: "-12.1975"; } - ListElement{ radius: "90"; angle: "50"; value: "-9.2506"; } - ListElement{ radius: "90"; angle: "55"; value: "-6.59522"; } - ListElement{ radius: "90"; angle: "60"; value: "-4.25156"; } - ListElement{ radius: "90"; angle: "65"; value: "-2.23744"; } - ListElement{ radius: "90"; angle: "70"; value: "-0.568195"; } - ListElement{ radius: "90"; angle: "75"; value: "0.743465"; } - ListElement{ radius: "90"; angle: "80"; value: "1.68756"; } - ListElement{ radius: "90"; angle: "85"; value: "2.25691"; } - ListElement{ radius: "90"; angle: "90"; value: "2.44717"; } - ListElement{ radius: "90"; angle: "95"; value: "2.25691"; } - ListElement{ radius: "90"; angle: "100"; value: "1.68756"; } - ListElement{ radius: "90"; angle: "105"; value: "0.743465"; } - ListElement{ radius: "90"; angle: "110"; value: "-0.568195"; } - ListElement{ radius: "90"; angle: "115"; value: "-2.23744"; } - ListElement{ radius: "90"; angle: "120"; value: "-4.25156"; } - ListElement{ radius: "90"; angle: "125"; value: "-6.59522"; } - ListElement{ radius: "90"; angle: "130"; value: "-9.2506"; } - ListElement{ radius: "90"; angle: "135"; value: "-12.1975"; } - ListElement{ radius: "90"; angle: "140"; value: "-15.4134"; } - ListElement{ radius: "90"; angle: "145"; value: "-18.874"; } - ListElement{ radius: "90"; angle: "150"; value: "-22.5528"; } - ListElement{ radius: "90"; angle: "155"; value: "-26.4219"; } - ListElement{ radius: "90"; angle: "160"; value: "-30.4518"; } - ListElement{ radius: "90"; angle: "165"; value: "-34.6119"; } - ListElement{ radius: "90"; angle: "170"; value: "-38.8704"; } - ListElement{ radius: "90"; angle: "175"; value: "-43.195"; } - ListElement{ radius: "90"; angle: "180"; value: "-47.5528"; } - ListElement{ radius: "90"; angle: "185"; value: "-51.9106"; } - ListElement{ radius: "90"; angle: "190"; value: "-56.2352"; } - ListElement{ radius: "90"; angle: "195"; value: "-60.4938"; } - ListElement{ radius: "90"; angle: "200"; value: "-64.6538"; } - ListElement{ radius: "90"; angle: "205"; value: "-68.6837"; } - ListElement{ radius: "90"; angle: "210"; value: "-72.5528"; } - ListElement{ radius: "90"; angle: "215"; value: "-76.2316"; } - ListElement{ radius: "90"; angle: "220"; value: "-79.6922"; } - ListElement{ radius: "90"; angle: "225"; value: "-82.9082"; } - ListElement{ radius: "90"; angle: "230"; value: "-85.855"; } - ListElement{ radius: "90"; angle: "235"; value: "-88.5104"; } - ListElement{ radius: "90"; angle: "240"; value: "-90.8541"; } - ListElement{ radius: "90"; angle: "245"; value: "-92.8682"; } - ListElement{ radius: "90"; angle: "250"; value: "-94.5375"; } - ListElement{ radius: "90"; angle: "255"; value: "-95.8491"; } - ListElement{ radius: "90"; angle: "260"; value: "-96.7932"; } - ListElement{ radius: "90"; angle: "265"; value: "-97.3626"; } - ListElement{ radius: "90"; angle: "270"; value: "-97.5528"; } - ListElement{ radius: "90"; angle: "275"; value: "-97.3626"; } - ListElement{ radius: "90"; angle: "280"; value: "-96.7932"; } - ListElement{ radius: "90"; angle: "285"; value: "-95.8491"; } - ListElement{ radius: "90"; angle: "290"; value: "-94.5375"; } - ListElement{ radius: "90"; angle: "295"; value: "-92.8682"; } - ListElement{ radius: "90"; angle: "300"; value: "-90.8541"; } - ListElement{ radius: "90"; angle: "305"; value: "-88.5104"; } - ListElement{ radius: "90"; angle: "310"; value: "-85.855"; } - ListElement{ radius: "90"; angle: "315"; value: "-82.9082"; } - ListElement{ radius: "90"; angle: "320"; value: "-79.6922"; } - ListElement{ radius: "90"; angle: "325"; value: "-76.2316"; } - ListElement{ radius: "90"; angle: "330"; value: "-72.5528"; } - ListElement{ radius: "90"; angle: "335"; value: "-68.6837"; } - ListElement{ radius: "90"; angle: "340"; value: "-64.6538"; } - ListElement{ radius: "90"; angle: "345"; value: "-60.4938"; } - ListElement{ radius: "90"; angle: "350"; value: "-56.2352"; } - ListElement{ radius: "90"; angle: "355"; value: "-51.9106"; } - ListElement{ radius: "90"; angle: "360"; value: "-47.5528"; } - ListElement{ radius: "95"; angle: "0"; value: "-49.3844"; } - ListElement{ radius: "95"; angle: "5"; value: "-45.0266"; } - ListElement{ radius: "95"; angle: "10"; value: "-40.702"; } - ListElement{ radius: "95"; angle: "15"; value: "-36.4435"; } - ListElement{ radius: "95"; angle: "20"; value: "-32.2834"; } - ListElement{ radius: "95"; angle: "25"; value: "-28.2535"; } - ListElement{ radius: "95"; angle: "30"; value: "-24.3844"; } - ListElement{ radius: "95"; angle: "35"; value: "-20.7056"; } - ListElement{ radius: "95"; angle: "40"; value: "-17.245"; } - ListElement{ radius: "95"; angle: "45"; value: "-14.0291"; } - ListElement{ radius: "95"; angle: "50"; value: "-11.0822"; } - ListElement{ radius: "95"; angle: "55"; value: "-8.42681"; } - ListElement{ radius: "95"; angle: "60"; value: "-6.08315"; } - ListElement{ radius: "95"; angle: "65"; value: "-4.06903"; } - ListElement{ radius: "95"; angle: "70"; value: "-2.39979"; } - ListElement{ radius: "95"; angle: "75"; value: "-1.08813"; } - ListElement{ radius: "95"; angle: "80"; value: "-0.144029"; } - ListElement{ radius: "95"; angle: "85"; value: "0.425318"; } - ListElement{ radius: "95"; angle: "90"; value: "0.615583"; } - ListElement{ radius: "95"; angle: "95"; value: "0.425318"; } - ListElement{ radius: "95"; angle: "100"; value: "-0.144029"; } - ListElement{ radius: "95"; angle: "105"; value: "-1.08813"; } - ListElement{ radius: "95"; angle: "110"; value: "-2.39979"; } - ListElement{ radius: "95"; angle: "115"; value: "-4.06903"; } - ListElement{ radius: "95"; angle: "120"; value: "-6.08315"; } - ListElement{ radius: "95"; angle: "125"; value: "-8.42681"; } - ListElement{ radius: "95"; angle: "130"; value: "-11.0822"; } - ListElement{ radius: "95"; angle: "135"; value: "-14.0291"; } - ListElement{ radius: "95"; angle: "140"; value: "-17.245"; } - ListElement{ radius: "95"; angle: "145"; value: "-20.7056"; } - ListElement{ radius: "95"; angle: "150"; value: "-24.3844"; } - ListElement{ radius: "95"; angle: "155"; value: "-28.2535"; } - ListElement{ radius: "95"; angle: "160"; value: "-32.2834"; } - ListElement{ radius: "95"; angle: "165"; value: "-36.4435"; } - ListElement{ radius: "95"; angle: "170"; value: "-40.702"; } - ListElement{ radius: "95"; angle: "175"; value: "-45.0266"; } - ListElement{ radius: "95"; angle: "180"; value: "-49.3844"; } - ListElement{ radius: "95"; angle: "185"; value: "-53.7422"; } - ListElement{ radius: "95"; angle: "190"; value: "-58.0668"; } - ListElement{ radius: "95"; angle: "195"; value: "-62.3254"; } - ListElement{ radius: "95"; angle: "200"; value: "-66.4854"; } - ListElement{ radius: "95"; angle: "205"; value: "-70.5153"; } - ListElement{ radius: "95"; angle: "210"; value: "-74.3844"; } - ListElement{ radius: "95"; angle: "215"; value: "-78.0632"; } - ListElement{ radius: "95"; angle: "220"; value: "-81.5238"; } - ListElement{ radius: "95"; angle: "225"; value: "-84.7398"; } - ListElement{ radius: "95"; angle: "230"; value: "-87.6866"; } - ListElement{ radius: "95"; angle: "235"; value: "-90.342"; } - ListElement{ radius: "95"; angle: "240"; value: "-92.6857"; } - ListElement{ radius: "95"; angle: "245"; value: "-94.6998"; } - ListElement{ radius: "95"; angle: "250"; value: "-96.369"; } - ListElement{ radius: "95"; angle: "255"; value: "-97.6807"; } - ListElement{ radius: "95"; angle: "260"; value: "-98.6248"; } - ListElement{ radius: "95"; angle: "265"; value: "-99.1942"; } - ListElement{ radius: "95"; angle: "270"; value: "-99.3844"; } - ListElement{ radius: "95"; angle: "275"; value: "-99.1942"; } - ListElement{ radius: "95"; angle: "280"; value: "-98.6248"; } - ListElement{ radius: "95"; angle: "285"; value: "-97.6807"; } - ListElement{ radius: "95"; angle: "290"; value: "-96.369"; } - ListElement{ radius: "95"; angle: "295"; value: "-94.6998"; } - ListElement{ radius: "95"; angle: "300"; value: "-92.6857"; } - ListElement{ radius: "95"; angle: "305"; value: "-90.342"; } - ListElement{ radius: "95"; angle: "310"; value: "-87.6866"; } - ListElement{ radius: "95"; angle: "315"; value: "-84.7398"; } - ListElement{ radius: "95"; angle: "320"; value: "-81.5238"; } - ListElement{ radius: "95"; angle: "325"; value: "-78.0632"; } - ListElement{ radius: "95"; angle: "330"; value: "-74.3844"; } - ListElement{ radius: "95"; angle: "335"; value: "-70.5153"; } - ListElement{ radius: "95"; angle: "340"; value: "-66.4854"; } - ListElement{ radius: "95"; angle: "345"; value: "-62.3254"; } - ListElement{ radius: "95"; angle: "350"; value: "-58.0668"; } - ListElement{ radius: "95"; angle: "355"; value: "-53.7422"; } - ListElement{ radius: "95"; angle: "360"; value: "-49.3844"; } - ListElement{ radius: "100"; angle: "0"; value: "-50"; } - ListElement{ radius: "100"; angle: "5"; value: "-45.6422"; } - ListElement{ radius: "100"; angle: "10"; value: "-41.3176"; } - ListElement{ radius: "100"; angle: "15"; value: "-37.059"; } - ListElement{ radius: "100"; angle: "20"; value: "-32.899"; } - ListElement{ radius: "100"; angle: "25"; value: "-28.8691"; } - ListElement{ radius: "100"; angle: "30"; value: "-25"; } - ListElement{ radius: "100"; angle: "35"; value: "-21.3212"; } - ListElement{ radius: "100"; angle: "40"; value: "-17.8606"; } - ListElement{ radius: "100"; angle: "45"; value: "-14.6447"; } - ListElement{ radius: "100"; angle: "50"; value: "-11.6978"; } - ListElement{ radius: "100"; angle: "55"; value: "-9.0424"; } - ListElement{ radius: "100"; angle: "60"; value: "-6.69873"; } - ListElement{ radius: "100"; angle: "65"; value: "-4.68461"; } - ListElement{ radius: "100"; angle: "70"; value: "-3.01537"; } - ListElement{ radius: "100"; angle: "75"; value: "-1.70371"; } - ListElement{ radius: "100"; angle: "80"; value: "-0.759612"; } - ListElement{ radius: "100"; angle: "85"; value: "-0.190265"; } - ListElement{ radius: "100"; angle: "90"; value: "0"; } - ListElement{ radius: "100"; angle: "95"; value: "-0.190265"; } - ListElement{ radius: "100"; angle: "100"; value: "-0.759612"; } - ListElement{ radius: "100"; angle: "105"; value: "-1.70371"; } - ListElement{ radius: "100"; angle: "110"; value: "-3.01537"; } - ListElement{ radius: "100"; angle: "115"; value: "-4.68461"; } - ListElement{ radius: "100"; angle: "120"; value: "-6.69873"; } - ListElement{ radius: "100"; angle: "125"; value: "-9.0424"; } - ListElement{ radius: "100"; angle: "130"; value: "-11.6978"; } - ListElement{ radius: "100"; angle: "135"; value: "-14.6447"; } - ListElement{ radius: "100"; angle: "140"; value: "-17.8606"; } - ListElement{ radius: "100"; angle: "145"; value: "-21.3212"; } - ListElement{ radius: "100"; angle: "150"; value: "-25"; } - ListElement{ radius: "100"; angle: "155"; value: "-28.8691"; } - ListElement{ radius: "100"; angle: "160"; value: "-32.899"; } - ListElement{ radius: "100"; angle: "165"; value: "-37.059"; } - ListElement{ radius: "100"; angle: "170"; value: "-41.3176"; } - ListElement{ radius: "100"; angle: "175"; value: "-45.6422"; } - ListElement{ radius: "100"; angle: "180"; value: "-50"; } - ListElement{ radius: "100"; angle: "185"; value: "-54.3578"; } - ListElement{ radius: "100"; angle: "190"; value: "-58.6824"; } - ListElement{ radius: "100"; angle: "195"; value: "-62.941"; } - ListElement{ radius: "100"; angle: "200"; value: "-67.101"; } - ListElement{ radius: "100"; angle: "205"; value: "-71.1309"; } - ListElement{ radius: "100"; angle: "210"; value: "-75"; } - ListElement{ radius: "100"; angle: "215"; value: "-78.6788"; } - ListElement{ radius: "100"; angle: "220"; value: "-82.1394"; } - ListElement{ radius: "100"; angle: "225"; value: "-85.3553"; } - ListElement{ radius: "100"; angle: "230"; value: "-88.3022"; } - ListElement{ radius: "100"; angle: "235"; value: "-90.9576"; } - ListElement{ radius: "100"; angle: "240"; value: "-93.3013"; } - ListElement{ radius: "100"; angle: "245"; value: "-95.3154"; } - ListElement{ radius: "100"; angle: "250"; value: "-96.9846"; } - ListElement{ radius: "100"; angle: "255"; value: "-98.2963"; } - ListElement{ radius: "100"; angle: "260"; value: "-99.2404"; } - ListElement{ radius: "100"; angle: "265"; value: "-99.8097"; } - ListElement{ radius: "100"; angle: "270"; value: "-100"; } - ListElement{ radius: "100"; angle: "275"; value: "-99.8097"; } - ListElement{ radius: "100"; angle: "280"; value: "-99.2404"; } - ListElement{ radius: "100"; angle: "285"; value: "-98.2963"; } - ListElement{ radius: "100"; angle: "290"; value: "-96.9846"; } - ListElement{ radius: "100"; angle: "295"; value: "-95.3154"; } - ListElement{ radius: "100"; angle: "300"; value: "-93.3013"; } - ListElement{ radius: "100"; angle: "305"; value: "-90.9576"; } - ListElement{ radius: "100"; angle: "310"; value: "-88.3022"; } - ListElement{ radius: "100"; angle: "315"; value: "-85.3553"; } - ListElement{ radius: "100"; angle: "320"; value: "-82.1394"; } - ListElement{ radius: "100"; angle: "325"; value: "-78.6788"; } - ListElement{ radius: "100"; angle: "330"; value: "-75"; } - ListElement{ radius: "100"; angle: "335"; value: "-71.1309"; } - ListElement{ radius: "100"; angle: "340"; value: "-67.101"; } - ListElement{ radius: "100"; angle: "345"; value: "-62.941"; } - ListElement{ radius: "100"; angle: "350"; value: "-58.6824"; } - ListElement{ radius: "100"; angle: "355"; value: "-54.3578"; } - ListElement{ radius: "100"; angle: "360"; value: "-50"; } - } -} diff --git a/libraries/disp/viewers/qml/NewButton.qml b/libraries/disp/viewers/qml/NewButton.qml deleted file mode 100644 index 19309cca237..00000000000 --- a/libraries/disp/viewers/qml/NewButton.qml +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 or (at your option) any later version -** approved by the KDE Free Qt Foundation. The licenses are as published by -** the Free Software Foundation and appearing in the file LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.1 -import QtQuick.Controls 1.0 -import QtQuick.Controls.Styles 1.0 - -Item { - id: newbutton - - property alias text: buttonText.text - - signal clicked - - implicitWidth: buttonText.implicitWidth + 5 - implicitHeight: buttonText.implicitHeight + 10 - - Button { - id: buttonText - width: parent.width - height: parent.height - - style: ButtonStyle { - label: Component { - Text { - text: buttonText.text - clip: true - wrapMode: Text.WordWrap - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - anchors.fill: parent - } - } - } - onClicked: newbutton.clicked() - } -} diff --git a/libraries/disp/viewers/qml/tfview.qml b/libraries/disp/viewers/qml/tfview.qml deleted file mode 100644 index 2c0e5f956ae..00000000000 --- a/libraries/disp/viewers/qml/tfview.qml +++ /dev/null @@ -1,271 +0,0 @@ -import QtQuick 2.1 -import QtQuick.Layouts 1.0 -import QtQuick.Window 2.1 -import QtDataVisualization 1.2 -import "." - -Item { - id: mainview - visible: true - width: parent.width - height: parent.height - - Data { - id: surfaceData - } - - Item { - id: surfaceView - width: mainview.width - height: mainview.height - anchors.top: mainview.top - anchors.left: mainview.left - - ColorGradient { - id: surfaceGradient - ColorGradientStop { position: 0.0; color: "red" } - ColorGradientStop { position: 0.3; color: "yellow" } - ColorGradientStop { position: 0.7; color: "cyan" } - ColorGradientStop { position: 1.0; color: "blue" } - } - - ValueAxis3D { - id: xAxis - segmentCount: 8 - labelFormat: "%i\u00B0" - title: "Time" - titleVisible: true - titleFixed: false - } - - ValueAxis3D { - id: yAxis - segmentCount: 8 - labelFormat: "%i \%" - title: "Value" - titleVisible: true - labelAutoRotation: 0 - titleFixed: false - } - - ValueAxis3D { - id: zAxis - segmentCount: 5 - labelFormat: "%i nm" - title: "Frequency" - titleVisible: true - titleFixed: false - } - - Theme3D { - id: customTheme - type: Theme3D.ThemeQt - // Don't show specular spotlight as we don't want it to distort the colors - lightStrength: 0.0 - ambientLightStrength: 1.0 - backgroundEnabled: false - gridLineColor: "#AAAAAA" - windowColor: "#EEEEEE" - } - - - //! [5] - TouchInputHandler3D { - id: customInputHandler - rotationEnabled: false - } - //! [5] - - //! [0] - //! [7] - Surface3D { - //! [7] - id: surfaceGraph - width: surfaceView.width - height: surfaceView.height - - shadowQuality: AbstractGraph3D.ShadowQualityNone - selectionMode: AbstractGraph3D.SelectionSlice | AbstractGraph3D.SelectionItemAndColumn - axisX: xAxis - axisY: yAxis - axisZ: zAxis - - theme: customTheme - //! [6] - inputHandler: customInputHandler - //! [6] - - // Remove the perspective and view the graph from top down to achieve 2D effect - //! [1] - orthoProjection: true - scene.activeCamera.cameraPreset: Camera3D.CameraPresetDirectlyAbove - //! [1] - - //! [2] - flipHorizontalGrid: true - //! [2] - - //! [4] - radialLabelOffset: 0.01 - //! [4] - - horizontalAspectRatio: 1 - scene.activeCamera.zoomLevel: 85 - - Surface3DSeries { - id: surfaceSeries - flatShadingEnabled: false - drawMode: Surface3DSeries.DrawSurface - baseGradient: surfaceGradient - colorStyle: Theme3D.ColorStyleRangeGradient - itemLabelFormat: "(@xLabel, @zLabel): @yLabel" - - ItemModelSurfaceDataProxy { - itemModel: surfaceData.model - rowRole: "radius" - columnRole: "angle" - yPosRole: "value" - } - } - } - //! [0] - } - - RowLayout { - id: buttonLayout - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - opacity: 0.5 - - //! [3] - NewButton { - id: polarToggle - Layout.fillWidth: true - Layout.fillHeight: true - text: "Switch to polar" - onClicked: { - if (surfaceGraph.polar === false) { - surfaceGraph.polar = true - text = "Switch to cartesian" - } else { - surfaceGraph.polar = false - text = "Switch to polar" - } - } - } - //! [3] - - NewButton { - id: orthoToggle - Layout.fillWidth: true - Layout.fillHeight: true - text: "Switch to perspective" - onClicked: { - if (surfaceGraph.orthoProjection === true) { - surfaceGraph.orthoProjection = false; - xAxis.labelAutoRotation = 30 - yAxis.labelAutoRotation = 30 - zAxis.labelAutoRotation = 30 - customInputHandler.rotationEnabled = true - text = "Switch to orthographic" - } else { - surfaceGraph.orthoProjection = true; - surfaceGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetDirectlyAbove - surfaceSeries.drawMode &= ~Surface3DSeries.DrawWireframe; - xAxis.labelAutoRotation = 0 - yAxis.labelAutoRotation = 0 - zAxis.labelAutoRotation = 0 - customInputHandler.rotationEnabled = false - text = "Switch to perspective" - } - } - } - - NewButton { - id: flipGridToggle - Layout.fillWidth: true - Layout.fillHeight: true - text: "Toggle axis grid on top" - onClicked: { - onClicked: { - if (surfaceGraph.flipHorizontalGrid === true) { - surfaceGraph.flipHorizontalGrid = false; - } else { - surfaceGraph.flipHorizontalGrid = true; - } - } - } - } - - NewButton { - id: labelOffsetToggle - Layout.fillWidth: true - Layout.fillHeight: true - text: "Toggle radial label position" - visible: surfaceGraph.polar - onClicked: { - if (surfaceGraph.radialLabelOffset >= 1.0) { - surfaceGraph.radialLabelOffset = 0.01 - } else { - surfaceGraph.radialLabelOffset = 1.0 - } - } - } - - NewButton { - id: surfaceGridToggle - Layout.fillWidth: true - Layout.fillHeight: true - text: "Toggle surface grid" - visible: !surfaceGraph.orthoProjection - onClicked: { - if (surfaceSeries.drawMode & Surface3DSeries.DrawWireframe) { - surfaceSeries.drawMode &= ~Surface3DSeries.DrawWireframe; - } else { - surfaceSeries.drawMode |= Surface3DSeries.DrawWireframe; - } - } - } - - } - - Rectangle { - id: legend - anchors.margins: 20 - anchors.bottom: parent.bottom - anchors.top: buttonLayout.bottom - anchors.right: parent.right - border.color: "black" - border.width: 1 - width: 50 - rotation: 180 - gradient: Gradient { - GradientStop { position: 0.0; color: "red" } - GradientStop { position: 0.3; color: "yellow" } - GradientStop { position: 0.7; color: "cyan" } - GradientStop { position: 1.0; color: "blue" } - } - } - - Text { - anchors.verticalCenter: legend.bottom - anchors.right: legend.left - anchors.margins: 2 - text: surfaceGraph.axisY.min + "%" - } - - Text { - anchors.verticalCenter: legend.verticalCenter - anchors.right: legend.left - anchors.margins: 2 - text: (surfaceGraph.axisY.max + surfaceGraph.axisY.min) / 2 + "%" - } - - Text { - anchors.verticalCenter: legend.top - anchors.right: legend.left - anchors.margins: 2 - text: surfaceGraph.axisY.max + "%" - } -} From f3794d5824cb3e1c16d595346cb82d90318c135f Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Mon, 19 Apr 2021 15:42:32 -0400 Subject: [PATCH 20/57] MAINT: add button and start sending data to function --- .../plugins/timefrequency/timefrequency.cpp | 26 ++++++++++++++++++- .../plugins/timefrequency/timefrequency.h | 3 +++ .../helpers/timefrequencysceneitem.cpp | 2 -- libraries/rtprocessing/timefrequency.cpp | 3 ++- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 1e772025f0d..25c47ece1bf 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -51,6 +51,8 @@ #include #include +#include + //============================================================================================================= // USED NAMESPACES //============================================================================================================= @@ -116,7 +118,20 @@ QMenu *TimeFrequency::getMenu() QDockWidget *TimeFrequency::getControl() { - return Q_NULLPTR; + QDockWidget* pDock = new QDockWidget(getName()); + + QWidget* pWidget = new QWidget(pDock); + QVBoxLayout* pLayout = new QVBoxLayout(pDock); + QPushButton* pButton = new QPushButton("Press me.", pWidget); + + pLayout->addWidget(pButton); + pWidget->setLayout(pLayout); + pDock->setWidget(pWidget); + + connect(pButton, &QPushButton::pressed, + this, &TimeFrequency::computeTimeFreqency); + + return pDock; } //============================================================================================================= @@ -211,3 +226,12 @@ void TimeFrequency::setChannelSelection(const QVariant &data) // } } } + +//============================================================================================================= + +void TimeFrequency::computeTimeFreqency() +{ + qDebug() << "[TimeFrequency::computeTimeFreqency]"; + + RTPROCESSINGLIB::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); +} diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h index 52f95c750bf..443fcd96825 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.h +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -138,6 +138,9 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlu //========================================================================================================= void onModelChanged(QSharedPointer pNewModel); + //========================================================================================================= + void computeTimeFreqency(); + //========================================================================================================= /** * Sets channel selection for views based on QVariant with a SelectionItem object diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp index 22a9b5bac5c..b5b04a10c93 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp @@ -42,8 +42,6 @@ // QT INCLUDES //============================================================================================================= -#include -#include #include #include diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index b8cd84f69ed..9f5ee300f0d 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -67,6 +67,7 @@ using namespace RTPROCESSINGLIB; void computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { - + auto evokedList = evokedSet.evoked; + qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; } From 5080cfa098adf9c705b7a54fb83b0d374e2b8d36 Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Mon, 19 Apr 2021 16:14:39 -0400 Subject: [PATCH 21/57] FIX: fix namspace to avoid runtime error --- libraries/rtprocessing/timefrequency.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 9f5ee300f0d..15c2082718c 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -49,13 +49,6 @@ // EIGEN INCLUDES //============================================================================================================= -//============================================================================================================= -// USED NAMESPACES -//============================================================================================================= - -using namespace RTPROCESSINGLIB; - - //TimeFrequency::TimeFrequency() //{ @@ -65,7 +58,7 @@ using namespace RTPROCESSINGLIB; // DEFINE GLOBAL RTPROCESSINGLIB METHODS //============================================================================================================= -void computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) +void RTPROCESSINGLIB::computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { auto evokedList = evokedSet.evoked; qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; From e17887c020d0631316252fd077e7434e7b17b7bd Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 20 Apr 2021 11:55:59 -0400 Subject: [PATCH 22/57] ENH:testing tfplot with one channel and plotting --- .../plugins/timefrequency/timefrequency.cpp | 7 ++++- libraries/disp/viewers/helpers/colorlib.cpp | 26 +++++++++---------- libraries/disp/viewers/helpers/colorlib.h | 26 +++++++++---------- libraries/rtprocessing/timefrequency.cpp | 10 ++++++- libraries/rtprocessing/timefrequency.h | 2 +- 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 25c47ece1bf..48e97895b6c 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -233,5 +234,9 @@ void TimeFrequency::computeTimeFreqency() { qDebug() << "[TimeFrequency::computeTimeFreqency]"; - RTPROCESSINGLIB::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); + Eigen::MatrixXd spectr = RTPROCESSINGLIB::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); + + DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr, m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); + + tfplot->show(); } diff --git a/libraries/disp/viewers/helpers/colorlib.cpp b/libraries/disp/viewers/helpers/colorlib.cpp index 33579213c12..1b0723ba590 100644 --- a/libraries/disp/viewers/helpers/colorlib.cpp +++ b/libraries/disp/viewers/helpers/colorlib.cpp @@ -20,19 +20,19 @@ using namespace DISPLIB; // DEFINE STATIC METHODS //============================================================================================================= -ColorMap ColorMap::fromGradient(const ColorGradient &gradient, - int resolution) -{ - ColorMap map; - map.m_iResolution = resolution; - - for (int i = 0 ; i < resolution; i++){ - float value = static_cast(i) / static_cast(resolution); - map.m_vColors.push_back(gradient.getColor(value)); - } - - return map; -} +//ColorMap ColorMap::fromGradient(const ColorGradient &gradient, +// int resolution) +//{ +// ColorMap map; +// map.m_iResolution = resolution; + +// for (int i = 0 ; i < resolution; i++){ +// float value = static_cast(i) / static_cast(resolution); +// map.m_vColors.push_back(gradient.getColor(value)); +// } + +// return map; +//} //============================================================================================================= // DEFINE MEMBER METHODS diff --git a/libraries/disp/viewers/helpers/colorlib.h b/libraries/disp/viewers/helpers/colorlib.h index f898e64b8d1..d10d65a5e56 100644 --- a/libraries/disp/viewers/helpers/colorlib.h +++ b/libraries/disp/viewers/helpers/colorlib.h @@ -83,21 +83,21 @@ struct ColorPoint /** * Holds a colormap */ -class ColorMap -{ -public: - uint size() const {return m_vColors.size();} +//class ColorMap +//{ +//public: +// uint size() const {return m_vColors.size();} - int resolution() const {return m_iResolution;} +// int resolution() const {return m_iResolution;} - static ColorMap fromGradient(const ColorGradient& gradient, - int resolution = 256); -private: - ColorMap(); +// static ColorMap fromGradient(const ColorGradient& gradient, +// int resolution = 256); +//private: +// ColorMap(); - int m_iResolution; - std::vector m_vColors; -}; +// int m_iResolution; +// std::vector m_vColors; +//}; //============================================================================================================= /** @@ -114,7 +114,7 @@ class ColorGradient #ifdef QT_CORE_LIB QLinearGradient getQGradient(QPoint from, QPoint to) const; #endif - ColorMap getColorMap(); +// ColorMap getColorMap(); private: diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 15c2082718c..ab26e6c1c46 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -41,6 +41,8 @@ #include #include +#include + //============================================================================================================= // QT INCLUDES //============================================================================================================= @@ -58,9 +60,15 @@ // DEFINE GLOBAL RTPROCESSINGLIB METHODS //============================================================================================================= -void RTPROCESSINGLIB::computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) +Eigen::MatrixXd RTPROCESSINGLIB::computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { auto evokedList = evokedSet.evoked; + + Eigen::VectorXd dataCol = evokedList.first().data.row(0).transpose(); + Eigen::MatrixXd dataSpectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, evokedList.first().info.sfreq * 0.2); + + return dataSpectrum; + qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; } diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index 5c22541e693..9238f9b96d0 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -76,7 +76,7 @@ namespace RTPROCESSINGLIB // TimeFrequency(); //}; -RTPROCESINGSHARED_EXPORT void computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); +RTPROCESINGSHARED_EXPORT Eigen::MatrixXd computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); }//namespace #endif // TIMEFREQUENCY_RTPROCESSING_H From c5c49bba708043b2b8e30e29294adb8fba56686e Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 20 Apr 2021 17:49:18 -0400 Subject: [PATCH 23/57] ENH: calculation on all channels in the pased data --- .../plugins/timefrequency/timefrequency.cpp | 4 ++-- .../viewers/helpers/timefrequencymodel.cpp | 16 ++++++++++++++++ .../disp/viewers/helpers/timefrequencymodel.h | 9 ++++++++- libraries/rtprocessing/timefrequency.cpp | 18 ++++++++++++------ libraries/rtprocessing/timefrequency.h | 2 +- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 48e97895b6c..043978c3f07 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -234,9 +234,9 @@ void TimeFrequency::computeTimeFreqency() { qDebug() << "[TimeFrequency::computeTimeFreqency]"; - Eigen::MatrixXd spectr = RTPROCESSINGLIB::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); + auto spectr = RTPROCESSINGLIB::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); - DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr, m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); + DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); tfplot->show(); } diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index b858c294d6f..4a0480f3fb8 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -57,3 +57,19 @@ TimeFrequencyModel::TimeFrequencyModel() { } + +//============================================================================================================= + +TimeFrequencyModel::TimeFrequencyModel(std::vector& spectr) +: vecSpectr(std::move(spectr)) +{ + +} + +//============================================================================================================= + +void TimeFrequencyModel::setSpectr(std::vector& spectr) +{ + vecSpectr.clear(); + vecSpectr = std::move(spectr); +} diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h index 6551bcb0339..6523035518a 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.h +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -51,6 +51,7 @@ // EIGEN INCLUDES //============================================================================================================= +#include //============================================================================================================= // DEFINE NAMESPACE DISPLIB @@ -64,11 +65,17 @@ class TimeFrequencyModel public: TimeFrequencyModel(); + TimeFrequencyModel(std::vector& spectr); + + void setSpectr(std::vector& spectr); + private: // QSharedPointer m_pChannelInfoModel; - QLinearGradient m_Gradient; +// QLinearGradient m_Gradient; + + std::vector vecSpectr; }; }//namespace diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index ab26e6c1c46..669817ead1c 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -60,15 +60,21 @@ // DEFINE GLOBAL RTPROCESSINGLIB METHODS //============================================================================================================= -Eigen::MatrixXd RTPROCESSINGLIB::computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) +std::vector RTPROCESSINGLIB::computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { - auto evokedList = evokedSet.evoked; + qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; - Eigen::VectorXd dataCol = evokedList.first().data.row(0).transpose(); - Eigen::MatrixXd dataSpectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, evokedList.first().info.sfreq * 0.2); + auto& evoked = evokedSet.evoked.first(); + float fSampFreq = evoked.info.sfreq; - return dataSpectrum; + std::vector tfvector; - qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; + for (int i = 0; i < evoked.data.rows(); i++){ + Eigen::VectorXd dataCol = evoked.data.row(0).transpose(); + Eigen::MatrixXd Spectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, fSampFreq * 0.2); + tfvector.push_back(Spectrum); + } + + return tfvector; } diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index 9238f9b96d0..a60376359ce 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -76,7 +76,7 @@ namespace RTPROCESSINGLIB // TimeFrequency(); //}; -RTPROCESINGSHARED_EXPORT Eigen::MatrixXd computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); +RTPROCESINGSHARED_EXPORT std::vector computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); }//namespace #endif // TIMEFREQUENCY_RTPROCESSING_H From d44fe86a1e4e81066d3f6715210b38a5648f2018 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Wed, 21 Apr 2021 10:34:07 -0400 Subject: [PATCH 24/57] ENH: return data from timefrequencymodel --- .../viewers/helpers/timefrequencymodel.cpp | 76 ++++++++++++++++++- .../disp/viewers/helpers/timefrequencymodel.h | 57 +++++++++++++- 2 files changed, 128 insertions(+), 5 deletions(-) diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index 4a0480f3fb8..a09f8b57840 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -61,7 +61,7 @@ TimeFrequencyModel::TimeFrequencyModel() //============================================================================================================= TimeFrequencyModel::TimeFrequencyModel(std::vector& spectr) -: vecSpectr(std::move(spectr)) +: m_vSpectr(std::move(spectr)) { } @@ -70,6 +70,76 @@ TimeFrequencyModel::TimeFrequencyModel(std::vector& spectr) void TimeFrequencyModel::setSpectr(std::vector& spectr) { - vecSpectr.clear(); - vecSpectr = std::move(spectr); + m_vSpectr.clear(); + m_vSpectr = std::move(spectr); +} + +//============================================================================================================= + +int TimeFrequencyModel::rowCount(const QModelIndex & /*parent*/) const +{ + return m_vSpectr.size(); +} + +//============================================================================================================= + +int TimeFrequencyModel::columnCount(const QModelIndex & /*parent*/) const +{ + return 3; +} + +//============================================================================================================= + +QVariant TimeFrequencyModel::data(const QModelIndex &index, + int role) const +{ + if(role != Qt::DisplayRole && role != Qt::BackgroundRole) { + return QVariant(); + } + + if(!index.isValid()) { + return QVariant(); + } + + int row = index.row(); + + if(index.column() == 0 && role == Qt::DisplayRole) { + // return QVariant(m_pEvokedSet->info.ch_names); + + } + + if(index.column() == 1) { //timefrequencyview + switch(role){ + case Qt::BackgroundRole:{ + return QVariant(); + } + case Qt::DisplayRole:{ + QVariant variant; + variant.setValue(m_vSpectr[0]); + return variant; + } + } + } + if(index.column() == 2) { //timefrequencyview + switch(role){ + case Qt::BackgroundRole:{ + return QVariant(); + } + case Qt::DisplayRole:{ + QVariant variant; + variant.setValue(m_vSpectr[row]); + return variant; + } + } + } + +} + +//============================================================================================================= + +QVariant TimeFrequencyModel::headerData(int section, + Qt::Orientation orientation, + int role) const +{ + return QVariant(); } diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h index 6523035518a..f3b886f482d 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.h +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -46,6 +46,7 @@ //============================================================================================================= #include +#include //============================================================================================================= // EIGEN INCLUDES @@ -60,7 +61,7 @@ namespace DISPLIB { -class TimeFrequencyModel +class TimeFrequencyModel : public QAbstractTableModel { public: TimeFrequencyModel(); @@ -69,14 +70,66 @@ class TimeFrequencyModel void setSpectr(std::vector& spectr); + //========================================================================================================= + /** + * Returns the number of rows under the given parent. When the parent is valid it means that rowCount is returning the number of children of parent. + * + * @param[in] parent not used + * + * @return number of rows + */ + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const ; + + //========================================================================================================= + /** + * Returns the number of columns for the children of the given parent. + * + * @param[in] parent not used + * + * @return number of columns + */ + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + + //========================================================================================================= + /** + * Returns the data stored under the given role for the item referred to by the index. + * + * @param[in] index determines item location + * @param[in] role role to return + * + * @return accessed data + */ + virtual QVariant data(const QModelIndex &index, + int role = Qt::DisplayRole) const; + + //========================================================================================================= + /** + * Returns the data for the given role and section in the header with the specified orientation. + * + * @param[in] section For horizontal headers, the section number corresponds to the column number. Similarly, for vertical headers, the section number corresponds to the row number. + * @param[in] orientation Qt::Horizontal or Qt::Vertical + * @param[in] role role to show + * + * @return accessed eader data + */ + virtual QVariant headerData(int section, + Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + private: // QSharedPointer m_pChannelInfoModel; // QLinearGradient m_Gradient; - std::vector vecSpectr; + std::vector m_vSpectr; }; }//namespace + +#ifndef metatype_matrixXd +#define metatype_matrixXd +Q_DECLARE_METATYPE(Eigen::MatrixXd); +#endif + #endif // TIMEFREQUENCYMODEL_H From 7eb2d3210e5478c43acb9366fcb817b1e173d3cf Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Wed, 21 Apr 2021 11:52:31 -0400 Subject: [PATCH 25/57] Creating and setting model, passing data matrix to plot --- .../plugins/timefrequency/timefrequency.cpp | 12 +++++++-- .../plugins/timefrequency/timefrequency.h | 3 +++ .../viewers/helpers/timefrequencymodel.cpp | 27 ++++++++++++++++--- .../disp/viewers/helpers/timefrequencymodel.h | 25 ++++++++++++++++- .../disp/viewers/timefrequencylayoutview.cpp | 9 +++++++ .../disp/viewers/timefrequencylayoutview.h | 4 +++ libraries/disp/viewers/timefrequencyview.cpp | 17 ++++++++++++ libraries/disp/viewers/timefrequencyview.h | 4 +++ 8 files changed, 95 insertions(+), 6 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 043978c3f07..f5d2e637697 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,8 @@ QSharedPointer TimeFrequency::clone() const void TimeFrequency::init() { m_pCommu = new Communicator(this); + + m_pTFModel = QSharedPointer(new DISPLIB::TimeFrequencyModel()); } //============================================================================================================= @@ -236,7 +239,12 @@ void TimeFrequency::computeTimeFreqency() auto spectr = RTPROCESSINGLIB::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); - DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); +// DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); + +// tfplot->show(); + + m_pTFModel->setSpectr(spectr); + m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); - tfplot->show(); + m_pTimeFreqView->setTimeFrequencyModel(m_pTFModel); } diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h index 443fcd96825..2a55d63e872 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.h +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -68,6 +68,7 @@ namespace DISPLIB { class ProgressView; class TimeFrequencyView; class TimeFrequencyLayoutView; + class TimeFrequencyModel; class EvokedSetModel; } @@ -158,6 +159,8 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlu QSharedPointer m_pEvokedModel; /**< Pointer to model used to display averaging data from m_pFiffEvokedSet and m_pFiffEvoked */ QSharedPointer m_pAvgModel; /**< Pointer to currently loaded FiffRawView Model */ + QSharedPointer m_pTFModel; + }; //============================================================================================================= diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index a09f8b57840..0551d88acd8 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -97,12 +97,12 @@ QVariant TimeFrequencyModel::data(const QModelIndex &index, return QVariant(); } - if(!index.isValid()) { + int row = index.row(); + + if(!index.isValid() && row >= m_vSpectr.size()) { return QVariant(); } - int row = index.row(); - if(index.column() == 0 && role == Qt::DisplayRole) { // return QVariant(m_pEvokedSet->info.ch_names); @@ -137,9 +137,30 @@ QVariant TimeFrequencyModel::data(const QModelIndex &index, //============================================================================================================= +QVariant TimeFrequencyModel::data(int row, int column, int role) const +{ + return data(index(row, column), role); +} + +//============================================================================================================= + QVariant TimeFrequencyModel::headerData(int section, Qt::Orientation orientation, int role) const { return QVariant(); } + +//============================================================================================================= + +void TimeFrequencyModel::setFiffInfo(const FIFFLIB::FiffInfo &info) +{ + m_Info = info; +} + +//============================================================================================================= + +float TimeFrequencyModel::getSamplingFrequency() +{ + return m_Info.sfreq; +} diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h index f3b886f482d..51341273d15 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.h +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -41,6 +41,8 @@ #include "../../disp_global.h" +#include + //============================================================================================================= // QT INCLUDES //============================================================================================================= @@ -61,8 +63,9 @@ namespace DISPLIB { -class TimeFrequencyModel : public QAbstractTableModel +class DISPSHARED_EXPORT TimeFrequencyModel : public QAbstractTableModel { + Q_OBJECT public: TimeFrequencyModel(); @@ -70,6 +73,10 @@ class TimeFrequencyModel : public QAbstractTableModel void setSpectr(std::vector& spectr); + void setFiffInfo(const FIFFLIB::FiffInfo& info); + + float getSamplingFrequency(); + //========================================================================================================= /** * Returns the number of rows under the given parent. When the parent is valid it means that rowCount is returning the number of children of parent. @@ -102,6 +109,20 @@ class TimeFrequencyModel : public QAbstractTableModel virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + //========================================================================================================= + /** + * Data for the row and column and given display role + * + * @param [in] row index row + * @param [in] column index column + * @param [in] role display role to access + * + * @return the accessed data + */ + QVariant data(int row, + int column, + int role = Qt::DisplayRole) const; + //========================================================================================================= /** * Returns the data for the given role and section in the header with the specified orientation. @@ -124,6 +145,8 @@ class TimeFrequencyModel : public QAbstractTableModel std::vector m_vSpectr; + FIFFLIB::FiffInfo m_Info; + }; }//namespace diff --git a/libraries/disp/viewers/timefrequencylayoutview.cpp b/libraries/disp/viewers/timefrequencylayoutview.cpp index a827cc07142..33549d1f7b7 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.cpp +++ b/libraries/disp/viewers/timefrequencylayoutview.cpp @@ -37,9 +37,11 @@ //============================================================================================================= #include "timefrequencylayoutview.h" + #include "helpers/timefrequencyscene.h" #include "helpers/timefrequencysceneitem.h" #include "helpers/selectionsceneitem.h" +#include "helpers/timefrequencymodel.h" //============================================================================================================= // QT INCLUDES @@ -164,3 +166,10 @@ void TimeFrequencyLayoutView::updateData() { } + +//============================================================================================================= + +void TimeFrequencyLayoutView::setTimeFrequencyModel(QSharedPointer pModel) +{ + m_pTFModel = pModel; +} diff --git a/libraries/disp/viewers/timefrequencylayoutview.h b/libraries/disp/viewers/timefrequencylayoutview.h index ab5dfc5b68c..545c078c378 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.h +++ b/libraries/disp/viewers/timefrequencylayoutview.h @@ -67,6 +67,7 @@ namespace DISPLIB class EvokedSetModel; class TimeFrequencyScene; +class TimeFrequencyModel; //============================================================================================================= class DISPSHARED_EXPORT TimeFrequencyLayoutView : public AbstractView @@ -127,11 +128,14 @@ class DISPSHARED_EXPORT TimeFrequencyLayoutView : public AbstractView */ void updateData(); + void setTimeFrequencyModel(QSharedPointer pModel); + protected: QPointer m_pTimeFreqScene; QPointer m_pTimeFreqGraphicsView; QSharedPointer m_pEvokedSetModel; /**< The evoked model */ + QSharedPointer m_pTFModel; }; }//namespace diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 6432651e167..39cb96a3574 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -39,6 +39,10 @@ #include "timefrequencyview.h" #include "helpers/evokedsetmodel.h" +#include "helpers/timefrequencymodel.h" +#include "helpers/timefrequencymodel.h" + +#include //============================================================================================================= // QT INCLUDES @@ -253,3 +257,16 @@ void TimeFrequencyView::paintAxes(QPainter& painter, { } + +//============================================================================================================= + +void TimeFrequencyView::setTimeFrequencyModel(QSharedPointer pModel) +{ + qDebug() << "[TimeFrequencyView::setTimeFrequencyModel]"; + + m_pTFModel = pModel; + + DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(m_pTFModel->data(1,1).value(), m_pTFModel->getSamplingFrequency(), 0, 100, DISPLIB::ColorMaps::Jet); + + tfplot->show(); +} diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index 7d5378a3649..eba69e875d2 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -64,6 +64,7 @@ namespace DISPLIB //============================================================================================================= class EvokedSetModel; +class TimeFrequencyModel; //============================================================================================================= /** @@ -131,6 +132,8 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView */ void setChartBorderSpacing(int iSpacing); + void setTimeFrequencyModel(QSharedPointer pModel); + protected: void initQMLView(); @@ -144,6 +147,7 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView QSharedPointer m_pEvokedSetModel; /**< The evoked model */ int m_iChartBorderSpacing; + QSharedPointer m_pTFModel; }; From e79daf9dff487d6de774a88a6d8127f44bbb6063 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Wed, 21 Apr 2021 16:48:38 -0400 Subject: [PATCH 26/57] ENH: getting tfplot into lyout view (or trying to) --- .../plugins/timefrequency/timefrequency.cpp | 7 +- .../viewers/helpers/timefrequencymodel.cpp | 2 + .../viewers/helpers/timefrequencyscene.cpp | 14 +++- .../disp/viewers/helpers/timefrequencyscene.h | 5 ++ .../helpers/timefrequencysceneitem.cpp | 65 +++++++++++++++++-- .../viewers/helpers/timefrequencysceneitem.h | 21 ++++++ .../disp/viewers/timefrequencylayoutview.cpp | 22 ++++++- libraries/disp/viewers/timefrequencyview.cpp | 4 +- 8 files changed, 126 insertions(+), 14 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index f5d2e637697..110116bfce3 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -149,6 +149,9 @@ QWidget *TimeFrequency::getView() m_pTimeFreqView = new DISPLIB::TimeFrequencyView(); m_pTimeFreqLayoutView = new DISPLIB::TimeFrequencyLayoutView(); + m_pTimeFreqView->setTimeFrequencyModel(m_pTFModel); + m_pTimeFreqLayoutView->setTimeFrequencyModel(m_pTFModel); + pTabView->addTab(m_pTimeFreqView, "Average View"); pTabView->addTab(m_pTimeFreqLayoutView, "Layout View"); @@ -243,8 +246,6 @@ void TimeFrequency::computeTimeFreqency() // tfplot->show(); - m_pTFModel->setSpectr(spectr); m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); - - m_pTimeFreqView->setTimeFrequencyModel(m_pTFModel); + m_pTFModel->setSpectr(spectr); } diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index 0551d88acd8..0f79fa34f43 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -72,6 +72,8 @@ void TimeFrequencyModel::setSpectr(std::vector& spectr) { m_vSpectr.clear(); m_vSpectr = std::move(spectr); + + emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); } //============================================================================================================= diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.cpp b/libraries/disp/viewers/helpers/timefrequencyscene.cpp index d338f465c14..73faf0fdb35 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.cpp +++ b/libraries/disp/viewers/helpers/timefrequencyscene.cpp @@ -85,6 +85,7 @@ void TimeFrequencyScene::repaintItems(const QList &selectedChan void TimeFrequencyScene::repaintSelectionItems(const DISPLIB::SelectionItem &selectedChannelItems) { this->clear(); + m_vItems.clear(); for (int i = 0; i < selectedChannelItems.m_iChannelKind.size(); i++){ TimeFrequencySceneItem* averageSceneItemTemp = new TimeFrequencySceneItem(selectedChannelItems.m_sChannelName[i], @@ -95,7 +96,10 @@ void TimeFrequencyScene::repaintSelectionItems(const DISPLIB::SelectionItem &sel QGraphicsProxyWidget* pWidget = this->addWidget(averageSceneItemTemp); - pWidget->setPos(selectedChannelItems.m_qpChannelPosition[i]); + m_vItems.push_back(averageSceneItemTemp); + + pWidget->setPos(75*selectedChannelItems.m_qpChannelPosition[i].x(), -75*selectedChannelItems.m_qpChannelPosition[i].y()); +// pWidget->resize(200,150); } } @@ -106,3 +110,11 @@ void TimeFrequencyScene::updateScene() this->update(); } +//============================================================================================================= + +std::vector TimeFrequencyScene::getItems() const +{ + return m_vItems; +} + + diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.h b/libraries/disp/viewers/helpers/timefrequencyscene.h index e15dc723135..b8bed46aecc 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.h +++ b/libraries/disp/viewers/helpers/timefrequencyscene.h @@ -64,6 +64,7 @@ namespace DISPLIB class SelectionSceneItem; class SelectionItem; +class TimeFrequencySceneItem; class DISPSHARED_EXPORT TimeFrequencyScene : public LayoutScene { @@ -95,6 +96,10 @@ class DISPSHARED_EXPORT TimeFrequencyScene : public LayoutScene */ void updateScene(); + std::vector getItems() const; + +private: + std::vector m_vItems; }; }//namespace #endif // TIMEFREQUENCYSCENE_H diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp index b5b04a10c93..7dd839ad845 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp @@ -42,8 +42,8 @@ // QT INCLUDES //============================================================================================================= -#include #include +#include //============================================================================================================= // EIGEN INCLUDES @@ -64,8 +64,26 @@ TimeFrequencySceneItem::TimeFrequencySceneItem(const QString& channelName, const QPointF& channelPosition, int channelKind, int channelUnit) +: m_sChannelName(channelName) +, m_iChannelNumber(channelNumber) +, m_iChannelKind(channelKind) +, m_iChannelUnit(channelUnit) +, m_iTotalNumberChannels(0) +, m_iFontTextSize(15) +, m_iMaxWidth(1500) +, m_iMaxHeigth(150) +, m_bIsBad(false) +, m_qpChannelPosition(channelPosition) +, m_pPlot(Q_NULLPTR) { - initQMLView(); + //initQMLView(); + +// m_rectBoundingRect = QRectF(-m_iMaxWidth/2, -m_iMaxHeigth/2, m_iMaxWidth, m_iMaxHeigth); +// QLabel* widget = new QLabel("Test"); + + m_pLayout = new QVBoxLayout(); +// m_pLayout->addWidget(widget); + this->setLayout(m_pLayout); } //============================================================================================================= @@ -77,11 +95,46 @@ void TimeFrequencySceneItem::initQMLView() // widget->setSource(source); // widget->setResizeMode(QQuickWidget::SizeRootObjectToView); - QLabel* widget = new QLabel("Test"); +// QLabel* widget = new QLabel("Test"); + +// QVBoxLayout* layout = new QVBoxLayout(); +// layout->addWidget(widget); - QVBoxLayout* layout = new QVBoxLayout(); - layout->addWidget(widget); +// this->setLayout(layout); +} + +//============================================================================================================= + +int TimeFrequencySceneItem::getChannelNumber() const +{ + return m_iChannelNumber; +} + +//============================================================================================================= - this->setLayout(layout); +void TimeFrequencySceneItem::setData(const Eigen::MatrixXd &data) +{ + m_data = data; + + if(!m_pLayout->isEmpty()){ + m_pLayout->removeWidget(m_pPlot); + m_pPlot->deleteLater(); + } + + m_pPlot = new TFplot(m_data, m_fSampleRate, 0, 100, DISPLIB::ColorMaps::Jet); + m_pPlot->show(); + +// m_pLayout->addWidget(m_pPlot); + +// m_pLayout->addWidget(m_pPlot); +// this->setLayout(m_pLayout); +} + +//============================================================================================================= + +void TimeFrequencySceneItem::setSampleRate(float fFreq) +{ + m_fSampleRate = fFreq; + qDebug() << "freq:" << fFreq; } diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.h b/libraries/disp/viewers/helpers/timefrequencysceneitem.h index 09e4bce5698..12c464b4878 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.h +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.h @@ -41,17 +41,23 @@ #include "../../disp_global.h" +#include + //============================================================================================================= // QT INCLUDES //============================================================================================================= #include #include +#include +#include //============================================================================================================= // EIGEN INCLUDES //============================================================================================================= +#include + //============================================================================================================= // DEFINE NAMESPACE DISPLIB //============================================================================================================= @@ -70,6 +76,13 @@ class DISPSHARED_EXPORT TimeFrequencySceneItem : public QWidget int channelKind, int channelUnit); + void setData(const Eigen::MatrixXd& data); + + void setSampleRate(float fFreq); + + int getChannelNumber() const; + + protected: void initQMLView(); @@ -88,6 +101,14 @@ class DISPSHARED_EXPORT TimeFrequencySceneItem : public QWidget QPointF m_qpChannelPosition; /**< The channels 2D position in the scene.*/ + Eigen::MatrixXd m_data; + float m_fSampleRate; +// QRectF m_rectBoundingRect; /**< The bounding rect. */ + + QPointer m_pLayout; + + QPointer m_pPlot; + }; }//namespace #endif // TIMEFREQUENCYSCENEITEM_H diff --git a/libraries/disp/viewers/timefrequencylayoutview.cpp b/libraries/disp/viewers/timefrequencylayoutview.cpp index 33549d1f7b7..c3dad5cd620 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.cpp +++ b/libraries/disp/viewers/timefrequencylayoutview.cpp @@ -159,17 +159,35 @@ void TimeFrequencyLayoutView::channelSelectionChanged(const QVariant &data) //Repaint the average items in the average scene based on the input parameter selectedChannelItems and update them with current data m_pTimeFreqScene->repaintSelectionItems(*pSelectionItem); +// updateData(); } //============================================================================================================= void TimeFrequencyLayoutView::updateData() { - + if(m_pTFModel){ + auto sceneItems = m_pTimeFreqScene->getItems(); + + for (auto item : sceneItems){ + item->setSampleRate(m_pTFModel->getSamplingFrequency()); +// item->setData(m_pTFModel->data(item->getChannelNumber(), 2).value()); +// qDebug() << "ch num:" << item->getChannelNumber(); + } + qDebug() << "vec size:" << sceneItems.size(); + sceneItems.front()->setData(m_pTFModel->data(sceneItems.front()->getChannelNumber(), 2).value()); + +// DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(m_pTFModel->data(1,2).value(), m_pTFModel->getSamplingFrequency(), 0, 100, DISPLIB::ColorMaps::Jet); +// tfplot->show(); + } } //============================================================================================================= void TimeFrequencyLayoutView::setTimeFrequencyModel(QSharedPointer pModel) { - m_pTFModel = pModel; + if(pModel){ + m_pTFModel = pModel; + connect(m_pTFModel.data(), &TimeFrequencyModel::dataChanged, + this, &TimeFrequencyLayoutView::updateData, Qt::UniqueConnection); + } } diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 39cb96a3574..0d92941a6a7 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -266,7 +266,7 @@ void TimeFrequencyView::setTimeFrequencyModel(QSharedPointerdata(1,1).value(), m_pTFModel->getSamplingFrequency(), 0, 100, DISPLIB::ColorMaps::Jet); +// DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(m_pTFModel->data(1,1).value(), m_pTFModel->getSamplingFrequency(), 0, 100, DISPLIB::ColorMaps::Jet); - tfplot->show(); +// tfplot->show(); } From 27758fdd4e5ba0cc38fae7efa54979f3dccdd85a Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Thu, 22 Apr 2021 10:43:48 -0400 Subject: [PATCH 27/57] ENH: single view based of tfplot --- .../plugins/timefrequency/timefrequency.cpp | 4 + .../disp/viewers/timefrequencylayoutview.h | 7 +- libraries/disp/viewers/timefrequencyview.cpp | 170 ++++++++++-------- libraries/disp/viewers/timefrequencyview.h | 23 ++- 4 files changed, 121 insertions(+), 83 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 110116bfce3..3154fdfdf4b 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -68,6 +68,7 @@ using namespace ANSHAREDLIB; TimeFrequency::TimeFrequency() : m_sSettingsPath("MNEANALYZE/TimeFrequency") +, m_pAvgModel(Q_NULLPTR) { m_pEvokedModel = QSharedPointer(new DISPLIB::EvokedSetModel()); loadSettings(); @@ -239,6 +240,9 @@ void TimeFrequency::setChannelSelection(const QVariant &data) void TimeFrequency::computeTimeFreqency() { qDebug() << "[TimeFrequency::computeTimeFreqency]"; + if (!m_pAvgModel){ + return; + } auto spectr = RTPROCESSINGLIB::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); diff --git a/libraries/disp/viewers/timefrequencylayoutview.h b/libraries/disp/viewers/timefrequencylayoutview.h index 545c078c378..466a049f4e6 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.h +++ b/libraries/disp/viewers/timefrequencylayoutview.h @@ -122,15 +122,16 @@ class DISPSHARED_EXPORT TimeFrequencyLayoutView : public AbstractView */ void clearView(); + void setTimeFrequencyModel(QSharedPointer pModel); + +protected: + //========================================================================================================= /** * call this function whenever the items' data needs to be updated */ void updateData(); - void setTimeFrequencyModel(QSharedPointer pModel); - -protected: QPointer m_pTimeFreqScene; QPointer m_pTimeFreqGraphicsView; diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 0d92941a6a7..7fe8f2800b7 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -65,7 +65,8 @@ using namespace DISPLIB; TimeFrequencyView::TimeFrequencyView() : TimeFrequencyView("", Q_NULLPTR) { - + m_pLayout = new QVBoxLayout(); + this->setLayout(m_pLayout); } //============================================================================================================= @@ -142,95 +143,95 @@ void TimeFrequencyView::initQMLView() // this->setLayout(layout); } -//============================================================================================================= +////============================================================================================================= -void TimeFrequencyView::paintEvent(QPaintEvent *event) -{ - if (m_pEvokedSetModel){ - QPainter painter(this); +//void TimeFrequencyView::paintEvent(QPaintEvent *event) +//{ +// if (m_pEvokedSetModel){ +// QPainter painter(this); - painter.save(); - painter.setBrush(QBrush()); - painter.drawRect(QRect(-1,-1,this->width()+2,this->height()+2)); - painter.restore(); +// painter.save(); +// painter.setBrush(QBrush()); +// painter.drawRect(QRect(-1,-1,this->width()+2,this->height()+2)); +// painter.restore(); - //paint chart - painter.save(); - painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); - QRect chartBound(m_iChartBorderSpacing,m_iChartBorderSpacing,this->width()-m_iChartBorderSpacing * 4 ,this->height()- m_iChartBorderSpacing * 2); - painter.drawRect(chartBound); - painter.restore(); +// //paint chart +// painter.save(); +// painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); +// QRect chartBound(m_iChartBorderSpacing,m_iChartBorderSpacing,this->width()-m_iChartBorderSpacing * 4 ,this->height()- m_iChartBorderSpacing * 2); +// painter.drawRect(chartBound); +// painter.restore(); - //paint gradient bar +// //paint gradient bar - painter.save(); +// painter.save(); - QLinearGradient linGrad(this->width() - m_iChartBorderSpacing * 1.5f, chartBound.topRight().y(), this->width() - m_iChartBorderSpacing * 1.5f, chartBound.bottomRight().y()); - painter.save(); - painter.setBrush(linGrad); - painter.drawRect(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); +// QLinearGradient linGrad(this->width() - m_iChartBorderSpacing * 1.5f, chartBound.topRight().y(), this->width() - m_iChartBorderSpacing * 1.5f, chartBound.bottomRight().y()); +// painter.save(); +// painter.setBrush(linGrad); +// painter.drawRect(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); - painter.restore(); +// painter.restore(); - //paint axis labels - //test - if(m_pEvokedSetModel->getNumSamples() > 0) { - painter.save(); - painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); +// //paint axis labels +// //test +// if(m_pEvokedSetModel->getNumSamples() > 0) { +// painter.save(); +// painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); - float fDx = (float)(chartBound.width()) / ((float)m_pEvokedSetModel->getNumSamples()); - float posX = fDx * ((float)m_pEvokedSetModel->getNumPreStimSamples()); - painter.drawLine(chartBound.bottomLeft().x()+posX, chartBound.bottomRight().y(), chartBound.bottomLeft().x() + posX, chartBound.topRight().y()); +// float fDx = (float)(chartBound.width()) / ((float)m_pEvokedSetModel->getNumSamples()); +// float posX = fDx * ((float)m_pEvokedSetModel->getNumPreStimSamples()); +// painter.drawLine(chartBound.bottomLeft().x()+posX, chartBound.bottomRight().y(), chartBound.bottomLeft().x() + posX, chartBound.topRight().y()); - painter.drawText(QPointF(posX+chartBound.bottomLeft().x(),chartBound.bottomRight().y()-5), QString("0ms / Stimulus")); +// painter.drawText(QPointF(posX+chartBound.bottomLeft().x(),chartBound.bottomRight().y()-5), QString("0ms / Stimulus")); - painter.restore(); +// painter.restore(); - painter.save(); - QColor colorTimeSpacer = Qt::black; - colorTimeSpacer.setAlphaF(0.5); - painter.setPen(QPen(colorTimeSpacer, 1, Qt::DashLine)); +// painter.save(); +// QColor colorTimeSpacer = Qt::black; +// colorTimeSpacer.setAlphaF(0.5); +// painter.setPen(QPen(colorTimeSpacer, 1, Qt::DashLine)); - float yStart = chartBound.topLeft().y(); - float yEnd = chartBound.bottomRight().y(); +// float yStart = chartBound.topLeft().y(); +// float yEnd = chartBound.bottomRight().y(); - float sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); - int counter = 1; - float timeDistanceMSec = 50.0; - float timeDistanceSamples = (timeDistanceMSec/1000.0)*m_pEvokedSetModel->getSamplingFrequency(); //time distance corresponding to sampling frequency +// float sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); +// int counter = 1; +// float timeDistanceMSec = 50.0; +// float timeDistanceSamples = (timeDistanceMSec/1000.0)*m_pEvokedSetModel->getSamplingFrequency(); //time distance corresponding to sampling frequency - //spacers before stim - while(sampleCounter-timeDistanceSamples>0) { - sampleCounter-=timeDistanceSamples; - float x = chartBound.bottomLeft().x() + fDx*sampleCounter; - painter.drawLine(x, yStart, x, yEnd); - painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("-%1ms").arg(timeDistanceMSec*counter)); - counter++; - } +// //spacers before stim +// while(sampleCounter-timeDistanceSamples>0) { +// sampleCounter-=timeDistanceSamples; +// float x = chartBound.bottomLeft().x() + fDx*sampleCounter; +// painter.drawLine(x, yStart, x, yEnd); +// painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("-%1ms").arg(timeDistanceMSec*counter)); +// counter++; +// } - //spacers after stim - counter = 1; - sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); - while(sampleCounter+timeDistanceSamplesgetNumSamples()) { - sampleCounter+=timeDistanceSamples; - float x = chartBound.bottomLeft().x() + fDx*sampleCounter; - painter.drawLine(x, yStart, x, yEnd); - painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("%1ms").arg(timeDistanceMSec*counter)); - counter++; - } +// //spacers after stim +// counter = 1; +// sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); +// while(sampleCounter+timeDistanceSamplesgetNumSamples()) { +// sampleCounter+=timeDistanceSamples; +// float x = chartBound.bottomLeft().x() + fDx*sampleCounter; +// painter.drawLine(x, yStart, x, yEnd); +// painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("%1ms").arg(timeDistanceMSec*counter)); +// counter++; +// } - painter.restore(); +// painter.restore(); - } +// } - } +// } - return QWidget::paintEvent(event); -} +// return QWidget::paintEvent(event); +//} //============================================================================================================= @@ -244,19 +245,19 @@ void TimeFrequencyView::setEvokedSetModel(QSharedPointer model) //============================================================================================================= -void TimeFrequencyView::paintChart(QPainter& painter, - const QRect chartBound) -{ +//void TimeFrequencyView::paintChart(QPainter& painter, +// const QRect chartBound) +//{ -} +//} -//============================================================================================================= +////============================================================================================================= -void TimeFrequencyView::paintAxes(QPainter& painter, - const QRect chartBound) -{ +//void TimeFrequencyView::paintAxes(QPainter& painter, +// const QRect chartBound) +//{ -} +//} //============================================================================================================= @@ -266,7 +267,26 @@ void TimeFrequencyView::setTimeFrequencyModel(QSharedPointerdata(1,1).value(), m_pTFModel->getSamplingFrequency(), 0, 100, DISPLIB::ColorMaps::Jet); // tfplot->show(); } + +//============================================================================================================= + +void TimeFrequencyView::updateData() +{ + if(!m_pLayout->isEmpty()){ + m_pLayout->removeWidget(m_pPlot); + m_pPlot->deleteLater(); + } + + m_pPlot = new TFplot(m_pTFModel->data(1,1).value(), m_pTFModel->getSamplingFrequency(), 0, 100, DISPLIB::ColorMaps::Jet); + m_pLayout->addWidget(m_pPlot); +} diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index eba69e875d2..435371337b9 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -41,11 +41,14 @@ #include "../disp_global.h" #include "abstractview.h" +#include //============================================================================================================= // QT INCLUDES //============================================================================================================= +#include +#include //============================================================================================================= // EIGEN INCLUDES @@ -134,21 +137,31 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView void setTimeFrequencyModel(QSharedPointer pModel); + protected: void initQMLView(); - virtual void paintEvent(QPaintEvent *event); +// virtual void paintEvent(QPaintEvent *event); + +// void paintChart(QPainter& painter, +// const QRect chartBound); - void paintChart(QPainter& painter, - const QRect chartBound); +// void paintAxes(QPainter& painter, +// const QRect chartBound); - void paintAxes(QPainter& painter, - const QRect chartBound); + //========================================================================================================= + /** + * call this function whenever the items' data needs to be updated + */ + void updateData(); QSharedPointer m_pEvokedSetModel; /**< The evoked model */ int m_iChartBorderSpacing; QSharedPointer m_pTFModel; + QPointer m_pLayout; + QPointer m_pPlot; + }; } //namespace From 3de6ae77683ff2814daf67478ffc347e21e1dbf4 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Thu, 22 Apr 2021 14:17:44 -0400 Subject: [PATCH 28/57] ENH: control view. testing qgraphicsobject vs qwidget for layout vciew --- .../plugins/timefrequency/timefrequency.cpp | 31 +++- libraries/disp/disp.pro | 3 + .../formfiles/timefrequencysettingsview.ui | 158 ++++++++++++++++++ .../viewers/helpers/timefrequencymodel.cpp | 25 +++ .../disp/viewers/helpers/timefrequencymodel.h | 9 + .../viewers/helpers/timefrequencyscene.cpp | 4 +- .../helpers/timefrequencysceneitem.cpp | 54 +++++- .../viewers/helpers/timefrequencysceneitem.h | 8 +- .../disp/viewers/timefrequencylayoutview.cpp | 1 + .../viewers/timefrequencysettingsview.cpp | 143 ++++++++++++++++ .../disp/viewers/timefrequencysettingsview.h | 124 ++++++++++++++ libraries/disp/viewers/timefrequencyview.cpp | 8 +- 12 files changed, 546 insertions(+), 22 deletions(-) create mode 100644 libraries/disp/viewers/formfiles/timefrequencysettingsview.ui create mode 100644 libraries/disp/viewers/timefrequencysettingsview.cpp create mode 100644 libraries/disp/viewers/timefrequencysettingsview.h diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 3154fdfdf4b..b4e589a96fa 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -125,16 +126,30 @@ QDockWidget *TimeFrequency::getControl() { QDockWidget* pDock = new QDockWidget(getName()); - QWidget* pWidget = new QWidget(pDock); - QVBoxLayout* pLayout = new QVBoxLayout(pDock); - QPushButton* pButton = new QPushButton("Press me.", pWidget); +// QWidget* pWidget = new QWidget(pDock); +// QVBoxLayout* pLayout = new QVBoxLayout(pDock); +// QPushButton* pButton = new QPushButton("Press me.", pWidget); - pLayout->addWidget(pButton); - pWidget->setLayout(pLayout); - pDock->setWidget(pWidget); +// pLayout->addWidget(pButton); +// pWidget->setLayout(pLayout); +// pDock->setWidget(pWidget); + +// connect(pButton, &QPushButton::pressed, +// this, &TimeFrequency::computeTimeFreqency); + + DISPLIB::TimeFrequencySettingsView* pSettings = new DISPLIB::TimeFrequencySettingsView(); + + connect(pSettings, &DISPLIB::TimeFrequencySettingsView::computePushed, + this, &TimeFrequency::computeTimeFreqency, Qt::UniqueConnection); + + connect(pSettings, &DISPLIB::TimeFrequencySettingsView::minFreqChanged, + m_pTFModel.data(), &DISPLIB::TimeFrequencyModel::setMinFreq, Qt::UniqueConnection); + + connect(pSettings, &DISPLIB::TimeFrequencySettingsView::maxFreqChanged, + m_pTFModel.data(), &DISPLIB::TimeFrequencyModel::setMaxFreq, Qt::UniqueConnection); + + pDock->setWidget(pSettings); - connect(pButton, &QPushButton::pressed, - this, &TimeFrequency::computeTimeFreqency); return pDock; } diff --git a/libraries/disp/disp.pro b/libraries/disp/disp.pro index 43e1f128b17..7dbbe16c1b0 100644 --- a/libraries/disp/disp.pro +++ b/libraries/disp/disp.pro @@ -129,6 +129,7 @@ SOURCES += \ viewers/fiffrawviewsettings.cpp \ viewers/averageselectionview.cpp \ viewers/timefrequencylayoutview.cpp \ + viewers/timefrequencysettingsview.cpp \ viewers/timefrequencyview.cpp \ viewers/triggerdetectionview.cpp \ viewers/quickcontrolview.cpp \ @@ -194,6 +195,7 @@ HEADERS += \ viewers/fiffrawviewsettings.h \ viewers/averageselectionview.h \ viewers/timefrequencylayoutview.h \ + viewers/timefrequencysettingsview.h \ viewers/timefrequencyview.h \ viewers/triggerdetectionview.h \ viewers/quickcontrolview.h \ @@ -247,6 +249,7 @@ FORMS += \ viewers/formfiles/progressview.ui \ viewers/formfiles/spharasettingsview.ui \ viewers/formfiles/fiffrawviewsettings.ui \ + viewers/formfiles/timefrequencysettingsview.ui \ viewers/formfiles/triggerdetectionview.ui \ viewers/formfiles/quickcontrolview.ui \ viewers/formfiles/tfsettingsview.ui \ diff --git a/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui b/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui new file mode 100644 index 00000000000..29457fe127e --- /dev/null +++ b/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui @@ -0,0 +1,158 @@ + + + TimeFrequencySettingsWidget + + + + 0 + 0 + 322 + 432 + + + + Form + + + + + + + 0 + 0 + + + + Parameters + + + + + + + + + 0 + 0 + + + + Frequency: + + + + + + + + 0 + 0 + + + + Hz + + + 0 + + + 999 + + + 0 + + + + + + + - + + + + + + + + 0 + 0 + + + + Hz + + + 0 + + + 999 + + + 100 + + + + + + + + + + + + 0 + 0 + + + + Color Map: + + + + + + + + 0 + 0 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Auto recompute for new averages. + + + + + + + Compute + + + + + + + + diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index 0f79fa34f43..b78cd14c857 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -54,6 +54,8 @@ using namespace DISPLIB; TimeFrequencyModel::TimeFrequencyModel() +: m_iMinFreq(0) +, m_iMaxFreq(100) { } @@ -62,6 +64,8 @@ TimeFrequencyModel::TimeFrequencyModel() TimeFrequencyModel::TimeFrequencyModel(std::vector& spectr) : m_vSpectr(std::move(spectr)) +, m_iMinFreq(0) +, m_iMaxFreq(100) { } @@ -166,3 +170,24 @@ float TimeFrequencyModel::getSamplingFrequency() { return m_Info.sfreq; } + +//============================================================================================================= + +void TimeFrequencyModel::setMinFreq(int iFreq) +{ + m_iMinFreq = iFreq; +} + +//============================================================================================================= + +void TimeFrequencyModel::setMaxFreq(int iFreq) +{ + m_iMaxFreq = iFreq; +} + +//============================================================================================================= + +std::pair TimeFrequencyModel::getFreqRange() const +{ + return std::pair(m_iMinFreq,m_iMaxFreq); +} diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h index 51341273d15..de43fc831f1 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.h +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -137,6 +137,12 @@ class DISPSHARED_EXPORT TimeFrequencyModel : public QAbstractTableModel Qt::Orientation orientation, int role = Qt::DisplayRole) const; + void setMinFreq(int iFreq); + + void setMaxFreq(int iFreq); + + std::pair getFreqRange() const; + private: // QSharedPointer m_pChannelInfoModel; @@ -147,6 +153,9 @@ class DISPSHARED_EXPORT TimeFrequencyModel : public QAbstractTableModel FIFFLIB::FiffInfo m_Info; + int m_iMinFreq; + int m_iMaxFreq; + }; }//namespace diff --git a/libraries/disp/viewers/helpers/timefrequencyscene.cpp b/libraries/disp/viewers/helpers/timefrequencyscene.cpp index 73faf0fdb35..8cdbd2bcddc 100644 --- a/libraries/disp/viewers/helpers/timefrequencyscene.cpp +++ b/libraries/disp/viewers/helpers/timefrequencyscene.cpp @@ -94,11 +94,11 @@ void TimeFrequencyScene::repaintSelectionItems(const DISPLIB::SelectionItem &sel selectedChannelItems.m_iChannelKind[i], selectedChannelItems.m_iChannelUnit[i]); - QGraphicsProxyWidget* pWidget = this->addWidget(averageSceneItemTemp); + /*QGraphicsProxyWidget* pWidget = */this->addItem(averageSceneItemTemp); m_vItems.push_back(averageSceneItemTemp); - pWidget->setPos(75*selectedChannelItems.m_qpChannelPosition[i].x(), -75*selectedChannelItems.m_qpChannelPosition[i].y()); +// pWidget->setPos(75*selectedChannelItems.m_qpChannelPosition[i].x(), -75*selectedChannelItems.m_qpChannelPosition[i].y()); // pWidget->resize(200,150); } } diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp index 7dd839ad845..2800b6299bc 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp @@ -37,6 +37,7 @@ //============================================================================================================= #include "timefrequencysceneitem.h" +#include //============================================================================================================= // QT INCLUDES @@ -81,9 +82,13 @@ TimeFrequencySceneItem::TimeFrequencySceneItem(const QString& channelName, // m_rectBoundingRect = QRectF(-m_iMaxWidth/2, -m_iMaxHeigth/2, m_iMaxWidth, m_iMaxHeigth); // QLabel* widget = new QLabel("Test"); - m_pLayout = new QVBoxLayout(); -// m_pLayout->addWidget(widget); - this->setLayout(m_pLayout); +// m_pLayout = new QVBoxLayout(); +//// m_pLayout->addWidget(widget); +// this->setLayout(m_pLayout); + + m_rectBoundingRect = QRectF(-m_iMaxWidth/2, -m_iMaxHeigth/2, m_iMaxWidth, m_iMaxHeigth); + + this->setPos(75*m_qpChannelPosition.x(), -75*m_qpChannelPosition.y()); } //============================================================================================================= @@ -117,18 +122,24 @@ void TimeFrequencySceneItem::setData(const Eigen::MatrixXd &data) { m_data = data; - if(!m_pLayout->isEmpty()){ - m_pLayout->removeWidget(m_pPlot); - m_pPlot->deleteLater(); - } +// if(!m_pLayout->isEmpty()){ +// m_pLayout->removeWidget(m_pPlot); +// m_pPlot->deleteLater(); +// } + + //std::cout << data; + +// m_pPlot = new TFplot(m_data, m_fSampleRate, 0, 100, DISPLIB::ColorMaps::Jet); +// m_pPlot->show(); - m_pPlot = new TFplot(m_data, m_fSampleRate, 0, 100, DISPLIB::ColorMaps::Jet); - m_pPlot->show(); + paintPlot(); // m_pLayout->addWidget(m_pPlot); // m_pLayout->addWidget(m_pPlot); // this->setLayout(m_pLayout); + + } //============================================================================================================= @@ -138,3 +149,28 @@ void TimeFrequencySceneItem::setSampleRate(float fFreq) m_fSampleRate = fFreq; qDebug() << "freq:" << fFreq; } + +//============================================================================================================= + +QRectF TimeFrequencySceneItem::boundingRect() const +{ + return m_rectBoundingRect; +} + +void TimeFrequencySceneItem::paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + Q_UNUSED(painter); +} + +//============================================================================================================= + +void TimeFrequencySceneItem::paintPlot() +{ + QGraphicsSimpleTextItem* item = new QGraphicsSimpleTextItem("TEST", this); + item->setPos(0,0); + item->show(); +} diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.h b/libraries/disp/viewers/helpers/timefrequencysceneitem.h index 12c464b4878..8d3d1289987 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.h +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.h @@ -66,7 +66,7 @@ namespace DISPLIB { //============================================================================================================= -class DISPSHARED_EXPORT TimeFrequencySceneItem : public QWidget +class DISPSHARED_EXPORT TimeFrequencySceneItem : public QGraphicsObject { Q_OBJECT public: @@ -82,10 +82,14 @@ class DISPSHARED_EXPORT TimeFrequencySceneItem : public QWidget int getChannelNumber() const; + QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); protected: void initQMLView(); + void paintPlot(); + private: QString m_sChannelName; /**< The channel name.*/ @@ -103,7 +107,7 @@ class DISPSHARED_EXPORT TimeFrequencySceneItem : public QWidget Eigen::MatrixXd m_data; float m_fSampleRate; -// QRectF m_rectBoundingRect; /**< The bounding rect. */ + QRectF m_rectBoundingRect; /**< The bounding rect. */ QPointer m_pLayout; diff --git a/libraries/disp/viewers/timefrequencylayoutview.cpp b/libraries/disp/viewers/timefrequencylayoutview.cpp index c3dad5cd620..72d44c831b2 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.cpp +++ b/libraries/disp/viewers/timefrequencylayoutview.cpp @@ -178,6 +178,7 @@ void TimeFrequencyLayoutView::updateData() // DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(m_pTFModel->data(1,2).value(), m_pTFModel->getSamplingFrequency(), 0, 100, DISPLIB::ColorMaps::Jet); // tfplot->show(); + m_pTimeFreqScene->updateScene(); } } diff --git a/libraries/disp/viewers/timefrequencysettingsview.cpp b/libraries/disp/viewers/timefrequencysettingsview.cpp new file mode 100644 index 00000000000..3011f12c45e --- /dev/null +++ b/libraries/disp/viewers/timefrequencysettingsview.cpp @@ -0,0 +1,143 @@ +//============================================================================================================= +/** + * @file timefrequencysettingsview.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencySettingsWidget Class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequencysettingsview.h" + +#include "ui_timefrequencysettingsview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace DISPLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencySettingsView::TimeFrequencySettingsView(const QString& sSettingsPath, + QWidget *parent) +: AbstractView(parent) +, m_pUi(new Ui::TimeFrequencySettingsWidget) +{ + + m_sSettingsPath = sSettingsPath; + m_pUi->setupUi(this); + + this->setWindowTitle("Time-Frequency Settings"); + this->setMinimumWidth(330); + + initGUI(); +} + +//============================================================================================================= + +void TimeFrequencySettingsView::updateGuiMode(GuiMode mode) +{ + switch(mode) { + case GuiMode::Clinical: + break; + default: // default is research mode + break; + } +} + +//============================================================================================================= + +void TimeFrequencySettingsView::updateProcessingMode(ProcessingMode mode) +{ + switch(mode) { + case ProcessingMode::Offline: + + break; + default: // default is realtime mode + + break; + } +} + +//============================================================================================================= + +void TimeFrequencySettingsView::saveSettings() +{ + if(m_sSettingsPath.isEmpty()) { + return; + } + +} + +//============================================================================================================= + +void TimeFrequencySettingsView::loadSettings() +{ + if(m_sSettingsPath.isEmpty()) { + return; + } +} + +//============================================================================================================= + +void TimeFrequencySettingsView::clearView() +{ + +} + +//============================================================================================================= + +void TimeFrequencySettingsView::initGUI() +{ + //Freq + connect(m_pUi->spinBox_minFreq, QOverload::of(&QSpinBox::valueChanged), + this, &TimeFrequencySettingsView::minFreqChanged, Qt::UniqueConnection); + connect(m_pUi->spinBox_maxFreq, QOverload::of(&QSpinBox::valueChanged), + this, &TimeFrequencySettingsView::maxFreqChanged, Qt::UniqueConnection); + + //Color map + + connect(m_pUi->comboBox_colorMap, &QComboBox::currentTextChanged, + this, &TimeFrequencySettingsView::colorMapChanged, Qt::UniqueConnection); + + //Compute + + connect(m_pUi->pushButton_ciompute, &QPushButton::released, + this, &TimeFrequencySettingsView::computePushed, Qt::UniqueConnection); +} diff --git a/libraries/disp/viewers/timefrequencysettingsview.h b/libraries/disp/viewers/timefrequencysettingsview.h new file mode 100644 index 00000000000..02431b96c26 --- /dev/null +++ b/libraries/disp/viewers/timefrequencysettingsview.h @@ -0,0 +1,124 @@ +//============================================================================================================= +/** + * @file timefrequencysettingsview.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Declaration of the TimeFrequencySettingsWidget Class. + * + */ + +#ifndef TIMEFREQUENCYSETTINGSVIEW_H +#define TIMEFREQUENCYSETTINGSVIEW_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "../disp_global.h" +#include "abstractview.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace Ui { + class TimeFrequencySettingsWidget; +} + +//============================================================================================================= +// DEFINE NAMESPACE DISPLIB +//============================================================================================================= + +namespace DISPLIB +{ + +class DISPSHARED_EXPORT TimeFrequencySettingsView : public AbstractView +{ + Q_OBJECT +public: + TimeFrequencySettingsView(const QString& sSettingsPath = "", + QWidget *parent = Q_NULLPTR); + + //========================================================================================================= + /** + * Saves all important settings of this view via QSettings. + */ + void saveSettings(); + + //========================================================================================================= + /** + * Loads and inits all important settings of this view via QSettings. + */ + void loadSettings(); + + //========================================================================================================= + /** + * Update the views GUI based on the set GuiMode (Clinical=0, Research=1). + * + * @param mode The new mode (Clinical=0, Research=1). + */ + void updateGuiMode(GuiMode mode); + + //========================================================================================================= + /** + * Update the views GUI based on the set ProcessingMode (RealTime=0, Offline=1). + * + * @param mode The new mode (RealTime=0, Offline=1). + */ + void updateProcessingMode(ProcessingMode mode); + + //========================================================================================================= + /** + * Clears the view + */ + void clearView(); + +signals: + void minFreqChanged(int iMinFreq); + + void maxFreqChanged(int iMaxFreq); + + void computePushed(); + + void colorMapChanged(const QString &colormap); + +protected: + + void initGUI(); + + Ui::TimeFrequencySettingsWidget* m_pUi; /**< Holds the user interface for the AverageSettingsViewWidget.*/ + + +}; +}//namespace +#endif // TIMEFREQUENCYSETTINGSVIEW_H diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 7fe8f2800b7..8c227cd6b61 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -282,11 +282,17 @@ void TimeFrequencyView::setTimeFrequencyModel(QSharedPointerisEmpty()){ m_pLayout->removeWidget(m_pPlot); m_pPlot->deleteLater(); } - m_pPlot = new TFplot(m_pTFModel->data(1,1).value(), m_pTFModel->getSamplingFrequency(), 0, 100, DISPLIB::ColorMaps::Jet); + auto freqRange = m_pTFModel->getFreqRange(); + + m_pPlot = new TFplot(m_pTFModel->data(1,1).value(), m_pTFModel->getSamplingFrequency(), freqRange.first, freqRange.second, DISPLIB::ColorMaps::Jet); m_pLayout->addWidget(m_pPlot); } From 76d6f4e1a019bbf98902a5895de6f25b6342f7ac Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Thu, 22 Apr 2021 16:57:46 -0400 Subject: [PATCH 29/57] ENH: starting mne scan pluign for time frequency --- .../libs/scMeas/realtimetimefrequency.cpp | 58 ++++++ .../libs/scMeas/realtimetimefrequency.h | 67 ++++++ applications/mne_scan/libs/scMeas/scMeas.pro | 6 +- applications/mne_scan/plugins/plugins.pro | 1 + .../FormFiles/timefrequencysetup.ui | 98 +++++++++ .../FormFiles/timefrequencysetupwidget.cpp | 70 +++++++ .../FormFiles/timefrequencysetupwidget.h | 99 +++++++++ .../images/icons/timefrequencyadjustments.png | Bin 0 -> 23774 bytes .../plugins/timefrequency/timefrequency.cpp | 190 ++++++++++++++++++ .../plugins/timefrequency/timefrequency.h | 145 +++++++++++++ .../plugins/timefrequency/timefrequency.json | 0 .../plugins/timefrequency/timefrequency.pro | 132 ++++++++++++ .../plugins/timefrequency/timefrequency.qrc | 5 + .../timefrequency/timefrequency_global.h | 54 +++++ 14 files changed, 923 insertions(+), 2 deletions(-) create mode 100644 applications/mne_scan/libs/scMeas/realtimetimefrequency.cpp create mode 100644 applications/mne_scan/libs/scMeas/realtimetimefrequency.h create mode 100644 applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetup.ui create mode 100644 applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.cpp create mode 100644 applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.h create mode 100644 applications/mne_scan/plugins/timefrequency/images/icons/timefrequencyadjustments.png create mode 100644 applications/mne_scan/plugins/timefrequency/timefrequency.cpp create mode 100644 applications/mne_scan/plugins/timefrequency/timefrequency.h create mode 100644 applications/mne_scan/plugins/timefrequency/timefrequency.json create mode 100644 applications/mne_scan/plugins/timefrequency/timefrequency.pro create mode 100644 applications/mne_scan/plugins/timefrequency/timefrequency.qrc create mode 100644 applications/mne_scan/plugins/timefrequency/timefrequency_global.h diff --git a/applications/mne_scan/libs/scMeas/realtimetimefrequency.cpp b/applications/mne_scan/libs/scMeas/realtimetimefrequency.cpp new file mode 100644 index 00000000000..b0858741050 --- /dev/null +++ b/applications/mne_scan/libs/scMeas/realtimetimefrequency.cpp @@ -0,0 +1,58 @@ +//============================================================================================================= +/** + * @file realtimetimefrequency.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the definition of the RealTimeTimeFrequency class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "realtimetimefrequency.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace SCMEASLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +RealTimeTimeFrequency::RealTimeTimeFrequency() +{ + +} diff --git a/applications/mne_scan/libs/scMeas/realtimetimefrequency.h b/applications/mne_scan/libs/scMeas/realtimetimefrequency.h new file mode 100644 index 00000000000..1c185b21268 --- /dev/null +++ b/applications/mne_scan/libs/scMeas/realtimetimefrequency.h @@ -0,0 +1,67 @@ +//============================================================================================================= +/** + * @file realtimetimefrequency.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the RealTimeTimeFrequency class. + * + */ + +#ifndef REALTIMETIMEFREQUENCY_H +#define REALTIMETIMEFREQUENCY_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "scmeas_global.h" +#include "measurement.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace SCMEASLIB +{ + +class SCMEASSHARED_EXPORT RealTimeTimeFrequency : public Measurement +{ + Q_OBJECT +public: + RealTimeTimeFrequency(); +}; +}//namespace +#endif // REALTIMETIMEFREQUENCY_H diff --git a/applications/mne_scan/libs/scMeas/scMeas.pro b/applications/mne_scan/libs/scMeas/scMeas.pro index 4f164fe9ffa..f0fb36585dd 100644 --- a/applications/mne_scan/libs/scMeas/scMeas.pro +++ b/applications/mne_scan/libs/scMeas/scMeas.pro @@ -82,7 +82,8 @@ SOURCES += \ realtimecov.cpp \ realtimehpiresult.cpp \ realtimespectrum.cpp \ - realtimefwdsolution.cpp + realtimefwdsolution.cpp \ + realtimetimefrequency.cpp \ HEADERS += \ scmeas_global.h \ @@ -97,7 +98,8 @@ HEADERS += \ realtimecov.h \ realtimehpiresult.h \ realtimespectrum.h \ - realtimefwdsolution.h + realtimefwdsolution.h \ + realtimetimefrequency.h \ INCLUDEPATH += $${EIGEN_INCLUDE_DIR} INCLUDEPATH += $${MNE_INCLUDE_DIR} diff --git a/applications/mne_scan/plugins/plugins.pro b/applications/mne_scan/plugins/plugins.pro index 9e4b48f69b5..9e3652557df 100644 --- a/applications/mne_scan/plugins/plugins.pro +++ b/applications/mne_scan/plugins/plugins.pro @@ -77,3 +77,4 @@ SUBDIRS += \ writetofile \ hpi \ rtfwd \ + timefrequency \ diff --git a/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetup.ui b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetup.ui new file mode 100644 index 00000000000..c7baf50bf05 --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetup.ui @@ -0,0 +1,98 @@ + + + TimeFrequencySetupWidgetClass + + + + 0 + 0 + 600 + 450 + + + + DummySetupWidget + + + + + + + 75 + true + + + + TimeFrequency + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + + + + 16777215 + 16777215 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Description:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">How to setup this plugin?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">How to control this plugin during the measurement?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Input data type:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Output data type:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + diff --git a/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.cpp b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.cpp new file mode 100644 index 00000000000..00c7e7ba204 --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.cpp @@ -0,0 +1,70 @@ +//============================================================================================================= +/** + * @file timefrequencysetupwidget.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequencySetupWidget class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequencysetupwidget.h" + +#include "../timefrequency.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace TIMEFREQUENCYPLUGIN; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencySetupWidget::TimeFrequencySetupWidget(TimeFrequency* toolbox, QWidget *parent) +: QWidget(parent) +, m_pTimeFrequency(toolbox) +{ + ui.setupUi(this); +} + +//============================================================================================================= + +TimeFrequencySetupWidget::~TimeFrequencySetupWidget() +{ +} diff --git a/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.h b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.h new file mode 100644 index 00000000000..cfea9b53db3 --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/FormFiles/timefrequencysetupwidget.h @@ -0,0 +1,99 @@ +//============================================================================================================= +/** + * @file timefrequencysetupwidget.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the TimeFrequencySetupWidget class. + * + */ + +#ifndef TIMEFREQUENCYSETUPWIDGET_H +#define TIMEFREQUENCYSETUPWIDGET_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "ui_timefrequencysetup.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// DEFINE NAMESPACE TIMEFREQUENCYPLUGIN +//============================================================================================================= + +namespace TIMEFREQUENCYPLUGIN +{ + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +class TimeFrequency; + +//============================================================================================================= +/** + * DECLARE CLASS TimeFrequencySetupWidget + * + * @brief The TimeFrequencySetupWidget class provides the TimeFrequencyToolbox configuration window. + */ +class TimeFrequencySetupWidget : public QWidget +{ + Q_OBJECT + +public: + + //========================================================================================================= + /** + * Constructs a TimeFrequencySetupWidget which is a child of parent. + * + * @param [in] toolbox a pointer to the corresponding TimeFrequency toolbox. + * @param [in] parent pointer to parent widget; If parent is 0, the new TimeFrequencySetupWidget becomes a window. If parent is another widget, TimeFrequencySetupWidget becomes a child window inside parent. TimeFrequencySetupWidget is deleted when its parent is deleted. + */ + TimeFrequencySetupWidget(TimeFrequency* toolbox, QWidget *parent = 0); + + //========================================================================================================= + /** + * Destroys the TimeFrequencySetupWidget. + * All TimeFrequencySetupWidget's children are deleted first. The application exits if TimeFrequencySetupWidget is the main widget. + */ + ~TimeFrequencySetupWidget(); + +private: + + TimeFrequency* m_pTimeFrequency; /**< Holds a pointer to corresponding TimeFrequency.*/ + + Ui::TimeFrequencySetupWidgetClass ui; /**< Holds the user interface for the TimeFrequencySetupWidget.*/ +}; +} // NAMESPACE + +#endif // TIMEFREQUENCYSETUPWIDGET_H diff --git a/applications/mne_scan/plugins/timefrequency/images/icons/timefrequencyadjustments.png b/applications/mne_scan/plugins/timefrequency/images/icons/timefrequencyadjustments.png new file mode 100644 index 0000000000000000000000000000000000000000..56b43e9b54a9fac40fc22a1b428ffa8e8aa1b014 GIT binary patch literal 23774 zcmb@tc{r5s8#eyT!pzu*L|L+hBum-JjGYQuLQ%FXWi4xw8B1AhnE*zrWw(JskCD=6>$wy3Xso&ilTv63<$gaIzg_0|0>2%+$~t z0HENnPyopaJ~qQg{(uiupy~M_0AS~1{(%6w`GNqzW_iWH;OtrNfZ%{2?|?utGXn#$ z!0Q2?SA0DHApA>#jhC&>(*Bd%)0_II6YvjD2UznX#jN#{@%!#e%Za0SP9=yx8t1oa zM;jTzg}RFpVE69fQ~0gqIg;4M5Z}a$@5Me&Nb1?0jd<+yxn+CdBmMQL?&7nJg4%ur z3CWRZdcsN-&rz-~iYCW)z3rU+rhtuRlL`cQkhPb^gZ3mL05wWS=coh;(FQ=mhuM(; z$vlswBplD+Ue?cXg5cvIq~QA+r;+%50QTlR{igud7=kazmbL+k;DAf7yW1Ra_88zI zgIgE|@CDSI2ngW#P@Er9bRQ7o^GGlRytRR6{dP%4fP)gS&-3(KO>JXccbq#s>f>y3Y@;c4IHRkLyKWpW3}TF6U#* zL{^4`o7)_HzP~aM3jnjhQG;}O#oB{-ZC1P=z4-7N-1`!HQOI_(=SyzvYoKW9i~U9* z(>6wr(i+Fd=f8a$JM~uI(Y43^7TxQOGs%9>cPC1Rw*8yj_EjqS_{C@wIF9C>$mh;jMrjQlQ4 zcSaSczN!m}xPPqdqC0Hsv<#0!FzM?y0Q_nWXdjV9!tma)v;AR=b z`m%RER*T5FD2`x7R7h6dchUp76yBU`;5r$|{l^tq*e=@=je_fSBl%p#za&81k{l%O zAq8@7Q^ng&;k?OGV(%07SxKC}uWG7non$L^&Q#>r$?H(fcqikg``X>W@fg~j78B)% z(J!q|j&Qs-Xe?7d7-w9}K5#i$IX88GQQpAyR|ij~s6AR7sPyLklB#Rar9}EJh&b`q zS4p9>L%&8t9+mFiTO;v|qq6g0wcRsVbK-CJ{+cj2Z?q8!r3Mev7jqTWGj%xQU@>M| zCMGPUg8qV1N5SH(-pEL#mz{nk-GttGE9iDyIo`okUh*?YpL&ih?){;x|<#{Tm2PMz=Ep4$Sk+tIV@{WFOZ%_c+&js_c<1S~c~8{_{t5)>T&VWqc|jxtbqi z_nVzAd0w0`e9&9Kd;3b&_uwYW;{IOjLUa|-B1QCK> z2f_ravd=s{Fr0j#%T`HU`A7C*4tGw#IS08qxk&!|J!~1LGNdzv

eoE1p(NSFoSk zIM-{NT7Jpq)(hivCv4`*Q6rg^=PC-${;(0U@haCYi?8r13$VpJi8{ZR$a=oxOoyex z6RV;c=ed?nF?RO@wc+yOKAe?zLZVgQO4ocGj|`P-&fXJgPCi*t{z%i{#HkbZwbmOC zJu!&6>}%BgU<=fuY-!d;RMPam^&?-82t8Ff)2Qs>GX}(#XrKg6!&cR{Qi{wHsNq!t>utno#5yb)On|REkH*^v1{U|mBGahtU-xu zhHKVr-2KKuoyVVy?;3NbTq%_=P}ecF84d@a}7yz%Lgr`l(<&vbqK z@Ui&g=N#3%lggvV7xNbLM)PLsT`q)QkgqGNYw$38`R&5f^J{f2{@xR2F{r>Ztx%_r9*Y{y_Eo80*A~I={MGu3l~eUiI%@bgZSf zrr&D1b$9P1f-`=ct5W2GNL0|P>-)6qw5D_W^4Bo8-fdNHPU%NPabLe+LUTxl+)v}4IHMO-X zYw?qW4=RKsh38KM4RmxHkgetiG3P;$5m`(-H^B+Dr6gZgqo)*?rkb9x#@7p#*TiuBNTJV*9E*%$&{zHoZ&n(m8Vs>KQ~m&@AyfrR^`|S_tUQFSBRUZ*Lf{_EqI3Z zKJ&Q!lK##=xn5B;1M%LcHtiY9`D1K#`cJ>xUXUG?L%j6zu=gZ>OzhFjtSmhGarHxO z&qSJf{yKrN%KL_Q_Ca0AozwQmL>v}cpIy~_sdMed1lt@x%h5Y_tj}~BlIrCAK3P_- z+Go9pYL&ie?h}2fy(gyqHN@u!`#HAx+qZs9j;>y`bWl7$^V;>#odO|U{=}pg`z8dk z_;F*hli~A1@c})=oXLl;$}8VCUhelC@?2V&K33?+m06Lskj3TCIsWAp=ZxK})!$o2 z6N*_MWha_r>kJwn6LlI|JWAj9ebmO-KC#`j{bQ@PHZ=9xb(HEqxF!_QvZb=}X~MB( zdr$X$+r&A@IrC4RpFDQWc5AmWFA^)3sF}Nd7oS`BU0dyf4Z-#hl3aD8jU%5#hECdA zr+z;A!-T8rP#e8qJ?t2#8t1vY`JG=S0}XF{TiQm=Y>RSgeF;s8cs7d|J`^hAC8Bs$ zKlfLzah^@?uA`e{ljR59!OzRnH)$plhq&`qbk5&6wPE}I%9o{>;dHNG{V4?*1-GIU zb|zgWit8d4-TP*)atEw8@dVEf88MOP@#I?)Mo3ApZgh~KNV`8oNC>;8L<6s`}fTLsi^BR zdwspl<6$yu&s!{8oHwzndgBID@t-h`^vSXHN!(RZSkcDdq{%kx?bv?${okqF1}v#L zsl9hN@BAp#(ACuZin+eGL@PDuzuYffC_pc!_r4I=uNX!B^kcMdFnjP()~~E|qF-dm z-ZJUOfvSnlH=Uww@54_hU)r?WU2PAW3=>&@Ji~4IEm908%kbW*`E4^$x|@C=J)HrE zWpB{jPaK;7^`@A+skJ!(+&l~b_*ekgVSvvi00>b6fMpi|(8>k?fq)0j?~DP!8f9jv zXB+-yrQk+`lu^bO?nXd>iW|&4Rw9Ybzag3oO`4$2rmz*Cn4^vhrIdYF*AFNb(~m7f z`XhsDKXANE>Ma`}CnQbC-s_cJPSD~?O2WTfH{WjMpE-oS;^pOa&f}bshwinu9MEVTIMPf-Pv z?31v`w8ksA)wp)T<|h=I2uqWC53lB?NRTu96>{y{Cz?d4s6c*-$abwTfWmhoXkNfB zq#qgz6BQZvqPFru87xjPny}A0N?ZaBm_5)zQ6tDeJ*6zDYCM+onzV>lY|=D_VxeL; zJ>C3X2{acG)vJqK2|q1KVKtf4>i8e{Bj(NeafgA)s|*Hk+KEiyBTuxlH*iql6ay4E z=2-S@%pQBRz00xJ&oBHMKLkY0+tP3vt^;~Vs~`I~gpn;Gc{8bxUizM-@Vh+EJ1qrB z0WluD;aZfdzM`w|*Pi;E7$zwek~^_3#C&dp10kVr^_aD(~AOCEO*d$NW)=57R3^e{H#R=_r}2sy;M_7F$| z%JN{*L1h8;ZAY&09pqMb`+8n%^6S1muNooLZJwwd6Y|9|^RBu4upZi^kM5C;ph5zq zGFtI8IOfRvNV3YaRp)a>ihmks2zQHn(jVZ|Qk230>OqQPpU6O`p185Q0Qqu%kahje zyL}(j_ZA5L8)o%{=8wmQN#ms5=;p)VQkUJh0;MTU$}_%3>W5&HaeJ(1tFVNJ)LJW} z_U-DtTQA=F)6x1IokycnU3L?wx$#NRsH!e8F6^N2&<`t>Qm5ppvGC_`JRDmfLG~rT zcDEhfqd!X#6Ab<|v(9>KV{s}!*57F^jx=9(6Pxf-IPv3l|1UvmZK_2g;UmC>-MS&6 zjyn^)qq%gvY7#2U5_t)9c9B9Iv`_8`^v=0aBXtjqG8T2NaMS90+aZt1Xdis4wh8En z55DAmzI`|+J>u}(;>#e*oE?v1a^v^KO=2yhQzfuC2+Q>3)gb6+C{EpQU_H3;=b1yV zr~H1e8vqZlL2e$|iaOPnq8-SuR=Q&l$8)|8X5mGR#0@%)9Qi3*`|FSzOBy$IN_1-B z;V^!#KrD^vt#j~T_CEy>+fZVj-@_IhQD`6QY4$S@ZGRc52Pi66qZ>%&yEBq;4uBKK zincyweLuA{sJ}oo$U5h?2?mWN+&0p}omnW9Vatz(H|%RxB#ScPTx z+p1Rf36sQAWKyIMv|$mvQ+s?3+w+kWkH;DB!VDwEMH}GZZCxZx0XuE@B9tLp-s!(_ zYP|9CODr;&4@Q7YXC?v6J}YuKpFy}hRUDr`YgJo=46Q$14c*{!`|-Qyr^n7gwV6^; zXtAH~q8&X}O{BL^q#%amtVWGJlvOh$Z1c)YX;)`_{(gZ;AB&wC6Kn5;$?hb*;QA3( ztI{82v^s<`A{C>DeCxcA7^V$xr~Drdx%$

f_!qhs zq=*8(fh&3ghio~{oNXB|HRTBAgJ!u3#Y{fQ7C-m~O4etcpk&q4HllGAZ!0iQZ#?mK zCZ&9E=WT#!3wdW4AHqBFisfSJTck9v-4xI^$@$6_oyCH)iRuVOi zEp+}J@PU>;6T9z+n-uZ95>e5`b78Ufu5!R%PDlrX6Q5-UY@XXR<3^vgg+8PUaYMS? zCQh)UB`1#OuM+yVOQSK(zfwa!%>>Y8ufsgQ#gXLPKd|ruyg*1YejAD~g>Ujh&A8QF zSf|uEppnpKJ&N8%J2ZNurg_gLyIJ^4<%7JW1 zL-j zqPd8ceG^l`_1z08@1f}GF~JShzuwJZ$&VX?#7>X!HRfqM)6-{UsWN0GvSU+R?e;Ov&6fX+wdQI;Wp?%k-#)%Pj`-3cl~V>_i>;FLFH{t z?c$$0ou}5+b>~A+)bOyy7@b@-=&>)lMsf=fI@FGHSD-HX&>~nE+=A{3?-2~)?IxC9 z0f`*NA`R7-h8_0;bdHciAQelt)#`1Bx z)Ue*2VHqlJKyYImGTqUI#~3O=r?aKrJD~t{5;9z!!k>tLbem)=U?Qe{q_4g35XJMN zzSW5hC(2Af!nO4iRDxT|&L)0+&wug4+vE2867gM-Dp1IXC*s|$v|I-Anum>M1yIo= zyeC;AoXU7YssZXgx-Y{umVro7CLH{AB64PLP0$G2h4!5R}F4g@l!2SGMqj)unJe(j4A`SVali z!7m3;?w&LxsZb!~kfz{bi8>aAB6>dKh$JgRekWba{k-gx(G%1pRun!o2_FWtH-m>a zzHcspJ*^SSaH z>No0)wVcJ3*d2OZGN19pRs$2?7Fk3)DP?sGFP&RY7hR9~yu8~WEwK+W0qwsJ@H|Qa zN?Z8+I`}$8mxEulcP3}q;b`?dL zgYOHm$b%Ll^VjS&^i$qIX`$50$0Jn<{9~RMYLBNn6yP@x>I#Qvf|i>?X>gUmA~hj9 zTro>hyAm$16|w}QH%({0_~FR4qL|V9q`^i!rZyEwxP8*#mividOkxT$yuP_H1V2F0 z7b_4u(r|}WV_$?z_fC_O8@BFn8W#?4Il(~I1MjO=%-eCLgu}a+%*h+=>FH8A2fjk| zt^G6eB1zBu1fJ?CenCb#j&b+xINx~_G-JU~HNw6Mg( z@v^)SIrOFs^yLzM^M*9VO1+$YFx5qiHaoaw`QWlf`5~M0*_Zmv$ zpreGWVJ6GiR@>_^Dl9UDDrxqB-}ei}UXALdKAJlzxjz(yfO0Yu0*UzY5AF(-ODk=F zxL7_HZmxPSRYZ)s$UU2+N{uz2Hw6;BjY!S&@NhoJ4j;>QM<#-;MkG3z+EKNNlZqXu z??{H0o=CNblMw4>b>Rhy<(CD&Tf#3}@|}_S&Of%lthiM^P_N#qB+Bf;v$u6r5f$p< z`u*|*BT@$#Vto1dxwBfNEatScVJ++>&@ZPhEZf(w;*Qf#?@gc7rzr9QA|qvIpx6;< z=)DXiMGiXje$|L{H2B7aE}b_=es46+2BcXNU$$dD@596K-uX!C14B}`gqZUIip7Xn znYqfRElX|M-Gj6Z!s&KrC>AaOy=Ni>yQKvg9(x?iJzR3doI;FS2%$Q*lbiQ?SsC~4 z+y#MX0)}vb#CHSa887MecV+6>;c>1Av5}3dTy${|@a**AMsn3BqD=6?B8oUPIEn1t zj?oskbXAAG0H!N`jGKm%KJSc9eOtUtTcBkrJERj{w&QNbk#R7JIk-=NjTO>%A-lkY zEwupAh9fqB(YSS7w!?$6qK2EgOT1L-Qd8~vCqI@m3et4`&tiX=6DV0Jy0I<<;} z)5CUCd1>o_9TX$?^9xrXFQtR6je(E?424X!St|?!RRqKe0B(cwrm=B!!$YN0d%CMX zgPya=Q)gJ^VNp6H#tD}Exu`{rMsq0k)q9kNXbH?14Y}e$nufhNXyouA>?p%Hgc=mR zm5q;KtoqM0YQ=SXQ}K)g8yXED!@V+RhRv)IR%U~Wn5wjTd2BX+dHX;r;Ro`~msOkq zg^OHj5LI}EOzhIx?++5b-#*AGM2Z4@3sLx}7tMcng|cWjUWw}6!aQjAWk{@vZV3PO zK>>qy=%Rbk9V`qL!7~~H*tdE&tNWuMa2%nISQUFK@(cZ_vBQqnc;Bte&Dz7Fi@>(`N)0??A*4?wWp{Q|hQXy%v}ijo_aJppT@Ib2d^8&f`80g8lX{c`bY!pu_Haxr zf*sakJt{9dl#iP_%CMpM>>i4qY7w%gI4@nB#~?IB!b23k_xCgcH_%G54A+!K%t*V? z#rPU2vpU3rpu7LjB%dnC_ab5{4&*WJu|#Ybe|-wem^8+GV)f9McHMf{u-)AYJN+!5 z0mOo?^Uc=uNv~c}qkInPG?D)oaBmQzAxypeKuY@x{Yo5PpztXK2d_pQ>!pfbD{XB! zFRg2ER`IPhhET`I8QW7?>e1cJ*Y*5X7=I1$ciW`Hd4Zfy433qYjee-YnFp7n7akcW z;N1(XGm)|ahL@6t!a|O7M^rdZwKHsUr)Jmv$z{rLhP{o`T9)pwH)4$3mysQUK?FD+ zQ^>k98#OK9cwJJaNYjF(28Ou)Lp_P`emCb%e;&LxCt{`AC0Q zJkcH1zqS2(Hb9|Tt@hWtz=!mhMZLu*>(J5D0Chft1-GU1Or$gzOQS)l_IGBkO-Kv4 z;4UVe8t?mfA|&fi!Kqqp+SJ{XV_l`IIM%%DbdQ+E_qPt+X;(jj(;ZpBSh3-y%nIQ; zwY|=zOL!4gOQZhV7D!O$E|hogR3z>A&mYo{XWH}l8!$$E<|c)E#_2``<=wp;h!H6@ zI-paj+Wk6k>1*47zs~5?liYoC3*uy9wV6oCy8I^#uIe30KVRaNzU?tzcP#lM>!N1HS!HyJ#rH$15mTx9 zsw~drTB{K3N+f>+f>?T8_3p*!i@^t4Y9-Z1MfJ-G{bb_tYBH{pPpa)Yy?hmOibCi) z`4r)>hwBmCU`GLr6=w;m<)Y{=K)~LDy3Oxj@g%+CvmX~~GM6GO$pfb0@DsJn09JDEHjMBEn}<^@=%u{f*JFz^8U|6Zq%zsl;_S)*XD0=Q63V4CGEDf{chsK_FWo7qI zd<$sva^Hq`qY_eojL{4g67k2z?@oVGE*56@e!5D`2efGi+(EJdMcU4V9aw%q%1&rX ztS&2pTtj+%lf%}g`p-=EjWh1OC4E`QgnN1Th~@_1%`fj)vmv&jfyr@A>a-o*F)vM5 z)tyEWhgpyb!cvYhUTQON@O+^kq*No|gZvG?g;<;&{7D2fbRbfIGpzQCq|4y=Brmk? z7^Sa?!vJJSaCF@U%RKQTNAZn8LOm-yUN_BfRxl*eG#|o!G<9el7?ALj~%jf7gW}fBZGBR70OUC7~)0rTR6x?3h+Wz;%fx`YIG50*ufS2(0J(Pv+YSFh?^%5o8_>)JwpTo$+- zkLj<&O=;q)%j1vcy=-F3>2f;6d%?Pkw3x0*OExa$szAH7)M!^0po=>(A|1AaydIJhc9Ig~|gO%y*Z6 z9uDi>J@Ev2Hqj;g+wSC|5ndQ?u4A25RHzNk(gTE*ktD#f)F%Nr~MFCU|3+?{aS+k11@y~zVxb(4|v9G@!^A?n{vcH8!%cH=< zj760_Y1DbZ_g!WL@T-!c7lTtrD;ZtuA|-=UE}(JNwLBjXTmH)SD(40-fYTG9S6tk2 z{;{<2Q9Pd$=kq1-ahyEhX&u>f-U?N8fHI>X3EeV292269a2PsFkzv8GJF+O*WP$I= zvC*%9oT|yFEyFAl@7(dHCYu8~O}$A^WvSfD&|p4@(czfI_o%Y`QE0>_HG+kHEGPOH z!gsgF860$pQqSw1yNcsN6IMo5AWDzBNTO=rxA`Db6)**C1hnF-t3#y?N9Tvk)WJ<# zreOmp#10mma|rzrxX7VuX-o|}-el_l`CJnI)?|;q_Vcd(6D zyTi$=>wPy-@3x$WJB4H}LzL?Kf$o`ybNe9?k9pg#ZRnF%54XwaAc;?vQNB}e`deYH zn_B?}@kIXcmwV|_;ER~N%yD`R62HWoPUJ?ooRuN-fs%tulqLVO0X5?QyPp8C;kcDk z|L*Cce)XQv%-<~zEQFd4d~bjDfD7NBNL(po?mnu%_Q66GmEYgp*i97~eyRMJ3-@V^ zZbI(gnql*)C*Jv!M|*Z zZ7D=QuF2rhq7^)zkfqfEJILv5GfATE{#9qz4yXLwPtOAMN!?#DpCBBOlw z1^s2rm=~BB?}?%uU9r3*Q6f!7klg=p?dKe#}jK+IaN#m z-=c8)Aa6e0crfYRv1`!KqR4pSOTL{~F}U)?lXeiLLyqD@piX%tvXcISR`q*xNB_v* ziL&7xuIGAG!W6t4kfxyBe$}(l_eAi5>X4`NkHm#n=7KtAPQB3@>+*@mtkg__7JAHy zcI``NCcx>_8xk%}Sh!AJ_-S~3$a-tvonvpV3*h^OX&5Va@~0k=}D zjI$QMZOWaK;UrGdEf!oMKSa3%_DlWdGZEM@7f#WR!W}cQ6m`?n+g&=23zv11<|Ll^ z2NV>;84RDZ@fZ~T)Za(0Y4?f3rfUw z5Ga{{_Q0JNJ7}c~mv`%jAV9+lm*0o}^xy=+s0tKyErrzu=^M3Uz=q{2 z#Euy&a32O5xCZ!M;^{uleHIiI z4K8k+ex-b-y{v-($9|-}a+xO>?x#g0;%S|v)|y*T{Zj}qguOeQ$6D0H(AAQzueL=@ z;)w%b^oCL=zOYO;`7uh3713U4blmpa9lHt zU?4(wn_qV#Rs3liOI8Zq-Cd*9=Tfw2d)@!cdyoZ(!b`k(uL&q4=z2yZ|FKK+RWB&F zMDVXIw(TgXneb+1N?g+VhN64e<57OvtwSrdDd796KV1m5_g57m1Gf*swu7$$U&Npb zphk{N`1usRACPekJG1_jJcFDDS_sQS5LUVfv zjotyl@nW(k^9nw(8-~N6(-hGwKmfdrP57Q)_gu1Hv^vDO<3jQYewxrcT>kCncKaJd z0xI9Zm9p)(8~=GW;AGuW8i*PMnAlbegi{jTbuAuz`~IOqLL`tIB6J<5xb zrH+%HO(uU9`No2Hbz`R_DZ}DWAE?eJbD#=Rs1XxrMd1z*Huvo8^WBcDan!TBLCF7R zI1iHSdnzaj^&HHjJ~wX%y)NxnS5M1eoHv}Fz+_U#;gD*@z!IS{8%;=cjX2chEIJL~ zh7zG|Yjy}?S0P83$=cKD{XRc2tj$(G4wGyqFDoVaJR%=j5X|jP$veNM409~p=Gtzx zeYYE3&)4tINVB7JH)b&Gb*gAS^?P@feI7{p^Vvg-v>-}+R5i*IU1$+1+7le6HCgm+ zCUPoocOzaCtu)%zU{6Wa2hLpX{2;%r1Do)>ZuCxqEF}ZgzqE76%%LPos9K1JxXe^s zDbsW>A@{!P8%=QR-46-h^#jg4_||IyNadI*Y?`mKR*U`?f@^2Wqn(l{Zr4ig zNEU_**OnC}3#P<2gP;pI7TbM;N^!Dlb!b48M3o6JuH#V~59ulEePcL?q&=PMnpp)S<%581m9q;}ZqPG79whs`s@zt?#g0gX%o zhCSv9iZ-^O+b5-R#8f`bha?}bBv-W6r#lsC$Nl266Y^y|UE9i9JtWJAZd>ecj2`_6 z@m{{{FRN>;5l|9(U2npR+)rQQWTOuzborO#H+LQ3kx#zvkZpZ~Dv!?{o}w(CpehE0 zQ@Bgs_n&8@Uk4(8o$zg(xRgUCOusE)#o3Re%D&$zn2jpzo}}>QWQZM>!PC~|F6?ac zibz<#icVJhc?0!FifN`3B~6J0|jh;15CY@`HuCznarA6rO)o58K1K8T^j0dO+zs8NP2d zqubK%sR@Okkc|W#Dx`in#<`AY_(vzvZ@;ZaqS)H@vG=I6Gwm2K6LU9hZ>WN&Z!g&C zgAf0dbA$U9SA{=!`&b-C-m!S!#P(D@=$?9e9-^ezScrP+a=e=zUreeZ&*;dw)I^wP zh`=ykrzhODXG+7l=q5auB4*}v{!2z6T_1L0Ytaods6Wh^Mksoz{?pL&O|ESCw^Zx3 zt@YrD>`B8S@{AMutVtp{ern?w)o)$MEuJ_>aa zB&WtFpMJWcR^|n}HMmS90Ns`x#?iz<_ovQUWQmGn=uPtk&`uL{pJ;DAKG;_8^FSHzz8oO73DO{>{{Gpo2cqo+T?w&(jiZ$Mew4$vPTNli zBzR5`Z@0WHN}He~tlN(LX|SU&E@wUf%5p351eoR1u?7FRCxwhgS;{sq&{}AuZA7vT z3wWMl3K!OMs3U@#`)8|!g53%(`eM&kYF1+QOpEdYWaY-t_+7l8H;3VSp_7DR!rF#x z&(2Y5y@AS>&;D0}RBx&65m4g{ZR;%>QniM{6ax1L27YYE-BtFy>n{#o`8PtTC-c^C zDh3(6I>(bO8hr`kEK!t&bTIub0z(`Iw|lylzk4(Pd^$kuhhE-24UF`i^cU-a@VL<= zTu^nfGnes%N1P&b3vMwgAvxrd(Ko4@b+_PV(?uxb-bpFh=d9kRZN$V|rmb_{=~XS` zlWRUf9=)3J2ZbbfR&jx>7(##C$$bve4WYEdNL}ns_@|M&;`%|%6#NVcf>aad+>ZIU zgW#tb(NvCLFF~AopJq0kVnHfjLRSk;^b-4mv7m?Ubp@2q9PpLs`|Is9{*3W4Yho_P8;qv{Ks%tHjsrEg=Yo>eyy%8j#@j=8xd#JLyQCVl8xa!qrMx3cE!YoQF0H z9&WE~VPe6ATRCD06_bm){rY2*NQ`8hU@B7MttRB$Q`l!#WU9FgB~_eAPS=uL3eQde4)z$A8h1vcdfUc#dFPhx75iUO=nITQ0x> zUWmS}1T<3%ebz(EWIXr{YH*<^( zy+vR%(ENNfARb0#_n61nrh_}3hfrirbB#!&S`lZoK6sQqa-T~>D32@q4X%&j(BF>p z1KR%z{ft+S&aL5~j1=Z1vyf$Tz@s3i>cSo!{iDCN)0MPnOD=@Wq0N2R9u6|ph4A6Y zh#o&gKfICi1bb4{5`KP-UYTSN{dnvlm*B$K4^HapDnQpt_>wL9>%x&!zagm}2Sn*|ENOF0UCCP|{ zh^I0l!Sj}(*>&NE8v?J^8z!qX<|~;il7VJg??LnhT!mP29&FPL+>vx~a68-eF$n~Q8{XI9XtMruf@86EWel`QlhBm z#&=$|*BlB>+aU4A^U%&M%SZvjVeVn9GZF&WgbPL_-imd>>?C{(pAy#uEdw$%nZqVpR9g4hWFXs}Rc?3VF9eOpCn zA7WbX^~addcbTYNryb@_c+8&8tl%)`0f4HmHQK5v9BEaFZ0Od64Bx-iHXb+lt@Nce zsNotq-g102!_8W|=mu(Z{ALr--{cN8TcGDI|7tQ?yP^3re=-N;j@H?LyN-M8;t(Y< zuO|L(S2nu-hywI!^%8!-2y5C5ZfI`9Nyx~_smOp(^_n<5&+i1hfs@ijqlP8C<}2An z#oXIlK=5KfjfWmM6Xn8*(UV!4MwD(~y`#~8-Z_j?^>J%d6j+6L%P|)G7s8qnO(n1i zH}mng*VgS=gAe)hn^G`B<8(Ju>0s2&U*~b#IfO z7jU2dL7Kp0m@95ZQoTQJ*nz71b8$Wqth$OLxb?!SGQi-sLst)ILP9=V)aEfRAaZS? zc>(?n6EXpR^e{9Itj>~$=oO7V%<<{OVGlDz8{H zJEF!i_+Eo&Px_0uFYaHv*&CvDgq^4|?pU643HW3@KYud*@LE_VioV$J3HJk9#H^Ka zL=3czNlW*q^YFN>NRZvgrWNLhmi9*ORzobMB#IdZyue&u%NENe?v<)Wr-Yg${6h=X!vLtc#Gu8pzth2*yfi=%(@(PFT;cXD)x4Mh78kJRBg>A9RCn+7J>%o?=mRgw znYL=tIT(I`B1it2J9?X<09`(XXc^w?JCQiHmGxgQwfIFC!etn~p+aPz{e&uOawqF= z7b^JnyvzKrMJjL!e@r~G;w_%%k|9<^1SWJFTno6G*E*~bwpMx{09!#p^tsC754=U!Ph4v^B%XIV69Qd$eEh zl{iCenh1;oH&v~{B5N(*Yiw!b0 zuwUD4ms>uN@2k98h;05+lo|`44`PfQWznyP0~+`mKAofkA6TbXq@Bd|_e0KQA(`c? zBQer*Ti5C%_L--p`=2?Zp{I0oV4@Jhy2Vy}r%_AN z;fP?~5%wCBoi^AiipSjk9awhqu7x+kv&j&T97i?qOtc1^$~wb^7Y4*>fh7^T?dGra zvj_=>Z7|OMH$)#S-cB$Mx*eel*31|-NVt?oTm%Ii z3M|$>s0d!XCCZA3z2S$Po}@ZS%V5Du?AcVsCbRI@osW?YU>982|26)YF~(`%b>&PF zsQ`%O;^76$z{5QX^1vgyhDAJ&cmlq}KeEET2)tc?Q_GiDU2b?*f?0aBziCuqSP-00;WAQC!y*Y# zMo%5TYsIWCcSfgWBClHFnX9{AW%XYVKPH2|s5$%{%~nDdtVI`0M}7y^jg|oP3#3C* zNJVBZidnTzmGs;H>fk>s+>cnj{$HOmVtR*TBz!>umdC2WRsv(zv`?F!hJTVbjgyCR zUEBDi_HP5@@hfaHBC$W2#*&3C1(uleBMo|2zDZ3^wj4^dV?XKtCnAcgpbDy=aNc=<1P^ zmH#X$`D4=X87$85yMzmC-T5@bzwh#CVNKtPF)ds6KYN4MBoe`3ncv=&_B@Myz{W4K=H)QR+2+XKk0^IXG*J5Qh(@6$G zIQD_fN*qeB-u^fDL#Gf4f`%lC?H1wx=2gIKq?~|1LYCEpFeicgHwodd3qJpvh=Ptz zc!x5@OR5?(EgWS;f`i>u8GR+{C37wy9{-^PRCeqCnL5B}P1-F3nFN;2 ziCaATFK|G2!)cd5bAu82zn<-z$i#!7xo4A@hGGKcJqo-QF{E1H+t*NM|5@LPITARX z(^L6Xyn4*Fnt-SRt$KS+wf8@({WUb`jdyFRrx48la-mcF7bDdpcl-HyAz;rcIVklb zcB+Hr|4?wfzgNY0LR*<_@Uka#5h?(4JV%YF3WU1!n0M;i9)ku-6wP(c?yFYb&{;Jk z#q+a+OZ9f6Ff=GyTv2@q3K^;Nq5+cm>>v77xC(WfGl?0AxwMC zJAZ=%EhYLgSdbuMk)}qQ*Fmp=xZ-4|hx|2iO#=RkONJpH{Ol1cW0;kLF1@``In{s8 z4)G70ps^uhhF~eRZy)9m&3pk8n6|q^VJpDDawjKxgZwn{53PrRIOJg}_tjmm*eDqp zfR~KjcJk07vkA~LxOl{qnUd}ymp9KcT-J?~-Z4gBa{qEtZ9&v#>|V4FNF##^XkcE8 zHA*mq;~`AU@UDBP-~>2c>12?M>R20 z*WFW2!NC<%?paP?h)GM;H~6vY)@X{|i1Jxe_~rA+;C$qOAXrTH<_C52%I;z;PG*}i zXaW}``!RV8+5J*5`_zMPvhFEca3-U8%;OG5`7w&g1kQ>*>8jYtjoE+guFI;4RO>H+ z@=4s7lm0mK59dMJFhk)ev?3V#A~2nTVtT+HE)O+*a5-m)32Y7_T361-`rqqs)Th5u z^Hu`-^nuh3uo8~>eeJKRqf~AQ=+NEhc$@n$(@FCf}t0844SEd2BRK?$}M|($QL?TR~I`ra`5-Pq!;#0GA^oL1ew8{Tzxp^ zXa*OOF9fp>@GKOYu+oDuoWSv*t05W(n>DKx{)Rn}0ZI_$ z&n)txH~tJOLlUb%up&44Cin)p?4f(n*P)lz=!T3qag0{3R6#}n0_k;L(H^$ozk}+7E84-g!qsj1ZXT)J+ zaXtKFoY7sU;b5#Xsk!pI^VOr^K;P!%JDKI%1Z1Rg%#Y{)kxr|BMspTO=iY+pV3kqx zD)At7JK;q$6Utzs%sY7HJqnxwXYr9boNqhk@GCb!`oR|Xft(lE4 zV-8<=aI^JaM9T+PUA)J{UBdSmoK5Ji^C!}}3781Lx!m8?X7ZAuVLN7l3pY;2dBhS+ zd#7I8)`~F!^7dWnU-p!^mw{VpCtd-`XJ~&XIGbP@F$f5KC>AbE%S+n`s92pj4F^X< zUS$3a$0IeU>W@aMjx_HfjQ)*O&R5Ayr{EjyQd(oB;NA6EX3B2<*?7hRTv8cs9#gT3 zxeMOEuz;BZOn3U~CeQwc)NdA?$ja~;CI>Qgz}wa>k-r=TG9Fl_8K8Qtep^J~AB~nM zgo6AI$DgGf@}8gB%Ew{;WeO0~{9xd~@q!VQfTUIM1oO~eqk;14E))K4AKEcnQ*^&$ zzlAbYM5-@HV8IB>bSsbp$qC?Lqu*|Ku44o~5rLiis}`1MugT}MvXRDECq^eZ0@W0drK%T?Sk~bL{{v6x+=l60D->Q0!FU=>wV`nT&(ZS1K^a=C zr+`J4m9Q46gH-w9T0A(Ax1rwb$Bz-^!fCUkJbD&fN6RAererBA! z@$hkpX5Wl}SzeFE)hka5epywl0FQg}@t{PjE&#mSA^N<)Y&AQ@mb~Pk%{ZVy?ibwP zd^ANbJ_RBX%)On5#H1i+xwT=_}mmyoRx7@Rp(&pU$KY1i65vC ztpcmmZ{3ihxCyKfpgOGK!5`J}r}hk|EC7p55a-OD0_z&=9+-AIl-M=6!=tb;=XU2f zDX87!yU`L(V0t3^lSiIj#G~#;*KBM7F}Q;i?VQClUl0(X$#}j=>gixjL(U+{9L=hU ze5wWcQ0~?&pZnMSQ)axI`9D?2J|sI;j_)h||EHGoifUr}_xQ{tA%PeOCrXiyRF&pY zK#Bnb3rIVtR3!>_1eB^ENkA!zf*w&kRK2@o=O zdmrvv|Cjr8Z=SNU)}G0pwP){N`F_6r0xvdndxaz_b`?EuUY>;;#b?@W+`8Y_fgRU& zfbqJbM?gU**-_ZO)boxhK+<+TkXL={)GEcF{mZ!HpP_B4BnXVlg7lQTg7Je2jfi9y z4bS=m8X58FY##m>Iq|W>BIy0CRSQ#L8^@}u%K6~s@dYr?4X;->aVm^X|Ngu3IsuAk zVxqoiSwvt-=lfILcbodkdfe8A<7Ba8ofQhQl{2*Ch-6l83bM$;7e7_gL@VD}2Y~#V|rv!$5TRtBk<<-pfq!PvP)~qIL|MDi3-pbz4P- zFP!tWrGi-Y6DU5Mw`$u0lI3=213}YgjU?fu!>bRH@|?6>rSChK{fED=NEWR$){kT5 z0$v7c>`)Us0t|-CddAARlDNy)Oco1JuGS_cJ)SCoIVwHl4NhE;8i-uc92VE6)iq%^ z*wA#eaUtg&yKaSwEc`N}-0z7tk|lF|i-Azd*n2d|$4=L}yedvyizL(wh`&3(hwNc- z<-Yjw=7UyQtc2xZ=6TS;5-1-sZ~bt2Un=v-ckjvXVno+<6_fhzlXo_42l2EwQDP>- z@fXnZs99@%l1KaSL-yQsm2ss`eAEt;R9)~4hr-Hfwj8V0K{L3^9Ihk<1b>d3)0Q6c zD?YEjxs(=IX%Pf=8r6|a<1EX1LY+dLoaDMy`N$#JM?%u2iD4+IUg&6`oNEW`*t8ZJ z!Cl(0NG*bc6}dl!tF_Oc?0J;{E}dQIE~E7>x=kxt|z%W?NV zk$}(pLzQpMcM5C&`Wy6>3aK_^-QFhZthq9Xj+sIPrk2}5dTg-l)Z8f{y zfhoi_zFdz31l&DZbgI?ZUU}9SnPrGxGu(Z(R%WyGo-9mB*0$$9U2lR4HclT$f8@w{ zE9SiuGMPO;da9Uh2Y@LZek}@qoiv30S_Q=;O@yhC<1@o=<~twA!v1yU8$9~t{qCHd z+|IULybY32R=4*v@meNb#rEvC;zqknQeuPEScO&cH9JbQt(O`=PmaiXc3`nMqY52R zqlW4<3lzFcQ%6So(1Evn9jXoVy3(}Y?nUPeCu@|P2dM!m9hs=6HkVHC=j%M2Q4+;a zh{~kNLeiHl`0O(n{^Js2zvr6Ld3pGT;0|9Ym8s1LAyBlw8%(0+E;9`OUFXO#@r zhEne60RRN?0x3tR6te9d5>|=S1^9QLpqnum;Iyup!d;p&mBb+kcO7)Whvta`a}$vi zva&9Sxz@vF-;Mxg`At*RF;kJny2VJG1BJH(DOF$1=s6U=ZyCdvgO%f%gA>fO^mNi? z5ZZ7092sFZdLfhkOnrN3abbs$hJx(uujcOT$VD4NVaW|CmsAwzRkupZ()O0}bUN2r zLKS743dUAozQhm9%u`GA|LX3^53P{F|4642ODdf07 ztD$0Dm}=36%USi!ZT7IFXYHg8fBz%cr^OhY)4URKRokrf`G-S=d995rTb+<8J(y~2 zfm76S`ueze-h1v&dPZjMqrlv^@bf`P8oZG{pi`9x)24mT&=}y13fFk`{$hOaqW8o4 znc=mv;Ek>T6TGa*yVMEKu9b*)O@y$v-t{0(T{L(Zep}TQDa{XK4H1{f{OULR`C~n( zaGk4bi-}gHVZvK!jN>$Vh2XW{6$;bF4M6tpP|GuNl_TeMm-VDhM2g6WLhGjfN+e&u zN57g$3QH1V#0CX#;gN82QKCG{Ha}x%hJFNn&kVkYZHErxN)KKl9c-XkQj-5RESa&J z&Hto5@=?hW2Jn}z;svDG4t+&GvglpQm{FR*K&Rj>Tys~@X7-zXUmc%*?HJN(io{=n zNF}OBl&QLOV7s_Ppt^kJ4Yq#i8zN~@wWi)bShDhGOVc$#LVh)bo{sI|MfyG@l4M68 z%KT~9+m8;oH$Dii<<T9U!1PdFk}vJd(_<9s?r+LB84(xH;)3 zesHUO#YtH{SvC?2YkOfos_{;g)x@9Xb3q$tJ())X7QL@axd%Zz*HhdB%BM*UM+XbD z*dy_9%_dV8Kk)($+J`XXN9oV6cryRemcr9lak@d9G~U9@!{Z4_R|~kt3YyTcxl`r0 z>-Q0cb-skq-R{Bd3$D`8edx>#8D)LIQPno+tVf+87L{xY9 zUB~b2G7q^F0`{g}Jq}u`KZ(Cru0GB>8a%Hx-Ew6ob03rDVN#h>VP3C5!leB6=) zi>h%8M>K|e3oTr)lQM_od5TF(P7d(ai(_i}!gCA_vo{A{UR~V8z%Fs#PcUgrq!+>- z%fG=3&jM{+Il9;$eG^ujxKrqhRR3g5C3e)KB(7R`NQOZ<$4iH`!+{ZLR_}rkF z1}ZL#^`5t;nm2a#K+ROj@N=^z;%2%9KDmi}vSD?>={Oq^C&0_Cv=2x_cmj?`Vi)4y0k{(Ka^cptkDX zgXRh1=kgcV!#U4_KGUOK&i?qW!0e;6=G$-lhw6DB$%i($V!vIj2J#fO+6nsh=1`JF z3(qS0O7OB;_7Gd(FIjj%cJ#5nXo!YVsQ86ZS%C@ipshGPQNLPxMr4NUom5MN*u{au zYyPlOg=m&=D&3t%K+D((SC>eSK9b#Hd$5@JraSdPnN`sz!u0`r0nVGEcEXjNl7(Jc zVw_vgPiPyYbCa3$x+Vzg!`(uLd!(ydc!7eki?pmV*XXR^r4H}9gd-H*QYTJbE>nBd zeqrMmr1X#?iV+l7&wa2C#N_Ho!OO1mEnMST9vSoRpdQQT9owH36MBv~=P&lR4Pr52 z?UyxKhZD0Kx?ka+MOI*5xHOEz%2_EQ`&Q7X9$EZg7RRQGkhn^8`chSM+k_6E?!q}!uXV^@Apwk*Y)o+WitasyAe&g@t zZ@wOyUv3LULA(9FKL&!Fs8w}YC6B@a zL6|SlPbJMaS&f;mheiY!1CHF^#gXB)a=OmS zvS?L8g3G=&pC_eE_6|dOjPb0Rp#+2LHX)35gRRFa7cQyuJ&Mf}C4+N;>y(fKPx#FH zV>|V3=>9vwiZz$6;(yt~5x%Z8?4%jej{uJ-UNg8}VD@x-RJeZ3;B-HY0j(;c%Q;;R#1W3tEM?pNf z+en!jl*O=1@TwE|hb`bW-2x7^W$c;t)7;P^m{gHwWKo6EL&aI z(T!VMMpBHo9*0EZzu_$C2W|GojB4~(Pt(Jv2_16gal$}Sck=G6xb>4>M1yIotgjSH zT7xRXsMk?u9$jrUHn5_7{F#hnAC|PhRp%YfnVwX4^SnC{%`@WuI`?jIHSR`E%`KJ|;Dr%MK={7A4o=h! z=HzVTgH6UXjk78lX|3rC?B}id!>!gY_I|)cPeIMx;AbUjiVJ|D!X?A~i!P7yd=#nf zf}Yc!3vl`IX|#gvZ?N?{W$I2@s7aA96^pn^N>=e$ir}`3QNw&^Yx*5M0y=|U2f2+Q)Jl`q5}VxT$~67fU8Tr0 z^oDs{VdA9960P3RDX112*sCIxkV>#_!9_eL1Wn&;o(^5&|=y;y8%1y)dbG?{y|ejCZ^Ch2xV7~|GC%NKGzTaA%R zpha=L?q%oFl%A(L#FTfZo0r~%K*>4uRb2eU{>6*{A?8*)!3~Vbr|!k~)(b}NY|vta zSPEkUGxwDkugM9|-it0>Ew?Z#&FEMN8>q5L<^Niu;>!BGYq;D0Gw1ybYF{-6B-&QT*F}?Rv>)~HCujHdsY{tTZ)m&juXiU|?Kdv%xWJxU zmS}Bq%MthXICngo^d(Q_1(DffC`us94z2#;lPno1?fYWHSQdStN6tIN>?qVzV~=h_ZtcNV88bs1)| znLA9-biO*06K1!~VmZurMgOcSFpC#f&v(|wXpUMEb)-ncOX2c2ZZ4TBXCVb--c{Av z()X#nNswfefX1@PK9>>gv6F*iJ7x6oyY4_quoC%+7Q>>tLEZcg0(Rq1+1-$tP^6GN zShju($#(_O7lU24veoim$ft%ws-=AspqA5=gDQ!Ld^J8d>7Ok~>2hU}DZ~FsFjl5H zW~qRYlb1*?jA`k)>PjEe;FvoJK+L>j*o?3A8CojOmZmAwXF2RLmd5-)KL0&7oc}vo z_ATjxxN=)q4-K5UdM@D>d>p!hRHkV+{z=j24+!|~Bq~Uu;ntu2b!F}6457O;cmV+j z7SBOgGAyx)Opz;;Pxg++qW)M!1C#oBu++ezI4HOK}0Zf{=3g}kE*YcF(0Thv4>JWP}2fFb8tg0O^v z&NugDZCX;!Gwp3ZXm5;NGD+)!)NlUhlcmA!Uyb)v)X8l^O0|_m4*V6Ub;QS^mo^$~ zX51=lA&x`R)8FqekZW|kntBL`S_*x~;^kTMu4qgVDUp|tN4*br-SKuIeM&SFsW949 zIP=~_SxKpy}w$$Pz|;}?qSgPYf){H2H4u-pU1XB z?<|nwG{@_QiiygiQ-YOJcX1l^1_4C&B&m*6r$<9U2?>SFpZ=VgO~*SeA`oM{ax^_! z+q#eI9Ft1Dv9D20Lgb&I%x_bI{P#4xly%ysu<=f62&6kitDIr!^A~s_Sm!z-NiV1! zUvmJ}D5Uc2-gX{4N0yclQ*1gy4Pfd8NbQ|`orbN(!2Y_jB=BElPp5f@+5Sk5p7aNL zGGZcLOXNA_ydi8eqPrRfbVx|r*H74yA%P32JMaEr;S(KEGT#^e$0qIZPY&F)sU$7Q z0Q#T@q2;)2c)YEb__S`Pk)u_5RH{vSIU{>SBi$qN3*HxV=n!OcLM g`+qe|+#|+_kWOe??Te2A-Vpd~b@Ot4;KE4#FG`_RO8@`> literal 0 HcmV?d00001 diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.cpp b/applications/mne_scan/plugins/timefrequency/timefrequency.cpp new file mode 100644 index 00000000000..fd83db4e591 --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.cpp @@ -0,0 +1,190 @@ +//============================================================================================================= +/** + * @file timefrequency.cpp + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Definition of the TimeFrequency class. + * + */ + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequency.h" +#include "FormFiles/timefrequencysetupwidget.h" + +#include + +#include +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace TIMEFREQUENCYPLUGIN; +using namespace SCSHAREDLIB; +using namespace SCMEASLIB; +using namespace UTILSLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequency::TimeFrequency() +: m_pCircularBuffer(CircularBuffer::SPtr::create(40)) +{ +} + +//============================================================================================================= + +TimeFrequency::~TimeFrequency() +{ + if(this->isRunning()) + stop(); +} + +//============================================================================================================= + +QSharedPointer TimeFrequency::clone() const +{ + QSharedPointer pTimeFrequencyClone(new TimeFrequency); + return pTimeFrequencyClone; +} + +//============================================================================================================= + +void TimeFrequency::unload() +{ +} + +//============================================================================================================= + +bool TimeFrequency::start() +{ + QThread::start(); + + return true; +} + +//============================================================================================================= + +bool TimeFrequency::stop() +{ + requestInterruption(); + wait(500); + + m_bPluginControlWidgetsInit = false; + + return true; +} + +//============================================================================================================= + +AbstractPlugin::PluginType TimeFrequency::getType() const +{ + return _IAlgorithm; +} + +//============================================================================================================= + +QString TimeFrequency::getName() const +{ + return "TimeFrequency"; +} + +//============================================================================================================= + +QWidget* TimeFrequency::setupWidget() +{ + TimeFrequencySetupWidget* setupWidget = new TimeFrequencySetupWidget(this);//widget is later distroyed by CentralWidget - so it has to be created everytime new + return setupWidget; +} + +//============================================================================================================= + +void TimeFrequency::update(SCMEASLIB::Measurement::SPtr pMeasurement) +{ + +} + +//============================================================================================================= + +void TimeFrequency::init() +{ + // Input + m_pTimeFrequencyInput = PluginInputData::create(this, "TfIn", "Time frequency input data"); + + connect(m_pTimeFrequencyInput.data(), &PluginInputConnector::notify, + this, &TimeFrequency::update, Qt::DirectConnection); + + //Output + m_pTimeFrequencyOutput = PluginOutputData::create(this, "TfOut", "Time frequency output data"); + m_pTimeFrequencyOutput->measurementData()->setName(getName()); + m_outputConnectors.append(m_pTimeFrequencyOutput); +} + +//============================================================================================================= + +void TimeFrequency::initPluginControlWidgets() +{ + if(m_pFiffInfo) { + + } +} + +//============================================================================================================= + +void TimeFrequency::run() +{ + FIFFLIB::FiffEvokedSet evokedSet; + QStringList lResponsibleTriggerTypes; + + while(!isInterruptionRequested()){ +// if(m_pCircularBuffer->pop(evokedSet)) { +// m_qMutex.lock(); +// lResponsibleTriggerTypes = m_lResponsibleTriggerTypes; +// m_qMutex.unlock(); + +// m_pTimeFrequencyOutput->measurementData()->setValue(evokedSet, +// m_pFiffInfo, +// lResponsibleTriggerTypes); +// } + } +} diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.h b/applications/mne_scan/plugins/timefrequency/timefrequency.h new file mode 100644 index 00000000000..4b9c9cdc0ec --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.h @@ -0,0 +1,145 @@ +//============================================================================================================= +/** + * @file timefrequency.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the declaration of the TimeFrequency class. + * + */ + +#ifndef TIMEFREQUENCY_H +#define TIMEFREQUENCY_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "timefrequency_global.h" + +#include +#include + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +namespace SCMEASLIB{ + class RealTimeEvokedSet; + class RealTimeTimeFrequency; +} + +//============================================================================================================= +// DEFINE NAMESPACE TIMEFREQUENCYPLUGIN +//============================================================================================================= + +namespace TIMEFREQUENCYPLUGIN +{ + +//============================================================================================================= +// TIMEFREQUENCYPLUGIN FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +/** + * DECLARE CLASS TimeFrequency + * + * @brief The TimeFrequency class provides a TimeFrequency algorithm structure. + */ +class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public SCSHAREDLIB::AbstractAlgorithm +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "scsharedlib/1.0" FILE "timefrequency.json") //New Qt5 Plugin system replaces Q_EXPORT_PLUGIN2 macro + // Use the Q_INTERFACES() macro to tell Qt's meta-object system about the interfaces + Q_INTERFACES(SCSHAREDLIB::AbstractAlgorithm) + + friend class TimeFrequencySettingsWidget; + +public: + //========================================================================================================= + /** + * Constructs a TimeFrequency. + */ + TimeFrequency(); + + //========================================================================================================= + /** + * Destroys the TimeFrequency. + */ + ~TimeFrequency(); + + //========================================================================================================= + /** + * Inits widgets which are used to control this plugin, then emits them in form of a QList. + */ + void initPluginControlWidgets(); + + //========================================================================================================= + /** + * Reimplemented virtual functions + */ + virtual void unload(); + virtual QSharedPointer clone() const; + virtual bool start(); + virtual bool stop(); + virtual SCSHAREDLIB::AbstractPlugin::PluginType getType() const; + virtual QString getName() const; + virtual QWidget* setupWidget(); + void update(SCMEASLIB::Measurement::SPtr pMeasurement); + + //========================================================================================================= + /** + * Initialise input and output connectors. + */ + virtual void init(); + +private: + virtual void run(); + + SCSHAREDLIB::PluginInputData::SPtr m_pTimeFrequencyInput; /**< The RealTimeSampleArray of the TimeFrequency input.*/ + SCSHAREDLIB::PluginOutputData::SPtr m_pTimeFrequencyOutput; /**< The RealTimeEvoked of the TimeFrequency output.*/ + + UTILSLIB::CircularBuffer::SPtr m_pCircularBuffer; /**< Holds incoming fiff evoked sets. */ + + QMutex m_qMutex; /**< Provides access serialization between threads. */ + + FIFFLIB::FiffInfo::SPtr m_pFiffInfo; /**< Fiff measurement info.*/ + + QMap m_mapStimChsIndexNames; /**< The currently available stim channels and their corresponding index in the data. */ + +signals: + +}; +} // NAMESPACE + +#endif // TIMEFREQUENCY_H diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.json b/applications/mne_scan/plugins/timefrequency/timefrequency.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.pro b/applications/mne_scan/plugins/timefrequency/timefrequency.pro new file mode 100644 index 00000000000..3d745c95fe0 --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.pro @@ -0,0 +1,132 @@ +#============================================================================================================== +# +# @file timefrequency.pro +# @author Gabriel Motta +# @since 0.1.9 +# @date April, 2021 +# +# @section LICENSE +# +# Copyright (C) 2021, Gabriel Motta. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted provided that +# the following conditions are met: +# * Redistributions of source code must retain the above copyright notice, this list of conditions and the +# following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and +# the following disclaimer in the documentation and/or other materials provided with the distribution. +# * Neither the name of MNE-CPP authors nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# +# @brief This project file generates the makefile for the timefrequency plug-in. +# +#============================================================================================================== + +include(../../../../mne-cpp.pri) + +TEMPLATE = lib + +QT += core widgets + +CONFIG += skip_target_version_ext plugin + +DEFINES += TIMEFREQUENCY_PLUGIN + +DESTDIR = $${MNE_BINARY_DIR}/mne_scan_plugins + +TARGET = timefrequency +CONFIG(debug, debug|release) { + TARGET = $$join(TARGET,,,d) +} + +contains(MNECPP_CONFIG, static) { + CONFIG += staticlib + DEFINES += STATICBUILD +} else { + CONFIG += shared +} + +LIBS += -L$${MNE_LIBRARY_DIR} +CONFIG(debug, debug|release) { + LIBS += -lscSharedd \ + -lscDispd \ + -lscMeasd \ + -lmnecppDispd \ + -lmnecppRtProcessingd \ + -lmnecppConnectivityd \ + -lmnecppInversed \ + -lmnecppFwdd \ + -lmnecppMned \ + -lmnecppFiffd \ + -lmnecppFsd \ + -lmnecppUtilsd \ +} else { + LIBS += -lscShared \ + -lscDisp \ + -lscMeas \ + -lmnecppDisp \ + -lmnecppRtProcessing \ + -lmnecppConnectivity \ + -lmnecppInverse \ + -lmnecppFwd \ + -lmnecppMne \ + -lmnecppFiff \ + -lmnecppFs \ + -lmnecppUtils \ +} + +SOURCES += \ + timefrequency.cpp \ + FormFiles/timefrequencysetupwidget.cpp \ + +HEADERS += \ + timefrequency_global.h \ + timefrequency.h \ + FormFiles/timefrequencysetupwidget.h \ + +FORMS += \ + FormFiles/timefrequencysetup.ui \ + +RESOURCES += \ + timefrequency.qrc + +OTHER_FILES += \ + timefrequency.json + +INCLUDEPATH += $${EIGEN_INCLUDE_DIR} +INCLUDEPATH += $${MNE_INCLUDE_DIR} +INCLUDEPATH += $${MNE_SCAN_INCLUDE_DIR} + +unix:!macx { + QMAKE_RPATHDIR += $ORIGIN/../../lib +} + +# Activate FFTW backend in Eigen for non-static builds only +contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { + DEFINES += EIGEN_FFTW_DEFAULT + INCLUDEPATH += $$shell_path($${FFTW_DIR_INCLUDE}) + LIBS += -L$$shell_path($${FFTW_DIR_LIBS}) + + win32 { + # On Windows + LIBS += -llibfftw3-3 \ + -llibfftw3f-3 \ + -llibfftw3l-3 \ + } + + unix:!macx { + # On Linux + LIBS += -lfftw3 \ + -lfftw3_threads \ + } +} diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.qrc b/applications/mne_scan/plugins/timefrequency/timefrequency.qrc new file mode 100644 index 00000000000..f987ec0e96f --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.qrc @@ -0,0 +1,5 @@ + + + images/icons/timefrequencyadjustments.png + + diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency_global.h b/applications/mne_scan/plugins/timefrequency/timefrequency_global.h new file mode 100644 index 00000000000..54c5dc01a9f --- /dev/null +++ b/applications/mne_scan/plugins/timefrequency/timefrequency_global.h @@ -0,0 +1,54 @@ +//============================================================================================================= +/** + * @file timefrequency_global.h + * @author Gabriel Motta + * @since 0.1.9 + * @date April, 2021 + * + * @section LICENSE + * + * Copyright (C) 2021, Gabriel Motta. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided with the distribution. + * * Neither the name of MNE-CPP authors nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * + * @brief Contains the TimeFrequency library export/import macros. + * + */ + +#ifndef TIMEFREQUENCY_GLOBAL_H +#define TIMEFREQUENCY_GLOBAL_H + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// PREPROCESSOR DEFINES +//============================================================================================================= + +#if defined(TIMEFREQUENCY_PLUGIN) +# define TIMEFREQUENCYSHARED_EXPORT Q_DECL_EXPORT /**< Q_DECL_EXPORT must be added to the declarations of symbols used when compiling a shared library. */ +#else +# define TIMEFREQUENCYSHARED_EXPORT Q_DECL_IMPORT /**< Q_DECL_IMPORT must be added to the declarations of symbols used when compiling a client that uses the shared library. */ +#endif + +#endif // TIMEFREQUENCY_GLOBAL_H From f68db82f33e854d21aeb759c0f1bb9c605f53e98 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Fri, 23 Apr 2021 14:02:02 -0400 Subject: [PATCH 30/57] ENH: function to return spectrogram as complex --- .../disp/viewers/timefrequencylayoutview.cpp | 4 + .../disp/viewers/timefrequencylayoutview.h | 2 + libraries/utils/spectrogram.cpp | 83 +++++++++++++++++++ libraries/utils/spectrogram.h | 32 +++++++ 4 files changed, 121 insertions(+) diff --git a/libraries/disp/viewers/timefrequencylayoutview.cpp b/libraries/disp/viewers/timefrequencylayoutview.cpp index 72d44c831b2..27f1387394b 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.cpp +++ b/libraries/disp/viewers/timefrequencylayoutview.cpp @@ -155,6 +155,10 @@ void TimeFrequencyLayoutView::channelSelectionChanged(const QVariant &data) return; } + if (m_listWidgets.empty()){ + + } + SelectionItem* pSelectionItem = data.value(); //Repaint the average items in the average scene based on the input parameter selectedChannelItems and update them with current data diff --git a/libraries/disp/viewers/timefrequencylayoutview.h b/libraries/disp/viewers/timefrequencylayoutview.h index 466a049f4e6..affa688facf 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.h +++ b/libraries/disp/viewers/timefrequencylayoutview.h @@ -138,6 +138,8 @@ class DISPSHARED_EXPORT TimeFrequencyLayoutView : public AbstractView QSharedPointer m_pEvokedSetModel; /**< The evoked model */ QSharedPointer m_pTFModel; + std::list m_listWidgets(); + }; }//namespace diff --git a/libraries/utils/spectrogram.cpp b/libraries/utils/spectrogram.cpp index e9f0bd9e1eb..65226814623 100644 --- a/libraries/utils/spectrogram.cpp +++ b/libraries/utils/spectrogram.cpp @@ -103,6 +103,45 @@ MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0) //============================================================================================================= +MatrixXcd Spectrogram::makeComplexSpectrogram(VectorXd signal, qint32 windowSize = 0) +{ + //QElapsedTimer timer; + //timer.start(); + + signal.array() -= signal.mean(); + QList lData; + int iThreadSize = QThread::idealThreadCount()*2; + int iStepsSize = signal.rows()/iThreadSize; + int iResidual = signal.rows()%iThreadSize; + + SpectogramInputData dataTemp; + dataTemp.vecInputData = signal; + dataTemp.window_size = windowSize; + if(dataTemp.window_size == 0) { + dataTemp.window_size = signal.rows()/15; + } + + for (int i = 0; i < iThreadSize; ++i) { + dataTemp.iRangeLow = i*iStepsSize; + dataTemp.iRangeHigh = i*iStepsSize+iStepsSize; + lData.append(dataTemp); + } + + dataTemp.iRangeLow = iThreadSize*iStepsSize; + dataTemp.iRangeHigh = iThreadSize*iStepsSize+iResidual; + lData.append(dataTemp); + + QFuture resultMat = QtConcurrent::mappedReduced(lData, + computeComplex, + reduceComplex); + resultMat.waitForFinished(); + + //qDebug() << "Spectrogram::make_spectrogram - timer.elapsed()" << timer.elapsed(); + return resultMat.result(); +} + +//============================================================================================================= + VectorXd Spectrogram::gaussWindow(qint32 sample_count, qreal scale, quint32 translation) { VectorXd gauss = VectorXd::Zero(sample_count); @@ -150,6 +189,38 @@ MatrixXd Spectrogram::compute(const SpectogramInputData& inputData) //============================================================================================================= +MatrixXcd Spectrogram::computeComplex(const SpectogramInputData& inputData) +{ + #ifdef EIGEN_FFTW_DEFAULT + fftw_make_planner_thread_safe(); + #endif + + Eigen::FFT fft; + MatrixXcd tf_matrix = MatrixXcd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows()); + VectorXd envelope, windowed_sig; + VectorXcd fft_win_sig, coeffs; + qint32 window_size = inputData.window_size; + + for(quint32 translate = inputData.iRangeLow; translate < inputData.iRangeHigh; translate++) { + envelope = gaussWindow(inputData.vecInputData.rows(), window_size, translate); + + windowed_sig = VectorXd::Zero(inputData.vecInputData.rows()); + fft_win_sig = VectorXcd::Zero(inputData.vecInputData.rows()); + + windowed_sig = inputData.vecInputData.array() * envelope.array();\ + + fft.fwd(fft_win_sig, windowed_sig); + + coeffs = fft_win_sig.segment(0,inputData.vecInputData.rows()/2).array(); + + tf_matrix.col(translate) = coeffs; + } + + return tf_matrix; +} + +//============================================================================================================= + void Spectrogram::reduce(MatrixXd &resultData, const MatrixXd &data) { @@ -159,3 +230,15 @@ void Spectrogram::reduce(MatrixXd &resultData, resultData += data; } } + +//============================================================================================================= + +void Spectrogram::reduceComplex(MatrixXcd &resultData, + const MatrixXcd &data) +{ + if(resultData.size() == 0) { + resultData = data; + } else { + resultData += data; + } +} diff --git a/libraries/utils/spectrogram.h b/libraries/utils/spectrogram.h index b7a3276931c..12c9ebf8b25 100644 --- a/libraries/utils/spectrogram.h +++ b/libraries/utils/spectrogram.h @@ -76,6 +76,18 @@ class UTILSSHARED_EXPORT Spectrogram static Eigen::MatrixXd makeSpectrogram(Eigen::VectorXd signal, qint32 windowSize); + //========================================================================================================= + /** + * Calculates the spectrogram (tf-representation) of a given signal + * + * @param[in] signal input-signal to calculate spectrogram of + * @param[in] windowSize size of the window which is used (resolution in time an frequency is depending on it) + * + * @return spectrogram-matrix (tf-representation of the input signal) + */ + static Eigen::MatrixXcd makeComplexSpectrogram(Eigen::VectorXd signal, + qint32 windowSize); + private: //========================================================================================================= /** @@ -101,6 +113,16 @@ class UTILSSHARED_EXPORT Spectrogram */ static Eigen::MatrixXd compute(const SpectogramInputData& data); + //========================================================================================================= + /** + * Calculates the spectogram matrix for a given input data matrix. + * + * @param[in] data The input data. + * + * @return The spectogram matrix. + */ + static Eigen::MatrixXcd computeComplex(const SpectogramInputData& data); + //========================================================================================================= /** * Sums up (reduces) the in parallel processed spectogram matrix. @@ -110,6 +132,16 @@ class UTILSSHARED_EXPORT Spectrogram */ static void reduce(Eigen::MatrixXd &resultData, const Eigen::MatrixXd &data); + + //========================================================================================================= + /** + * Sums up (reduces) the in parallel processed spectogram matrix. + * + * @param[out] resultData The result data. + * @param[in] data The incoming, temporary result data. + */ + static void reduceComplex(Eigen::MatrixXcd &resultData, + const Eigen::MatrixXcd &data); }; }//namespace From 99c9d6f3958eec62b41c9e9e4776499c8541425b Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Mon, 26 Apr 2021 13:07:45 -0400 Subject: [PATCH 31/57] ENH: leaving matrix as complex --- .../plugins/timefrequency/timefrequency.cpp | 2 +- .../viewers/helpers/timefrequencymodel.cpp | 41 ++++++++++++------- .../disp/viewers/helpers/timefrequencymodel.h | 17 ++++++-- .../disp/viewers/timefrequencylayoutview.cpp | 4 +- libraries/rtprocessing/timefrequency.cpp | 18 ++++++++ libraries/rtprocessing/timefrequency.h | 3 ++ 6 files changed, 63 insertions(+), 22 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index b4e589a96fa..fde25160636 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -259,7 +259,7 @@ void TimeFrequency::computeTimeFreqency() return; } - auto spectr = RTPROCESSINGLIB::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); + auto spectr = RTPROCESSINGLIB::computeComplexTimeFrequency(*m_pAvgModel->getEvokedSet()); // DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index b78cd14c857..fbbb19a3558 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -62,7 +62,7 @@ TimeFrequencyModel::TimeFrequencyModel() //============================================================================================================= -TimeFrequencyModel::TimeFrequencyModel(std::vector& spectr) +TimeFrequencyModel::TimeFrequencyModel(std::vector& spectr) : m_vSpectr(std::move(spectr)) , m_iMinFreq(0) , m_iMaxFreq(100) @@ -72,7 +72,7 @@ TimeFrequencyModel::TimeFrequencyModel(std::vector& spectr) //============================================================================================================= -void TimeFrequencyModel::setSpectr(std::vector& spectr) +void TimeFrequencyModel::setSpectr(std::vector& spectr) { m_vSpectr.clear(); m_vSpectr = std::move(spectr); @@ -121,23 +121,27 @@ QVariant TimeFrequencyModel::data(const QModelIndex &index, } case Qt::DisplayRole:{ QVariant variant; - variant.setValue(m_vSpectr[0]); - return variant; - } - } - } - if(index.column() == 2) { //timefrequencyview - switch(role){ - case Qt::BackgroundRole:{ - return QVariant(); - } - case Qt::DisplayRole:{ - QVariant variant; - variant.setValue(m_vSpectr[row]); +// Eigen::MatrixXd mat = Eigen::MatrixXd::Zero(m_vSpectr[0].rows(), m_vSpectr[0].cols()); +// auto matr = m_vSpectr[0].real(); + auto tempMat = m_vSpectr[0]; + Eigen::MatrixXd mat = tempMat.cwiseAbs2(); + variant.setValue(mat); return variant; } } } +// if(index.column() == 2) { //timefrequencyview +// switch(role){ +// case Qt::BackgroundRole:{ +// return QVariant(); +// } +// case Qt::DisplayRole:{ +// QVariant variant; +// variant.setValue(m_vSpectr[row]); +// return variant; +// } +// } +// } } @@ -191,3 +195,10 @@ std::pair TimeFrequencyModel::getFreqRange() const { return std::pair(m_iMinFreq,m_iMaxFreq); } + +//============================================================================================================= + +void TimeFrequencyModel::computeAverage() +{ + +} diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h index de43fc831f1..d3f2476d609 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.h +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -69,14 +69,16 @@ class DISPSHARED_EXPORT TimeFrequencyModel : public QAbstractTableModel public: TimeFrequencyModel(); - TimeFrequencyModel(std::vector& spectr); + TimeFrequencyModel(std::vector& spectr); - void setSpectr(std::vector& spectr); + void setSpectr(std::vector& spectr); void setFiffInfo(const FIFFLIB::FiffInfo& info); float getSamplingFrequency(); + void computeAverage(); + //========================================================================================================= /** * Returns the number of rows under the given parent. When the parent is valid it means that rowCount is returning the number of children of parent. @@ -149,9 +151,11 @@ class DISPSHARED_EXPORT TimeFrequencyModel : public QAbstractTableModel // QLinearGradient m_Gradient; - std::vector m_vSpectr; + std::vector m_vSpectr; + + Eigen::MatrixXd m_Average; - FIFFLIB::FiffInfo m_Info; + FIFFLIB::FiffInfo m_Info; int m_iMinFreq; int m_iMaxFreq; @@ -164,4 +168,9 @@ class DISPSHARED_EXPORT TimeFrequencyModel : public QAbstractTableModel Q_DECLARE_METATYPE(Eigen::MatrixXd); #endif +//#ifndef metatype_matrixXcd +//#define metatype_matrixXcd +//Q_DECLARE_METATYPE(Eigen::MatrixXcd); +//#endif + #endif // TIMEFREQUENCYMODEL_H diff --git a/libraries/disp/viewers/timefrequencylayoutview.cpp b/libraries/disp/viewers/timefrequencylayoutview.cpp index 27f1387394b..a328a01ce0d 100644 --- a/libraries/disp/viewers/timefrequencylayoutview.cpp +++ b/libraries/disp/viewers/timefrequencylayoutview.cpp @@ -155,9 +155,9 @@ void TimeFrequencyLayoutView::channelSelectionChanged(const QVariant &data) return; } - if (m_listWidgets.empty()){ +// if (m_listWidgets.empty()){ - } +// } SelectionItem* pSelectionItem = data.value(); diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 669817ead1c..7b83c79cf82 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -78,3 +78,21 @@ std::vector RTPROCESSINGLIB::computeTimeFrequency(const FIFFLIB return tfvector; } +std::vector RTPROCESSINGLIB::computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) +{ + qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; + + auto& evoked = evokedSet.evoked.first(); + float fSampFreq = evoked.info.sfreq; + + std::vector tfvector; + + for (int i = 0; i < evoked.data.rows(); i++){ + Eigen::VectorXd dataCol = evoked.data.row(0).transpose(); + Eigen::MatrixXcd Spectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, fSampFreq * 0.2); + tfvector.push_back(Spectrum); + } + + return tfvector; +} + diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index a60376359ce..1cd3bf9ebc7 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -78,5 +78,8 @@ namespace RTPROCESSINGLIB RTPROCESINGSHARED_EXPORT std::vector computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); +RTPROCESINGSHARED_EXPORT std::vector computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); + + }//namespace #endif // TIMEFREQUENCY_RTPROCESSING_H From 1cc513f5e7587507003d8799b3868397d76fe2c9 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Mon, 26 Apr 2021 17:34:03 -0400 Subject: [PATCH 32/57] MAINT: gettign channel selection to diplay average --- .../plugins/timefrequency/timefrequency.cpp | 9 ++++- .../viewers/helpers/timefrequencymodel.cpp | 36 +++++++++++++++++-- .../disp/viewers/helpers/timefrequencymodel.h | 3 ++ libraries/disp/viewers/timefrequencyview.h | 2 ++ libraries/rtprocessing/timefrequency.cpp | 22 ++++++++---- libraries/rtprocessing/timefrequency.h | 16 +++++---- 6 files changed, 72 insertions(+), 16 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index fde25160636..da11296156e 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -247,6 +247,13 @@ void TimeFrequency::setChannelSelection(const QVariant &data) // } else { // emit showSelectedChannels(data.value()->m_iChannelNumber); // } + + } + + if(m_pTFModel){ + if(data.value()->m_sViewsToApply.contains("butterflyview")){ + m_pTFModel->setChannelSelection(data.value()->m_iChannelNumber); + } } } @@ -259,7 +266,7 @@ void TimeFrequency::computeTimeFreqency() return; } - auto spectr = RTPROCESSINGLIB::computeComplexTimeFrequency(*m_pAvgModel->getEvokedSet()); + auto spectr = RTPROCESSINGLIB::TimeFrequencyData::computeComplexTimeFrequency(*m_pAvgModel->getEvokedSet()); // DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index fbbb19a3558..98346982ca7 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -52,7 +52,6 @@ using namespace DISPLIB; // DEFINE MEMBER METHODS //============================================================================================================= - TimeFrequencyModel::TimeFrequencyModel() : m_iMinFreq(0) , m_iMaxFreq(100) @@ -123,9 +122,30 @@ QVariant TimeFrequencyModel::data(const QModelIndex &index, QVariant variant; // Eigen::MatrixXd mat = Eigen::MatrixXd::Zero(m_vSpectr[0].rows(), m_vSpectr[0].cols()); // auto matr = m_vSpectr[0].real(); - auto tempMat = m_vSpectr[0]; + Eigen::MatrixXcd matrix = Eigen::MatrixXcd::Zero(m_vSpectr[0].rows(), m_vSpectr[0].cols()); + +// for (auto& channel : m_vSpectr){ +// matrix += channel; +// } + + for (int iChIndex : m_listSelection){ + if (iChIndex < m_vSpectr.size()){ + matrix += m_vSpectr[iChIndex]; + qDebug() << "Adding channel" << iChIndex; + } + } + + matrix /= m_vSpectr.size(); + + auto tempMat = matrix; Eigen::MatrixXd mat = tempMat.cwiseAbs2(); variant.setValue(mat); + + qDebug() << "Hi there"; + +// auto tempMat = m_vSpectr[0]; +// Eigen::MatrixXd mat = tempMat.cwiseAbs2(); +// variant.setValue(mat); return variant; } } @@ -202,3 +222,15 @@ void TimeFrequencyModel::computeAverage() { } + +//============================================================================================================= +#include +void TimeFrequencyModel::setChannelSelection(QList selectionList) +{ + for (int i = 0; i< selectionList.size(); i++){ + m_listSelection.append(selectionList.value(i)); + std::cout << selectionList.value(i); + } + + emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); +} diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h index d3f2476d609..e684ccf58c6 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.h +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -77,6 +77,8 @@ class DISPSHARED_EXPORT TimeFrequencyModel : public QAbstractTableModel float getSamplingFrequency(); + void setChannelSelection(QList selectionList); + void computeAverage(); //========================================================================================================= @@ -152,6 +154,7 @@ class DISPSHARED_EXPORT TimeFrequencyModel : public QAbstractTableModel // QLinearGradient m_Gradient; std::vector m_vSpectr; + QList m_listSelection; Eigen::MatrixXd m_Average; diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index 435371337b9..a1530c4d3d4 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -137,6 +137,8 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView void setTimeFrequencyModel(QSharedPointer pModel); + void setSelectedChannels(QList selectionList); + protected: void initQMLView(); diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 7b83c79cf82..505f6dfa821 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -51,16 +51,17 @@ // EIGEN INCLUDES //============================================================================================================= -//TimeFrequency::TimeFrequency() -//{ +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= -//} +using namespace RTPROCESSINGLIB; //============================================================================================================= -// DEFINE GLOBAL RTPROCESSINGLIB METHODS +// DEFINE STATIC RTPROCESSINGLIB METHODS //============================================================================================================= -std::vector RTPROCESSINGLIB::computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) +std::vector TimeFrequencyData::computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; @@ -78,7 +79,7 @@ std::vector RTPROCESSINGLIB::computeTimeFrequency(const FIFFLIB return tfvector; } -std::vector RTPROCESSINGLIB::computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) +std::vector TimeFrequencyData::computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; @@ -96,3 +97,12 @@ std::vector RTPROCESSINGLIB::computeComplexTimeFrequency(const return tfvector; } +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +TimeFrequencyData::TimeFrequencyData() +{ + +} + diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index 1cd3bf9ebc7..cb74320eeaa 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -70,15 +70,17 @@ namespace FIFFLIB { namespace RTPROCESSINGLIB { -//class TimeFrequency -//{ -//public: -// TimeFrequency(); -//}; +class RTPROCESINGSHARED_EXPORT TimeFrequencyData +{ +public: + TimeFrequencyData(); + + static std::vector computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); -RTPROCESINGSHARED_EXPORT std::vector computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); + static std::vector computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); -RTPROCESINGSHARED_EXPORT std::vector computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); +private: +}; }//namespace From 46080f4c5ce0f59ec7466f33f899dd20aed68755 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Mon, 26 Apr 2021 17:49:27 -0400 Subject: [PATCH 33/57] DEBUG: add guard for having data and channel select info to aprevent crash --- .../viewers/helpers/timefrequencymodel.cpp | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index 98346982ca7..e6a56e86824 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -128,10 +128,16 @@ QVariant TimeFrequencyModel::data(const QModelIndex &index, // matrix += channel; // } - for (int iChIndex : m_listSelection){ - if (iChIndex < m_vSpectr.size()){ - matrix += m_vSpectr[iChIndex]; - qDebug() << "Adding channel" << iChIndex; + if(m_listSelection.size() > 0){ + for (int iChIndex : m_listSelection){ + if (iChIndex < m_vSpectr.size()){ + matrix += m_vSpectr[iChIndex]; + qDebug() << "Adding channel" << iChIndex; + } + } + }else{ + for (auto& channel : m_vSpectr){ + matrix += channel; } } @@ -227,10 +233,13 @@ void TimeFrequencyModel::computeAverage() #include void TimeFrequencyModel::setChannelSelection(QList selectionList) { + m_listSelection.clear(); for (int i = 0; i< selectionList.size(); i++){ m_listSelection.append(selectionList.value(i)); - std::cout << selectionList.value(i); + std::cout << selectionList.value(i) << std::endl; } - emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); + if(m_vSpectr.size() > 0){ + emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); + } } From d1950c9910e9cf1ebb322f11bb657d3adaa1b227 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 27 Apr 2021 10:52:01 -0400 Subject: [PATCH 34/57] ENH: averaging tf in real time and updating display --- .../plugins/timefrequency/timefrequency.cpp | 13 +++++- .../viewers/helpers/timefrequencymodel.cpp | 41 ++++++++++++------- .../helpers/timefrequencysceneitem.cpp | 2 +- libraries/disp/viewers/timefrequencyview.cpp | 2 +- libraries/rtprocessing/timefrequency.cpp | 14 ++++++- 5 files changed, 53 insertions(+), 19 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index da11296156e..1656a9fef23 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -269,9 +269,20 @@ void TimeFrequency::computeTimeFreqency() auto spectr = RTPROCESSINGLIB::TimeFrequencyData::computeComplexTimeFrequency(*m_pAvgModel->getEvokedSet()); // DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); - // tfplot->show(); + auto spectr2 = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); + + DISPLIB::TFplot* tfplot2 = new DISPLIB::TFplot(spectr2.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); + tfplot2->show(); + + DISPLIB::TFplot* tfplot3 = new DISPLIB::TFplot(spectr2.at(20), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); + tfplot3->show(); + + DISPLIB::TFplot* tfplot4 = new DISPLIB::TFplot(spectr2.at(80), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); + tfplot4->show(); + + m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); m_pTFModel->setSpectr(spectr); } diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index e6a56e86824..67c3b7e3ec6 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -120,6 +120,14 @@ QVariant TimeFrequencyModel::data(const QModelIndex &index, } case Qt::DisplayRole:{ QVariant variant; +// Eigen::MatrixXcd returnMat = m_vSpectr.front(); +// Eigen::MatrixXd realmat = returnMat.cwiseAbs2(); + +// variant.setValue(realmat); + +// return variant; + + // Eigen::MatrixXd mat = Eigen::MatrixXd::Zero(m_vSpectr[0].rows(), m_vSpectr[0].cols()); // auto matr = m_vSpectr[0].real(); Eigen::MatrixXcd matrix = Eigen::MatrixXcd::Zero(m_vSpectr[0].rows(), m_vSpectr[0].cols()); @@ -127,12 +135,13 @@ QVariant TimeFrequencyModel::data(const QModelIndex &index, // for (auto& channel : m_vSpectr){ // matrix += channel; // } - + int a = 0; if(m_listSelection.size() > 0){ for (int iChIndex : m_listSelection){ if (iChIndex < m_vSpectr.size()){ matrix += m_vSpectr[iChIndex]; - qDebug() << "Adding channel" << iChIndex; + qDebug() << a << "Adding channel" << iChIndex; + a++; } } }else{ @@ -156,18 +165,22 @@ QVariant TimeFrequencyModel::data(const QModelIndex &index, } } } -// if(index.column() == 2) { //timefrequencyview -// switch(role){ -// case Qt::BackgroundRole:{ -// return QVariant(); -// } -// case Qt::DisplayRole:{ -// QVariant variant; -// variant.setValue(m_vSpectr[row]); -// return variant; -// } -// } -// } + if(index.column() == 2) { //timefrequencyview + switch(role){ + case Qt::BackgroundRole:{ + return QVariant(); + } + case Qt::DisplayRole:{ + QVariant variant; + + auto tempMat = m_vSpectr[0]; + Eigen::MatrixXd mat = tempMat.cwiseAbs2(); + variant.setValue(mat); + + return variant; + } + } + } } diff --git a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp index 2800b6299bc..d35cae07730 100644 --- a/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp +++ b/libraries/disp/viewers/helpers/timefrequencysceneitem.cpp @@ -147,7 +147,7 @@ void TimeFrequencySceneItem::setData(const Eigen::MatrixXd &data) void TimeFrequencySceneItem::setSampleRate(float fFreq) { m_fSampleRate = fFreq; - qDebug() << "freq:" << fFreq; + //qDebug() << "freq:" << fFreq; } //============================================================================================================= diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 8c227cd6b61..99e4ca38117 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -288,7 +288,7 @@ void TimeFrequencyView::updateData() if(!m_pLayout->isEmpty()){ m_pLayout->removeWidget(m_pPlot); - m_pPlot->deleteLater(); + delete m_pPlot; } auto freqRange = m_pTFModel->getFreqRange(); diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 505f6dfa821..03546e7cfbf 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -38,6 +38,8 @@ #include "timefrequency.h" +#include + #include #include @@ -65,13 +67,21 @@ std::vector TimeFrequencyData::computeTimeFrequency(const FIFFL { qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; + int a = 0; + qDebug() << a; + + std::cout << "SIZE:" << evokedSet.evoked.size(); + auto& evoked = evokedSet.evoked.first(); float fSampFreq = evoked.info.sfreq; + std::cout << "ROWS: " << evoked.data.rows(); + std::vector tfvector; for (int i = 0; i < evoked.data.rows(); i++){ - Eigen::VectorXd dataCol = evoked.data.row(0).transpose(); + Eigen::VectorXd dataCol = evoked.data.row(i).transpose(); + //std::cout << "First data sample from evoked: " << dataCol(0); Eigen::MatrixXd Spectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, fSampFreq * 0.2); tfvector.push_back(Spectrum); } @@ -89,7 +99,7 @@ std::vector TimeFrequencyData::computeComplexTimeFrequency(con std::vector tfvector; for (int i = 0; i < evoked.data.rows(); i++){ - Eigen::VectorXd dataCol = evoked.data.row(0).transpose(); + Eigen::VectorXd dataCol = evoked.data.row(i).transpose(); Eigen::MatrixXcd Spectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, fSampFreq * 0.2); tfvector.push_back(Spectrum); } From 641ce1c636a926839b470f631c35327b1fa8b9b4 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 27 Apr 2021 15:50:49 -0400 Subject: [PATCH 35/57] DEBUG: taking real values after computing absolute values --- libraries/disp/plots/tfplot.cpp | 8 +++++++- libraries/disp/plots/tfplot.h | 2 ++ libraries/disp/viewers/helpers/timefrequencymodel.cpp | 2 +- libraries/disp/viewers/timefrequencyview.cpp | 4 ++++ libraries/rtprocessing/timefrequency.cpp | 2 +- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libraries/disp/plots/tfplot.cpp b/libraries/disp/plots/tfplot.cpp index f2a6c551987..1c53ddef38d 100644 --- a/libraries/disp/plots/tfplot.cpp +++ b/libraries/disp/plots/tfplot.cpp @@ -305,10 +305,16 @@ void TFplot::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); + adjustViewSize(); +} + +//============================================================================================================= + +void TFplot::adjustViewSize() +{ QWidget *widget = this->layout()->itemAt(0)-> widget(); if (widget != NULL ) { QGraphicsView* view = (QGraphicsView*)widget; view->fitInView(view->sceneRect(),Qt::KeepAspectRatio); } } - diff --git a/libraries/disp/plots/tfplot.h b/libraries/disp/plots/tfplot.h index 6d3f654a5ac..4fe5ca67b6b 100644 --- a/libraries/disp/plots/tfplot.h +++ b/libraries/disp/plots/tfplot.h @@ -122,6 +122,8 @@ class DISPSHARED_EXPORT TFplot : public QWidget qreal sample_rate, ColorMaps cmap); + void adjustViewSize(); + protected: //========================================================================================================= /** diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index 67c3b7e3ec6..ca06f9196ce 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -153,7 +153,7 @@ QVariant TimeFrequencyModel::data(const QModelIndex &index, matrix /= m_vSpectr.size(); auto tempMat = matrix; - Eigen::MatrixXd mat = tempMat.cwiseAbs2(); + Eigen::MatrixXd mat = tempMat.cwiseAbs2().real(); variant.setValue(mat); qDebug() << "Hi there"; diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 99e4ca38117..3ef7558440f 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -287,6 +287,7 @@ void TimeFrequencyView::updateData() } if(!m_pLayout->isEmpty()){ + m_pPlot->hide(); m_pLayout->removeWidget(m_pPlot); delete m_pPlot; } @@ -295,4 +296,7 @@ void TimeFrequencyView::updateData() m_pPlot = new TFplot(m_pTFModel->data(1,1).value(), m_pTFModel->getSamplingFrequency(), freqRange.first, freqRange.second, DISPLIB::ColorMaps::Jet); m_pLayout->addWidget(m_pPlot); + + //m_pPlot->adjustSize(); + m_pPlot->adjustViewSize(); } diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 03546e7cfbf..9812469cd1b 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -100,7 +100,7 @@ std::vector TimeFrequencyData::computeComplexTimeFrequency(con for (int i = 0; i < evoked.data.rows(); i++){ Eigen::VectorXd dataCol = evoked.data.row(i).transpose(); - Eigen::MatrixXcd Spectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, fSampFreq * 0.2); + Eigen::MatrixXcd Spectrum = UTILSLIB::Spectrogram::makeComplexSpectrogram(dataCol, fSampFreq * 0.2); tfvector.push_back(Spectrum); } From c76ea9187f359130821abc069699076c54b24fd0 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 27 Apr 2021 17:12:37 -0400 Subject: [PATCH 36/57] ENH: measurment and measurement widget --- .../scDisp/realtimetimefrequencywidget.cpp | 25 ++++++++++++ .../libs/scDisp/realtimetimefrequencywidget.h | 39 +++++++++++++++++++ applications/mne_scan/libs/scDisp/scDisp.pro | 2 + .../mne_scan/libs/scMeas/realtimeevokedset.h | 1 + applications/mne_scan/mne_scan/main.cpp | 1 + .../plugins/timefrequency/timefrequency.cpp | 20 +++++++--- .../plugins/timefrequency/timefrequency.h | 6 +-- 7 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp create mode 100644 applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h diff --git a/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp new file mode 100644 index 00000000000..89b1ebade6d --- /dev/null +++ b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp @@ -0,0 +1,25 @@ +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "realtimetimefrequencywidget.h" + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +//============================================================================================================= +// USED NAMESPACES +//============================================================================================================= + +using namespace SCDISPLIB; +using namespace SCMEASLIB; + +//============================================================================================================= +// DEFINE MEMBER METHODS +//============================================================================================================= + +RealTimeTimeFrequencyWidget::RealTimeTimeFrequencyWidget() +{ + +} diff --git a/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h new file mode 100644 index 00000000000..8db3f83d966 --- /dev/null +++ b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h @@ -0,0 +1,39 @@ +#ifndef REALTIMETIMEFREQUENCYWIDGET_H +#define REALTIMETIMEFREQUENCYWIDGET_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "scdisp_global.h" +#include "measurementwidget.h" + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include +#include + +//============================================================================================================= +// DEFINE NAMESPACE SCDISPLIB +//============================================================================================================= + +namespace SCDISPLIB +{ + +class SCDISPSHARED_EXPORT RealTimeTimeFrequencyWidget : public MeasurementWidget +{ + Q_OBJECT +public: + RealTimeTimeFrequencyWidget(); +}; +}//namespace +#endif // REALTIMETIMEFREQUENCYWIDGET_H diff --git a/applications/mne_scan/libs/scDisp/scDisp.pro b/applications/mne_scan/libs/scDisp/scDisp.pro index 148086b87fd..5364d40073e 100644 --- a/applications/mne_scan/libs/scDisp/scDisp.pro +++ b/applications/mne_scan/libs/scDisp/scDisp.pro @@ -97,8 +97,10 @@ SOURCES += \ realtimecovwidget.cpp \ realtimespectrumwidget.cpp \ realtime3dwidget.cpp \ + realtimetimefrequencywidget.cpp HEADERS += \ + realtimetimefrequencywidget.h \ scdisp_global.h \ measurementwidget.h \ realtimemultisamplearraywidget.h \ diff --git a/applications/mne_scan/libs/scMeas/realtimeevokedset.h b/applications/mne_scan/libs/scMeas/realtimeevokedset.h index cf60b462314..9629b6f5e12 100644 --- a/applications/mne_scan/libs/scMeas/realtimeevokedset.h +++ b/applications/mne_scan/libs/scMeas/realtimeevokedset.h @@ -44,6 +44,7 @@ #include "realtimesamplearraychinfo.h" #include +#include //============================================================================================================= // QT INCLUDES diff --git a/applications/mne_scan/mne_scan/main.cpp b/applications/mne_scan/mne_scan/main.cpp index 978cea99da6..813218c5ee2 100644 --- a/applications/mne_scan/mne_scan/main.cpp +++ b/applications/mne_scan/mne_scan/main.cpp @@ -94,6 +94,7 @@ Q_IMPORT_PLUGIN(NeuronalConnectivity) Q_IMPORT_PLUGIN(FtBuffer) Q_IMPORT_PLUGIN(WriteToFile) Q_IMPORT_PLUGIN(Hpi) +Q_IMPORT_PLUGIN(TimeFrequency) //Q_IMPORT_PLUGIN(DummyToolbox) #ifdef WITHGUSBAMP Q_IMPORT_PLUGIN(GUSBAmp) diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.cpp b/applications/mne_scan/plugins/timefrequency/timefrequency.cpp index fd83db4e591..0cbd4759a26 100644 --- a/applications/mne_scan/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.cpp @@ -68,7 +68,7 @@ using namespace UTILSLIB; //============================================================================================================= TimeFrequency::TimeFrequency() -: m_pCircularBuffer(CircularBuffer::SPtr::create(40)) +: m_pCircularEvokedBuffer(CircularBuffer::SPtr::create(40)) { } @@ -141,7 +141,17 @@ QWidget* TimeFrequency::setupWidget() void TimeFrequency::update(SCMEASLIB::Measurement::SPtr pMeasurement) { - + if(QSharedPointer pRTES = pMeasurement.dynamicCast()) { + FIFFLIB::FiffEvokedSet::SPtr pFiffEvokedSet = pRTES->getValue(); + + if(this->isRunning()) { + for(int i = 0; i < pFiffEvokedSet->evoked.size(); ++i) { + while(!m_pCircularEvokedBuffer->push(pFiffEvokedSet->evoked.at(i))) { + //Do nothing until the circular buffer is ready to accept new data again + } + } + } + } } //============================================================================================================= @@ -173,11 +183,11 @@ void TimeFrequency::initPluginControlWidgets() void TimeFrequency::run() { - FIFFLIB::FiffEvokedSet evokedSet; + FIFFLIB::FiffEvoked evoked; QStringList lResponsibleTriggerTypes; while(!isInterruptionRequested()){ -// if(m_pCircularBuffer->pop(evokedSet)) { + if(m_pCircularEvokedBuffer->pop(evoked)) { // m_qMutex.lock(); // lResponsibleTriggerTypes = m_lResponsibleTriggerTypes; // m_qMutex.unlock(); @@ -185,6 +195,6 @@ void TimeFrequency::run() // m_pTimeFrequencyOutput->measurementData()->setValue(evokedSet, // m_pFiffInfo, // lResponsibleTriggerTypes); -// } + } } } diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.h b/applications/mne_scan/plugins/timefrequency/timefrequency.h index 4b9c9cdc0ec..1052d38668b 100644 --- a/applications/mne_scan/plugins/timefrequency/timefrequency.h +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.h @@ -126,10 +126,10 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public SCSHAREDLIB::AbstractAlg private: virtual void run(); - SCSHAREDLIB::PluginInputData::SPtr m_pTimeFrequencyInput; /**< The RealTimeSampleArray of the TimeFrequency input.*/ - SCSHAREDLIB::PluginOutputData::SPtr m_pTimeFrequencyOutput; /**< The RealTimeEvoked of the TimeFrequency output.*/ + SCSHAREDLIB::PluginInputData::SPtr m_pTimeFrequencyInput; /**< The RealTimeSampleArray of the TimeFrequency input.*/ + SCSHAREDLIB::PluginOutputData::SPtr m_pTimeFrequencyOutput; /**< The RealTimeEvoked of the TimeFrequency output.*/ - UTILSLIB::CircularBuffer::SPtr m_pCircularBuffer; /**< Holds incoming fiff evoked sets. */ + QSharedPointer> m_pCircularEvokedBuffer; /**< Holds incoming RealTimeMultiSampleArray data.*/ QMutex m_qMutex; /**< Provides access serialization between threads. */ From 6facf996dd69b6cfb7479703acb3b4e1b57d2a9c Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Wed, 28 Apr 2021 12:06:01 -0400 Subject: [PATCH 37/57] ENH: rttfwidget and measurement for real time tfview --- .../scDisp/realtimetimefrequencywidget.cpp | 26 ++++++++++- .../libs/scDisp/realtimetimefrequencywidget.h | 45 ++++++++++++++++++- .../scShared/Management/displaymanager.cpp | 5 +++ 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp index 89b1ebade6d..e8e204a9e07 100644 --- a/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp +++ b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.cpp @@ -4,10 +4,17 @@ #include "realtimetimefrequencywidget.h" +#include + +#include +#include + //============================================================================================================= // QT INCLUDES //============================================================================================================= +#include + //============================================================================================================= // USED NAMESPACES //============================================================================================================= @@ -19,7 +26,24 @@ using namespace SCMEASLIB; // DEFINE MEMBER METHODS //============================================================================================================= -RealTimeTimeFrequencyWidget::RealTimeTimeFrequencyWidget() +RealTimeTimeFrequencyWidget::RealTimeTimeFrequencyWidget(QSharedPointer &pTime, + QWidget* parent) +: MeasurementWidget(parent) { + m_pRTTFLayout = new QVBoxLayout(this); + + m_pTFView = new DISPLIB::TimeFrequencyView(); + + m_pRTTFLayout->addWidget(m_pTFView); + this->setLayout(m_pRTTFLayout); +} + +//============================================================================================================= + +void RealTimeTimeFrequencyWidget::update(SCMEASLIB::Measurement::SPtr pMeasurement) +{ + if(!m_pRTTF) { + m_pRTTF = qSharedPointerDynamicCast(pMeasurement); + } } diff --git a/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h index 8db3f83d966..5be59048d68 100644 --- a/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h +++ b/applications/mne_scan/libs/scDisp/realtimetimefrequencywidget.h @@ -22,6 +22,23 @@ #include #include +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +class QTime; + +namespace SCMEASLIB { + class RealTimeTimeFrequency; +} + +namespace DISPLIB { + class TimeFrequencyView; + class TimeFrequencySettingsView; +} + +class QVBoxLayout; + //============================================================================================================= // DEFINE NAMESPACE SCDISPLIB //============================================================================================================= @@ -33,7 +50,33 @@ class SCDISPSHARED_EXPORT RealTimeTimeFrequencyWidget : public MeasurementWidget { Q_OBJECT public: - RealTimeTimeFrequencyWidget(); + RealTimeTimeFrequencyWidget(QSharedPointer &pTime, + QWidget* parent = 0); + + //========================================================================================================= + /** + * Initialise the MeasurementWidget. + */ + virtual void init(){} + + //========================================================================================================= + /** + * Is called when new data are available. + * + * @param [in] pMeasurement pointer to measurement -> not used because its direct attached to the measurement. + */ + virtual void update(SCMEASLIB::Measurement::SPtr pMeasurement); + +private: + + QSharedPointer m_pRTTF; + + QPointer m_pTFView; + + QPointer m_pRTTFLayout; /**< RTE Widget layout */ + + + }; }//namespace #endif // REALTIMETIMEFREQUENCYWIDGET_H diff --git a/applications/mne_scan/libs/scShared/Management/displaymanager.cpp b/applications/mne_scan/libs/scShared/Management/displaymanager.cpp index fe5d49c6975..54f820da0ac 100644 --- a/applications/mne_scan/libs/scShared/Management/displaymanager.cpp +++ b/applications/mne_scan/libs/scShared/Management/displaymanager.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -52,6 +53,7 @@ #include #include #include +#include //============================================================================================================= // QT INCLUDES @@ -182,6 +184,9 @@ QWidget* DisplayManager::show(AbstractPlugin::OutputConnectorList &outputConnect vboxLayout->addWidget(fsWidget); fsWidget->init(); + } else if (pPluginOutputConnector.dynamicCast< PluginOutputData >()) { + RealTimeTimeFrequencyWidget* tfWidget = new RealTimeTimeFrequencyWidget(pRealTimeFrequency, pT, newDisp); + } } From bd29616e6eb822608a7762405dc5c7aa9cfb3c0a Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Thu, 29 Apr 2021 12:39:54 -0400 Subject: [PATCH 38/57] ENH: rolling queue of data comined into single matrix for processing --- .../libs/scMeas/realtimetimefrequency.h | 15 ++++ .../scShared/Management/displaymanager.cpp | 9 ++- .../plugins/timefrequency/timefrequency.cpp | 75 ++++++++++++++++++- .../plugins/timefrequency/timefrequency.h | 40 ++++++++-- libraries/rtprocessing/rtprocessing.pro | 2 + libraries/rtprocessing/rttimefrequency.cpp | 8 ++ libraries/rtprocessing/rttimefrequency.h | 48 ++++++++++++ 7 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 libraries/rtprocessing/rttimefrequency.cpp create mode 100644 libraries/rtprocessing/rttimefrequency.h diff --git a/applications/mne_scan/libs/scMeas/realtimetimefrequency.h b/applications/mne_scan/libs/scMeas/realtimetimefrequency.h index 1c185b21268..f7e787a41a4 100644 --- a/applications/mne_scan/libs/scMeas/realtimetimefrequency.h +++ b/applications/mne_scan/libs/scMeas/realtimetimefrequency.h @@ -50,10 +50,20 @@ // EIGEN INCLUDES //============================================================================================================= +#include + //============================================================================================================= // FORWARD DECLARATIONS //============================================================================================================= +namespace FIFFLIB { + class FiffInfo; +} + +//============================================================================================================= +// DEFINE NAMESPACE SCMEASLIB +//============================================================================================================= + namespace SCMEASLIB { @@ -62,6 +72,11 @@ class SCMEASSHARED_EXPORT RealTimeTimeFrequency : public Measurement Q_OBJECT public: RealTimeTimeFrequency(); + + Eigen::MatrixXcd m_matData; + QSharedPointer m_pFiffInfo; /**< Fiff info */ + + }; }//namespace #endif // REALTIMETIMEFREQUENCY_H diff --git a/applications/mne_scan/libs/scShared/Management/displaymanager.cpp b/applications/mne_scan/libs/scShared/Management/displaymanager.cpp index 54f820da0ac..72a77a05dcc 100644 --- a/applications/mne_scan/libs/scShared/Management/displaymanager.cpp +++ b/applications/mne_scan/libs/scShared/Management/displaymanager.cpp @@ -185,8 +185,15 @@ QWidget* DisplayManager::show(AbstractPlugin::OutputConnectorList &outputConnect vboxLayout->addWidget(fsWidget); fsWidget->init(); } else if (pPluginOutputConnector.dynamicCast< PluginOutputData >()) { - RealTimeTimeFrequencyWidget* tfWidget = new RealTimeTimeFrequencyWidget(pRealTimeFrequency, pT, newDisp); + RealTimeTimeFrequencyWidget* tfWidget = new RealTimeTimeFrequencyWidget(pT, newDisp); + qListActions.append(tfWidget->getDisplayActions()); + + connect(pPluginOutputConnector.data(), &PluginOutputConnector::notify, + tfWidget, &RealTimeTimeFrequencyWidget::update, Qt::BlockingQueuedConnection); + + vboxLayout->addWidget(tfWidget); + tfWidget->init(); } } diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.cpp b/applications/mne_scan/plugins/timefrequency/timefrequency.cpp index 0cbd4759a26..c08d459bcf0 100644 --- a/applications/mne_scan/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.cpp @@ -43,6 +43,9 @@ #include #include +#include + +#include //============================================================================================================= // QT INCLUDES @@ -69,6 +72,7 @@ using namespace UTILSLIB; TimeFrequency::TimeFrequency() : m_pCircularEvokedBuffer(CircularBuffer::SPtr::create(40)) +, m_iDataQueueBlockSize(25) { } @@ -142,6 +146,10 @@ QWidget* TimeFrequency::setupWidget() void TimeFrequency::update(SCMEASLIB::Measurement::SPtr pMeasurement) { if(QSharedPointer pRTES = pMeasurement.dynamicCast()) { + if(!m_pFiffInfo) { + m_pFiffInfo = pRTES->info(); + } + FIFFLIB::FiffEvokedSet::SPtr pFiffEvokedSet = pRTES->getValue(); if(this->isRunning()) { @@ -152,6 +160,28 @@ void TimeFrequency::update(SCMEASLIB::Measurement::SPtr pMeasurement) } } } + if(QSharedPointer pRTMSA = pMeasurement.dynamicCast()) { + //Fiff information + if(!m_pFiffInfo) { + m_pFiffInfo = pRTMSA->info(); + } + +// if (!m_pRTTF){ +// } + + if (m_pFiffInfo){ + QMutexLocker locker(&m_qMutex); + for(unsigned char i = 0; i < pRTMSA->getMultiSampleArray().size(); ++i) { + // Please note that we do not need a copy here since this function will block until + // the buffer accepts new data again. Hence, the data is not deleted in the actual + // Measurement function after it emitted the notify signal. + m_DataQueue.push_back(pRTMSA->getMultiSampleArray()[i]); +// while(!m_pCircularTimeSeriesBuffer->push(pRTMSA->getMultiSampleArray()[i])) { +// //Do nothing until the circular buffer is ready to accept new data again +// } + } + } + } } //============================================================================================================= @@ -159,10 +189,15 @@ void TimeFrequency::update(SCMEASLIB::Measurement::SPtr pMeasurement) void TimeFrequency::init() { // Input - m_pTimeFrequencyInput = PluginInputData::create(this, "TfIn", "Time frequency input data"); + m_pTimeFrequencyEvokedInput = PluginInputData::create(this, "TfEvokedIn", "Time frequency input data"); + connect(m_pTimeFrequencyEvokedInput.data(), &PluginInputConnector::notify, + this, &TimeFrequency::update, Qt::DirectConnection); + m_inputConnectors.append(m_pTimeFrequencyEvokedInput); - connect(m_pTimeFrequencyInput.data(), &PluginInputConnector::notify, + m_pTimeFrequencyTimeSeriesInput = PluginInputData::create(this, "TfTimeSeiresIn", "Time frequency input data"); + connect(m_pTimeFrequencyTimeSeriesInput.data(), &PluginInputConnector::notify, this, &TimeFrequency::update, Qt::DirectConnection); + m_inputConnectors.append(m_pTimeFrequencyTimeSeriesInput); //Output m_pTimeFrequencyOutput = PluginOutputData::create(this, "TfOut", "Time frequency output data"); @@ -187,7 +222,16 @@ void TimeFrequency::run() QStringList lResponsibleTriggerTypes; while(!isInterruptionRequested()){ - if(m_pCircularEvokedBuffer->pop(evoked)) { + if(m_DataQueue.size() > m_iDataQueueBlockSize){ + QMutexLocker locker(&m_qMutex); + + computeTimeFrequency(); + + while(m_DataQueue.size() > m_iDataQueueBlockSize){ + m_DataQueue.pop_front(); + } + } +// if(m_pCircularEvokedBuffer->pop(evoked)) { // m_qMutex.lock(); // lResponsibleTriggerTypes = m_lResponsibleTriggerTypes; // m_qMutex.unlock(); @@ -195,6 +239,29 @@ void TimeFrequency::run() // m_pTimeFrequencyOutput->measurementData()->setValue(evokedSet, // m_pFiffInfo, // lResponsibleTriggerTypes); - } +// } } } + +//============================================================================================================= + +void TimeFrequency::computeTimeFrequency() +{ + int iCols = 0; + + std::cout<< "First matrix r:" << m_DataQueue.front().rows() << " | c: " << m_DataQueue.front().cols() << std::endl; + + for (auto mat : m_DataQueue){ + iCols += mat.cols(); + } + + std::cout << "COLS: " << iCols << std::endl; + + Eigen::MatrixXd dataMat(m_DataQueue.front().rows(), iCols); + + for (auto mat : m_DataQueue){ + dataMat << mat; + } + + std::cout << "New Matrix - r: " << dataMat.rows() << " | c: " << dataMat.cols() << std::endl; +} diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.h b/applications/mne_scan/plugins/timefrequency/timefrequency.h index 1052d38668b..71b8a62a2ed 100644 --- a/applications/mne_scan/plugins/timefrequency/timefrequency.h +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.h @@ -46,10 +46,21 @@ #include +#include + //============================================================================================================= // QT INCLUDES //============================================================================================================= +#include +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + //============================================================================================================= // FORWARD DECLARATIONS //============================================================================================================= @@ -57,6 +68,11 @@ namespace SCMEASLIB{ class RealTimeEvokedSet; class RealTimeTimeFrequency; + class RealTimeMultiSampleArray; +} + +namespace RTPROCESSINGLIB{ + class RtTimeFrequency; } //============================================================================================================= @@ -126,17 +142,29 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public SCSHAREDLIB::AbstractAlg private: virtual void run(); - SCSHAREDLIB::PluginInputData::SPtr m_pTimeFrequencyInput; /**< The RealTimeSampleArray of the TimeFrequency input.*/ - SCSHAREDLIB::PluginOutputData::SPtr m_pTimeFrequencyOutput; /**< The RealTimeEvoked of the TimeFrequency output.*/ + void computeTimeFrequency(); + + SCSHAREDLIB::PluginInputData::SPtr m_pTimeFrequencyTimeSeriesInput; /**< The RealTimeMultiSampleArray of the NoiseReduction input.*/ + SCSHAREDLIB::PluginInputData::SPtr m_pTimeFrequencyEvokedInput; /**< The RealTimeSampleArray of the TimeFrequency input.*/ + SCSHAREDLIB::PluginOutputData::SPtr m_pTimeFrequencyOutput; /**< The RealTimeEvoked of the TimeFrequency output.*/ + + QSharedPointer> m_pCircularEvokedBuffer; /**< Holds incoming RealTimeMultiSampleArray data.*/ + QSharedPointer m_pCircularTimeSeriesBuffer; /**< Holds incoming raw data. */ + + QSharedPointer m_pRTTF; + + QMutex m_qMutex; /**< Provides access serialization between threads. */ - QSharedPointer> m_pCircularEvokedBuffer; /**< Holds incoming RealTimeMultiSampleArray data.*/ + FIFFLIB::FiffInfo::SPtr m_pFiffInfo; /**< Fiff measurement info.*/ - QMutex m_qMutex; /**< Provides access serialization between threads. */ + std::deque m_DataQueue; - FIFFLIB::FiffInfo::SPtr m_pFiffInfo; /**< Fiff measurement info.*/ + QMap m_mapStimChsIndexNames; /**< The currently available stim channels and their corresponding index in the data. */ - QMap m_mapStimChsIndexNames; /**< The currently available stim channels and their corresponding index in the data. */ + QFuture m_Future; + QFutureWatcher m_FutureWatcher; + int m_iDataQueueBlockSize; signals: }; diff --git a/libraries/rtprocessing/rtprocessing.pro b/libraries/rtprocessing/rtprocessing.pro index d165b63956d..a2ca41fdbc2 100644 --- a/libraries/rtprocessing/rtprocessing.pro +++ b/libraries/rtprocessing/rtprocessing.pro @@ -88,6 +88,7 @@ SOURCES += \ rthpis.cpp \ filter.cpp \ rtconnectivity.cpp \ + rttimefrequency.cpp \ sphara.cpp \ detecttrigger.cpp \ helpers/cosinefilter.cpp \ @@ -107,6 +108,7 @@ HEADERS += \ rthpis.h \ filter.h \ detecttrigger.h \ + rttimefrequency.h \ sphara.h \ rtconnectivity.h \ helpers/cosinefilter.h \ diff --git a/libraries/rtprocessing/rttimefrequency.cpp b/libraries/rtprocessing/rttimefrequency.cpp new file mode 100644 index 00000000000..927bbdb15b9 --- /dev/null +++ b/libraries/rtprocessing/rttimefrequency.cpp @@ -0,0 +1,8 @@ +#include "rttimefrequency.h" + +using namespace RTPROCESSINGLIB; + +RtTimeFrequency::RtTimeFrequency() +{ + +} diff --git a/libraries/rtprocessing/rttimefrequency.h b/libraries/rtprocessing/rttimefrequency.h new file mode 100644 index 00000000000..125a784dd66 --- /dev/null +++ b/libraries/rtprocessing/rttimefrequency.h @@ -0,0 +1,48 @@ +#ifndef RTTIMEFREQUENCY_H +#define RTTIMEFREQUENCY_H + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include "rtprocessing_global.h" + +#include +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// EIGEN INCLUDES +//============================================================================================================= + +#include + +//============================================================================================================= +// FORWARD DECLARATIONS +//============================================================================================================= + +//============================================================================================================= +// DEFINE NAMESPACE RTPROCESSINGLIB +//============================================================================================================= + +namespace RTPROCESSINGLIB +{ + +//============================================================================================================= +// RTPROCESSINGLIB FORWARD DECLARATIONS +//============================================================================================================= + + +class RtTimeFrequency : public QObject +{ +public: + RtTimeFrequency(); +}; +}//namespace +#endif // RTTIMEFREQUENCY_H From aea53545a399edb9af0efb267a61c46a4cd8a11d Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Fri, 30 Apr 2021 12:19:29 -0400 Subject: [PATCH 39/57] ENH: change storage of data in mne scan plugin --- .../plugins/timefrequency/timefrequency.cpp | 19 +++-- .../plugins/timefrequency/timefrequency.h | 4 ++ .../plugins/timefrequency/timefrequency.cpp | 72 ++++++++++++++----- .../formfiles/timefrequencysettingsview.ui | 40 ++++++++++- .../viewers/helpers/timefrequencymodel.cpp | 4 ++ .../viewers/timefrequencysettingsview.cpp | 4 ++ .../disp/viewers/timefrequencysettingsview.h | 2 + libraries/rtprocessing/timefrequency.h | 3 + 8 files changed, 124 insertions(+), 24 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 1656a9fef23..52edd066d93 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -148,6 +148,8 @@ QDockWidget *TimeFrequency::getControl() connect(pSettings, &DISPLIB::TimeFrequencySettingsView::maxFreqChanged, m_pTFModel.data(), &DISPLIB::TimeFrequencyModel::setMaxFreq, Qt::UniqueConnection); + + pDock->setWidget(pSettings); @@ -230,6 +232,9 @@ void TimeFrequency::onModelChanged(QSharedPointer pN m_pEvokedModel->setEvokedSet(m_pAvgModel->data(QModelIndex()).value>()); m_pTimeFreqView->setEvokedSetModel(m_pEvokedModel); } + if(pNewModel->getType() == MODEL_TYPE::ANSHAREDLIB_FIFFRAW_MODEL) { + m_pFiffRawModel = qSharedPointerCast(pNewModel); + } } //============================================================================================================= @@ -271,16 +276,16 @@ void TimeFrequency::computeTimeFreqency() // DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); // tfplot->show(); - auto spectr2 = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); +// auto spectr2 = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); - DISPLIB::TFplot* tfplot2 = new DISPLIB::TFplot(spectr2.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); - tfplot2->show(); +// DISPLIB::TFplot* tfplot2 = new DISPLIB::TFplot(spectr2.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); +// tfplot2->show(); - DISPLIB::TFplot* tfplot3 = new DISPLIB::TFplot(spectr2.at(20), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); - tfplot3->show(); +// DISPLIB::TFplot* tfplot3 = new DISPLIB::TFplot(spectr2.at(20), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); +// tfplot3->show(); - DISPLIB::TFplot* tfplot4 = new DISPLIB::TFplot(spectr2.at(80), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); - tfplot4->show(); +// DISPLIB::TFplot* tfplot4 = new DISPLIB::TFplot(spectr2.at(80), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); +// tfplot4->show(); m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h index 2a55d63e872..fe05199f9c8 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.h +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -158,9 +158,13 @@ class TIMEFREQUENCYSHARED_EXPORT TimeFrequency : public ANSHAREDLIB::AbstractPlu QSharedPointer m_pEvokedModel; /**< Pointer to model used to display averaging data from m_pFiffEvokedSet and m_pFiffEvoked */ QSharedPointer m_pAvgModel; /**< Pointer to currently loaded FiffRawView Model */ + QSharedPointer m_pFiffRawModel; /**< Pointer to currently loaded FiffRawView Model. */ + QSharedPointer m_pTFModel; + bool m_bComputeWithAverage; + }; //============================================================================================================= diff --git a/applications/mne_scan/plugins/timefrequency/timefrequency.cpp b/applications/mne_scan/plugins/timefrequency/timefrequency.cpp index c08d459bcf0..35be6730b8a 100644 --- a/applications/mne_scan/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_scan/plugins/timefrequency/timefrequency.cpp @@ -45,6 +45,8 @@ #include #include +#include + #include //============================================================================================================= @@ -72,7 +74,7 @@ using namespace UTILSLIB; TimeFrequency::TimeFrequency() : m_pCircularEvokedBuffer(CircularBuffer::SPtr::create(40)) -, m_iDataQueueBlockSize(25) +, m_iDataQueueBlockSize(15) { } @@ -172,13 +174,14 @@ void TimeFrequency::update(SCMEASLIB::Measurement::SPtr pMeasurement) if (m_pFiffInfo){ QMutexLocker locker(&m_qMutex); for(unsigned char i = 0; i < pRTMSA->getMultiSampleArray().size(); ++i) { + std::cout << "pRTMSA->getMultiSampleArray().size() " << pRTMSA->getMultiSampleArray().size(); // Please note that we do not need a copy here since this function will block until // the buffer accepts new data again. Hence, the data is not deleted in the actual // Measurement function after it emitted the notify signal. - m_DataQueue.push_back(pRTMSA->getMultiSampleArray()[i]); -// while(!m_pCircularTimeSeriesBuffer->push(pRTMSA->getMultiSampleArray()[i])) { -// //Do nothing until the circular buffer is ready to accept new data again -// } +// m_DataQueue.push_back(pRTMSA->getMultiSampleArray()[i]); + while(!m_pCircularTimeSeriesBuffer->push(pRTMSA->getMultiSampleArray()[i])) { + //Do nothing until the circular buffer is ready to accept new data again + } } } } @@ -215,21 +218,50 @@ void TimeFrequency::initPluginControlWidgets() } //============================================================================================================= - +#include void TimeFrequency::run() { FIFFLIB::FiffEvoked evoked; QStringList lResponsibleTriggerTypes; + Eigen::MatrixXd matData; + while(!isInterruptionRequested()){ - if(m_DataQueue.size() > m_iDataQueueBlockSize){ - QMutexLocker locker(&m_qMutex); + if(m_pCircularTimeSeriesBuffer->pop(matData)){ - computeTimeFrequency(); +// int iCols = 0; - while(m_DataQueue.size() > m_iDataQueueBlockSize){ - m_DataQueue.pop_front(); - } +// std::cout<< "First matrix r:" << m_DataQueue.front().rows() << " | c: " << m_DataQueue.front().cols() << std::endl; + +// for (auto mat : m_DataQueue){ +// iCols += mat.cols(); +// } + +// std::cout << "COLS: " << iCols << std::endl; + +// Eigen::MatrixXd dataMat(m_DataQueue.front().rows(), iCols); + +// for (auto mat : m_DataQueue){ +// Eigen::MatrixXd temp = mat; +// dataMat << temp; +// } + +// std::cout << "New Matrix - r: " << dataMat.rows() << " | c: " << dataMat.cols() << std::endl; + +// if((testing_counter % 20) == 0){ +// Eigen::VectorXd dataCol = dataMat.row(1).transpose(); + +// Eigen::MatrixXd Spectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, m_pFiffInfo->sfreq * 0.2); + +//// DISPLIB::TFplot* tfplot2 = new DISPLIB::TFplot(Spectrum, m_pFiffInfo->sfreq, 0, 50, DISPLIB::ColorMaps::Jet); + +//// tfplot2->show(); +// } + +// while(m_DataQueue.size() > m_iDataQueueBlockSize){ +// m_DataQueue.pop_front(); +// } +// testing_counter++; } // if(m_pCircularEvokedBuffer->pop(evoked)) { // m_qMutex.lock(); @@ -251,17 +283,25 @@ void TimeFrequency::computeTimeFrequency() std::cout<< "First matrix r:" << m_DataQueue.front().rows() << " | c: " << m_DataQueue.front().cols() << std::endl; + Eigen::MatrixXd dataMat(m_DataQueue.front().rows(), iCols); + + { + QMutexLocker locker(&m_qMutex); for (auto mat : m_DataQueue){ iCols += mat.cols(); } std::cout << "COLS: " << iCols << std::endl; - - Eigen::MatrixXd dataMat(m_DataQueue.front().rows(), iCols); - for (auto mat : m_DataQueue){ dataMat << mat; } - + } std::cout << "New Matrix - r: " << dataMat.rows() << " | c: " << dataMat.cols() << std::endl; + +// for(int i = 0; i < dataMat.rows(); i++){ +// Eigen::VectorXd dataCol = dataMat.row(i).transpose(); + +// Eigen::MatrixXd Spectrum = UTILSLIB::Spectrogram::makeSpectrogram(dataCol, m_pFiffInfo->sfreq * 0.2); +// } + } diff --git a/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui b/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui index 29457fe127e..bf7f67410f9 100644 --- a/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui +++ b/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui @@ -121,6 +121,44 @@ + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Use average + + + true + + + + + + + Use raw data + + + false + + + + + + @@ -138,7 +176,7 @@ - + Auto recompute for new averages. diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index ca06f9196ce..c376c17e19f 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -219,6 +219,8 @@ float TimeFrequencyModel::getSamplingFrequency() void TimeFrequencyModel::setMinFreq(int iFreq) { m_iMinFreq = iFreq; + + emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); } //============================================================================================================= @@ -226,6 +228,8 @@ void TimeFrequencyModel::setMinFreq(int iFreq) void TimeFrequencyModel::setMaxFreq(int iFreq) { m_iMaxFreq = iFreq; + + emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1)); } //============================================================================================================= diff --git a/libraries/disp/viewers/timefrequencysettingsview.cpp b/libraries/disp/viewers/timefrequencysettingsview.cpp index 3011f12c45e..b88a6dff450 100644 --- a/libraries/disp/viewers/timefrequencysettingsview.cpp +++ b/libraries/disp/viewers/timefrequencysettingsview.cpp @@ -140,4 +140,8 @@ void TimeFrequencySettingsView::initGUI() connect(m_pUi->pushButton_ciompute, &QPushButton::released, this, &TimeFrequencySettingsView::computePushed, Qt::UniqueConnection); + + + connect(m_pUi->radioButton_avg, &QRadioButton::toggled, + this, &TimeFrequencySettingsView::computeWithAvg, Qt::UniqueConnection); } diff --git a/libraries/disp/viewers/timefrequencysettingsview.h b/libraries/disp/viewers/timefrequencysettingsview.h index 02431b96c26..8cce1cf9ffa 100644 --- a/libraries/disp/viewers/timefrequencysettingsview.h +++ b/libraries/disp/viewers/timefrequencysettingsview.h @@ -112,6 +112,8 @@ class DISPSHARED_EXPORT TimeFrequencySettingsView : public AbstractView void colorMapChanged(const QString &colormap); + void computeWithAvg(bool checked); + protected: void initGUI(); diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index cb74320eeaa..15d08cc996d 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -80,6 +80,9 @@ class RTPROCESINGSHARED_EXPORT TimeFrequencyData static std::vector computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); private: + + Eigen::MatrixXcd m_TFData; + }; From 0d41f0c6ca0ef99a59cdba6d421676173d996dfa Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Wed, 5 May 2021 13:22:46 -0400 Subject: [PATCH 40/57] MAINT: function to compute epoch tf properly --- .../plugins/timefrequency/timefrequency.cpp | 14 +++++++--- libraries/rtprocessing/timefrequency.cpp | 26 +++++++++++++++++++ libraries/rtprocessing/timefrequency.h | 9 ++++++- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 52edd066d93..7b972c19a3f 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -267,11 +268,11 @@ void TimeFrequency::setChannelSelection(const QVariant &data) void TimeFrequency::computeTimeFreqency() { qDebug() << "[TimeFrequency::computeTimeFreqency]"; - if (!m_pAvgModel){ + if (!m_pFiffRawModel){ return; } - auto spectr = RTPROCESSINGLIB::TimeFrequencyData::computeComplexTimeFrequency(*m_pAvgModel->getEvokedSet()); +// auto spectr = RTPROCESSINGLIB::TimeFrequencyData::computeComplexTimeFrequency(*m_pAvgModel->getEvokedSet()); // DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); // tfplot->show(); @@ -288,6 +289,11 @@ void TimeFrequency::computeTimeFreqency() // tfplot4->show(); - m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); - m_pTFModel->setSpectr(spectr); + auto tfData = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data(), + m_pFiffRawModel->getEventModel()->getEventMatrix(9999), + -100, + 300); + +// m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); +// m_pTFModel->setSpectr(spectr); } diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 9812469cd1b..0a4b955ff6f 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -45,6 +45,8 @@ #include +#include + //============================================================================================================= // QT INCLUDES //============================================================================================================= @@ -89,6 +91,8 @@ std::vector TimeFrequencyData::computeTimeFrequency(const FIFFL return tfvector; } +//============================================================================================================= + std::vector TimeFrequencyData::computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; @@ -107,6 +111,27 @@ std::vector TimeFrequencyData::computeComplexTimeFrequency(con return tfvector; } +//============================================================================================================= + +std::vector TimeFrequencyData::computeTimeFrequency(const FIFFLIB::FiffRawData &raw, + const Eigen::MatrixXi &matEvents, + float fTMinS, + float fTMaxS) +{ + + QMap mapReject; + mapReject.insert("eog", 300e-06); + int iType = 1; + + MNELIB::MNEEpochDataList lstEpochDataList = MNELIB::MNEEpochDataList::readEpochs(raw, + matEvents, + fTMinS, + fTMaxS, + iType, + mapReject); + +} + //============================================================================================================= // DEFINE MEMBER METHODS //============================================================================================================= @@ -116,3 +141,4 @@ TimeFrequencyData::TimeFrequencyData() } +//============================================================================================================= diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index 15d08cc996d..600b6247656 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -79,10 +79,17 @@ class RTPROCESINGSHARED_EXPORT TimeFrequencyData static std::vector computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); + static std::vector computeTimeFrequency(const FIFFLIB::FiffRawData& raw, + const Eigen::MatrixXi& matEvents, + float fTMinS, + float fTMaxS); + + Eigen::MatrixXcd getData(); private: - Eigen::MatrixXcd m_TFData; + void setTFData(Eigen::MatrixXcd matData); + Eigen::MatrixXcd m_TFData; }; From a13a3b0d2218838345917dfd6bfd46dcee38e905 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Fri, 7 May 2021 10:33:29 -0400 Subject: [PATCH 41/57] ENH: getting tf data from each epoch --- .../disp/viewers/helpers/timefrequencymodel.h | 4 ++++ libraries/rtprocessing/timefrequency.cpp | 22 +++++++++++++++++++ libraries/rtprocessing/timefrequency.h | 19 ++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.h b/libraries/disp/viewers/helpers/timefrequencymodel.h index e684ccf58c6..d4722ff2ed4 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.h +++ b/libraries/disp/viewers/helpers/timefrequencymodel.h @@ -43,6 +43,8 @@ #include +#include + //============================================================================================================= // QT INCLUDES //============================================================================================================= @@ -154,6 +156,8 @@ class DISPSHARED_EXPORT TimeFrequencyModel : public QAbstractTableModel // QLinearGradient m_Gradient; std::vector m_vSpectr; + std::vector m_vTfData; + QList m_listSelection; Eigen::MatrixXd m_Average; diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 0a4b955ff6f..609e7d4ee83 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -130,6 +130,28 @@ std::vector TimeFrequencyData::computeTimeFrequency(const FIF iType, mapReject); + std::vector data; + + for (int i = 0 ; i < lstEpochDataList.size() ; i++){ + Eigen::MatrixXcd matrix = Eigen::MatrixXcd::Zero(lstEpochDataList[0]->epoch.rows(), lstEpochDataList[0]->epoch.cols()); + TimeFrequencyData tfData; + tfData = matrix; + data.push_back(tfData); + } + + for (auto& epoch : lstEpochDataList){ + for(int i = 0; i < epoch->epoch.rows(); i++){ + Eigen::VectorXd dataCol = epoch->epoch.row(i).transpose(); + Eigen::MatrixXcd Spectrum = UTILSLIB::Spectrogram::makeComplexSpectrogram(dataCol, raw.info.sfreq * 0.2); + data[i] += Spectrum; + } + } + + for (auto tfData : data) { + tfData /= lstEpochDataList.size(); + } + + return data; } //============================================================================================================= diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index 600b6247656..b37dd839a39 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -85,6 +85,25 @@ class RTPROCESINGSHARED_EXPORT TimeFrequencyData float fTMaxS); Eigen::MatrixXcd getData(); + + TimeFrequencyData& operator=(const Eigen::MatrixXcd& mat) + { + this->m_TFData = mat; + return *this; + } + + TimeFrequencyData& operator+=(const Eigen::MatrixXcd& mat) + { + this->m_TFData += mat; + return *this; + } + + TimeFrequencyData& operator/=(int i) + { + this->m_TFData /= i; + return *this; + } + private: void setTFData(Eigen::MatrixXcd matData); From 99299227e0e1b24446be3a3b5b70809c2891ffb0 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Fri, 7 May 2021 13:37:16 -0400 Subject: [PATCH 42/57] MAINT: get matrix size, init to zeroes --- .../plugins/timefrequency/timefrequency.cpp | 7 ++- libraries/rtprocessing/timefrequency.cpp | 49 +++++++++++++------ libraries/rtprocessing/timefrequency.h | 4 +- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 7b972c19a3f..3139abbd00e 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -291,8 +291,11 @@ void TimeFrequency::computeTimeFreqency() auto tfData = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data(), m_pFiffRawModel->getEventModel()->getEventMatrix(9999), - -100, - 300); + -0.100f, + 0.300f); + + m_pTFModel->setFiffInfo(m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data()->info); + m_pTFModel->setSpectr(tfData); // m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); // m_pTFModel->setSpectr(spectr); diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 609e7d4ee83..51fce5343ed 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -113,7 +113,7 @@ std::vector TimeFrequencyData::computeComplexTimeFrequency(con //============================================================================================================= -std::vector TimeFrequencyData::computeTimeFrequency(const FIFFLIB::FiffRawData &raw, +std::vector TimeFrequencyData::computeTimeFrequency(const FIFFLIB::FiffRawData &raw, const Eigen::MatrixXi &matEvents, float fTMinS, float fTMaxS) @@ -130,27 +130,39 @@ std::vector TimeFrequencyData::computeTimeFrequency(const FIF iType, mapReject); - std::vector data; + std::vector data; - for (int i = 0 ; i < lstEpochDataList.size() ; i++){ - Eigen::MatrixXcd matrix = Eigen::MatrixXcd::Zero(lstEpochDataList[0]->epoch.rows(), lstEpochDataList[0]->epoch.cols()); - TimeFrequencyData tfData; - tfData = matrix; - data.push_back(tfData); - } + if(!lstEpochDataList.isEmpty()){ + + Eigen::VectorXd col = lstEpochDataList.front()->epoch.row(0).transpose(); + Eigen::MatrixXcd spctr = UTILSLIB::Spectrogram::makeComplexSpectrogram(col, raw.info.sfreq * 0.2); + + int iCols = spctr.cols(); + int iRows = spctr.rows(); - for (auto& epoch : lstEpochDataList){ - for(int i = 0; i < epoch->epoch.rows(); i++){ - Eigen::VectorXd dataCol = epoch->epoch.row(i).transpose(); - Eigen::MatrixXcd Spectrum = UTILSLIB::Spectrogram::makeComplexSpectrogram(dataCol, raw.info.sfreq * 0.2); - data[i] += Spectrum; + qDebug() << "Rows:" << iRows << " | Cols:" << iCols; + + for(int i = 0; i < lstEpochDataList.front()->epoch.rows(); i++){ + Eigen::MatrixXcd matrix = Eigen::MatrixXcd::Zero(iRows, iCols); + data.push_back(matrix); + } + + //Do subsequent epochs + for (auto& epoch : lstEpochDataList){ + for(int i = 0; i < epoch->epoch.rows(); i++){ + Eigen::VectorXd dataCol = epoch->epoch.row(i).transpose(); + Eigen::MatrixXcd Spectrum = UTILSLIB::Spectrogram::makeComplexSpectrogram(dataCol, raw.info.sfreq * 0.2); + data[i] += Spectrum; + } } - } - for (auto tfData : data) { - tfData /= lstEpochDataList.size(); + for (auto tfData : data) { + tfData /= lstEpochDataList.size(); + } } + qDebug() << "Vector size:" << data.size(); + return data; } @@ -164,3 +176,8 @@ TimeFrequencyData::TimeFrequencyData() } //============================================================================================================= + +TimeFrequencyData::TimeFrequencyData(Eigen::MatrixXcd mat) +{ + this->m_TFData = mat; +} diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index b37dd839a39..f258cbe0a04 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -75,11 +75,13 @@ class RTPROCESINGSHARED_EXPORT TimeFrequencyData public: TimeFrequencyData(); + TimeFrequencyData(Eigen::MatrixXcd mat); + static std::vector computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); static std::vector computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); - static std::vector computeTimeFrequency(const FIFFLIB::FiffRawData& raw, + static std::vector computeTimeFrequency(const FIFFLIB::FiffRawData& raw, const Eigen::MatrixXi& matEvents, float fTMinS, float fTMaxS); From ca155586cf8b97d8edf23d0c783ff522f296da14 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Fri, 7 May 2021 15:06:53 -0400 Subject: [PATCH 43/57] ENH: view now uses painter instread of qgraphicsscene --- .../plugins/timefrequency/timefrequency.cpp | 19 +- .../formfiles/timefrequencysettingsview.ui | 2 +- libraries/disp/viewers/timefrequencyview.cpp | 237 ++++++++++++------ libraries/disp/viewers/timefrequencyview.h | 7 +- 4 files changed, 180 insertions(+), 85 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 3139abbd00e..01285e7c209 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -272,7 +272,6 @@ void TimeFrequency::computeTimeFreqency() return; } -// auto spectr = RTPROCESSINGLIB::TimeFrequencyData::computeComplexTimeFrequency(*m_pAvgModel->getEvokedSet()); // DISPLIB::TFplot* tfplot = new DISPLIB::TFplot(spectr.front(), m_pAvgModel->getEvokedSet()->evoked.first().info.sfreq, 0, 100, DISPLIB::ColorMaps::Jet); // tfplot->show(); @@ -289,14 +288,16 @@ void TimeFrequency::computeTimeFreqency() // tfplot4->show(); - auto tfData = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data(), - m_pFiffRawModel->getEventModel()->getEventMatrix(9999), - -0.100f, - 0.300f); +// auto tfData = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data(), +// m_pFiffRawModel->getEventModel()->getEventMatrix(9999), +// -0.100f, +// 0.300f); - m_pTFModel->setFiffInfo(m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data()->info); - m_pTFModel->setSpectr(tfData); +// m_pTFModel->setFiffInfo(m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data()->info); +// m_pTFModel->setSpectr(tfData); -// m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); -// m_pTFModel->setSpectr(spectr); + auto spectr = RTPROCESSINGLIB::TimeFrequencyData::computeComplexTimeFrequency(*m_pAvgModel->getEvokedSet()); + + m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); + m_pTFModel->setSpectr(spectr); } diff --git a/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui b/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui index bf7f67410f9..11623bc787a 100644 --- a/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui +++ b/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui @@ -82,7 +82,7 @@ Hz - 0 + 20 999 diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index 3ef7558440f..a2abfbe9af8 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -43,6 +43,7 @@ #include "helpers/timefrequencymodel.h" #include +#include //============================================================================================================= // QT INCLUDES @@ -143,95 +144,101 @@ void TimeFrequencyView::initQMLView() // this->setLayout(layout); } -////============================================================================================================= +//============================================================================================================= -//void TimeFrequencyView::paintEvent(QPaintEvent *event) -//{ -// if (m_pEvokedSetModel){ -// QPainter painter(this); +void TimeFrequencyView::paintEvent(QPaintEvent *event) +{ + if (m_pEvokedSetModel){ + QPainter painter(this); -// painter.save(); -// painter.setBrush(QBrush()); -// painter.drawRect(QRect(-1,-1,this->width()+2,this->height()+2)); -// painter.restore(); + painter.save(); + painter.setBrush(QBrush()); + painter.drawRect(QRect(-1,-1,this->width()+2,this->height()+2)); + painter.restore(); -// //paint chart -// painter.save(); -// painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); -// QRect chartBound(m_iChartBorderSpacing,m_iChartBorderSpacing,this->width()-m_iChartBorderSpacing * 4 ,this->height()- m_iChartBorderSpacing * 2); -// painter.drawRect(chartBound); -// painter.restore(); + //paint chart + painter.save(); + painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); + QRect chartBound(m_iChartBorderSpacing,m_iChartBorderSpacing,this->width()-m_iChartBorderSpacing * 4 ,this->height()- m_iChartBorderSpacing * 2); + painter.drawRect(chartBound); + painter.restore(); -// //paint gradient bar + painter.save(); + painter.drawPixmap(chartBound, m_Pixmap); -// painter.save(); + painter.restore(); -// QLinearGradient linGrad(this->width() - m_iChartBorderSpacing * 1.5f, chartBound.topRight().y(), this->width() - m_iChartBorderSpacing * 1.5f, chartBound.bottomRight().y()); -// painter.save(); -// painter.setBrush(linGrad); -// painter.drawRect(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); -// painter.restore(); + //paint gradient bar + painter.save(); -// //paint axis labels -// //test -// if(m_pEvokedSetModel->getNumSamples() > 0) { -// painter.save(); -// painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); + QLinearGradient linGrad(this->width() - m_iChartBorderSpacing * 1.5f, chartBound.topRight().y(), this->width() - m_iChartBorderSpacing * 1.5f, chartBound.bottomRight().y()); + painter.save(); + painter.setBrush(linGrad); + painter.drawRect(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); -// float fDx = (float)(chartBound.width()) / ((float)m_pEvokedSetModel->getNumSamples()); -// float posX = fDx * ((float)m_pEvokedSetModel->getNumPreStimSamples()); -// painter.drawLine(chartBound.bottomLeft().x()+posX, chartBound.bottomRight().y(), chartBound.bottomLeft().x() + posX, chartBound.topRight().y()); + painter.restore(); -// painter.drawText(QPointF(posX+chartBound.bottomLeft().x(),chartBound.bottomRight().y()-5), QString("0ms / Stimulus")); -// painter.restore(); + //paint axis labels + //test + if(m_pEvokedSetModel->getNumSamples() > 0) { + painter.save(); + painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); -// painter.save(); -// QColor colorTimeSpacer = Qt::black; -// colorTimeSpacer.setAlphaF(0.5); -// painter.setPen(QPen(colorTimeSpacer, 1, Qt::DashLine)); + float fDx = (float)(chartBound.width()) / ((float)m_pEvokedSetModel->getNumSamples()); + float posX = fDx * ((float)m_pEvokedSetModel->getNumPreStimSamples()); + painter.drawLine(chartBound.bottomLeft().x()+posX, chartBound.bottomRight().y(), chartBound.bottomLeft().x() + posX, chartBound.topRight().y()); -// float yStart = chartBound.topLeft().y(); -// float yEnd = chartBound.bottomRight().y(); + painter.drawText(QPointF(posX+chartBound.bottomLeft().x(),chartBound.bottomRight().y()-5), QString("0ms / Stimulus")); -// float sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); -// int counter = 1; -// float timeDistanceMSec = 50.0; -// float timeDistanceSamples = (timeDistanceMSec/1000.0)*m_pEvokedSetModel->getSamplingFrequency(); //time distance corresponding to sampling frequency + painter.restore(); -// //spacers before stim -// while(sampleCounter-timeDistanceSamples>0) { -// sampleCounter-=timeDistanceSamples; -// float x = chartBound.bottomLeft().x() + fDx*sampleCounter; -// painter.drawLine(x, yStart, x, yEnd); -// painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("-%1ms").arg(timeDistanceMSec*counter)); -// counter++; -// } + painter.save(); + QColor colorTimeSpacer = Qt::black; + colorTimeSpacer.setAlphaF(0.5); + painter.setPen(QPen(colorTimeSpacer, 1, Qt::DashLine)); -// //spacers after stim -// counter = 1; -// sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); -// while(sampleCounter+timeDistanceSamplesgetNumSamples()) { -// sampleCounter+=timeDistanceSamples; -// float x = chartBound.bottomLeft().x() + fDx*sampleCounter; -// painter.drawLine(x, yStart, x, yEnd); -// painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("%1ms").arg(timeDistanceMSec*counter)); -// counter++; -// } + float yStart = chartBound.topLeft().y(); + float yEnd = chartBound.bottomRight().y(); -// painter.restore(); + float sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); + int counter = 1; + float timeDistanceMSec = 50.0; + float timeDistanceSamples = (timeDistanceMSec/1000.0)*m_pEvokedSetModel->getSamplingFrequency(); //time distance corresponding to sampling frequency -// } + //spacers before stim + while(sampleCounter-timeDistanceSamples>0) { + sampleCounter-=timeDistanceSamples; + float x = chartBound.bottomLeft().x() + fDx*sampleCounter; + painter.drawLine(x, yStart, x, yEnd); + painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("-%1ms").arg(timeDistanceMSec*counter)); + counter++; + } -// } + //spacers after stim + counter = 1; + sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); + while(sampleCounter+timeDistanceSamplesgetNumSamples()) { + sampleCounter+=timeDistanceSamples; + float x = chartBound.bottomLeft().x() + fDx*sampleCounter; + painter.drawLine(x, yStart, x, yEnd); + painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("%1ms").arg(timeDistanceMSec*counter)); + counter++; + } -// return QWidget::paintEvent(event); -//} + painter.restore(); + + } + + } + + return QWidget::paintEvent(event); +} //============================================================================================================= @@ -286,17 +293,99 @@ void TimeFrequencyView::updateData() return; } - if(!m_pLayout->isEmpty()){ - m_pPlot->hide(); - m_pLayout->removeWidget(m_pPlot); - delete m_pPlot; - } +// if(!m_pLayout->isEmpty()){ +// m_pPlot->hide(); +// m_pLayout->removeWidget(m_pPlot); +// delete m_pPlot; +// } auto freqRange = m_pTFModel->getFreqRange(); - m_pPlot = new TFplot(m_pTFModel->data(1,1).value(), m_pTFModel->getSamplingFrequency(), freqRange.first, freqRange.second, DISPLIB::ColorMaps::Jet); - m_pLayout->addWidget(m_pPlot); +// m_pPlot = new TFplot(m_pTFModel->data(1,1).value(), m_pTFModel->getSamplingFrequency(), freqRange.first, freqRange.second, DISPLIB::ColorMaps::Jet); +// m_pLayout->addWidget(m_pPlot); + +// //m_pPlot->adjustSize(); +// m_pPlot->adjustViewSize(); + + auto data = m_pTFModel->data(1,1); + if (!data.isNull()) { + Eigen::MatrixXd tf_matrix = data.value(); + qreal sample_rate = m_pTFModel->getSamplingFrequency(); + qreal lower_frq = freqRange.first; + qreal upper_frq = freqRange.second; + ColorMaps cmap = DISPLIB::ColorMaps::Jet; + + qreal max_frq = sample_rate/2.0; + qreal frq_per_px = max_frq/tf_matrix.rows(); + + if(upper_frq > max_frq || upper_frq <= 0) upper_frq = max_frq; + if(lower_frq < 0 || lower_frq >= max_frq) lower_frq = 0; + if(upper_frq < lower_frq) { + qreal temp = upper_frq; + upper_frq = lower_frq; + lower_frq = temp; + } + + qint32 lower_px = floor(lower_frq / frq_per_px); + qint32 upper_px = floor(upper_frq / frq_per_px); + + Eigen::MatrixXd zoomed_tf_matrix = Eigen::MatrixXd::Zero(upper_px-lower_px, tf_matrix.cols()); + + qint32 pxls = 0; + for(qint32 it = lower_px; it < upper_px; it++) { + zoomed_tf_matrix.row(pxls) = tf_matrix.row(it); + pxls++; + } + + generatePixmap(zoomed_tf_matrix, cmap); + } + + repaint(); +} + +//============================================================================================================= + +void TimeFrequencyView::generatePixmap(Eigen::MatrixXd tf_matrix, + ColorMaps cmap) +{ + + qreal norm1 = tf_matrix.maxCoeff(); + qreal mnorm = tf_matrix.minCoeff(); + if(std::fabs(mnorm) > norm1) norm1 = mnorm; + tf_matrix /= norm1; + + QImage * image_to_tf_plot = new QImage(tf_matrix.cols(), tf_matrix.rows(), QImage::Format_RGB32); + + //setup pixelcolors in image + QColor color; + for ( qint32 y = 0; y < tf_matrix.rows(); y++ ) { + for ( qint32 x = 0; x < tf_matrix.cols(); x++ ) { + switch (cmap) { + case Jet: + color.setRgb(ColorMap::valueToJet(std::fabs(tf_matrix(y, x)))); + break; + case Hot: + color.setRgb(ColorMap::valueToHot(std::fabs(tf_matrix(y, x)))); + break; + case HotNeg1: + color.setRgb(ColorMap::valueToHotNegative1(std::fabs(tf_matrix(y, x)))); + break; + case HotNeg2: + color.setRgb(ColorMap::valueToHotNegative2(std::fabs(tf_matrix(y, x)))); + break; + case Bone: + color.setRgb(ColorMap::valueToBone(std::fabs(tf_matrix(y, x)))); + break; + case RedBlue: + color.setRgb(ColorMap::valueToRedBlue(std::fabs(tf_matrix(y, x)))); + break; + } + image_to_tf_plot->setPixel(x, tf_matrix.rows() - 1 - y, color.rgb()); + } + } + + *image_to_tf_plot = image_to_tf_plot->scaled(tf_matrix.cols(), tf_matrix.cols()/2, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + *image_to_tf_plot = image_to_tf_plot->scaledToWidth(/*0.9 **/ 1026, Qt::SmoothTransformation); - //m_pPlot->adjustSize(); - m_pPlot->adjustViewSize(); + m_Pixmap = QPixmap::fromImage(*image_to_tf_plot); } diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index a1530c4d3d4..282f63c60a8 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -143,7 +143,7 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView protected: void initQMLView(); -// virtual void paintEvent(QPaintEvent *event); + virtual void paintEvent(QPaintEvent *event); // void paintChart(QPainter& painter, // const QRect chartBound); @@ -151,6 +151,9 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView // void paintAxes(QPainter& painter, // const QRect chartBound); + void generatePixmap(Eigen::MatrixXd tf_matrix, + ColorMaps cmap); + //========================================================================================================= /** * call this function whenever the items' data needs to be updated @@ -164,6 +167,8 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView QPointer m_pLayout; QPointer m_pPlot; + QPixmap m_Pixmap; + }; } //namespace From dfb76b20942061186d934ccf233d306be37d0513 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Mon, 10 May 2021 15:05:39 -0400 Subject: [PATCH 44/57] ENH: draw gradient bar --- .../plugins/timefrequency/timefrequency.cpp | 18 +++---- .../formfiles/timefrequencysettingsview.ui | 7 --- libraries/disp/viewers/timefrequencyview.cpp | 51 +++++++++++++++---- libraries/disp/viewers/timefrequencyview.h | 4 +- 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 01285e7c209..c17fc5f0643 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -288,16 +288,16 @@ void TimeFrequency::computeTimeFreqency() // tfplot4->show(); -// auto tfData = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data(), -// m_pFiffRawModel->getEventModel()->getEventMatrix(9999), -// -0.100f, -// 0.300f); + auto tfData = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data(), + m_pFiffRawModel->getEventModel()->getEventMatrix(9999), + -0.100f, + 0.300f); -// m_pTFModel->setFiffInfo(m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data()->info); -// m_pTFModel->setSpectr(tfData); + m_pTFModel->setFiffInfo(m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data()->info); + m_pTFModel->setSpectr(tfData); - auto spectr = RTPROCESSINGLIB::TimeFrequencyData::computeComplexTimeFrequency(*m_pAvgModel->getEvokedSet()); +// auto spectr = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); - m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); - m_pTFModel->setSpectr(spectr); +// m_pTFModel->setFiffInfo(m_pAvgModel->getEvokedSet()->evoked.first().info); +// m_pTFModel->setSpectr(spectr); } diff --git a/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui b/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui index 11623bc787a..8b41362da5f 100644 --- a/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui +++ b/libraries/disp/viewers/formfiles/timefrequencysettingsview.ui @@ -175,13 +175,6 @@ - - - - Auto recompute for new averages. - - - diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index a2abfbe9af8..b68c57c36d2 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -156,9 +156,6 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) painter.drawRect(QRect(-1,-1,this->width()+2,this->height()+2)); painter.restore(); - - - //paint chart painter.save(); painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); @@ -167,23 +164,22 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) painter.restore(); painter.save(); - painter.drawPixmap(chartBound, m_Pixmap); + painter.drawPixmap(chartBound, m_PlotPixmap); painter.restore(); - //paint gradient bar painter.save(); + painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); + QRect gradientBar(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); + painter.drawRect(gradientBar); + painter.restore(); - QLinearGradient linGrad(this->width() - m_iChartBorderSpacing * 1.5f, chartBound.topRight().y(), this->width() - m_iChartBorderSpacing * 1.5f, chartBound.bottomRight().y()); painter.save(); - painter.setBrush(linGrad); - painter.drawRect(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); - + painter.drawPixmap(gradientBar, m_CoefficientPixmap); painter.restore(); - //paint axis labels //test if(m_pEvokedSetModel->getNumSamples() > 0) { @@ -387,5 +383,38 @@ void TimeFrequencyView::generatePixmap(Eigen::MatrixXd tf_matrix, *image_to_tf_plot = image_to_tf_plot->scaled(tf_matrix.cols(), tf_matrix.cols()/2, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); *image_to_tf_plot = image_to_tf_plot->scaledToWidth(/*0.9 **/ 1026, Qt::SmoothTransformation); - m_Pixmap = QPixmap::fromImage(*image_to_tf_plot); + m_PlotPixmap = QPixmap::fromImage(*image_to_tf_plot); + + QImage * coeffs_image = new QImage(10, tf_matrix.rows(), QImage::Format_RGB32); + qreal norm = tf_matrix.maxCoeff(); + for(qint32 it = 0; it < tf_matrix.rows(); it++) { + for ( qint32 x = 0; x < 10; x++ ) { + switch (cmap) { + case Jet: + color.setRgb(ColorMap::valueToJet(it*norm/tf_matrix.rows())); + break; + case Hot: + color.setRgb(ColorMap::valueToHot(it*norm/tf_matrix.rows())); + break; + case HotNeg1: + color.setRgb(ColorMap::valueToHotNegative1(it*norm/tf_matrix.rows())); + break; + case HotNeg2: + color.setRgb(ColorMap::valueToHotNegative2(it*norm/tf_matrix.rows())); + break; + case Bone: + color.setRgb(ColorMap::valueToBone(it*norm/tf_matrix.rows())); + break; + case RedBlue: + color.setRgb(ColorMap::valueToRedBlue(it*norm/tf_matrix.rows())); + break; + } + coeffs_image->setPixel(x, tf_matrix.rows() - 1 - it, color.rgb()); + } + } + + *coeffs_image = coeffs_image->scaled(10, tf_matrix.cols()/2, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + *coeffs_image = coeffs_image->scaledToHeight(image_to_tf_plot->height(), Qt::SmoothTransformation); + + m_CoefficientPixmap = QPixmap::fromImage(*coeffs_image); } diff --git a/libraries/disp/viewers/timefrequencyview.h b/libraries/disp/viewers/timefrequencyview.h index 282f63c60a8..c3b90fa053c 100644 --- a/libraries/disp/viewers/timefrequencyview.h +++ b/libraries/disp/viewers/timefrequencyview.h @@ -167,7 +167,9 @@ class DISPSHARED_EXPORT TimeFrequencyView : public AbstractView QPointer m_pLayout; QPointer m_pPlot; - QPixmap m_Pixmap; + QPixmap m_PlotPixmap; + + QPixmap m_CoefficientPixmap; }; From e58927c66863bd6decf24f040cdf044098aeaee7 Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Mon, 10 May 2021 15:39:25 -0400 Subject: [PATCH 45/57] Add disp params, remove scan plugin from loading, add libs to static build --- .../mne_analyze/mne_analyze/mne_analyze.pro | 1 + .../plugins/timefrequency/timefrequency.h | 4 +- .../plugins/timefrequency/timefrequency.pro | 2 + applications/mne_scan/plugins/plugins.pro | 2 +- libraries/disp/viewers/timefrequencyview.cpp | 109 ++++++++++-------- 5 files changed, 67 insertions(+), 51 deletions(-) diff --git a/applications/mne_analyze/mne_analyze/mne_analyze.pro b/applications/mne_analyze/mne_analyze/mne_analyze.pro index bd6fe66e6d3..73aa6c40445 100644 --- a/applications/mne_analyze/mne_analyze/mne_analyze.pro +++ b/applications/mne_analyze/mne_analyze/mne_analyze.pro @@ -88,6 +88,7 @@ contains(MNECPP_CONFIG, static) { -lcontrolmanager \ -lchannelselection \ -lcoregistration \ + -ltimefrequency \ # Add Qt3D/Disp3D based plugins only if not building against WASM, which does not support Qt3D !contains(DEFINES, WASMBUILD) { diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.h b/applications/mne_analyze/plugins/timefrequency/timefrequency.h index fe05199f9c8..bf35ecd7deb 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.h +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.h @@ -32,8 +32,8 @@ * */ -#ifndef TIMEFREQUENCY_H -#define TIMEFREQUENCY_H +#ifndef TIMEFREQUENCY_AN_PLUGIN_H +#define TIMEFREQUENCY_AN_PLUGIN_H //============================================================================================================= // INCLUDES diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.pro b/applications/mne_analyze/plugins/timefrequency/timefrequency.pro index 1ba9ac22c3f..721aa14ff09 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.pro +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.pro @@ -64,6 +64,7 @@ LIBS += -L$${MNE_LIBRARY_DIR} CONFIG(debug, debug|release) { LIBS += -lanSharedd \ -lmnecppDispd \ + -lmnecppEventsd \ -lmnecppConnectivityd \ -lmnecppRtProcessingd \ -lmnecppInversed \ @@ -75,6 +76,7 @@ CONFIG(debug, debug|release) { } else { LIBS += -lanShared \ -lmnecppDisp \ + -lmnecppEvents \ -lmnecppConnectivity \ -lmnecppRtProcessing \ -lmnecppInverse \ diff --git a/applications/mne_scan/plugins/plugins.pro b/applications/mne_scan/plugins/plugins.pro index 9e3652557df..3c385c5cd34 100644 --- a/applications/mne_scan/plugins/plugins.pro +++ b/applications/mne_scan/plugins/plugins.pro @@ -77,4 +77,4 @@ SUBDIRS += \ writetofile \ hpi \ rtfwd \ - timefrequency \ + #timefrequency \ diff --git a/libraries/disp/viewers/timefrequencyview.cpp b/libraries/disp/viewers/timefrequencyview.cpp index b68c57c36d2..01e80926ae0 100644 --- a/libraries/disp/viewers/timefrequencyview.cpp +++ b/libraries/disp/viewers/timefrequencyview.cpp @@ -148,7 +148,7 @@ void TimeFrequencyView::initQMLView() void TimeFrequencyView::paintEvent(QPaintEvent *event) { - if (m_pEvokedSetModel){ +// if (m_pEvokedSetModel){ QPainter painter(this); painter.save(); @@ -170,68 +170,81 @@ void TimeFrequencyView::paintEvent(QPaintEvent *event) //paint gradient bar - painter.save(); - painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); - QRect gradientBar(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); - painter.drawRect(gradientBar); - painter.restore(); +// painter.save(); +// painter.setPen(QPen(Qt::black, 1, Qt::SolidLine)); +// QRect gradientBar(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); +// painter.drawRect(gradientBar); +// painter.restore(); + +// painter.save(); +// painter.drawPixmap(gradientBar, m_CoefficientPixmap); +// painter.restore(); painter.save(); - painter.drawPixmap(gradientBar, m_CoefficientPixmap); + + painter.drawPixmap(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height(), m_CoefficientPixmap); + painter.restore(); - //paint axis labels - //test - if(m_pEvokedSetModel->getNumSamples() > 0) { - painter.save(); - painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); +// QLinearGradient linGrad(this->width() - m_iChartBorderSpacing * 1.5f, chartBound.topRight().y(), this->width() - m_iChartBorderSpacing * 1.5f, chartBound.bottomRight().y()); +// painter.save(); +// painter.setBrush(linGrad); +// painter.drawRect(chartBound.topRight().x() + m_iChartBorderSpacing, chartBound.topRight().y(), m_iChartBorderSpacing, chartBound.height()); - float fDx = (float)(chartBound.width()) / ((float)m_pEvokedSetModel->getNumSamples()); - float posX = fDx * ((float)m_pEvokedSetModel->getNumPreStimSamples()); - painter.drawLine(chartBound.bottomLeft().x()+posX, chartBound.bottomRight().y(), chartBound.bottomLeft().x() + posX, chartBound.topRight().y()); - painter.drawText(QPointF(posX+chartBound.bottomLeft().x(),chartBound.bottomRight().y()-5), QString("0ms / Stimulus")); - painter.restore(); +// //paint axis labels +// //test +// if(m_pEvokedSetModel->getNumSamples() > 0) { +// painter.save(); +// painter.setPen(QPen(Qt::red, 1, Qt::DashLine)); - painter.save(); - QColor colorTimeSpacer = Qt::black; - colorTimeSpacer.setAlphaF(0.5); - painter.setPen(QPen(colorTimeSpacer, 1, Qt::DashLine)); +// float fDx = (float)(chartBound.width()) / ((float)m_pEvokedSetModel->getNumSamples()); +// float posX = fDx * ((float)m_pEvokedSetModel->getNumPreStimSamples()); +// painter.drawLine(chartBound.bottomLeft().x()+posX, chartBound.bottomRight().y(), chartBound.bottomLeft().x() + posX, chartBound.topRight().y()); - float yStart = chartBound.topLeft().y(); - float yEnd = chartBound.bottomRight().y(); +// painter.drawText(QPointF(posX+chartBound.bottomLeft().x(),chartBound.bottomRight().y()-5), QString("0ms / Stimulus")); - float sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); - int counter = 1; - float timeDistanceMSec = 50.0; - float timeDistanceSamples = (timeDistanceMSec/1000.0)*m_pEvokedSetModel->getSamplingFrequency(); //time distance corresponding to sampling frequency +// painter.restore(); - //spacers before stim - while(sampleCounter-timeDistanceSamples>0) { - sampleCounter-=timeDistanceSamples; - float x = chartBound.bottomLeft().x() + fDx*sampleCounter; - painter.drawLine(x, yStart, x, yEnd); - painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("-%1ms").arg(timeDistanceMSec*counter)); - counter++; - } +// painter.save(); +// QColor colorTimeSpacer = Qt::black; +// colorTimeSpacer.setAlphaF(0.5); +// painter.setPen(QPen(colorTimeSpacer, 1, Qt::DashLine)); - //spacers after stim - counter = 1; - sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); - while(sampleCounter+timeDistanceSamplesgetNumSamples()) { - sampleCounter+=timeDistanceSamples; - float x = chartBound.bottomLeft().x() + fDx*sampleCounter; - painter.drawLine(x, yStart, x, yEnd); - painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("%1ms").arg(timeDistanceMSec*counter)); - counter++; - } +// float yStart = chartBound.topLeft().y(); +// float yEnd = chartBound.bottomRight().y(); - painter.restore(); +// float sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); +// int counter = 1; +// float timeDistanceMSec = 50.0; +// float timeDistanceSamples = (timeDistanceMSec/1000.0)*m_pEvokedSetModel->getSamplingFrequency(); //time distance corresponding to sampling frequency - } +// //spacers before stim +// while(sampleCounter-timeDistanceSamples>0) { +// sampleCounter-=timeDistanceSamples; +// float x = chartBound.bottomLeft().x() + fDx*sampleCounter; +// painter.drawLine(x, yStart, x, yEnd); +// painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("-%1ms").arg(timeDistanceMSec*counter)); +// counter++; +// } - } +// //spacers after stim +// counter = 1; +// sampleCounter = m_pEvokedSetModel->getNumPreStimSamples(); +// while(sampleCounter+timeDistanceSamplesgetNumSamples()) { +// sampleCounter+=timeDistanceSamples; +// float x = chartBound.bottomLeft().x() + fDx*sampleCounter; +// painter.drawLine(x, yStart, x, yEnd); +// painter.drawText(QPointF(x - m_iChartBorderSpacing/3, yEnd + m_iChartBorderSpacing/2), QString("%1ms").arg(timeDistanceMSec*counter)); +// counter++; +// } + +// painter.restore(); + +// } + +// } return QWidget::paintEvent(event); } From 0e0894524c167cbf617ba6c7e8bb909c35b4ac6b Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Tue, 11 May 2021 17:32:20 -0400 Subject: [PATCH 46/57] Changes to resolution and compute structure --- .../plugins/timefrequency/timefrequency.cpp | 7 +- .../viewers/helpers/timefrequencymodel.cpp | 12 -- libraries/rtprocessing/timefrequency.cpp | 103 +++++++++++++----- libraries/rtprocessing/timefrequency.h | 17 ++- libraries/utils/spectrogram.cpp | 2 +- 5 files changed, 96 insertions(+), 45 deletions(-) diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index c17fc5f0643..6b017b4e60c 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -288,13 +288,16 @@ void TimeFrequency::computeTimeFreqency() // tfplot4->show(); - auto tfData = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data(), + auto tfData = RTPROCESSINGLIB::TimeFrequencyData::computeEpochListTimeFrequency(*m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data(), m_pFiffRawModel->getEventModel()->getEventMatrix(9999), -0.100f, 0.300f); + auto averagedData = RTPROCESSINGLIB::TimeFrequencyData::averageEpochListTimeFrequency(tfData); + m_pTFModel->setFiffInfo(m_pFiffRawModel->getFiffIO()->m_qlistRaw.first().data()->info); - m_pTFModel->setSpectr(tfData); + + m_pTFModel->setSpectr(averagedData); // auto spectr = RTPROCESSINGLIB::TimeFrequencyData::computeTimeFrequency(*m_pAvgModel->getEvokedSet()); diff --git a/libraries/disp/viewers/helpers/timefrequencymodel.cpp b/libraries/disp/viewers/helpers/timefrequencymodel.cpp index c376c17e19f..269b79ed2d9 100644 --- a/libraries/disp/viewers/helpers/timefrequencymodel.cpp +++ b/libraries/disp/viewers/helpers/timefrequencymodel.cpp @@ -120,21 +120,9 @@ QVariant TimeFrequencyModel::data(const QModelIndex &index, } case Qt::DisplayRole:{ QVariant variant; -// Eigen::MatrixXcd returnMat = m_vSpectr.front(); -// Eigen::MatrixXd realmat = returnMat.cwiseAbs2(); -// variant.setValue(realmat); - -// return variant; - - -// Eigen::MatrixXd mat = Eigen::MatrixXd::Zero(m_vSpectr[0].rows(), m_vSpectr[0].cols()); -// auto matr = m_vSpectr[0].real(); Eigen::MatrixXcd matrix = Eigen::MatrixXcd::Zero(m_vSpectr[0].rows(), m_vSpectr[0].cols()); -// for (auto& channel : m_vSpectr){ -// matrix += channel; -// } int a = 0; if(m_listSelection.size() > 0){ for (int iChIndex : m_listSelection){ diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 51fce5343ed..9e3b4a38720 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -65,7 +65,7 @@ using namespace RTPROCESSINGLIB; // DEFINE STATIC RTPROCESSINGLIB METHODS //============================================================================================================= -std::vector TimeFrequencyData::computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) +std::vector TimeFrequencyData::computeEpochListTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; @@ -113,57 +113,104 @@ std::vector TimeFrequencyData::computeComplexTimeFrequency(con //============================================================================================================= -std::vector TimeFrequencyData::computeTimeFrequency(const FIFFLIB::FiffRawData &raw, - const Eigen::MatrixXi &matEvents, - float fTMinS, - float fTMaxS) +std::vector> TimeFrequencyData::computeEpochListTimeFrequency(const FIFFLIB::FiffRawData &raw, + const Eigen::MatrixXi &matEvents, + float fTMinS, + float fTMaxS) { QMap mapReject; mapReject.insert("eog", 300e-06); int iType = 1; - MNELIB::MNEEpochDataList lstEpochDataList = MNELIB::MNEEpochDataList::readEpochs(raw, + std::vector > epochTimeFrequencyList; //list of epochs x channels x tf + + MNELIB::MNEEpochDataList epochDataList = MNELIB::MNEEpochDataList::readEpochs(raw, matEvents, fTMinS, fTMaxS, iType, mapReject); - std::vector data; + for(QSharedPointer& epoch : epochDataList){ + epochTimeFrequencyList.emplace_back(computeEpochTimeFrequency(epoch, + raw.info.sfreq)); + } + + return epochTimeFrequencyList; +} - if(!lstEpochDataList.isEmpty()){ +//============================================================================================================= - Eigen::VectorXd col = lstEpochDataList.front()->epoch.row(0).transpose(); - Eigen::MatrixXcd spctr = UTILSLIB::Spectrogram::makeComplexSpectrogram(col, raw.info.sfreq * 0.2); - int iCols = spctr.cols(); - int iRows = spctr.rows(); +std::vector TimeFrequencyData::computeEpochTimeFrequency(const QSharedPointer& epoch, + float sampleFrequency) +{ + int numChannels(epoch->epoch.rows()); - qDebug() << "Rows:" << iRows << " | Cols:" << iCols; + std::vector channelTimeFrequencyList; - for(int i = 0; i < lstEpochDataList.front()->epoch.rows(); i++){ - Eigen::MatrixXcd matrix = Eigen::MatrixXcd::Zero(iRows, iCols); - data.push_back(matrix); + for(int channeli = 0; channeli < numChannels; channeli++){ + channelTimeFrequencyList.emplace_back(UTILSLIB::Spectrogram::makeComplexSpectrogram(epoch->epoch.row(channeli).transpose(), 200)); } - //Do subsequent epochs - for (auto& epoch : lstEpochDataList){ - for(int i = 0; i < epoch->epoch.rows(); i++){ - Eigen::VectorXd dataCol = epoch->epoch.row(i).transpose(); - Eigen::MatrixXcd Spectrum = UTILSLIB::Spectrogram::makeComplexSpectrogram(dataCol, raw.info.sfreq * 0.2); - data[i] += Spectrum; - } - } + return channelTimeFrequencyList; +} + + + +//============================================================================================================= + +Eigen::MatrixXcd TimeFrequencyData::averageEpochTimeFrequency(const std::vector& epochTimeFrequency) +{ + if (epochTimeFrequency.empty()){ + return Eigen::MatrixXcd(); + } + + Eigen::MatrixXcd averageTimeFrequency(epochTimeFrequency.front().rows(), epochTimeFrequency.front().cols()); - for (auto tfData : data) { - tfData /= lstEpochDataList.size(); + for(auto channelTimeFreq : epochTimeFrequency){ + averageTimeFrequency += channelTimeFreq; + } + + return averageTimeFrequency / epochTimeFrequency.size(); +} + +//============================================================================================================= + +std::vector TimeFrequencyData::averageEpochListTimeFrequency(const std::vector >& epochListTimeFrequency) +{ + int numFreqs(epochListTimeFrequency.front().front().rows()); + int numSamples(epochListTimeFrequency.front().front().cols()); + + int numEpochs(epochListTimeFrequency.size()); + + if (numSamples ==0 || numFreqs == 0 || numEpochs == 0){ + return std::vector(); + } + + int numChannelsInEpoch(epochListTimeFrequency.front().size()); + + for (int epochindex(1) ; epochindex < epochListTimeFrequency.size(); epochindex++){ + if (static_cast(epochListTimeFrequency[epochindex].size()) != numChannelsInEpoch){ + qDebug() << "Channel number does not match across epoch" << epochindex; + return std::vector(); } } - qDebug() << "Vector size:" << data.size(); + std::vector averagedEpochListTimeFrequency; + Eigen::MatrixXcd auxMatrix; + + for (int iChannel = 0; iChannel < numChannelsInEpoch; iChannel++){ + auxMatrix = Eigen::MatrixXcd::Zero(numFreqs, numSamples); + for (auto epoch : epochListTimeFrequency){ + auxMatrix += epoch[iChannel]; + } + auxMatrix /= numEpochs; + averagedEpochListTimeFrequency.push_back(auxMatrix); + } - return data; + return averagedEpochListTimeFrequency; } //============================================================================================================= diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index f258cbe0a04..e48d03dff2b 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -63,6 +63,10 @@ namespace FIFFLIB { class FiffEvokedSet; } +namespace MNELIB { + class MNEEpochData; +} + //============================================================================================================= // DEFINE NAMESPACE RTPROCESSINGLIB //============================================================================================================= @@ -77,15 +81,24 @@ class RTPROCESINGSHARED_EXPORT TimeFrequencyData TimeFrequencyData(Eigen::MatrixXcd mat); - static std::vector computeTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); + static std::vector computeEpochListTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); static std::vector computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet); - static std::vector computeTimeFrequency(const FIFFLIB::FiffRawData& raw, + static std::vector > computeEpochListTimeFrequency(const FIFFLIB::FiffRawData& raw, const Eigen::MatrixXi& matEvents, float fTMinS, float fTMaxS); + static std::vector computeEpochTimeFrequency(const QSharedPointer& epoch, + float sampleFrequency); + + static Eigen::MatrixXcd averageEpochTimeFrequency(const std::vector& epochTimeFrequency); + + static std::vector averageEpochListTimeFrequency(const std::vector >& epochListTimeFrequency); + + + Eigen::MatrixXcd getData(); TimeFrequencyData& operator=(const Eigen::MatrixXcd& mat) diff --git a/libraries/utils/spectrogram.cpp b/libraries/utils/spectrogram.cpp index 65226814623..da805e577f2 100644 --- a/libraries/utils/spectrogram.cpp +++ b/libraries/utils/spectrogram.cpp @@ -110,7 +110,7 @@ MatrixXcd Spectrogram::makeComplexSpectrogram(VectorXd signal, qint32 windowSize signal.array() -= signal.mean(); QList lData; - int iThreadSize = QThread::idealThreadCount()*2; + int iThreadSize = QThread::idealThreadCount(); int iStepsSize = signal.rows()/iThreadSize; int iResidual = signal.rows()%iThreadSize; From 66ae6a16f7de3bc457ab60fa57a8652037d524a1 Mon Sep 17 00:00:00 2001 From: juangpc Date: Wed, 12 May 2021 01:51:30 -0400 Subject: [PATCH 47/57] tracer working --- applications/mne_analyze/mne_analyze/main.cpp | 7 +- .../mne_analyze/mne_analyze/mne_analyze.pro | 2 +- .../plugins/timefrequency/timefrequency.cpp | 3 +- .../plugins/timefrequency/timefrequency.pro | 2 +- applications/mne_scan/mne_scan/main.cpp | 4 +- libraries/rtprocessing/rtprocessing.pro | 2 +- libraries/rtprocessing/timefrequency.cpp | 22 +- libraries/rtprocessing/timefrequency.h | 2 +- libraries/utils/spectrogram.cpp | 13 +- libraries/utils/tracer.cpp | 223 ++++++++++++++++++ libraries/utils/tracer.h | 129 ++++++++++ libraries/utils/utils.pro | 3 + 12 files changed, 392 insertions(+), 20 deletions(-) create mode 100644 libraries/utils/tracer.cpp create mode 100644 libraries/utils/tracer.h diff --git a/applications/mne_analyze/mne_analyze/main.cpp b/applications/mne_analyze/mne_analyze/main.cpp index ec80bbe0cd8..26a31309f3f 100644 --- a/applications/mne_analyze/mne_analyze/main.cpp +++ b/applications/mne_analyze/mne_analyze/main.cpp @@ -42,6 +42,7 @@ #include "info.h" #include "analyzecore.h" +#include "utils/tracer.h" //============================================================================================================= // Qt INCLUDES @@ -88,6 +89,7 @@ Q_IMPORT_PLUGIN(TimeFrequency) int main(int argc, char *argv[]) { + __TRACER_ENABLE // When building a static version of MNE Analyze we have to init all resource (.qrc) files here manually #ifdef STATICBUILD #ifndef WASMBUILD @@ -110,5 +112,8 @@ int main(int argc, char *argv[]) QScopedPointer pAnalyzeCore (new AnalyzeCore); pAnalyzeCore->showMainWindow(); - return app.exec(); + int main_return_value(app.exec()); + __TRACER_DISABLE + + return main_return_value; } diff --git a/applications/mne_analyze/mne_analyze/mne_analyze.pro b/applications/mne_analyze/mne_analyze/mne_analyze.pro index 73aa6c40445..b010b65ea1b 100644 --- a/applications/mne_analyze/mne_analyze/mne_analyze.pro +++ b/applications/mne_analyze/mne_analyze/mne_analyze.pro @@ -36,7 +36,7 @@ #============================================================================================================== include(../../../mne-cpp.pri) - +DEFINES += TRACE TEMPLATE = app QT += gui widgets network opengl svg concurrent charts diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index 6b017b4e60c..e326a9c22b8 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -56,7 +56,7 @@ #include #include - +#include //============================================================================================================= // USED NAMESPACES //============================================================================================================= @@ -267,6 +267,7 @@ void TimeFrequency::setChannelSelection(const QVariant &data) void TimeFrequency::computeTimeFreqency() { + __TRACE_FUNC(); qDebug() << "[TimeFrequency::computeTimeFreqency]"; if (!m_pFiffRawModel){ return; diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.pro b/applications/mne_analyze/plugins/timefrequency/timefrequency.pro index 721aa14ff09..4759ef82002 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.pro +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.pro @@ -35,7 +35,7 @@ include(../../../../mne-cpp.pri) TEMPLATE = lib - +DEFINES += TRACE QT += gui widgets CONFIG += skip_target_version_ext plugin diff --git a/applications/mne_scan/mne_scan/main.cpp b/applications/mne_scan/mne_scan/main.cpp index 813218c5ee2..bc177edbed9 100644 --- a/applications/mne_scan/mne_scan/main.cpp +++ b/applications/mne_scan/mne_scan/main.cpp @@ -177,5 +177,7 @@ int main(int argc, char *argv[]) mainWin.hideSplashScreen(); - return app.exec(); + int return_value(app.exec()); + + return return_value; } diff --git a/libraries/rtprocessing/rtprocessing.pro b/libraries/rtprocessing/rtprocessing.pro index a2ca41fdbc2..2d13fed3377 100644 --- a/libraries/rtprocessing/rtprocessing.pro +++ b/libraries/rtprocessing/rtprocessing.pro @@ -36,7 +36,7 @@ include(../../mne-cpp.pri) TEMPLATE = lib - +DEFINES += TRACE CONFIG += skip_target_version_ext QT += network concurrent diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index 9e3b4a38720..d8810c3c6b2 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -46,6 +46,7 @@ #include #include +#include //============================================================================================================= // QT INCLUDES @@ -67,6 +68,7 @@ using namespace RTPROCESSINGLIB; std::vector TimeFrequencyData::computeEpochListTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { + __TRACE_FUNC(); qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; int a = 0; @@ -95,6 +97,7 @@ std::vector TimeFrequencyData::computeEpochListTimeFrequency(co std::vector TimeFrequencyData::computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { + __TRACE_FUNC(); qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; auto& evoked = evokedSet.evoked.first(); @@ -118,7 +121,7 @@ std::vector> TimeFrequencyData::computeEpochListTi float fTMinS, float fTMaxS) { - + __TRACE_FUNC(); QMap mapReject; mapReject.insert("eog", 300e-06); int iType = 1; @@ -143,18 +146,19 @@ std::vector> TimeFrequencyData::computeEpochListTi //============================================================================================================= -std::vector TimeFrequencyData::computeEpochTimeFrequency(const QSharedPointer& epoch, +std::vector TimeFrequencyData::computeEpochTimeFrequency(QSharedPointer& epoch, float sampleFrequency) { - int numChannels(epoch->epoch.rows()); + __TRACE_FUNC(); + int numChannels(epoch->epoch.rows()); - std::vector channelTimeFrequencyList; + std::vector channelTimeFrequencyList; - for(int channeli = 0; channeli < numChannels; channeli++){ - channelTimeFrequencyList.emplace_back(UTILSLIB::Spectrogram::makeComplexSpectrogram(epoch->epoch.row(channeli).transpose(), 200)); - } + for(int channeli = 0; channeli < numChannels; channeli++){ + channelTimeFrequencyList.emplace_back(UTILSLIB::Spectrogram::makeComplexSpectrogram(epoch->epoch.row(channeli).transpose(), 200)); + } - return channelTimeFrequencyList; + return channelTimeFrequencyList; } @@ -163,6 +167,7 @@ std::vector TimeFrequencyData::computeEpochTimeFrequency(const Eigen::MatrixXcd TimeFrequencyData::averageEpochTimeFrequency(const std::vector& epochTimeFrequency) { + __TRACE_FUNC(); if (epochTimeFrequency.empty()){ return Eigen::MatrixXcd(); } @@ -180,6 +185,7 @@ Eigen::MatrixXcd TimeFrequencyData::averageEpochTimeFrequency(const std::vector< std::vector TimeFrequencyData::averageEpochListTimeFrequency(const std::vector >& epochListTimeFrequency) { + __TRACE_FUNC(); int numFreqs(epochListTimeFrequency.front().front().rows()); int numSamples(epochListTimeFrequency.front().front().cols()); diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index e48d03dff2b..59d6f44365b 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -90,7 +90,7 @@ class RTPROCESINGSHARED_EXPORT TimeFrequencyData float fTMinS, float fTMaxS); - static std::vector computeEpochTimeFrequency(const QSharedPointer& epoch, + static std::vector computeEpochTimeFrequency(QSharedPointer& epoch, float sampleFrequency); static Eigen::MatrixXcd averageEpochTimeFrequency(const std::vector& epochTimeFrequency); diff --git a/libraries/utils/spectrogram.cpp b/libraries/utils/spectrogram.cpp index da805e577f2..f43b8dfaf64 100644 --- a/libraries/utils/spectrogram.cpp +++ b/libraries/utils/spectrogram.cpp @@ -36,7 +36,7 @@ //============================================================================================================= #include "spectrogram.h" - +#include "utils/tracer.h" //============================================================================================================= // EIGEN INCLUDES //============================================================================================================= @@ -68,7 +68,7 @@ MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0) { //QElapsedTimer timer; //timer.start(); - + __TRACE_FUNC(); signal.array() -= signal.mean(); QList lData; int iThreadSize = QThread::idealThreadCount()*2; @@ -107,7 +107,7 @@ MatrixXcd Spectrogram::makeComplexSpectrogram(VectorXd signal, qint32 windowSize { //QElapsedTimer timer; //timer.start(); - + __TRACE_FUNC(); signal.array() -= signal.mean(); QList lData; int iThreadSize = QThread::idealThreadCount(); @@ -144,6 +144,7 @@ MatrixXcd Spectrogram::makeComplexSpectrogram(VectorXd signal, qint32 windowSize VectorXd Spectrogram::gaussWindow(qint32 sample_count, qreal scale, quint32 translation) { + __TRACE_FUNC(); VectorXd gauss = VectorXd::Zero(sample_count); for(qint32 n = 0; n < sample_count; n++) @@ -162,7 +163,7 @@ MatrixXd Spectrogram::compute(const SpectogramInputData& inputData) #ifdef EIGEN_FFTW_DEFAULT fftw_make_planner_thread_safe(); #endif - + __TRACE_FUNC(); Eigen::FFT fft; MatrixXd tf_matrix = MatrixXd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows()); VectorXd envelope, windowed_sig, real_coeffs; @@ -194,7 +195,7 @@ MatrixXcd Spectrogram::computeComplex(const SpectogramInputData& inputData) #ifdef EIGEN_FFTW_DEFAULT fftw_make_planner_thread_safe(); #endif - + __TRACE_FUNC(); Eigen::FFT fft; MatrixXcd tf_matrix = MatrixXcd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows()); VectorXd envelope, windowed_sig; @@ -224,6 +225,7 @@ MatrixXcd Spectrogram::computeComplex(const SpectogramInputData& inputData) void Spectrogram::reduce(MatrixXd &resultData, const MatrixXd &data) { + __TRACE_FUNC(); if(resultData.size() == 0) { resultData = data; } else { @@ -236,6 +238,7 @@ void Spectrogram::reduce(MatrixXd &resultData, void Spectrogram::reduceComplex(MatrixXcd &resultData, const MatrixXcd &data) { + __TRACE_FUNC(); if(resultData.size() == 0) { resultData = data; } else { diff --git a/libraries/utils/tracer.cpp b/libraries/utils/tracer.cpp new file mode 100644 index 00000000000..1e83a29302b --- /dev/null +++ b/libraries/utils/tracer.cpp @@ -0,0 +1,223 @@ +#include "tracer.h" + +using namespace UTILSLIB; + +int Tracer::numTracers = 0; +bool Tracer::isEnabled = false; +std::ofstream Tracer::outputFileStream; +bool Tracer::isFirstEvent = true; +bool Tracer::outFileMutex = false; +long long Tracer::zeroTime = 0; + +Tracer::Tracer(const std::string &function, const std::string &file, const int num) +: printToTerminal(false) +, fileName(file) +, threadId("0") +, beginTime(0) +, endTime(0) +, durationMicros(0) +, durationMilis(0.0) +{ + if (isEnabled) + { + initialize(function, file, num); + writeBeginEvent(); + } +} + +Tracer::~Tracer() +{ + if (isEnabled) + { + registerFinalTime(); + writeEndEvent(); + if (printToTerminal) + { + calculateDuration(); + printDurationMiliSec(); + } + } +} + +void Tracer::enable(const std::string &jsonFileName) +{ + outputFileStream.open(jsonFileName); + outFileMutex = false; + writeHeader(); + setZeroTime(); + isEnabled = true; +} + +void Tracer::enable() +{ + enable("default_tracer_file.json"); +} + +void Tracer::disable() +{ + if (Tracer::isEnabled) + { + writeFooter(); + outputFileStream.close(); + outFileMutex = false; + isEnabled = false; + } +} + +void Tracer::start(const std::string &jsonFileName) +{ + enable(jsonFileName); +} + +void Tracer::start() +{ + enable(); +} + +void Tracer::stop() +{ + disable(); +} + +void Tracer::traceQuantity(std::string &name, long val) +{ + long long timeNow = getTimeNow() - zeroTime; + std::string s; + s.append("{\"name\":\"").append(name).append("\",\"ph\":\"C\",\"ts\":"); + s.append(std::to_string(timeNow)).append(",\"pid\":1,\"tid\":1"); + s.append(",\"args\":{\"").append(name).append("\":").append(std::to_string(val)).append("}}\n"); + writeToFile(s); +} + +void Tracer::initialize(const std::string &function, const std::string &file, const int num) +{ + numTracers++; + + initializeFunctionName(function); + initializeFile(file); + lineNumber = num; + + registerThreadId(); + registerInitialTime(); +} + +void Tracer::setZeroTime() +{ + zeroTime = getTimeNow(); +} + +void Tracer::registerInitialTime() +{ + beginTime = getTimeNow() - zeroTime; +} + +void Tracer::registerFinalTime() +{ + endTime = getTimeNow() - zeroTime; +} + +long long Tracer::getTimeNow() +{ + auto timeNow = std::chrono::high_resolution_clock::now(); + return std::chrono::time_point_cast(timeNow).time_since_epoch().count(); +} + +void Tracer::registerThreadId() +{ + auto longId = std::hash{}(std::this_thread::get_id()); + threadId = std::to_string(longId).substr(0, 5); +} + +void Tracer::initializeFunctionName(const std::string &function) +{ + functionName = function; + std::string pattern(" __cdecl"); + size_t pos = functionName.find("__cdecl"); + if (pos != std::string::npos) + functionName.replace(pos, pattern.length(), ""); +} + +void Tracer::initializeFile(std::string file) +{ + std::string patternIn("\\"); + std::string patternOut("\\\\"); + size_t start_pos = 0; + while ((start_pos = file.find(patternIn, start_pos)) != std::string::npos) + { + file.replace(start_pos, 1, patternOut); + start_pos += patternOut.length(); + } + + fileName = file; +} + +void Tracer::calculateDuration() +{ + durationMicros = endTime - beginTime; + durationMilis = durationMicros * 0.001; +} + +void Tracer::printDurationMiliSec() +{ + std::cout << "Scope: " << fileName << " - " << functionName << " DurationMs: " << durationMilis << "ms.\n"; +} + +void Tracer::writeHeader() +{ + writeToFile("{\"displayTimeUnit\": \"ms\",\"traceEvents\":[\n"); +} + +void Tracer::writeFooter() +{ + writeToFile("]}"); +} + +void Tracer::writeToFile(const std::string &str) +{ + if (outFileMutex) + { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + writeToFile(str); + } + else + { + outFileMutex = true; + outputFileStream << str; + outputFileStream.flush(); + outFileMutex = false; + } +} + +void Tracer::writeBeginEvent() +{ + std::string s; + if (!isFirstEvent) + s.append(","); + + s.append("{\"name\":\"").append(functionName).append("\",\"cat\":\"bst\","); + s.append("\"ph\":\"B\",\"ts\":").append(std::to_string(beginTime)).append(",\"pid\":1,\"tid\":"); + s.append(threadId).append(",\"args\":{\"file path\":\"").append(fileName).append("\",\"line number\":"); + s.append(std::to_string(lineNumber)).append("}}\n"); + writeToFile(s); + isFirstEvent = false; +} + +void Tracer::writeEndEvent() +{ + std::string s; + s.append(",{\"name\":\"").append(functionName).append("\",\"cat\":\"bst\","); + s.append("\"ph\":\"E\",\"ts\":").append(std::to_string(endTime)).append(",\"pid\":1,\"tid\":"); + s.append(threadId).append(",\"args\":{\"file path\":\"").append(fileName).append("\",\"line number\":"); + s.append(std::to_string(lineNumber)).append("}}\n"); + writeToFile(s); +} + +bool Tracer::printToTerminalIsSet() +{ + return printToTerminal; +} + +void Tracer::setPrintToTerminal(bool s) +{ + printToTerminal = s; +} diff --git a/libraries/utils/tracer.h b/libraries/utils/tracer.h new file mode 100644 index 00000000000..1a1e458ff22 --- /dev/null +++ b/libraries/utils/tracer.h @@ -0,0 +1,129 @@ +#ifndef TRACER_H +#define TRACER_H + +#include "utils_global.h" + +#include +#include +#include +#include +#include + +#define __PRETTY_FUNCTION__ __FUNCSIG__ + +#ifdef TRACE +#define __TRACE_FUNC() UTILSLIB::Tracer _t__LINE__(__PRETTY_FUNCTION__, __FILE__, __LINE__); +#define __TRACER_ENABLE UTILSLIB::Tracer::enable("chrome_tracer.json"); +#define __TRACER_DISABLE UTILSLIB::Tracer::disable(); +#define __TRACE_VALUE(NAME, VALUE) UTILSLIB::Tracer::traceQuantity(NAME, VALUE); +#else +#define __TRACE_FUNC() PEPE +#define __TRACER_ENABLE PEPE +#define __TRACER_DISABLE PEPE +#define __TRACE_VALUE() PEPE +#endif + +#ifdef TRACE_MEMORY +#define __TRACE_MEMORY_REPORT \ + std::cout << "Total Memory Allocated : " << 0.000001 * __totalMemAllocated << " MB\n";\ + std::cout << "Total Memory Deleted : " << 0.000001 * __totalMemDeleted << " MB\n";\ + std::cout << "Total Memory Diff : " << 0.000001 * (__totalMemAllocated - __totalMemDeleted) << " MB\n";\ + +size_t __totalMemAllocated(0); +size_t __totalMemDeleted(0); +void *operator new(size_t size) +{ + // std::cout << "Allocating " << size << " Bytes.\n"; + __totalMemAllocated += size; + return malloc(size); +} + +void operator delete(void *memory, size_t size) +{ + // std::cout << "Deleting " << size << " Bytes.\n"; + __totalMemDeleted += size; + free(memory); +} +#else +#define __TRACE_MEMORY_REPORT +#endif + +namespace UTILSLIB +{ + + class UTILSSHARED_EXPORT Tracer + { + public: + Tracer(const std::string &function, const std::string &file, const int num); + + ~Tracer(); + + static void enable(const std::string &jsonFileName); + + static void enable(); + + static void disable(); + + static void start(const std::string &jsonFileName); + + static void start(); + + static void stop(); + + static void traceQuantity(std::string &name, long val); + + bool printToTerminalIsSet(); + + void setPrintToTerminal(bool s); + + private: + static void writeHeader(); + + static void writeFooter(); + + static void writeToFile(const std::string &str); + + static void setZeroTime(); + + static long long getTimeNow(); + + void initialize(const std::string &function, const std::string &file, const int num); + + void initializeFunctionName(const std::string &function); + + void initializeFile(std::string file); + + void registerInitialTime(); + + void registerFinalTime(); + + void registerThreadId(); + + void calculateDuration(); + + void printDurationMiliSec(); + + void writeBeginEvent(); + + void writeEndEvent(); + + static int numTracers; + static bool isEnabled; + static std::ofstream outputFileStream; + static bool isFirstEvent; + static bool outFileMutex; + static long long zeroTime; + + bool printToTerminal; + std::string functionName; + std::string fileName; + int lineNumber; + std::string threadId; + long long beginTime; + long long endTime; + long long durationMicros; + double durationMilis; + }; + +} // namespace ChromeTracer +#endif // TRACER_H diff --git a/libraries/utils/utils.pro b/libraries/utils/utils.pro index 96110f033cc..e782fa0f847 100644 --- a/libraries/utils/utils.pro +++ b/libraries/utils/utils.pro @@ -45,6 +45,7 @@ QT -= gui QT += concurrent DEFINES += UTILS_LIBRARY +DEFINES += TRACE DESTDIR = $${MNE_LIBRARY_DIR} @@ -69,6 +70,7 @@ SOURCES += \ layoutmaker.cpp \ selectionio.cpp \ spectrogram.cpp \ + tracer.cpp \ warp.cpp \ sphere.cpp \ generics/observerpattern.cpp \ @@ -77,6 +79,7 @@ SOURCES += \ HEADERS += \ kmeans.h\ + tracer.h \ utils_global.h \ mnemath.h \ ioutils.h \ From 786479a0c58ecb108c555ebc8f9be2ab5142bdc2 Mon Sep 17 00:00:00 2001 From: juangpc Date: Thu, 13 May 2021 03:33:52 -0400 Subject: [PATCH 48/57] new superlet toolbox --- libraries/libraries.pro | 1 + libraries/rtprocessing/timefrequency.cpp | 6 +- libraries/rtprocessing/timefrequency.h | 3 +- libraries/timefrequency/convolver.cpp | 200 ++++ libraries/timefrequency/convolver.h | 75 ++ libraries/timefrequency/include/fftw.h | 27 + libraries/timefrequency/interface.cpp | 221 ++++ libraries/timefrequency/lib/libfftw3f-3.def | 1017 +++++++++++++++++ libraries/timefrequency/morlet.h | 72 ++ libraries/timefrequency/timefrequency.pro | 72 ++ .../wavelet_spectrum_analyzer.cpp | 152 +++ .../timefrequency/wavelet_spectrum_analyzer.h | 46 + libraries/utils/spectrogram.cpp | 42 +- libraries/utils/spectrogram.h | 4 +- 14 files changed, 1914 insertions(+), 24 deletions(-) create mode 100644 libraries/timefrequency/convolver.cpp create mode 100644 libraries/timefrequency/convolver.h create mode 100644 libraries/timefrequency/include/fftw.h create mode 100644 libraries/timefrequency/interface.cpp create mode 100644 libraries/timefrequency/lib/libfftw3f-3.def create mode 100644 libraries/timefrequency/morlet.h create mode 100644 libraries/timefrequency/timefrequency.pro create mode 100644 libraries/timefrequency/wavelet_spectrum_analyzer.cpp create mode 100644 libraries/timefrequency/wavelet_spectrum_analyzer.h diff --git a/libraries/libraries.pro b/libraries/libraries.pro index 9dbfedb00bb..f701d264230 100644 --- a/libraries/libraries.pro +++ b/libraries/libraries.pro @@ -51,6 +51,7 @@ SUBDIRS += \ rtprocessing \ connectivity \ disp \ + timefrequency \ qtHaveModule(charts) { # The Qt3D module is not yet Wasm supported diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index d8810c3c6b2..f5a3a59442c 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -146,7 +146,7 @@ std::vector> TimeFrequencyData::computeEpochListTi //============================================================================================================= -std::vector TimeFrequencyData::computeEpochTimeFrequency(QSharedPointer& epoch, +std::vector TimeFrequencyData::computeEpochTimeFrequency(const QSharedPointer& epoch, float sampleFrequency) { __TRACE_FUNC(); @@ -155,7 +155,9 @@ std::vector TimeFrequencyData::computeEpochTimeFrequency(QShar std::vector channelTimeFrequencyList; for(int channeli = 0; channeli < numChannels; channeli++){ - channelTimeFrequencyList.emplace_back(UTILSLIB::Spectrogram::makeComplexSpectrogram(epoch->epoch.row(channeli).transpose(), 200)); + channelTimeFrequencyList.push_back(Eigen::MatrixXcd::Zero(10,10)); +// channelTimeFrequencyList.emplace_back(UTILSLIB::Spectrogram::makeComplexSpectrogram(epoch->epoch.row(channeli).transpose(), 200)); +// channelTimeFrequencyList.emplace_back(UTILSLIB::Spectrogram::makeSpectrogram(epoch->epoch.row(channeli).transpose(),0)); } return channelTimeFrequencyList; diff --git a/libraries/rtprocessing/timefrequency.h b/libraries/rtprocessing/timefrequency.h index 59d6f44365b..f7b4d62271f 100644 --- a/libraries/rtprocessing/timefrequency.h +++ b/libraries/rtprocessing/timefrequency.h @@ -53,6 +53,7 @@ //============================================================================================================= #include +#include //============================================================================================================= // FORWARD DECLARATIONS @@ -90,7 +91,7 @@ class RTPROCESINGSHARED_EXPORT TimeFrequencyData float fTMinS, float fTMaxS); - static std::vector computeEpochTimeFrequency(QSharedPointer& epoch, + static std::vector computeEpochTimeFrequency(const QSharedPointer& epoch, float sampleFrequency); static Eigen::MatrixXcd averageEpochTimeFrequency(const std::vector& epochTimeFrequency); diff --git a/libraries/timefrequency/convolver.cpp b/libraries/timefrequency/convolver.cpp new file mode 100644 index 00000000000..5718f601bca --- /dev/null +++ b/libraries/timefrequency/convolver.cpp @@ -0,0 +1,200 @@ +#include "convolver.h" +#include "fftw.h" + +#include +#include + +using namespace TIMEFREQUENCYLIB; + +std::mutex fftw_mutex; + + +int nextpow2(int x) +{ + if (x < 0) + return 0; + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x + 1; +} + + +__forceinline std::complex conj(const std::complex& z) +{ + return std::complex(z.real(), -z.imag()); +} + + + + +void convolver::initialize(int signal_size, int kernel_size) +{ + _signal_size = signal_size; + _kernel_size = kernel_size; + _method = method::fft_convolution; + _shape = shape::same; + _operation = operation::convolution; + _convol_size = _signal_size + _kernel_size - 1; + + + switch (_method) + { + case method::fft_convolution: + _segment_size = 0; + _segment_count = 0; + _fft_size = nextpow2(_convol_size); + + alloc_fft_buffers(_fft_size); + break; + + default: + exit(-1); + } + +} + +void convolver::clear() +{ + _signal_size = 0; + _kernel_size = 0; + _convol_size = 0; + _fft_size = 0; + _segment_count = 0; + _segment_size = 0; + _shape = shape::same; + _operation = operation::convolution; + _method = method::automatic; + + fftw_mutex.lock(); + if (_signal_buffer) fftwf_free(_signal_buffer); + if (_fft_fwd) fftwf_destroy_plan(_fft_fwd); + if (_fft_rev) fftwf_destroy_plan(_fft_rev); + fftw_mutex.unlock(); + + _signal_buffer = nullptr; + _kernel_buffer = nullptr; + _output_buffer = nullptr; + _fft_fwd = nullptr; + _fft_rev = nullptr; +} + + + +void convolver::assign_kernel(std::complex* kernel, int size) +{ + int n = std::min(size, _kernel_size); + if (_method == method::fft_convolution || + _method == method::fft_overlap_add) + { + for (int i = 0; i < n; ++i) + _kernel_buffer[i] = kernel[i]; + + prepare_fft_kernel(); + } +} + + + + +void convolver::prepare_fft_kernel() +{ + for (int i = _kernel_size; i < _fft_size; ++i) + _kernel_buffer[i] = std::complex(); + + fftwf_execute_dft(_fft_fwd, _kernel_buffer, _kernel_buffer); + + // prepare kernel + float norm = float(1.0 / _fft_size); + if (_operation == operation::correlation) + { + for (int i = 0; i < _fft_size; ++i) + _kernel_buffer[i] = conj(_kernel_buffer[i]); + } + else + { + for (int i = 0; i < _fft_size; ++i) + _kernel_buffer[i] *= norm; + } +} + + + +void convolver::alloc_fft_buffers(int fft_size) +{ + fftw_mutex.lock(); + _signal_buffer = reinterpret_cast*>(fftwf_malloc(size_t(_fft_size) * 3 * sizeof(std::complex))); + _kernel_buffer = _signal_buffer + _fft_size; + _output_buffer = _kernel_buffer + _fft_size; + _fft_fwd = fftwf_plan_dft_1d(_fft_size, nullptr, nullptr, FFTW_FORWARD, FFTW_ESTIMATE); + _fft_rev = fftwf_plan_dft_1d(_fft_size, nullptr, nullptr, FFTW_BACKWARD, FFTW_ESTIMATE); + fftw_mutex.unlock(); + + if (!_signal_buffer || !_fft_fwd || !_fft_rev) + exit(-1); + + memset(_signal_buffer, 0, size_t(_fft_size) * 3 * sizeof(std::complex)); +} + + + + +void convolver::apply_fft_kernel() +{ + fftwf_execute_dft(_fft_fwd, _signal_buffer, _output_buffer); + + for (int i = 0; i < _fft_size; ++i) + _output_buffer[i] = _output_buffer[i] * _kernel_buffer[i]; + + fftwf_execute_dft(_fft_rev, _output_buffer, _output_buffer); +} + + + + +void convolver::conv_r2c_same(float* signal, std::complex* out) +{ + if (_method == method::fft_convolution) + { + for (int i = 0; i < _signal_size; ++i) _signal_buffer[i] = std::complex(signal[i]); + for (int i = _signal_size; i < _fft_size; ++i) _signal_buffer[i] = std::complex(); + + apply_fft_kernel(); + + auto opb = _output_buffer + _kernel_size / 2; + for (int i = 0; i < _signal_size; ++i) + out[i] = opb[i]; + } + else if (_method == method::fft_overlap_add) + { + for (int i = 0; i < _signal_size; ++i) + out[i] = std::complex(); + + int r_begin = 0; + while (r_begin < _signal_size) + { + int r_count = std::min(r_begin + _segment_size, _signal_size) - r_begin; + + for (int i = 0; i < r_count; ++i) _signal_buffer[i] = std::complex(signal[r_begin + i]); + for (int i = r_count; i < _segment_size; ++i) _signal_buffer[i] = std::complex(); + + apply_fft_kernel(); + + int w_begin = std::max(r_begin - _kernel_size / 2, 0); + int b_offset = std::max(_kernel_size / 2 - r_begin, 0); + int w_count = std::min(_fft_size - b_offset, _signal_size - w_begin - b_offset); + + auto cxbuf = _output_buffer + b_offset; + for (int i = 0; i < w_count; ++i) + out[w_begin + i] += cxbuf[i]; + + r_begin += _segment_size; + } + } +} + + + diff --git a/libraries/timefrequency/convolver.h b/libraries/timefrequency/convolver.h new file mode 100644 index 00000000000..70a23225ba5 --- /dev/null +++ b/libraries/timefrequency/convolver.h @@ -0,0 +1,75 @@ +#pragma once +#include + +namespace TIMEFREQUENCYLIB { + +class convolver +{ +public: + enum class method + { + automatic, + time_domain, + fft_overlap_add, + fft_convolution + }; + + enum class shape + { + same, + full + }; + + enum class operation + { + convolution, + correlation + }; + + +public: + convolver(int signal_size, int kernel_size) + { + initialize(signal_size, kernel_size); + } + + ~convolver() + { + clear(); + } + + void initialize(int signal_size, int kernel_size); + void clear(); + + void conv_r2c_same(float* signal, std::complex* output); + void assign_kernel(std::complex* kernel, int size); + +protected: + void prepare_fft_kernel(); + void alloc_fft_buffers(int fft_size); + void apply_fft_kernel(); + + +protected: + int _signal_size = 0; + int _kernel_size = 0; + int _convol_size = 0; + int _fft_size = 0; + int _segment_size = 0; + int _segment_count = 0; + shape _shape; + method _method; + operation _operation; + +private: + void *_fft_fwd = nullptr; + void *_fft_rev = nullptr; + std::complex *_signal_buffer = nullptr; + std::complex *_output_buffer = nullptr; + std::complex *_kernel_buffer = nullptr; + +private: + static const int default_segment_size = 512; +}; + +} diff --git a/libraries/timefrequency/include/fftw.h b/libraries/timefrequency/include/fftw.h new file mode 100644 index 00000000000..307f76ecb48 --- /dev/null +++ b/libraries/timefrequency/include/fftw.h @@ -0,0 +1,27 @@ +#pragma once +#include + +#pragma comment(lib, "libfftw3f-3.lib") + +// FFTW MINIMAL INTERFACE +extern "C" +{ + extern void* fftwf_malloc(unsigned long long size); + extern void fftwf_free(void* p); + extern void* fftwf_plan_dft_1d(int size, std::complex* in, std::complex* out, int sign, unsigned flags); + extern void* fftwf_plan_dft_r2c_1d(int size, float* in, std::complex* out, unsigned flags); + extern void* fftwf_plan_dft_c2r_1d(int size, std::complex* in, float* out, unsigned flags); + extern void* fftwf_plan_dft_2d(int n0, int n1, std::complex* in, std::complex* out, int sign, unsigned flags); + + extern void fftwf_execute(void* p); + extern void fftwf_execute_dft(void* p, std::complex* in, std::complex* out); + extern void fftwf_execute_dft_r2c(void* p, float* in, std::complex* out); + extern void fftwf_execute_dft_c2r(void* p, std::complex* in, float* out); + extern void fftwf_destroy_plan(void* p); + + +#define FFTW_FORWARD (-1) +#define FFTW_BACKWARD (+1) +#define FFTW_ESTIMATE (1U << 6) +} + diff --git a/libraries/timefrequency/interface.cpp b/libraries/timefrequency/interface.cpp new file mode 100644 index 00000000000..d0332b70828 --- /dev/null +++ b/libraries/timefrequency/interface.cpp @@ -0,0 +1,221 @@ +#include "wavelet_spectrum_analyzer.h" + +using namespace TIMEFREQUENCYLIB; + +#define P_INPUT_DATA 0 +#define P_SAMPLING_RATE 1 +#define P_FREQ_INTERVAL 2 +#define P_FREQ_COUNT 3 +#define P_CYCLE_COUNT 4 +#define P_SUPERRESOLUTION 5 +#define P_MULTIPLICATIVE 6 +#define P_FRACTIONAL 7 + + +bool is_integer(double x) +{ + return x - (long long)x == 0; +} + +int mxGetSize(mxArray* arr) +{ + return arr + ? (int)(mxGetM(arr) * mxGetN(arr)) + : 0; +} + + +void validate_params(int nrhs, mxArray** prhs) +{ + // check params + if (nrhs < 6) + mexErrMsgTxt("Parameter count not met! faslt expects at least 6 parameters! See below...\n \ + 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ + 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ + 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ + 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ + 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ + 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ + 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ + 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); + if (nrhs > 8) + mexErrMsgTxt("Parameter count exceeded! faslt expects at most 8 parameters! See below...\n \ + 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ + 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ + 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ + 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ + 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ + 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ + 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ + 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); + + // check data + if (!mxIsDouble(prhs[P_INPUT_DATA])) + mexErrMsgTxt("input_data needs to be a real-valued (double) matrix"); + + // check input size + if (!mxGetN(prhs[P_INPUT_DATA]) == 1) + mexErrMsgTxt("input_data is a column vector. faslt only accepts row vectors."); + + // check FS + if (mxGetScalar(prhs[P_SAMPLING_RATE]) <= 0.0) + mexErrMsgTxt("sampling_rate needs to be a positive non-zero scalar representing the sampling frequency of the input in Hz"); + + // check freq interval + if (!mxIsDouble(prhs[P_FREQ_INTERVAL]) || mxGetSize(prhs[P_FREQ_INTERVAL]) != 2) + mexErrMsgTxt("frequency_interval needs to be a tuple containing the lower and upper frequency bounds in Hz"); + else + { + double lower = mxGetPr(prhs[P_FREQ_INTERVAL])[0]; + double upper = mxGetPr(prhs[P_FREQ_INTERVAL])[1]; + double fs = mxGetScalar(prhs[P_SAMPLING_RATE]); + + if (lower <= 0 || lower >= fs / 2 || + upper <= 0 || upper >= fs / 2) + mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); + } + + // check frequency count + if (!is_integer(mxGetScalar(prhs[P_FREQ_COUNT])) || mxGetScalar(prhs[P_FREQ_COUNT]) <= 0) + mexErrMsgTxt("frequency_count needs to be a positive non-zero integer"); + + // check cycle count + if (mxGetScalar(prhs[P_CYCLE_COUNT]) <= 0.0) + mexErrMsgTxt("cycle_count needs to be a positive non-zero scalar representing the number of cycles of the shortest wavelets"); + + // check resolution + if (!mxIsDouble(prhs[P_SUPERRESOLUTION]) || mxGetSize(prhs[P_SUPERRESOLUTION]) != 2) + mexErrMsgTxt("superresolution needs to be a tuple containing the lower and upper frequency bounds in Hz"); + else + { + if (mxGetPr(prhs[P_SUPERRESOLUTION])[0] <= 0 || mxGetPr(prhs[P_SUPERRESOLUTION])[1] <= 0) + mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); + } + + // check multiplicative + if (nrhs > P_MULTIPLICATIVE && mxGetSize(prhs[P_MULTIPLICATIVE]) != 1) + mexErrMsgTxt("multiplicative needs to be a scalar (0 - false, !0 otherwise)"); + + // check fractional + if (nrhs > P_FRACTIONAL && mxGetSize(prhs[P_FRACTIONAL]) != 1) + mexErrMsgTxt("fractional needs to be a scalar (0 - false, !0 otherwise)"); +} + + + +void print_settings(wavelet_analyzer_settings& set) +{ + mexPrintf("wavelet_analyzer_settings:\n\ + sampling_rate: %f\n\ + freq_low: %f\n\ + freq_high: %f\n\ + freq_count: %d\n\ + input_size: %d\n\ + wavelet_cycles: %f\n\ + resolution_low: %f\n\ + resolution_high: %f\n\ + multiplicative: %s\n\ + fractional: %s\n", + set.sampling_rate, + set.freq_low, + set.freq_high, + set.freq_count, + set.input_size, + set.wavelet_cycles, + set.resolution_low, + set.resolution_high, + set.multiplicative ? "true" : "false", + set.fractional ? "true" : "false"); +} + + +void __declspec(dllexport) mexFunction(int nlhs, mxArray** plhs, int nrhs, mxArray** prhs) +{ + // Parameter Name - Parameter Type - Description + // + // input_data - Scalar Matrix - Input buffers (row major) - each row is a trial + // sampling_rate - Scalar Number - The sampling frequency in Hz + // frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency + // frequency_count - Integer Number - the number of frequency bins in the interval + // cycle_count - Scalar Number - the number of cycles of the shortest wavelets + // superresolution_order - Scalar Vector - tuple containing the lowest and the highest superresolution orders + // multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true) + // fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true) + // + //Return values + // S - Scalar Matrix - A matrix of size length(frequencies) x size(input_data, 2) + + validate_params(nrhs, prhs); + + // read parameters + wavelet_analyzer_settings set; + + // input dimensions + int input_count = (int)mxGetM(prhs[P_INPUT_DATA]); + set.input_size = (int)mxGetN(prhs[P_INPUT_DATA]); + + // sampling rate + set.sampling_rate = (float)mxGetScalar(prhs[P_SAMPLING_RATE]); + + // frequencies + set.freq_low = (float)mxGetPr(prhs[P_FREQ_INTERVAL])[0]; + set.freq_high = (float)mxGetPr(prhs[P_FREQ_INTERVAL])[1]; + set.freq_count = (int)mxGetScalar(prhs[P_FREQ_COUNT]); + + // res order + set.wavelet_cycles = (float)mxGetScalar(prhs[P_CYCLE_COUNT]); + set.resolution_low = (float)mxGetPr(prhs[P_SUPERRESOLUTION])[0]; + set.resolution_high = (float)mxGetPr(prhs[P_SUPERRESOLUTION])[1]; + + // flags + set.multiplicative = nrhs > P_MULTIPLICATIVE ? (bool)mxGetScalar(prhs[P_MULTIPLICATIVE]) : true; + set.fractional = nrhs > P_FRACTIONAL ? (bool)mxGetScalar(prhs[P_FRACTIONAL]) : true; + + // create output + nlhs = 1; + plhs[0] = mxCreateDoubleMatrix(set.freq_count, set.input_size, mxREAL); + + // alloc temporary buffers (for float conversion and IO) + float *flt_input_data = static_cast(mxCalloc(set.input_size, sizeof(float))); + float *flt_result = static_cast(mxCalloc(size_t(set.freq_count) * set.input_size, sizeof(float))); + double* in_ptr = mxGetPr(prhs[P_INPUT_DATA]); + double* out_ptr = mxGetPr(plhs[0]); + + // check buffers + if (!flt_input_data || !flt_result) + { + mexErrMsgTxt("Internal error!"); + return; + } + + // create analyzer + wavelet_spectrum_analyzer anl(set); + + // perform analysis + for (int i = 0; i < input_count; ++i) + { + for (int j = 0; j < set.input_size; ++j) + flt_input_data[j] = (float)in_ptr[i + j * input_count]; + + anl.analyze(flt_input_data, flt_result); + } + + // normalize and copy output + double idiv = 1.0 / input_count; + for (int i = 0; i < set.freq_count; ++i) + { + for (int j = 0; j < set.input_size; ++j) + { + out_ptr[i + j * set.freq_count] = flt_result[i * set.input_size + j] * idiv; + } + } + + mxFree(flt_input_data); + mxFree(flt_result); +} + + + + + + diff --git a/libraries/timefrequency/lib/libfftw3f-3.def b/libraries/timefrequency/lib/libfftw3f-3.def new file mode 100644 index 00000000000..d61a2c36c76 --- /dev/null +++ b/libraries/timefrequency/lib/libfftw3f-3.def @@ -0,0 +1,1017 @@ +LIBRARY libfftw3f-3.dll +EXPORTS +fftwf_alignment_of +fftwf_alloc_complex +fftwf_alloc_real +fftwf_assertion_failed +fftwf_bufdist +fftwf_check_alignment_of_sse2_pm +fftwf_choose_radix +fftwf_cleanup +fftwf_cleanup_threads +fftwf_codelet_e01_8 +fftwf_codelet_e10_8 +fftwf_codelet_hb_10 +fftwf_codelet_hb_12 +fftwf_codelet_hb_15 +fftwf_codelet_hb_16 +fftwf_codelet_hb_2 +fftwf_codelet_hb_20 +fftwf_codelet_hb2_16 +fftwf_codelet_hb2_20 +fftwf_codelet_hb2_25 +fftwf_codelet_hb2_32 +fftwf_codelet_hb2_4 +fftwf_codelet_hb_25 +fftwf_codelet_hb2_5 +fftwf_codelet_hb2_8 +fftwf_codelet_hb_3 +fftwf_codelet_hb_32 +fftwf_codelet_hb_4 +fftwf_codelet_hb_5 +fftwf_codelet_hb_6 +fftwf_codelet_hb_64 +fftwf_codelet_hb_7 +fftwf_codelet_hb_8 +fftwf_codelet_hb_9 +fftwf_codelet_hc2cb_10 +fftwf_codelet_hc2cb_12 +fftwf_codelet_hc2cb_16 +fftwf_codelet_hc2cb_2 +fftwf_codelet_hc2cb_20 +fftwf_codelet_hc2cb2_16 +fftwf_codelet_hc2cb2_20 +fftwf_codelet_hc2cb2_32 +fftwf_codelet_hc2cb2_4 +fftwf_codelet_hc2cb2_8 +fftwf_codelet_hc2cb_32 +fftwf_codelet_hc2cb_4 +fftwf_codelet_hc2cb_6 +fftwf_codelet_hc2cb_8 +fftwf_codelet_hc2cbdft_10 +fftwf_codelet_hc2cbdft_12 +fftwf_codelet_hc2cbdft_16 +fftwf_codelet_hc2cbdft_2 +fftwf_codelet_hc2cbdft_20 +fftwf_codelet_hc2cbdft2_16 +fftwf_codelet_hc2cbdft2_20 +fftwf_codelet_hc2cbdft2_32 +fftwf_codelet_hc2cbdft2_4 +fftwf_codelet_hc2cbdft2_8 +fftwf_codelet_hc2cbdft_32 +fftwf_codelet_hc2cbdft_4 +fftwf_codelet_hc2cbdft_6 +fftwf_codelet_hc2cbdft_8 +fftwf_codelet_hc2cbdftv_10_avx +fftwf_codelet_hc2cbdftv_10_sse2 +fftwf_codelet_hc2cbdftv_12_avx +fftwf_codelet_hc2cbdftv_12_sse2 +fftwf_codelet_hc2cbdftv_16_avx +fftwf_codelet_hc2cbdftv_16_sse2 +fftwf_codelet_hc2cbdftv_20_avx +fftwf_codelet_hc2cbdftv_20_sse2 +fftwf_codelet_hc2cbdftv_2_avx +fftwf_codelet_hc2cbdftv_2_sse2 +fftwf_codelet_hc2cbdftv_32_avx +fftwf_codelet_hc2cbdftv_32_sse2 +fftwf_codelet_hc2cbdftv_4_avx +fftwf_codelet_hc2cbdftv_4_sse2 +fftwf_codelet_hc2cbdftv_6_avx +fftwf_codelet_hc2cbdftv_6_sse2 +fftwf_codelet_hc2cbdftv_8_avx +fftwf_codelet_hc2cbdftv_8_sse2 +fftwf_codelet_hc2cf_10 +fftwf_codelet_hc2cf_12 +fftwf_codelet_hc2cf_16 +fftwf_codelet_hc2cf_2 +fftwf_codelet_hc2cf_20 +fftwf_codelet_hc2cf2_16 +fftwf_codelet_hc2cf2_20 +fftwf_codelet_hc2cf2_32 +fftwf_codelet_hc2cf2_4 +fftwf_codelet_hc2cf2_8 +fftwf_codelet_hc2cf_32 +fftwf_codelet_hc2cf_4 +fftwf_codelet_hc2cf_6 +fftwf_codelet_hc2cf_8 +fftwf_codelet_hc2cfdft_10 +fftwf_codelet_hc2cfdft_12 +fftwf_codelet_hc2cfdft_16 +fftwf_codelet_hc2cfdft_2 +fftwf_codelet_hc2cfdft_20 +fftwf_codelet_hc2cfdft2_16 +fftwf_codelet_hc2cfdft2_20 +fftwf_codelet_hc2cfdft2_32 +fftwf_codelet_hc2cfdft2_4 +fftwf_codelet_hc2cfdft2_8 +fftwf_codelet_hc2cfdft_32 +fftwf_codelet_hc2cfdft_4 +fftwf_codelet_hc2cfdft_6 +fftwf_codelet_hc2cfdft_8 +fftwf_codelet_hc2cfdftv_10_avx +fftwf_codelet_hc2cfdftv_10_sse2 +fftwf_codelet_hc2cfdftv_12_avx +fftwf_codelet_hc2cfdftv_12_sse2 +fftwf_codelet_hc2cfdftv_16_avx +fftwf_codelet_hc2cfdftv_16_sse2 +fftwf_codelet_hc2cfdftv_20_avx +fftwf_codelet_hc2cfdftv_20_sse2 +fftwf_codelet_hc2cfdftv_2_avx +fftwf_codelet_hc2cfdftv_2_sse2 +fftwf_codelet_hc2cfdftv_32_avx +fftwf_codelet_hc2cfdftv_32_sse2 +fftwf_codelet_hc2cfdftv_4_avx +fftwf_codelet_hc2cfdftv_4_sse2 +fftwf_codelet_hc2cfdftv_6_avx +fftwf_codelet_hc2cfdftv_6_sse2 +fftwf_codelet_hc2cfdftv_8_avx +fftwf_codelet_hc2cfdftv_8_sse2 +fftwf_codelet_hf_10 +fftwf_codelet_hf_12 +fftwf_codelet_hf_15 +fftwf_codelet_hf_16 +fftwf_codelet_hf_2 +fftwf_codelet_hf_20 +fftwf_codelet_hf2_16 +fftwf_codelet_hf2_20 +fftwf_codelet_hf2_25 +fftwf_codelet_hf2_32 +fftwf_codelet_hf2_4 +fftwf_codelet_hf_25 +fftwf_codelet_hf2_5 +fftwf_codelet_hf2_8 +fftwf_codelet_hf_3 +fftwf_codelet_hf_32 +fftwf_codelet_hf_4 +fftwf_codelet_hf_5 +fftwf_codelet_hf_6 +fftwf_codelet_hf_64 +fftwf_codelet_hf_7 +fftwf_codelet_hf_8 +fftwf_codelet_hf_9 +fftwf_codelet_n1_10 +fftwf_codelet_n1_11 +fftwf_codelet_n1_12 +fftwf_codelet_n1_13 +fftwf_codelet_n1_14 +fftwf_codelet_n1_15 +fftwf_codelet_n1_16 +fftwf_codelet_n1_2 +fftwf_codelet_n1_20 +fftwf_codelet_n1_25 +fftwf_codelet_n1_3 +fftwf_codelet_n1_32 +fftwf_codelet_n1_4 +fftwf_codelet_n1_5 +fftwf_codelet_n1_6 +fftwf_codelet_n1_64 +fftwf_codelet_n1_7 +fftwf_codelet_n1_8 +fftwf_codelet_n1_9 +fftwf_codelet_n1bv_10_avx +fftwf_codelet_n1bv_10_sse2 +fftwf_codelet_n1bv_11_avx +fftwf_codelet_n1bv_11_sse2 +fftwf_codelet_n1bv_128_avx +fftwf_codelet_n1bv_128_sse2 +fftwf_codelet_n1bv_12_avx +fftwf_codelet_n1bv_12_sse2 +fftwf_codelet_n1bv_13_avx +fftwf_codelet_n1bv_13_sse2 +fftwf_codelet_n1bv_14_avx +fftwf_codelet_n1bv_14_sse2 +fftwf_codelet_n1bv_15_avx +fftwf_codelet_n1bv_15_sse2 +fftwf_codelet_n1bv_16_avx +fftwf_codelet_n1bv_16_sse2 +fftwf_codelet_n1bv_20_avx +fftwf_codelet_n1bv_20_sse2 +fftwf_codelet_n1bv_25_avx +fftwf_codelet_n1bv_25_sse2 +fftwf_codelet_n1bv_2_avx +fftwf_codelet_n1bv_2_sse2 +fftwf_codelet_n1bv_32_avx +fftwf_codelet_n1bv_32_sse2 +fftwf_codelet_n1bv_3_avx +fftwf_codelet_n1bv_3_sse2 +fftwf_codelet_n1bv_4_avx +fftwf_codelet_n1bv_4_sse2 +fftwf_codelet_n1bv_5_avx +fftwf_codelet_n1bv_5_sse2 +fftwf_codelet_n1bv_64_avx +fftwf_codelet_n1bv_64_sse2 +fftwf_codelet_n1bv_6_avx +fftwf_codelet_n1bv_6_sse2 +fftwf_codelet_n1bv_7_avx +fftwf_codelet_n1bv_7_sse2 +fftwf_codelet_n1bv_8_avx +fftwf_codelet_n1bv_8_sse2 +fftwf_codelet_n1bv_9_avx +fftwf_codelet_n1bv_9_sse2 +fftwf_codelet_n1fv_10_avx +fftwf_codelet_n1fv_10_sse2 +fftwf_codelet_n1fv_11_avx +fftwf_codelet_n1fv_11_sse2 +fftwf_codelet_n1fv_128_avx +fftwf_codelet_n1fv_128_sse2 +fftwf_codelet_n1fv_12_avx +fftwf_codelet_n1fv_12_sse2 +fftwf_codelet_n1fv_13_avx +fftwf_codelet_n1fv_13_sse2 +fftwf_codelet_n1fv_14_avx +fftwf_codelet_n1fv_14_sse2 +fftwf_codelet_n1fv_15_avx +fftwf_codelet_n1fv_15_sse2 +fftwf_codelet_n1fv_16_avx +fftwf_codelet_n1fv_16_sse2 +fftwf_codelet_n1fv_20_avx +fftwf_codelet_n1fv_20_sse2 +fftwf_codelet_n1fv_25_avx +fftwf_codelet_n1fv_25_sse2 +fftwf_codelet_n1fv_2_avx +fftwf_codelet_n1fv_2_sse2 +fftwf_codelet_n1fv_32_avx +fftwf_codelet_n1fv_32_sse2 +fftwf_codelet_n1fv_3_avx +fftwf_codelet_n1fv_3_sse2 +fftwf_codelet_n1fv_4_avx +fftwf_codelet_n1fv_4_sse2 +fftwf_codelet_n1fv_5_avx +fftwf_codelet_n1fv_5_sse2 +fftwf_codelet_n1fv_64_avx +fftwf_codelet_n1fv_64_sse2 +fftwf_codelet_n1fv_6_avx +fftwf_codelet_n1fv_6_sse2 +fftwf_codelet_n1fv_7_avx +fftwf_codelet_n1fv_7_sse2 +fftwf_codelet_n1fv_8_avx +fftwf_codelet_n1fv_8_sse2 +fftwf_codelet_n1fv_9_avx +fftwf_codelet_n1fv_9_sse2 +fftwf_codelet_n2bv_10_avx +fftwf_codelet_n2bv_10_sse2 +fftwf_codelet_n2bv_12_avx +fftwf_codelet_n2bv_12_sse2 +fftwf_codelet_n2bv_14_avx +fftwf_codelet_n2bv_14_sse2 +fftwf_codelet_n2bv_16_avx +fftwf_codelet_n2bv_16_sse2 +fftwf_codelet_n2bv_20_avx +fftwf_codelet_n2bv_20_sse2 +fftwf_codelet_n2bv_2_avx +fftwf_codelet_n2bv_2_sse2 +fftwf_codelet_n2bv_32_avx +fftwf_codelet_n2bv_32_sse2 +fftwf_codelet_n2bv_4_avx +fftwf_codelet_n2bv_4_sse2 +fftwf_codelet_n2bv_64_avx +fftwf_codelet_n2bv_64_sse2 +fftwf_codelet_n2bv_6_avx +fftwf_codelet_n2bv_6_sse2 +fftwf_codelet_n2bv_8_avx +fftwf_codelet_n2bv_8_sse2 +fftwf_codelet_n2fv_10_avx +fftwf_codelet_n2fv_10_sse2 +fftwf_codelet_n2fv_12_avx +fftwf_codelet_n2fv_12_sse2 +fftwf_codelet_n2fv_14_avx +fftwf_codelet_n2fv_14_sse2 +fftwf_codelet_n2fv_16_avx +fftwf_codelet_n2fv_16_sse2 +fftwf_codelet_n2fv_20_avx +fftwf_codelet_n2fv_20_sse2 +fftwf_codelet_n2fv_2_avx +fftwf_codelet_n2fv_2_sse2 +fftwf_codelet_n2fv_32_avx +fftwf_codelet_n2fv_32_sse2 +fftwf_codelet_n2fv_4_avx +fftwf_codelet_n2fv_4_sse2 +fftwf_codelet_n2fv_64_avx +fftwf_codelet_n2fv_64_sse2 +fftwf_codelet_n2fv_6_avx +fftwf_codelet_n2fv_6_sse2 +fftwf_codelet_n2fv_8_avx +fftwf_codelet_n2fv_8_sse2 +fftwf_codelet_n2sv_16_avx +fftwf_codelet_n2sv_16_sse2 +fftwf_codelet_n2sv_32_avx +fftwf_codelet_n2sv_32_sse2 +fftwf_codelet_n2sv_4_avx +fftwf_codelet_n2sv_4_sse2 +fftwf_codelet_n2sv_64_avx +fftwf_codelet_n2sv_64_sse2 +fftwf_codelet_n2sv_8_avx +fftwf_codelet_n2sv_8_sse2 +fftwf_codelet_q1_2 +fftwf_codelet_q1_3 +fftwf_codelet_q1_4 +fftwf_codelet_q1_5 +fftwf_codelet_q1_6 +fftwf_codelet_q1_8 +fftwf_codelet_q1bv_2_avx +fftwf_codelet_q1bv_2_sse2 +fftwf_codelet_q1bv_4_avx +fftwf_codelet_q1bv_4_sse2 +fftwf_codelet_q1bv_5_avx +fftwf_codelet_q1bv_5_sse2 +fftwf_codelet_q1bv_8_avx +fftwf_codelet_q1bv_8_sse2 +fftwf_codelet_q1fv_2_avx +fftwf_codelet_q1fv_2_sse2 +fftwf_codelet_q1fv_4_avx +fftwf_codelet_q1fv_4_sse2 +fftwf_codelet_q1fv_5_avx +fftwf_codelet_q1fv_5_sse2 +fftwf_codelet_q1fv_8_avx +fftwf_codelet_q1fv_8_sse2 +fftwf_codelet_r2cb_10 +fftwf_codelet_r2cb_11 +fftwf_codelet_r2cb_12 +fftwf_codelet_r2cb_128 +fftwf_codelet_r2cb_13 +fftwf_codelet_r2cb_14 +fftwf_codelet_r2cb_15 +fftwf_codelet_r2cb_16 +fftwf_codelet_r2cb_2 +fftwf_codelet_r2cb_20 +fftwf_codelet_r2cb_25 +fftwf_codelet_r2cb_3 +fftwf_codelet_r2cb_32 +fftwf_codelet_r2cb_4 +fftwf_codelet_r2cb_5 +fftwf_codelet_r2cb_6 +fftwf_codelet_r2cb_64 +fftwf_codelet_r2cb_7 +fftwf_codelet_r2cb_8 +fftwf_codelet_r2cb_9 +fftwf_codelet_r2cbIII_10 +fftwf_codelet_r2cbIII_12 +fftwf_codelet_r2cbIII_15 +fftwf_codelet_r2cbIII_16 +fftwf_codelet_r2cbIII_2 +fftwf_codelet_r2cbIII_20 +fftwf_codelet_r2cbIII_25 +fftwf_codelet_r2cbIII_3 +fftwf_codelet_r2cbIII_32 +fftwf_codelet_r2cbIII_4 +fftwf_codelet_r2cbIII_5 +fftwf_codelet_r2cbIII_6 +fftwf_codelet_r2cbIII_64 +fftwf_codelet_r2cbIII_7 +fftwf_codelet_r2cbIII_8 +fftwf_codelet_r2cbIII_9 +fftwf_codelet_r2cf_10 +fftwf_codelet_r2cf_11 +fftwf_codelet_r2cf_12 +fftwf_codelet_r2cf_128 +fftwf_codelet_r2cf_13 +fftwf_codelet_r2cf_14 +fftwf_codelet_r2cf_15 +fftwf_codelet_r2cf_16 +fftwf_codelet_r2cf_2 +fftwf_codelet_r2cf_20 +fftwf_codelet_r2cf_25 +fftwf_codelet_r2cf_3 +fftwf_codelet_r2cf_32 +fftwf_codelet_r2cf_4 +fftwf_codelet_r2cf_5 +fftwf_codelet_r2cf_6 +fftwf_codelet_r2cf_64 +fftwf_codelet_r2cf_7 +fftwf_codelet_r2cf_8 +fftwf_codelet_r2cf_9 +fftwf_codelet_r2cfII_10 +fftwf_codelet_r2cfII_12 +fftwf_codelet_r2cfII_15 +fftwf_codelet_r2cfII_16 +fftwf_codelet_r2cfII_2 +fftwf_codelet_r2cfII_20 +fftwf_codelet_r2cfII_25 +fftwf_codelet_r2cfII_3 +fftwf_codelet_r2cfII_32 +fftwf_codelet_r2cfII_4 +fftwf_codelet_r2cfII_5 +fftwf_codelet_r2cfII_6 +fftwf_codelet_r2cfII_64 +fftwf_codelet_r2cfII_7 +fftwf_codelet_r2cfII_8 +fftwf_codelet_r2cfII_9 +fftwf_codelet_t1_10 +fftwf_codelet_t1_12 +fftwf_codelet_t1_15 +fftwf_codelet_t1_16 +fftwf_codelet_t1_2 +fftwf_codelet_t1_20 +fftwf_codelet_t1_25 +fftwf_codelet_t1_3 +fftwf_codelet_t1_32 +fftwf_codelet_t1_4 +fftwf_codelet_t1_5 +fftwf_codelet_t1_6 +fftwf_codelet_t1_64 +fftwf_codelet_t1_7 +fftwf_codelet_t1_8 +fftwf_codelet_t1_9 +fftwf_codelet_t1buv_10_avx +fftwf_codelet_t1buv_10_sse2 +fftwf_codelet_t1buv_2_avx +fftwf_codelet_t1buv_2_sse2 +fftwf_codelet_t1buv_3_avx +fftwf_codelet_t1buv_3_sse2 +fftwf_codelet_t1buv_4_avx +fftwf_codelet_t1buv_4_sse2 +fftwf_codelet_t1buv_5_avx +fftwf_codelet_t1buv_5_sse2 +fftwf_codelet_t1buv_6_avx +fftwf_codelet_t1buv_6_sse2 +fftwf_codelet_t1buv_7_avx +fftwf_codelet_t1buv_7_sse2 +fftwf_codelet_t1buv_8_avx +fftwf_codelet_t1buv_8_sse2 +fftwf_codelet_t1buv_9_avx +fftwf_codelet_t1buv_9_sse2 +fftwf_codelet_t1bv_10_avx +fftwf_codelet_t1bv_10_sse2 +fftwf_codelet_t1bv_12_avx +fftwf_codelet_t1bv_12_sse2 +fftwf_codelet_t1bv_15_avx +fftwf_codelet_t1bv_15_sse2 +fftwf_codelet_t1bv_16_avx +fftwf_codelet_t1bv_16_sse2 +fftwf_codelet_t1bv_20_avx +fftwf_codelet_t1bv_20_sse2 +fftwf_codelet_t1bv_25_avx +fftwf_codelet_t1bv_25_sse2 +fftwf_codelet_t1bv_2_avx +fftwf_codelet_t1bv_2_sse2 +fftwf_codelet_t1bv_32_avx +fftwf_codelet_t1bv_32_sse2 +fftwf_codelet_t1bv_3_avx +fftwf_codelet_t1bv_3_sse2 +fftwf_codelet_t1bv_4_avx +fftwf_codelet_t1bv_4_sse2 +fftwf_codelet_t1bv_5_avx +fftwf_codelet_t1bv_5_sse2 +fftwf_codelet_t1bv_64_avx +fftwf_codelet_t1bv_64_sse2 +fftwf_codelet_t1bv_6_avx +fftwf_codelet_t1bv_6_sse2 +fftwf_codelet_t1bv_7_avx +fftwf_codelet_t1bv_7_sse2 +fftwf_codelet_t1bv_8_avx +fftwf_codelet_t1bv_8_sse2 +fftwf_codelet_t1bv_9_avx +fftwf_codelet_t1bv_9_sse2 +fftwf_codelet_t1fuv_10_avx +fftwf_codelet_t1fuv_10_sse2 +fftwf_codelet_t1fuv_2_avx +fftwf_codelet_t1fuv_2_sse2 +fftwf_codelet_t1fuv_3_avx +fftwf_codelet_t1fuv_3_sse2 +fftwf_codelet_t1fuv_4_avx +fftwf_codelet_t1fuv_4_sse2 +fftwf_codelet_t1fuv_5_avx +fftwf_codelet_t1fuv_5_sse2 +fftwf_codelet_t1fuv_6_avx +fftwf_codelet_t1fuv_6_sse2 +fftwf_codelet_t1fuv_7_avx +fftwf_codelet_t1fuv_7_sse2 +fftwf_codelet_t1fuv_8_avx +fftwf_codelet_t1fuv_8_sse2 +fftwf_codelet_t1fuv_9_avx +fftwf_codelet_t1fuv_9_sse2 +fftwf_codelet_t1fv_10_avx +fftwf_codelet_t1fv_10_sse2 +fftwf_codelet_t1fv_12_avx +fftwf_codelet_t1fv_12_sse2 +fftwf_codelet_t1fv_15_avx +fftwf_codelet_t1fv_15_sse2 +fftwf_codelet_t1fv_16_avx +fftwf_codelet_t1fv_16_sse2 +fftwf_codelet_t1fv_20_avx +fftwf_codelet_t1fv_20_sse2 +fftwf_codelet_t1fv_25_avx +fftwf_codelet_t1fv_25_sse2 +fftwf_codelet_t1fv_2_avx +fftwf_codelet_t1fv_2_sse2 +fftwf_codelet_t1fv_32_avx +fftwf_codelet_t1fv_32_sse2 +fftwf_codelet_t1fv_3_avx +fftwf_codelet_t1fv_3_sse2 +fftwf_codelet_t1fv_4_avx +fftwf_codelet_t1fv_4_sse2 +fftwf_codelet_t1fv_5_avx +fftwf_codelet_t1fv_5_sse2 +fftwf_codelet_t1fv_64_avx +fftwf_codelet_t1fv_64_sse2 +fftwf_codelet_t1fv_6_avx +fftwf_codelet_t1fv_6_sse2 +fftwf_codelet_t1fv_7_avx +fftwf_codelet_t1fv_7_sse2 +fftwf_codelet_t1fv_8_avx +fftwf_codelet_t1fv_8_sse2 +fftwf_codelet_t1fv_9_avx +fftwf_codelet_t1fv_9_sse2 +fftwf_codelet_t1sv_16_avx +fftwf_codelet_t1sv_16_sse2 +fftwf_codelet_t1sv_2_avx +fftwf_codelet_t1sv_2_sse2 +fftwf_codelet_t1sv_32_avx +fftwf_codelet_t1sv_32_sse2 +fftwf_codelet_t1sv_4_avx +fftwf_codelet_t1sv_4_sse2 +fftwf_codelet_t1sv_8_avx +fftwf_codelet_t1sv_8_sse2 +fftwf_codelet_t2_10 +fftwf_codelet_t2_16 +fftwf_codelet_t2_20 +fftwf_codelet_t2_25 +fftwf_codelet_t2_32 +fftwf_codelet_t2_4 +fftwf_codelet_t2_5 +fftwf_codelet_t2_64 +fftwf_codelet_t2_8 +fftwf_codelet_t2bv_10_avx +fftwf_codelet_t2bv_10_sse2 +fftwf_codelet_t2bv_16_avx +fftwf_codelet_t2bv_16_sse2 +fftwf_codelet_t2bv_20_avx +fftwf_codelet_t2bv_20_sse2 +fftwf_codelet_t2bv_25_avx +fftwf_codelet_t2bv_25_sse2 +fftwf_codelet_t2bv_2_avx +fftwf_codelet_t2bv_2_sse2 +fftwf_codelet_t2bv_32_avx +fftwf_codelet_t2bv_32_sse2 +fftwf_codelet_t2bv_4_avx +fftwf_codelet_t2bv_4_sse2 +fftwf_codelet_t2bv_5_avx +fftwf_codelet_t2bv_5_sse2 +fftwf_codelet_t2bv_64_avx +fftwf_codelet_t2bv_64_sse2 +fftwf_codelet_t2bv_8_avx +fftwf_codelet_t2bv_8_sse2 +fftwf_codelet_t2fv_10_avx +fftwf_codelet_t2fv_10_sse2 +fftwf_codelet_t2fv_16_avx +fftwf_codelet_t2fv_16_sse2 +fftwf_codelet_t2fv_20_avx +fftwf_codelet_t2fv_20_sse2 +fftwf_codelet_t2fv_25_avx +fftwf_codelet_t2fv_25_sse2 +fftwf_codelet_t2fv_2_avx +fftwf_codelet_t2fv_2_sse2 +fftwf_codelet_t2fv_32_avx +fftwf_codelet_t2fv_32_sse2 +fftwf_codelet_t2fv_4_avx +fftwf_codelet_t2fv_4_sse2 +fftwf_codelet_t2fv_5_avx +fftwf_codelet_t2fv_5_sse2 +fftwf_codelet_t2fv_64_avx +fftwf_codelet_t2fv_64_sse2 +fftwf_codelet_t2fv_8_avx +fftwf_codelet_t2fv_8_sse2 +fftwf_codelet_t2sv_16_avx +fftwf_codelet_t2sv_16_sse2 +fftwf_codelet_t2sv_32_avx +fftwf_codelet_t2sv_32_sse2 +fftwf_codelet_t2sv_4_avx +fftwf_codelet_t2sv_4_sse2 +fftwf_codelet_t2sv_8_avx +fftwf_codelet_t2sv_8_sse2 +fftwf_codelet_t3bv_10_avx +fftwf_codelet_t3bv_10_sse2 +fftwf_codelet_t3bv_16_avx +fftwf_codelet_t3bv_16_sse2 +fftwf_codelet_t3bv_20_avx +fftwf_codelet_t3bv_20_sse2 +fftwf_codelet_t3bv_25_avx +fftwf_codelet_t3bv_25_sse2 +fftwf_codelet_t3bv_32_avx +fftwf_codelet_t3bv_32_sse2 +fftwf_codelet_t3bv_4_avx +fftwf_codelet_t3bv_4_sse2 +fftwf_codelet_t3bv_5_avx +fftwf_codelet_t3bv_5_sse2 +fftwf_codelet_t3bv_8_avx +fftwf_codelet_t3bv_8_sse2 +fftwf_codelet_t3fv_10_avx +fftwf_codelet_t3fv_10_sse2 +fftwf_codelet_t3fv_16_avx +fftwf_codelet_t3fv_16_sse2 +fftwf_codelet_t3fv_20_avx +fftwf_codelet_t3fv_20_sse2 +fftwf_codelet_t3fv_25_avx +fftwf_codelet_t3fv_25_sse2 +fftwf_codelet_t3fv_32_avx +fftwf_codelet_t3fv_32_sse2 +fftwf_codelet_t3fv_4_avx +fftwf_codelet_t3fv_4_sse2 +fftwf_codelet_t3fv_5_avx +fftwf_codelet_t3fv_5_sse2 +fftwf_codelet_t3fv_8_avx +fftwf_codelet_t3fv_8_sse2 +fftwf_compute_tilesz +fftwf_configure_planner +fftwf_cost +fftwf_cpy1d +fftwf_cpy2d +fftwf_cpy2d_ci +fftwf_cpy2d_co +fftwf_cpy2d_pair +fftwf_cpy2d_pair_ci +fftwf_cpy2d_pair_co +fftwf_cpy2d_tiled +fftwf_cpy2d_tiledbuf +fftwf_ct_applicable +fftwf_ct_genericbuf_register +fftwf_ct_generic_register +fftwf_ct_uglyp +fftwf_destroy_plan +fftwf_dft_bluestein_register +fftwf_dft_buffered_register +fftwf_dft_conf_standard +fftwf_dft_generic_register +fftwf_dft_indirect_register +fftwf_dft_indirect_transpose_register +fftwf_dft_nop_register +fftwf_dft_r2hc_register +fftwf_dft_rader_register +fftwf_dft_rank_geq2_register +fftwf_dft_solve +fftwf_dft_thr_vrank_geq1_register +fftwf_dft_vrank_geq1_register +fftwf_dft_zerotens +fftwf_dht_r2hc_register +fftwf_dht_rader_register +fftwf_dimcmp +fftwf_elapsed_since +fftwf_estimate_cost +fftwf_execute +fftwf_execute_dft +fftwf_execute_dft_c2r +fftwf_execute_dft_r2c +fftwf_execute_r2r +fftwf_execute_split_dft +fftwf_execute_split_dft_c2r +fftwf_execute_split_dft_r2c +fftwf_export_wisdom +fftwf_export_wisdom_to_file +fftwf_export_wisdom_to_filename +fftwf_export_wisdom_to_string +fftwf_extract_reim +fftwf_factors_into +fftwf_factors_into_small_primes +fftwf_find_generator +fftwf_first_divisor +fftwf_flops +fftwf_forget_wisdom +fftwf_fprint_plan +fftwf_free +fftwf_get_crude_time +fftwf_guru64_kosherp +fftwf_guru_kosherp +fftwf_hash +fftwf_have_simd_avx +fftwf_have_simd_sse2 +fftwf_hc2hc_applicable +fftwf_hc2hc_generic_register +fftwf_iabs +fftwf_ialignment_of +fftwf_iestimate_cost +fftwf_ifree +fftwf_ifree0 +fftwf_imax +fftwf_imin +fftwf_import_system_wisdom +fftwf_import_wisdom +fftwf_import_wisdom_from_file +fftwf_import_wisdom_from_filename +fftwf_import_wisdom_from_string +fftwf_init_threads +fftwf_is_prime +fftwf_isqrt +fftwf_ithreads_init +fftwf_join_taint +fftwf_kdft_dif_register +fftwf_kdft_difsq_register +fftwf_kdft_dit_register +fftwf_kdft_register +fftwf_kernel_free +fftwf_kernel_malloc +fftwf_khc2c_register +fftwf_khc2hc_register +fftwf_kr2c_register +fftwf_kr2r_register +fftwf_make_planner_thread_safe +fftwf_malloc +fftwf_malloc_plain +fftwf_many_kosherp +fftwf_mapflags +fftwf_map_r2r_kind +fftwf_md5begin +fftwf_md5end +fftwf_md5int +fftwf_md5INT +fftwf_md5putb +fftwf_md5putc +fftwf_md5puts +fftwf_md5unsigned +fftwf_measure_execution_time +fftwf_mkapiplan +fftwf_mkplan +fftwf_mkplan_d +fftwf_mkplan_dft +fftwf_mkplan_dftw +fftwf_mkplan_f_d +fftwf_mkplan_hc2c +fftwf_mkplan_hc2hc +fftwf_mkplanner +fftwf_mkplan_rdft +fftwf_mkplan_rdft2 +fftwf_mkprinter +fftwf_mkprinter_cnt +fftwf_mkprinter_file +fftwf_mkprinter_str +fftwf_mkproblem +fftwf_mkproblem_dft +fftwf_mkproblem_dft_d +fftwf_mkproblem_rdft +fftwf_mkproblem_rdft_0_d +fftwf_mkproblem_rdft_1 +fftwf_mkproblem_rdft_1_d +fftwf_mkproblem_rdft2 +fftwf_mkproblem_rdft2_d +fftwf_mkproblem_rdft2_d_3pointers +fftwf_mkproblem_rdft_d +fftwf_mkproblem_unsolvable +fftwf_mkscanner +fftwf_mksolver +fftwf_mksolver_ct +fftwf_mksolver_ct_threads +fftwf_mksolver_dft_direct +fftwf_mksolver_dft_directbuf +fftwf_mksolver_hc2c +fftwf_mksolver_hc2hc +fftwf_mksolver_hc2hc_threads +fftwf_mksolver_rdft2_direct +fftwf_mksolver_rdft_r2c_direct +fftwf_mksolver_rdft_r2c_directbuf +fftwf_mksolver_rdft_r2r_direct +fftwf_mkstride +fftwf_mktensor +fftwf_mktensor_0d +fftwf_mktensor_1d +fftwf_mktensor_2d +fftwf_mktensor_3d +fftwf_mktensor_4d +fftwf_mktensor_5d +fftwf_mktensor_iodims +fftwf_mktensor_iodims64 +fftwf_mktensor_rowmajor +fftwf_mktriggen +fftwf_modulo +fftwf_nbuf +fftwf_nbuf_redundant +fftwf_next_prime +fftwf_null_awake +fftwf_ops_add +fftwf_ops_add2 +fftwf_ops_cpy +fftwf_ops_madd +fftwf_ops_madd2 +fftwf_ops_other +fftwf_ops_zero +fftwf_pickdim +fftwf_plan_awake +fftwf_plan_destroy_internal +fftwf_plan_dft +fftwf_plan_dft_1d +fftwf_plan_dft_2d +fftwf_plan_dft_3d +fftwf_plan_dft_c2r +fftwf_plan_dft_c2r_1d +fftwf_plan_dft_c2r_2d +fftwf_plan_dft_c2r_3d +fftwf_plan_dft_r2c +fftwf_plan_dft_r2c_1d +fftwf_plan_dft_r2c_2d +fftwf_plan_dft_r2c_3d +fftwf_plan_guru64_dft +fftwf_plan_guru64_dft_c2r +fftwf_plan_guru64_dft_r2c +fftwf_plan_guru64_r2r +fftwf_plan_guru64_split_dft +fftwf_plan_guru64_split_dft_c2r +fftwf_plan_guru64_split_dft_r2c +fftwf_plan_guru_dft +fftwf_plan_guru_dft_c2r +fftwf_plan_guru_dft_r2c +fftwf_plan_guru_r2r +fftwf_plan_guru_split_dft +fftwf_plan_guru_split_dft_c2r +fftwf_plan_guru_split_dft_r2c +fftwf_plan_many_dft +fftwf_plan_many_dft_c2r +fftwf_plan_many_dft_r2c +fftwf_plan_many_r2r +fftwf_planner_destroy +fftwf_plan_null_destroy +fftwf_plan_r2r +fftwf_plan_r2r_1d +fftwf_plan_r2r_2d +fftwf_plan_r2r_3d +fftwf_plan_with_nthreads +fftwf_power_mod +fftwf_printer_destroy +fftwf_print_plan +fftwf_problem_destroy +fftwf_rader_tl_delete +fftwf_rader_tl_find +fftwf_rader_tl_insert +fftwf_rdft2_buffered_register +fftwf_rdft2_complex_n +fftwf_rdft2_inplace_strides +fftwf_rdft2_nop_register +fftwf_rdft2_pad +fftwf_rdft2_rank0_register +fftwf_rdft2_rank_geq2_register +fftwf_rdft2_rdft_register +fftwf_rdft2_solve +fftwf_rdft2_strides +fftwf_rdft2_tensor_max_index +fftwf_rdft2_thr_vrank_geq1_register +fftwf_rdft2_vrank_geq1_register +fftwf_rdft_buffered_register +fftwf_rdft_conf_standard +fftwf_rdft_dht_register +fftwf_rdft_generic_register +fftwf_rdft_indirect_register +fftwf_rdft_kind_str +fftwf_rdft_nop_register +fftwf_rdft_rank0_register +fftwf_rdft_rank_geq2_register +fftwf_rdft_solve +fftwf_rdft_thr_vrank_geq1_register +fftwf_rdft_vrank3_transpose_register +fftwf_rdft_vrank_geq1_register +fftwf_rdft_zerotens +fftwf_redft00e_r2hc_pad_register +fftwf_regsolver_ct_directw +fftwf_regsolver_ct_directwsq +fftwf_regsolver_hc2c_direct +fftwf_regsolver_hc2hc_direct +fftwf_reodft00e_splitradix_register +fftwf_reodft010e_r2hc_register +fftwf_reodft11e_r2hc_odd_register +fftwf_reodft11e_radix2_r2hc_register +fftwf_reodft_conf_standard +fftwf_rodft00e_r2hc_pad_register +fftwf_safe_mulmod +fftwf_scanner_destroy +fftwf_set_planner_hooks +fftwf_set_timelimit +fftwf_solver_destroy +fftwf_solver_register +fftwf_solver_use +fftwf_solvtab_exec +fftwf_spawn_loop +fftwf_sprint_plan +fftwf_stride_destroy +fftwf_taint +fftwf_tensor_append +fftwf_tensor_compress +fftwf_tensor_compress_contiguous +fftwf_tensor_copy +fftwf_tensor_copy_except +fftwf_tensor_copy_inplace +fftwf_tensor_copy_sub +fftwf_tensor_destroy +fftwf_tensor_destroy2 +fftwf_tensor_destroy4 +fftwf_tensor_equal +fftwf_tensor_inplace_locations +fftwf_tensor_inplace_strides +fftwf_tensor_inplace_strides2 +fftwf_tensor_kosherp +fftwf_tensor_max_index +fftwf_tensor_md5 +fftwf_tensor_min_istride +fftwf_tensor_min_ostride +fftwf_tensor_min_stride +fftwf_tensor_print +fftwf_tensor_split +fftwf_tensor_strides_decrease +fftwf_tensor_sz +fftwf_tensor_tornk1 +fftwf_the_planner +fftwf_threads_cleanup +fftwf_threads_conf_standard +fftwf_threads_register_planner_hooks +fftwf_tile2d +fftwf_toobig +fftwf_transpose +fftwf_transpose_tiled +fftwf_transpose_tiledbuf +fftwf_triggen_destroy +fftwf_twiddle_awake +fftwf_twiddle_length +fftwf_zero1d_pair +sfftw_cleanup_ +sfftw_cleanup__ +sfftw_cleanup_threads_ +sfftw_cleanup_threads__ +sfftw_cost_ +sfftw_cost__ +sfftw_destroy_plan_ +sfftw_destroy_plan__ +sfftw_estimate_cost_ +sfftw_estimate_cost__ +sfftw_execute_ +sfftw_execute__ +sfftw_execute_dft_ +sfftw_execute_dft__ +sfftw_execute_dft_c2r_ +sfftw_execute_dft_c2r__ +sfftw_execute_dft_r2c_ +sfftw_execute_dft_r2c__ +sfftw_execute_r2r_ +sfftw_execute_r2r__ +sfftw_execute_split_dft_ +sfftw_execute_split_dft__ +sfftw_execute_split_dft_c2r_ +sfftw_execute_split_dft_c2r__ +sfftw_execute_split_dft_r2c_ +sfftw_execute_split_dft_r2c__ +sfftw_export_wisdom_ +sfftw_export_wisdom__ +sfftw_flops_ +sfftw_flops__ +sfftw_forget_wisdom_ +sfftw_forget_wisdom__ +sfftw_import_system_wisdom_ +sfftw_import_system_wisdom__ +sfftw_import_wisdom_ +sfftw_import_wisdom__ +sfftw_init_threads_ +sfftw_init_threads__ +sfftw_plan_dft_ +sfftw_plan_dft__ +sfftw_plan_dft_1d_ +sfftw_plan_dft_1d__ +sfftw_plan_dft_2d_ +sfftw_plan_dft_2d__ +sfftw_plan_dft_3d_ +sfftw_plan_dft_3d__ +sfftw_plan_dft_c2r_ +sfftw_plan_dft_c2r__ +sfftw_plan_dft_c2r_1d_ +sfftw_plan_dft_c2r_1d__ +sfftw_plan_dft_c2r_2d_ +sfftw_plan_dft_c2r_2d__ +sfftw_plan_dft_c2r_3d_ +sfftw_plan_dft_c2r_3d__ +sfftw_plan_dft_r2c_ +sfftw_plan_dft_r2c__ +sfftw_plan_dft_r2c_1d_ +sfftw_plan_dft_r2c_1d__ +sfftw_plan_dft_r2c_2d_ +sfftw_plan_dft_r2c_2d__ +sfftw_plan_dft_r2c_3d_ +sfftw_plan_dft_r2c_3d__ +sfftw_plan_guru_dft_ +sfftw_plan_guru_dft__ +sfftw_plan_guru_dft_c2r_ +sfftw_plan_guru_dft_c2r__ +sfftw_plan_guru_dft_r2c_ +sfftw_plan_guru_dft_r2c__ +sfftw_plan_guru_r2r_ +sfftw_plan_guru_r2r__ +sfftw_plan_guru_split_dft_ +sfftw_plan_guru_split_dft__ +sfftw_plan_guru_split_dft_c2r_ +sfftw_plan_guru_split_dft_c2r__ +sfftw_plan_guru_split_dft_r2c_ +sfftw_plan_guru_split_dft_r2c__ +sfftw_plan_many_dft_ +sfftw_plan_many_dft__ +sfftw_plan_many_dft_c2r_ +sfftw_plan_many_dft_c2r__ +sfftw_plan_many_dft_r2c_ +sfftw_plan_many_dft_r2c__ +sfftw_plan_many_r2r_ +sfftw_plan_many_r2r__ +sfftw_plan_r2r_ +sfftw_plan_r2r__ +sfftw_plan_r2r_1d_ +sfftw_plan_r2r_1d__ +sfftw_plan_r2r_2d_ +sfftw_plan_r2r_2d__ +sfftw_plan_r2r_3d_ +sfftw_plan_r2r_3d__ +sfftw_plan_with_nthreads_ +sfftw_plan_with_nthreads__ +sfftw_print_plan_ +sfftw_print_plan__ +sfftw_set_timelimit_ +sfftw_set_timelimit__ diff --git a/libraries/timefrequency/morlet.h b/libraries/timefrequency/morlet.h new file mode 100644 index 00000000000..d465e070db3 --- /dev/null +++ b/libraries/timefrequency/morlet.h @@ -0,0 +1,72 @@ +#pragma once +#include +#include +#include + +namespace TIMEFREQUENCYLIB { + +static float morlet_SD_factor = 2.5f; +static float morlet_SD_spread = 6; +static float pi_f = 3.14159265359f; + +class morlet +{ +public: + morlet(float center_freq, float cycle_count, float sampling_rate) + { + float SD = (cycle_count / 2) * (1 / center_freq) / morlet_SD_factor; + int wl_size = int(2 * std::floor(std::round(SD * sampling_rate * morlet_SD_spread) / 2) + 1); + int half_size = wl_size / 2; + + _data.resize(wl_size); + float integral; + std::vector gauss(std::move(gausswin(wl_size, morlet_SD_spread / 2, integral))); + + float igsum = 1.f / integral; + float isd = 1.f / sampling_rate; + + for (int i = 0; i < wl_size; ++i) + { + float t = (i - half_size) * isd; + _data[i] = gauss[i] * expj(2 * pi_f * center_freq * t) * igsum; + } + } + + + int size() { return int(_data.size()); } + + std::complex* data() { return _data.data(); } + + +protected: + static std::vector gausswin(int n, float alpha, float& integral) + { + int halfsize = n / 2; + float idiv = alpha / halfsize; + + std::vector result(n); + double acc = 0; + for (int i = 0; i < n; ++i) + { + float t = (i - halfsize) * idiv; + result[i] = std::exp(-(t * t) * 0.5f); + acc += result[i]; + } + + integral = float(acc); + return result; + } + + static std::complex expj(float arg) + { + return std::complex(std::cos(arg), std::sin(arg)); + } + + + + std::vector> _data; + + +}; + +} diff --git a/libraries/timefrequency/timefrequency.pro b/libraries/timefrequency/timefrequency.pro new file mode 100644 index 00000000000..ff79dd3a28a --- /dev/null +++ b/libraries/timefrequency/timefrequency.pro @@ -0,0 +1,72 @@ + +include(../../mne-cpp.pri) + +TEMPLATE = lib + +CONFIG += skip_target_version_ext + +QT += network concurrent +QT -= gui + +DEFINES += TIMEFREQUENCY_LIBRARY + +DESTDIR = $${MNE_LIBRARY_DIR} + +TARGET = TimeFrequency +TARGET = $$join(TARGET,,mnecpp,) +CONFIG(debug, debug|release) { + TARGET = $$join(TARGET,,,d) +} + +contains(MNECPP_CONFIG, static) { + CONFIG += staticlib + DEFINES += STATICBUILD +} else { + CONFIG += shared +} + +LIBS += -L$${MNE_LIBRARY_DIR} +CONFIG(debug, debug|release) { + LIBS += -lmnecppUtilsd \ +} else { + LIBS += -lmnecppUtils \ +} + +SOURCES += \ + convolver.cpp \ + interface.cpp \ + wavelet_spectrum_analyzer.cpp + + +HEADERS += \ + convolver.h \ + morlet.h \ + wavelet_spectrum_analyzer.h + + +INCLUDEPATH += $${MNE_INCLUDE_DIR} + +header_files.files = $${HEADERS} +header_files.path = $${MNE_INSTALL_INCLUDE_DIR}/events + +INSTALLS += header_files + +contains(MNECPP_CONFIG, withCodeCov) { + QMAKE_CXXFLAGS += --coverage + QMAKE_LFLAGS += --coverage +} + +win32:!contains(MNECPP_CONFIG, static) { + QMAKE_POST_LINK += $$QMAKE_COPY $$shell_path($${MNE_LIBRARY_DIR}/$${TARGET}.dll) $${MNE_BINARY_DIR} +} + +macx { + QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/ +} + +win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -llibfftw3f-3 +else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -llibfftw3f-3d +else:unix: LIBS += -L$$PWD/lib/ -llibfftw3f-3 + +INCLUDEPATH += $$PWD/include +DEPENDPATH += $$PWD/include diff --git a/libraries/timefrequency/wavelet_spectrum_analyzer.cpp b/libraries/timefrequency/wavelet_spectrum_analyzer.cpp new file mode 100644 index 00000000000..4c85d223427 --- /dev/null +++ b/libraries/timefrequency/wavelet_spectrum_analyzer.cpp @@ -0,0 +1,152 @@ +#include "wavelet_spectrum_analyzer.h" +#include + +using namespace TIMEFREQUENCYLIB; + +std::vector linspace(float from, float to, int n) +{ + if (n <= 0) return { }; + else if (n == 1) return { from }; + else + { + std::vector result(n); + + float dv = (to - from) / (n - 1); + for (size_t i = 0; i < result.size(); ++i) + result[i] = from + i * dv; + + return result; + } +} + + +__forceinline float mag_sqr(const std::complex& z) +{ + return z.real() * z.real() + z.imag() * z.imag(); +} + +__forceinline float fractional(float x) +{ + return x - (int)x; +} + + + + +wavelet_spectrum_analyzer::wavelet_spectrum_analyzer(wavelet_analyzer_settings set) +{ + _set = set; + _filters .resize(_set.freq_count); + _superlets .resize(_set.freq_count); + _conv_buffer .resize(_set.input_size); + _pooling_buffer .resize(_set.input_size); + _frequencies = linspace(_set.freq_low, _set.freq_high, _set.freq_count); + _orders = linspace(_set.resolution_low, _set.resolution_high, _set.freq_count); + + if (!_set.fractional) + std::transform(_orders.begin(), _orders.end(), _orders.begin(), std::roundf); + + for (size_t i_freq = 0; i_freq < _set.freq_count; ++i_freq) + { + float center_freq = _frequencies[i_freq]; + int n_wavelets = int(std::ceilf(_orders[i_freq])); + + for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) + { + float ncyc = _set.multiplicative + ? (i_wave + 1) * _set.wavelet_cycles + : _set.wavelet_cycles + i_wave; + + _superlets[i_freq] .emplace_back(center_freq, ncyc, _set.sampling_rate); + _filters[i_freq] .push_back(new convolver(_set.input_size, _superlets[i_freq].back().size())); + _filters[i_freq] .back()->assign_kernel(_superlets[i_freq].back().data(), _superlets[i_freq].back().size()); + } + } +} + +wavelet_spectrum_analyzer::~wavelet_spectrum_analyzer() +{ + for (auto& fb : _filters) + { + for (auto& conv : fb) + delete conv; + fb.clear(); + } + + _filters .clear(); + _superlets .clear(); + _pooling_buffer .clear(); + _frequencies .clear(); + _orders .clear(); + _conv_buffer .clear(); + _set = wavelet_analyzer_settings(); +} + + + +void wavelet_spectrum_analyzer::analyze(float* input, float* output) +{ + size_t input_size = _set.input_size; + + for (size_t i_freq = 0; i_freq < _superlets.size(); ++i_freq) + { + // initialize the pooling buffer + std::fill(_pooling_buffer.begin(), _pooling_buffer.end(), 1.0); + + if (_superlets[i_freq].size() > 1) + { + // superresolution + size_t n_wavelets = size_t(std::floorf(_orders[i_freq])); + double r_factor = 1.0 / n_wavelets; + + for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) + { + // perform R2C convolution + _filters[i_freq][i_wave]->conv_r2c_same(input, _conv_buffer.data()); + + // pool with exponent = 1 + for (size_t i = 0; i < input_size; ++i) + { + _pooling_buffer[i] *= 2.0 * mag_sqr(_conv_buffer[i]); + } + } + + // determine if fractional superlet should be used + if (fractional(_orders[i_freq]) != 0 && // order is fractional + _set.fractional && // we are allowed to use it + _superlets[i_freq].size() == n_wavelets + 1 ) // we really have a wavelet available for it + { + double exponent = fractional(_orders[i_freq]); + r_factor = 1.0 / (n_wavelets + exponent); + + // perform convolution with the last wavelet + _filters[i_freq].back()->conv_r2c_same(input, _conv_buffer.data()); + + // pool with fractional exponent + for (size_t i = 0; i < input_size; ++i) + { + _pooling_buffer[i] *= std::pow(2.0 * mag_sqr(_conv_buffer[i]), exponent); + } + } + + // perform geometric mean and save to output buffer + for (size_t i = 0; i < input_size; ++i) + { + output[i] += float(std::pow(_pooling_buffer[i], r_factor)); + } + } + else + { + // standard CWT + _filters[i_freq].front()->conv_r2c_same(input, _conv_buffer.data()); + + for (size_t i = 0; i < input_size; ++i) + output[i] += float(2.0 * mag_sqr(_conv_buffer[i])); + } + + output += input_size; + } +} + + + diff --git a/libraries/timefrequency/wavelet_spectrum_analyzer.h b/libraries/timefrequency/wavelet_spectrum_analyzer.h new file mode 100644 index 00000000000..40d728d78ff --- /dev/null +++ b/libraries/timefrequency/wavelet_spectrum_analyzer.h @@ -0,0 +1,46 @@ +#pragma once +#include "morlet.h" +#include "convolver.h" + + +namespace TIMEFREQUENCYLIB { + +struct wavelet_analyzer_settings +{ + float sampling_rate; + float freq_low; + float freq_high; + int freq_count; + int input_size; + float wavelet_cycles; + float resolution_low; + float resolution_high; + bool multiplicative; + bool fractional; +}; + + +class wavelet_spectrum_analyzer +{ + using filter_bank = std::vector; + using superlet = std::vector; + +public: + wavelet_spectrum_analyzer(wavelet_analyzer_settings set); + ~wavelet_spectrum_analyzer(); + + void analyze(float* input, float* output); + +protected: + wavelet_analyzer_settings _set; + std::vector _filters; + std::vector _superlets; + std::vector> _conv_buffer; + std::vector _pooling_buffer; + std::vector _frequencies; + std::vector _orders; + +}; + +} + diff --git a/libraries/utils/spectrogram.cpp b/libraries/utils/spectrogram.cpp index f43b8dfaf64..4ea6022a481 100644 --- a/libraries/utils/spectrogram.cpp +++ b/libraries/utils/spectrogram.cpp @@ -43,6 +43,7 @@ #include #include +#include //============================================================================================================= // QT INCLUDES @@ -64,12 +65,12 @@ using namespace Eigen; // DEFINE MEMBER METHODS //============================================================================================================= -MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0) +MatrixXd Spectrogram::makeSpectrogram(const VectorXd& signal, qint32 windowSize) { //QElapsedTimer timer; //timer.start(); __TRACE_FUNC(); - signal.array() -= signal.mean(); +// signal.array() -= signal.mean(); QList lData; int iThreadSize = QThread::idealThreadCount()*2; int iStepsSize = signal.rows()/iThreadSize; @@ -79,7 +80,7 @@ MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0) dataTemp.vecInputData = signal; dataTemp.window_size = windowSize; if(dataTemp.window_size == 0) { - dataTemp.window_size = signal.rows()/15; + dataTemp.window_size = signal.rows()/5; } for (int i = 0; i < iThreadSize; ++i) { @@ -92,6 +93,8 @@ MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0) dataTemp.iRangeHigh = iThreadSize*iStepsSize+iResidual; lData.append(dataTemp); +// MatrixXd resultMat = compute(dataTemp); + QFuture resultMat = QtConcurrent::mappedReduced(lData, compute, reduce); @@ -103,12 +106,12 @@ MatrixXd Spectrogram::makeSpectrogram(VectorXd signal, qint32 windowSize = 0) //============================================================================================================= -MatrixXcd Spectrogram::makeComplexSpectrogram(VectorXd signal, qint32 windowSize = 0) +MatrixXcd Spectrogram::makeComplexSpectrogram(const VectorXd& signal, qint32 windowSize) { //QElapsedTimer timer; //timer.start(); __TRACE_FUNC(); - signal.array() -= signal.mean(); +// signal.array() -= signal.mean(); QList lData; int iThreadSize = QThread::idealThreadCount(); int iStepsSize = signal.rows()/iThreadSize; @@ -164,26 +167,27 @@ MatrixXd Spectrogram::compute(const SpectogramInputData& inputData) fftw_make_planner_thread_safe(); #endif __TRACE_FUNC(); - Eigen::FFT fft; - MatrixXd tf_matrix = MatrixXd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows()); - VectorXd envelope, windowed_sig, real_coeffs; - VectorXcd fft_win_sig; - qint32 window_size = inputData.window_size; + MatrixXd tf_matrix; +// Eigen::FFT fft; +// MatrixXd tf_matrix = MatrixXd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows()); +// VectorXd envelope, windowed_sig, real_coeffs; +// VectorXcd fft_win_sig; +// qint32 window_size = inputData.window_size; - for(quint32 translate = inputData.iRangeLow; translate < inputData.iRangeHigh; translate++) { - envelope = gaussWindow(inputData.vecInputData.rows(), window_size, translate); +// for(quint32 translate = inputData.iRangeLow; translate < inputData.iRangeHigh; translate++) { +// envelope = gaussWindow(inputData.vecInputData.rows(), window_size, translate); - windowed_sig = VectorXd::Zero(inputData.vecInputData.rows()); - fft_win_sig = VectorXcd::Zero(inputData.vecInputData.rows()); +// windowed_sig = VectorXd::Zero(inputData.vecInputData.rows()); +// fft_win_sig = VectorXcd::Zero(inputData.vecInputData.rows()); - windowed_sig = inputData.vecInputData.array() * envelope.array();\ +// windowed_sig = inputData.vecInputData.array() * envelope.array();\ - fft.fwd(fft_win_sig, windowed_sig); +// fft.fwd(fft_win_sig, windowed_sig); - real_coeffs = fft_win_sig.segment(0,inputData.vecInputData.rows()/2).array().abs2(); +// real_coeffs = fft_win_sig.segment(0,inputData.vecInputData.rows()/2).array().abs2(); - tf_matrix.col(translate) = real_coeffs; - } +// tf_matrix.col(translate) = real_coeffs; +// } return tf_matrix; } diff --git a/libraries/utils/spectrogram.h b/libraries/utils/spectrogram.h index 12c9ebf8b25..a4c2ae672bb 100644 --- a/libraries/utils/spectrogram.h +++ b/libraries/utils/spectrogram.h @@ -73,7 +73,7 @@ class UTILSSHARED_EXPORT Spectrogram * * @return spectrogram-matrix (tf-representation of the input signal). */ - static Eigen::MatrixXd makeSpectrogram(Eigen::VectorXd signal, + static Eigen::MatrixXd makeSpectrogram(const Eigen::VectorXd& signal, qint32 windowSize); //========================================================================================================= @@ -85,7 +85,7 @@ class UTILSSHARED_EXPORT Spectrogram * * @return spectrogram-matrix (tf-representation of the input signal) */ - static Eigen::MatrixXcd makeComplexSpectrogram(Eigen::VectorXd signal, + static Eigen::MatrixXcd makeComplexSpectrogram(const Eigen::VectorXd& signal, qint32 windowSize); private: From 7872822c636bd2411896c8b9467b8139a9a8b8ce Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Mon, 17 May 2021 09:00:55 -0400 Subject: [PATCH 49/57] ENH: time freuqency analyzer class --- libraries/timefrequency/interface.cpp | 210 +++++++++--------- libraries/timefrequency/timefrequency.pro | 2 + .../timefrequency/timefrequencyanalyzer.cpp | 10 + .../timefrequency/timefrequencyanalyzer.h | 31 +++ libraries/utils/utils.pro | 4 +- 5 files changed, 150 insertions(+), 107 deletions(-) create mode 100644 libraries/timefrequency/timefrequencyanalyzer.cpp create mode 100644 libraries/timefrequency/timefrequencyanalyzer.h diff --git a/libraries/timefrequency/interface.cpp b/libraries/timefrequency/interface.cpp index d0332b70828..161dc3c2ceb 100644 --- a/libraries/timefrequency/interface.cpp +++ b/libraries/timefrequency/interface.cpp @@ -25,111 +25,111 @@ int mxGetSize(mxArray* arr) } -void validate_params(int nrhs, mxArray** prhs) -{ - // check params - if (nrhs < 6) - mexErrMsgTxt("Parameter count not met! faslt expects at least 6 parameters! See below...\n \ - 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ - 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ - 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ - 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ - 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ - 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ - 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ - 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); - if (nrhs > 8) - mexErrMsgTxt("Parameter count exceeded! faslt expects at most 8 parameters! See below...\n \ - 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ - 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ - 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ - 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ - 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ - 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ - 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ - 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); - - // check data - if (!mxIsDouble(prhs[P_INPUT_DATA])) - mexErrMsgTxt("input_data needs to be a real-valued (double) matrix"); - - // check input size - if (!mxGetN(prhs[P_INPUT_DATA]) == 1) - mexErrMsgTxt("input_data is a column vector. faslt only accepts row vectors."); - - // check FS - if (mxGetScalar(prhs[P_SAMPLING_RATE]) <= 0.0) - mexErrMsgTxt("sampling_rate needs to be a positive non-zero scalar representing the sampling frequency of the input in Hz"); - - // check freq interval - if (!mxIsDouble(prhs[P_FREQ_INTERVAL]) || mxGetSize(prhs[P_FREQ_INTERVAL]) != 2) - mexErrMsgTxt("frequency_interval needs to be a tuple containing the lower and upper frequency bounds in Hz"); - else - { - double lower = mxGetPr(prhs[P_FREQ_INTERVAL])[0]; - double upper = mxGetPr(prhs[P_FREQ_INTERVAL])[1]; - double fs = mxGetScalar(prhs[P_SAMPLING_RATE]); - - if (lower <= 0 || lower >= fs / 2 || - upper <= 0 || upper >= fs / 2) - mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); - } - - // check frequency count - if (!is_integer(mxGetScalar(prhs[P_FREQ_COUNT])) || mxGetScalar(prhs[P_FREQ_COUNT]) <= 0) - mexErrMsgTxt("frequency_count needs to be a positive non-zero integer"); - - // check cycle count - if (mxGetScalar(prhs[P_CYCLE_COUNT]) <= 0.0) - mexErrMsgTxt("cycle_count needs to be a positive non-zero scalar representing the number of cycles of the shortest wavelets"); - - // check resolution - if (!mxIsDouble(prhs[P_SUPERRESOLUTION]) || mxGetSize(prhs[P_SUPERRESOLUTION]) != 2) - mexErrMsgTxt("superresolution needs to be a tuple containing the lower and upper frequency bounds in Hz"); - else - { - if (mxGetPr(prhs[P_SUPERRESOLUTION])[0] <= 0 || mxGetPr(prhs[P_SUPERRESOLUTION])[1] <= 0) - mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); - } - - // check multiplicative - if (nrhs > P_MULTIPLICATIVE && mxGetSize(prhs[P_MULTIPLICATIVE]) != 1) - mexErrMsgTxt("multiplicative needs to be a scalar (0 - false, !0 otherwise)"); - - // check fractional - if (nrhs > P_FRACTIONAL && mxGetSize(prhs[P_FRACTIONAL]) != 1) - mexErrMsgTxt("fractional needs to be a scalar (0 - false, !0 otherwise)"); -} - - - -void print_settings(wavelet_analyzer_settings& set) -{ - mexPrintf("wavelet_analyzer_settings:\n\ - sampling_rate: %f\n\ - freq_low: %f\n\ - freq_high: %f\n\ - freq_count: %d\n\ - input_size: %d\n\ - wavelet_cycles: %f\n\ - resolution_low: %f\n\ - resolution_high: %f\n\ - multiplicative: %s\n\ - fractional: %s\n", - set.sampling_rate, - set.freq_low, - set.freq_high, - set.freq_count, - set.input_size, - set.wavelet_cycles, - set.resolution_low, - set.resolution_high, - set.multiplicative ? "true" : "false", - set.fractional ? "true" : "false"); -} - - -void __declspec(dllexport) mexFunction(int nlhs, mxArray** plhs, int nrhs, mxArray** prhs) +//void validate_params(int nrhs, mxArray** prhs) +//{ +// // check params +// if (nrhs < 6) +// mexErrMsgTxt("Parameter count not met! faslt expects at least 6 parameters! See below...\n \ +// 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ +// 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ +// 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ +// 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ +// 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ +// 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ +// 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ +// 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); +// if (nrhs > 8) +// mexErrMsgTxt("Parameter count exceeded! faslt expects at most 8 parameters! See below...\n \ +// 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ +// 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ +// 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ +// 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ +// 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ +// 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ +// 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ +// 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); + +// // check data +// if (!mxIsDouble(prhs[P_INPUT_DATA])) +// mexErrMsgTxt("input_data needs to be a real-valued (double) matrix"); + +// // check input size +// if (!mxGetN(prhs[P_INPUT_DATA]) == 1) +// mexErrMsgTxt("input_data is a column vector. faslt only accepts row vectors."); + +// // check FS +// if (mxGetScalar(prhs[P_SAMPLING_RATE]) <= 0.0) +// mexErrMsgTxt("sampling_rate needs to be a positive non-zero scalar representing the sampling frequency of the input in Hz"); + +// // check freq interval +// if (!mxIsDouble(prhs[P_FREQ_INTERVAL]) || mxGetSize(prhs[P_FREQ_INTERVAL]) != 2) +// mexErrMsgTxt("frequency_interval needs to be a tuple containing the lower and upper frequency bounds in Hz"); +// else +// { +// double lower = mxGetPr(prhs[P_FREQ_INTERVAL])[0]; +// double upper = mxGetPr(prhs[P_FREQ_INTERVAL])[1]; +// double fs = mxGetScalar(prhs[P_SAMPLING_RATE]); + +// if (lower <= 0 || lower >= fs / 2 || +// upper <= 0 || upper >= fs / 2) +// mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); +// } + +// // check frequency count +// if (!is_integer(mxGetScalar(prhs[P_FREQ_COUNT])) || mxGetScalar(prhs[P_FREQ_COUNT]) <= 0) +// mexErrMsgTxt("frequency_count needs to be a positive non-zero integer"); + +// // check cycle count +// if (mxGetScalar(prhs[P_CYCLE_COUNT]) <= 0.0) +// mexErrMsgTxt("cycle_count needs to be a positive non-zero scalar representing the number of cycles of the shortest wavelets"); + +// // check resolution +// if (!mxIsDouble(prhs[P_SUPERRESOLUTION]) || mxGetSize(prhs[P_SUPERRESOLUTION]) != 2) +// mexErrMsgTxt("superresolution needs to be a tuple containing the lower and upper frequency bounds in Hz"); +// else +// { +// if (mxGetPr(prhs[P_SUPERRESOLUTION])[0] <= 0 || mxGetPr(prhs[P_SUPERRESOLUTION])[1] <= 0) +// mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); +// } + +// // check multiplicative +// if (nrhs > P_MULTIPLICATIVE && mxGetSize(prhs[P_MULTIPLICATIVE]) != 1) +// mexErrMsgTxt("multiplicative needs to be a scalar (0 - false, !0 otherwise)"); + +// // check fractional +// if (nrhs > P_FRACTIONAL && mxGetSize(prhs[P_FRACTIONAL]) != 1) +// mexErrMsgTxt("fractional needs to be a scalar (0 - false, !0 otherwise)"); +//} + + + +//void print_settings(wavelet_analyzer_settings& set) +//{ +// mexPrintf("wavelet_analyzer_settings:\n\ +// sampling_rate: %f\n\ +// freq_low: %f\n\ +// freq_high: %f\n\ +// freq_count: %d\n\ +// input_size: %d\n\ +// wavelet_cycles: %f\n\ +// resolution_low: %f\n\ +// resolution_high: %f\n\ +// multiplicative: %s\n\ +// fractional: %s\n", +// set.sampling_rate, +// set.freq_low, +// set.freq_high, +// set.freq_count, +// set.input_size, +// set.wavelet_cycles, +// set.resolution_low, +// set.resolution_high, +// set.multiplicative ? "true" : "false", +// set.fractional ? "true" : "false"); +//} + + +void mexFunction(int nlhs, mxArray** plhs, int nrhs, mxArray** prhs) { // Parameter Name - Parameter Type - Description // diff --git a/libraries/timefrequency/timefrequency.pro b/libraries/timefrequency/timefrequency.pro index ff79dd3a28a..07ea1debf9d 100644 --- a/libraries/timefrequency/timefrequency.pro +++ b/libraries/timefrequency/timefrequency.pro @@ -35,12 +35,14 @@ CONFIG(debug, debug|release) { SOURCES += \ convolver.cpp \ interface.cpp \ + timefrequencyanalyzer.cpp \ wavelet_spectrum_analyzer.cpp HEADERS += \ convolver.h \ morlet.h \ + timefrequencyanalyzer.h \ wavelet_spectrum_analyzer.h diff --git a/libraries/timefrequency/timefrequencyanalyzer.cpp b/libraries/timefrequency/timefrequencyanalyzer.cpp new file mode 100644 index 00000000000..98c55a0255e --- /dev/null +++ b/libraries/timefrequency/timefrequencyanalyzer.cpp @@ -0,0 +1,10 @@ +#include "timefrequencyanalyzer.h" + +using namespace TIMEFREQUENCYLIB; + +TimeFrequencyAnalyzer::TimeFrequencyAnalyzer(const TimeFrequencySettings& settings) + : m_pSettings(settings) +{ + + +} diff --git a/libraries/timefrequency/timefrequencyanalyzer.h b/libraries/timefrequency/timefrequencyanalyzer.h new file mode 100644 index 00000000000..a56eb5f1e92 --- /dev/null +++ b/libraries/timefrequency/timefrequencyanalyzer.h @@ -0,0 +1,31 @@ +#ifndef TIMEFREQUENCYANALYZER_H +#define TIMEFREQUENCYANALYZER_H + +#include + +namespace TIMEFREQUENCYLIB { + +enum Method{ + Superlets +}; + +struct TimeFrequencySettings { + Method m_method; + TimeFrequencySettings() = default; +}; + +class TimeFrequencyAnalyzer +{ +public: + TimeFrequencyAnalyzer(const TimeFrequencySettings& settings); + + void run(); + +private: + bool vaildateSettings(); + + TimeFrequencySettings m_pSettings; +}; +}//namespace + +#endif // TIMEFREQUENCYANALYZER_H diff --git a/libraries/utils/utils.pro b/libraries/utils/utils.pro index e782fa0f847..aa7a8bc10af 100644 --- a/libraries/utils/utils.pro +++ b/libraries/utils/utils.pro @@ -70,7 +70,7 @@ SOURCES += \ layoutmaker.cpp \ selectionio.cpp \ spectrogram.cpp \ - tracer.cpp \ +# tracer.cpp \ warp.cpp \ sphere.cpp \ generics/observerpattern.cpp \ @@ -79,7 +79,7 @@ SOURCES += \ HEADERS += \ kmeans.h\ - tracer.h \ +# tracer.h \ utils_global.h \ mnemath.h \ ioutils.h \ From 4e36ea86f424f55659b9a3897edf714a30444ac9 Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Mon, 17 May 2021 11:09:34 -0400 Subject: [PATCH 50/57] ENH: methods as separate classes which analyser calls --- .../timefrequency/methods/analysismethod.h | 15 ++++++++++ .../timefrequency/methods/helpers/.Rhistory | 0 .../methods/helpers/analysisIO.h | 22 ++++++++++++++ .../timefrequency/methods/helpers/morlet.cpp | 6 ++++ .../timefrequency/methods/helpers/morlet.h | 11 +++++++ libraries/timefrequency/methods/superlets.cpp | 6 ++++ libraries/timefrequency/methods/superlets.h | 29 +++++++++++++++++++ libraries/timefrequency/timefrequency.pro | 6 ++++ .../timefrequency/timefrequencyanalyzer.cpp | 16 ++++++++-- .../timefrequency/timefrequencyanalyzer.h | 24 +++++++-------- .../timefrequency/wavelet_spectrum_analyzer.h | 2 +- 11 files changed, 120 insertions(+), 17 deletions(-) create mode 100644 libraries/timefrequency/methods/analysismethod.h create mode 100644 libraries/timefrequency/methods/helpers/.Rhistory create mode 100644 libraries/timefrequency/methods/helpers/analysisIO.h create mode 100644 libraries/timefrequency/methods/helpers/morlet.cpp create mode 100644 libraries/timefrequency/methods/helpers/morlet.h create mode 100644 libraries/timefrequency/methods/superlets.cpp create mode 100644 libraries/timefrequency/methods/superlets.h diff --git a/libraries/timefrequency/methods/analysismethod.h b/libraries/timefrequency/methods/analysismethod.h new file mode 100644 index 00000000000..298774134fa --- /dev/null +++ b/libraries/timefrequency/methods/analysismethod.h @@ -0,0 +1,15 @@ +#ifndef ANALYSISMETHOD_H +#define ANALYSISMETHOD_H + + +class AnalysisMethod +{ +public: + AnalysisMethod() = default; + + virtual bool compute() = 0; + virtual bool validateSettings() = 0; + +}; + +#endif // ANALYSISMETHOD_H diff --git a/libraries/timefrequency/methods/helpers/.Rhistory b/libraries/timefrequency/methods/helpers/.Rhistory new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/timefrequency/methods/helpers/analysisIO.h b/libraries/timefrequency/methods/helpers/analysisIO.h new file mode 100644 index 00000000000..b504ae5b910 --- /dev/null +++ b/libraries/timefrequency/methods/helpers/analysisIO.h @@ -0,0 +1,22 @@ +#ifndef ANALYSISSETTINGS_H +#define ANALYSISSETTINGS_H + +namespace TIMEFREQUENCYLIB { + +} +struct AnalysisSettings +{ + float sampling_rate; + float freq_low; + float freq_high; + + AnalysisSettings() = default; +}; + +class TimeFrequencyResult +{ + +}; + +//namespace +#endif // ANALYSISSETTINGS_H diff --git a/libraries/timefrequency/methods/helpers/morlet.cpp b/libraries/timefrequency/methods/helpers/morlet.cpp new file mode 100644 index 00000000000..698df06b0cf --- /dev/null +++ b/libraries/timefrequency/methods/helpers/morlet.cpp @@ -0,0 +1,6 @@ +#include "morlet.h" + +Morlet::Morlet() +{ + +} diff --git a/libraries/timefrequency/methods/helpers/morlet.h b/libraries/timefrequency/methods/helpers/morlet.h new file mode 100644 index 00000000000..8a4bdde0701 --- /dev/null +++ b/libraries/timefrequency/methods/helpers/morlet.h @@ -0,0 +1,11 @@ +#ifndef MORLET_H +#define MORLET_H + + +class Morlet +{ +public: + Morlet(); +}; + +#endif // MORLET_H diff --git a/libraries/timefrequency/methods/superlets.cpp b/libraries/timefrequency/methods/superlets.cpp new file mode 100644 index 00000000000..7d021b7ce00 --- /dev/null +++ b/libraries/timefrequency/methods/superlets.cpp @@ -0,0 +1,6 @@ +#include "superlets.h" + +Superlets::Superlets() +{ + +} diff --git a/libraries/timefrequency/methods/superlets.h b/libraries/timefrequency/methods/superlets.h new file mode 100644 index 00000000000..bab6331e86b --- /dev/null +++ b/libraries/timefrequency/methods/superlets.h @@ -0,0 +1,29 @@ +#ifndef SUPERLETS_H +#define SUPERLETS_H + +#include "analysismethod.h" +#include "helpers/analysisIO.h" +#include "helpers/morlet.h" + +namespace TIMEFREQUENCYLIB { + +struct SuperletSettings{ + AnalysisSettings settings; + int freq_count; + int input_size; + float wavelet_cycles; + float resolution_low; + float resolution_high; +}; + +class Superlets : public AnalysisMethod +{ +public: + Superlets(); + + virtual bool compute(); + virtual bool validateSettings(); +}; +} //namespace + +#endif // SUPERLETS_H diff --git a/libraries/timefrequency/timefrequency.pro b/libraries/timefrequency/timefrequency.pro index 07ea1debf9d..230d8169063 100644 --- a/libraries/timefrequency/timefrequency.pro +++ b/libraries/timefrequency/timefrequency.pro @@ -35,12 +35,18 @@ CONFIG(debug, debug|release) { SOURCES += \ convolver.cpp \ interface.cpp \ + methods/helpers/morlet.cpp \ + methods/superlets.cpp \ timefrequencyanalyzer.cpp \ wavelet_spectrum_analyzer.cpp HEADERS += \ convolver.h \ + methods/analysismethod.h \ + methods/helpers/analysisIO.h \ + methods/helpers/morlet.h \ + methods/superlets.h \ morlet.h \ timefrequencyanalyzer.h \ wavelet_spectrum_analyzer.h diff --git a/libraries/timefrequency/timefrequencyanalyzer.cpp b/libraries/timefrequency/timefrequencyanalyzer.cpp index 98c55a0255e..5cdaec0f8ae 100644 --- a/libraries/timefrequency/timefrequencyanalyzer.cpp +++ b/libraries/timefrequency/timefrequencyanalyzer.cpp @@ -2,9 +2,21 @@ using namespace TIMEFREQUENCYLIB; -TimeFrequencyAnalyzer::TimeFrequencyAnalyzer(const TimeFrequencySettings& settings) - : m_pSettings(settings) +TimeFrequencyAnalyzer::TimeFrequencyAnalyzer(AnalysisMethod& method) + : m_method(method) { } + +bool TimeFrequencyAnalyzer::run() +{ + bool validRun = false; + bool validSettings = m_method.validateSettings(); + + if(validSettings){ + validRun = m_method.compute(); + } + + return validRun; +} diff --git a/libraries/timefrequency/timefrequencyanalyzer.h b/libraries/timefrequency/timefrequencyanalyzer.h index a56eb5f1e92..d3d0a5d17e6 100644 --- a/libraries/timefrequency/timefrequencyanalyzer.h +++ b/libraries/timefrequency/timefrequencyanalyzer.h @@ -3,28 +3,24 @@ #include -namespace TIMEFREQUENCYLIB { - -enum Method{ - Superlets -}; +#include "methods/analysismethod.h" +#include "methods/helpers/analysisIO.h" -struct TimeFrequencySettings { - Method m_method; - TimeFrequencySettings() = default; -}; +namespace TIMEFREQUENCYLIB { class TimeFrequencyAnalyzer { public: - TimeFrequencyAnalyzer(const TimeFrequencySettings& settings); + TimeFrequencyAnalyzer(); - void run(); + TimeFrequencyAnalyzer(AnalysisMethod& method); -private: - bool vaildateSettings(); + bool run(); - TimeFrequencySettings m_pSettings; + TimeFrequencyResult getResult(); + +private: + AnalysisMethod& m_method; }; }//namespace diff --git a/libraries/timefrequency/wavelet_spectrum_analyzer.h b/libraries/timefrequency/wavelet_spectrum_analyzer.h index 40d728d78ff..128bc3aad25 100644 --- a/libraries/timefrequency/wavelet_spectrum_analyzer.h +++ b/libraries/timefrequency/wavelet_spectrum_analyzer.h @@ -23,7 +23,7 @@ struct wavelet_analyzer_settings class wavelet_spectrum_analyzer { using filter_bank = std::vector; - using superlet = std::vector; + using superlet = std::vector; public: wavelet_spectrum_analyzer(wavelet_analyzer_settings set); From 0de01ce2f42de12122da6aba7e5328bfca8a420a Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Mon, 17 May 2021 13:01:22 -0400 Subject: [PATCH 51/57] ENH: samll changes and examples --- .../ex_time_frequency/ex_time_frequency.pro | 23 +++++++++++++++++++ examples/ex_time_frequency/main.cpp | 8 +++++++ examples/examples.pro | 3 ++- .../methods/helpers/analysisIO.h | 9 ++++++-- libraries/timefrequency/methods/superlets.h | 4 +--- libraries/timefrequency/timefrequency.pro | 2 +- 6 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 examples/ex_time_frequency/ex_time_frequency.pro create mode 100644 examples/ex_time_frequency/main.cpp diff --git a/examples/ex_time_frequency/ex_time_frequency.pro b/examples/ex_time_frequency/ex_time_frequency.pro new file mode 100644 index 00000000000..a0e3fda166b --- /dev/null +++ b/examples/ex_time_frequency/ex_time_frequency.pro @@ -0,0 +1,23 @@ +QT -= gui + +CONFIG += c++11 console +CONFIG -= app_bundle + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/examples/ex_time_frequency/main.cpp b/examples/ex_time_frequency/main.cpp new file mode 100644 index 00000000000..470a0307e24 --- /dev/null +++ b/examples/ex_time_frequency/main.cpp @@ -0,0 +1,8 @@ +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + return a.exec(); +} diff --git a/examples/examples.pro b/examples/examples.pro index 5587bc265ed..c5090fc120c 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -62,7 +62,8 @@ SUBDIRS += \ ex_read_evoked \ ex_read_fwd \ ex_read_raw \ - ex_read_write_raw \ + ex_read_write_raw \ \ + ex_time_frequency qtHaveModule(charts) { SUBDIRS += \ diff --git a/libraries/timefrequency/methods/helpers/analysisIO.h b/libraries/timefrequency/methods/helpers/analysisIO.h index b504ae5b910..0000bcedaac 100644 --- a/libraries/timefrequency/methods/helpers/analysisIO.h +++ b/libraries/timefrequency/methods/helpers/analysisIO.h @@ -1,6 +1,9 @@ #ifndef ANALYSISSETTINGS_H #define ANALYSISSETTINGS_H +#include +#include + namespace TIMEFREQUENCYLIB { } @@ -9,13 +12,15 @@ struct AnalysisSettings float sampling_rate; float freq_low; float freq_high; - - AnalysisSettings() = default; + int input_size; }; class TimeFrequencyResult { + template + std::complex getArray(); + Eigen::MatrixXcd getEigenMatrix(); }; //namespace diff --git a/libraries/timefrequency/methods/superlets.h b/libraries/timefrequency/methods/superlets.h index bab6331e86b..1fa2de0f8ff 100644 --- a/libraries/timefrequency/methods/superlets.h +++ b/libraries/timefrequency/methods/superlets.h @@ -7,10 +7,8 @@ namespace TIMEFREQUENCYLIB { -struct SuperletSettings{ - AnalysisSettings settings; +struct SuperletSettings : public AnalysisSettings{ int freq_count; - int input_size; float wavelet_cycles; float resolution_low; float resolution_high; diff --git a/libraries/timefrequency/timefrequency.pro b/libraries/timefrequency/timefrequency.pro index 230d8169063..81fe1e96657 100644 --- a/libraries/timefrequency/timefrequency.pro +++ b/libraries/timefrequency/timefrequency.pro @@ -51,7 +51,7 @@ HEADERS += \ timefrequencyanalyzer.h \ wavelet_spectrum_analyzer.h - +INCLUDEPATH += $${EIGEN_INCLUDE_DIR} INCLUDEPATH += $${MNE_INCLUDE_DIR} header_files.files = $${HEADERS} From 95c5b94e89476b2e58d7999ad7e859488a1ec043 Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Tue, 18 May 2021 09:53:42 -0400 Subject: [PATCH 52/57] ENH: moving functionality to Superlets class --- .../timefrequency/methods/analysismethod.h | 6 +- .../{ => methods/helpers}/convolver.cpp | 0 .../{ => methods/helpers}/convolver.h | 0 .../timefrequency/methods/helpers/morlet.cpp | 6 -- .../timefrequency/methods/helpers/morlet.h | 71 ++++++++++++++++-- libraries/timefrequency/methods/superlets.cpp | 5 +- libraries/timefrequency/methods/superlets.h | 19 ++++- libraries/timefrequency/morlet.h | 72 ------------------- libraries/timefrequency/timefrequency.pro | 5 +- .../timefrequency/timefrequencyanalyzer.cpp | 5 ++ 10 files changed, 100 insertions(+), 89 deletions(-) rename libraries/timefrequency/{ => methods/helpers}/convolver.cpp (100%) rename libraries/timefrequency/{ => methods/helpers}/convolver.h (100%) delete mode 100644 libraries/timefrequency/methods/helpers/morlet.cpp delete mode 100644 libraries/timefrequency/morlet.h diff --git a/libraries/timefrequency/methods/analysismethod.h b/libraries/timefrequency/methods/analysismethod.h index 298774134fa..ea55d23ac53 100644 --- a/libraries/timefrequency/methods/analysismethod.h +++ b/libraries/timefrequency/methods/analysismethod.h @@ -1,6 +1,9 @@ #ifndef ANALYSISMETHOD_H #define ANALYSISMETHOD_H +#include "helpers/analysisIO.h" + +namespace TIMEFREQUENCYLIB { class AnalysisMethod { @@ -9,7 +12,8 @@ class AnalysisMethod virtual bool compute() = 0; virtual bool validateSettings() = 0; + virtual TimeFrequencyResult getResult() = 0; }; - +}//namespace #endif // ANALYSISMETHOD_H diff --git a/libraries/timefrequency/convolver.cpp b/libraries/timefrequency/methods/helpers/convolver.cpp similarity index 100% rename from libraries/timefrequency/convolver.cpp rename to libraries/timefrequency/methods/helpers/convolver.cpp diff --git a/libraries/timefrequency/convolver.h b/libraries/timefrequency/methods/helpers/convolver.h similarity index 100% rename from libraries/timefrequency/convolver.h rename to libraries/timefrequency/methods/helpers/convolver.h diff --git a/libraries/timefrequency/methods/helpers/morlet.cpp b/libraries/timefrequency/methods/helpers/morlet.cpp deleted file mode 100644 index 698df06b0cf..00000000000 --- a/libraries/timefrequency/methods/helpers/morlet.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "morlet.h" - -Morlet::Morlet() -{ - -} diff --git a/libraries/timefrequency/methods/helpers/morlet.h b/libraries/timefrequency/methods/helpers/morlet.h index 8a4bdde0701..d465e070db3 100644 --- a/libraries/timefrequency/methods/helpers/morlet.h +++ b/libraries/timefrequency/methods/helpers/morlet.h @@ -1,11 +1,72 @@ -#ifndef MORLET_H -#define MORLET_H +#pragma once +#include +#include +#include +namespace TIMEFREQUENCYLIB { -class Morlet +static float morlet_SD_factor = 2.5f; +static float morlet_SD_spread = 6; +static float pi_f = 3.14159265359f; + +class morlet { public: - Morlet(); + morlet(float center_freq, float cycle_count, float sampling_rate) + { + float SD = (cycle_count / 2) * (1 / center_freq) / morlet_SD_factor; + int wl_size = int(2 * std::floor(std::round(SD * sampling_rate * morlet_SD_spread) / 2) + 1); + int half_size = wl_size / 2; + + _data.resize(wl_size); + float integral; + std::vector gauss(std::move(gausswin(wl_size, morlet_SD_spread / 2, integral))); + + float igsum = 1.f / integral; + float isd = 1.f / sampling_rate; + + for (int i = 0; i < wl_size; ++i) + { + float t = (i - half_size) * isd; + _data[i] = gauss[i] * expj(2 * pi_f * center_freq * t) * igsum; + } + } + + + int size() { return int(_data.size()); } + + std::complex* data() { return _data.data(); } + + +protected: + static std::vector gausswin(int n, float alpha, float& integral) + { + int halfsize = n / 2; + float idiv = alpha / halfsize; + + std::vector result(n); + double acc = 0; + for (int i = 0; i < n; ++i) + { + float t = (i - halfsize) * idiv; + result[i] = std::exp(-(t * t) * 0.5f); + acc += result[i]; + } + + integral = float(acc); + return result; + } + + static std::complex expj(float arg) + { + return std::complex(std::cos(arg), std::sin(arg)); + } + + + + std::vector> _data; + + }; -#endif // MORLET_H +} diff --git a/libraries/timefrequency/methods/superlets.cpp b/libraries/timefrequency/methods/superlets.cpp index 7d021b7ce00..0b94e0e7e30 100644 --- a/libraries/timefrequency/methods/superlets.cpp +++ b/libraries/timefrequency/methods/superlets.cpp @@ -1,6 +1,9 @@ #include "superlets.h" -Superlets::Superlets() +using namespace TIMEFREQUENCYLIB; + +Superlets::Superlets(SuperletSettings& settings) + : m_settings(settings) { } diff --git a/libraries/timefrequency/methods/superlets.h b/libraries/timefrequency/methods/superlets.h index 1fa2de0f8ff..68434d8a7d5 100644 --- a/libraries/timefrequency/methods/superlets.h +++ b/libraries/timefrequency/methods/superlets.h @@ -2,8 +2,12 @@ #define SUPERLETS_H #include "analysismethod.h" + #include "helpers/analysisIO.h" #include "helpers/morlet.h" +#include "helpers/convolver.h" + +#include namespace TIMEFREQUENCYLIB { @@ -16,11 +20,24 @@ struct SuperletSettings : public AnalysisSettings{ class Superlets : public AnalysisMethod { + using filter_bank = std::vector; + using superlet = std::vector; public: - Superlets(); + Superlets() = delete; + Superlets(SuperletSettings& settings); virtual bool compute(); virtual bool validateSettings(); + +protected: + SuperletSettings& m_settings; + std::vector m_filters; + std::vector m_superlets; + std::vector> m_conv_buffer; + std::vector m_pooling_buffer; + std::vector m_frequencies; + std::vector m_orders; + }; } //namespace diff --git a/libraries/timefrequency/morlet.h b/libraries/timefrequency/morlet.h deleted file mode 100644 index d465e070db3..00000000000 --- a/libraries/timefrequency/morlet.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#include -#include -#include - -namespace TIMEFREQUENCYLIB { - -static float morlet_SD_factor = 2.5f; -static float morlet_SD_spread = 6; -static float pi_f = 3.14159265359f; - -class morlet -{ -public: - morlet(float center_freq, float cycle_count, float sampling_rate) - { - float SD = (cycle_count / 2) * (1 / center_freq) / morlet_SD_factor; - int wl_size = int(2 * std::floor(std::round(SD * sampling_rate * morlet_SD_spread) / 2) + 1); - int half_size = wl_size / 2; - - _data.resize(wl_size); - float integral; - std::vector gauss(std::move(gausswin(wl_size, morlet_SD_spread / 2, integral))); - - float igsum = 1.f / integral; - float isd = 1.f / sampling_rate; - - for (int i = 0; i < wl_size; ++i) - { - float t = (i - half_size) * isd; - _data[i] = gauss[i] * expj(2 * pi_f * center_freq * t) * igsum; - } - } - - - int size() { return int(_data.size()); } - - std::complex* data() { return _data.data(); } - - -protected: - static std::vector gausswin(int n, float alpha, float& integral) - { - int halfsize = n / 2; - float idiv = alpha / halfsize; - - std::vector result(n); - double acc = 0; - for (int i = 0; i < n; ++i) - { - float t = (i - halfsize) * idiv; - result[i] = std::exp(-(t * t) * 0.5f); - acc += result[i]; - } - - integral = float(acc); - return result; - } - - static std::complex expj(float arg) - { - return std::complex(std::cos(arg), std::sin(arg)); - } - - - - std::vector> _data; - - -}; - -} diff --git a/libraries/timefrequency/timefrequency.pro b/libraries/timefrequency/timefrequency.pro index 81fe1e96657..ec48d9c7339 100644 --- a/libraries/timefrequency/timefrequency.pro +++ b/libraries/timefrequency/timefrequency.pro @@ -33,7 +33,7 @@ CONFIG(debug, debug|release) { } SOURCES += \ - convolver.cpp \ + methods/helpers/convolver.cpp \ interface.cpp \ methods/helpers/morlet.cpp \ methods/superlets.cpp \ @@ -42,12 +42,11 @@ SOURCES += \ HEADERS += \ - convolver.h \ + methods/helpers/convolver.h \ methods/analysismethod.h \ methods/helpers/analysisIO.h \ methods/helpers/morlet.h \ methods/superlets.h \ - morlet.h \ timefrequencyanalyzer.h \ wavelet_spectrum_analyzer.h diff --git a/libraries/timefrequency/timefrequencyanalyzer.cpp b/libraries/timefrequency/timefrequencyanalyzer.cpp index 5cdaec0f8ae..a94b48a874b 100644 --- a/libraries/timefrequency/timefrequencyanalyzer.cpp +++ b/libraries/timefrequency/timefrequencyanalyzer.cpp @@ -20,3 +20,8 @@ bool TimeFrequencyAnalyzer::run() return validRun; } + +TimeFrequencyResult TimeFrequencyAnalyzer::getResult() +{ + return m_method.getResult(); +} From 008d8a40defd1fad12e636380da4f64d0fd22cf1 Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Tue, 18 May 2021 11:03:56 -0400 Subject: [PATCH 53/57] ENG: load data in example --- examples/ex_disp/ex_disp.pro | 1 - .../ex_time_frequency/ex_time_frequency.pro | 103 ++++++++++--- examples/ex_time_frequency/main.cpp | 138 +++++++++++++++++- 3 files changed, 217 insertions(+), 25 deletions(-) diff --git a/examples/ex_disp/ex_disp.pro b/examples/ex_disp/ex_disp.pro index ea126b2661d..dd39ec1b57f 100644 --- a/examples/ex_disp/ex_disp.pro +++ b/examples/ex_disp/ex_disp.pro @@ -113,4 +113,3 @@ contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { -lfftw3_threads \ } } - diff --git a/examples/ex_time_frequency/ex_time_frequency.pro b/examples/ex_time_frequency/ex_time_frequency.pro index a0e3fda166b..6679017084a 100644 --- a/examples/ex_time_frequency/ex_time_frequency.pro +++ b/examples/ex_time_frequency/ex_time_frequency.pro @@ -1,23 +1,84 @@ QT -= gui -CONFIG += c++11 console -CONFIG -= app_bundle - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -SOURCES += \ - main.cpp - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target +include(../../mne-cpp.pri) + +TEMPLATE = app + +QT += core gui charts opengl widgets concurrent network + +CONFIG += console +!contains(MNECPP_CONFIG, withAppBundles) { + CONFIG -= app_bundle +} + +DESTDIR = $${MNE_BINARY_DIR} + +TARGET = ex_time_frequency +CONFIG(debug, debug|release) { + TARGET = $$join(TARGET,,,d) +} + +contains(MNECPP_CONFIG, static) { + CONFIG += static + DEFINES += STATICBUILD +} + +LIBS += -L$${MNE_LIBRARY_DIR} +CONFIG(debug, debug|release) { + LIBS += -lmnecppDispd \ + -lmnecppEventsd \ + -lmnecppRtProcessingd \ + -lmnecppConnectivityd \ + -lmnecppInversed \ + -lmnecppFwdd \ + -lmnecppMned \ + -lmnecppFiffd \ + -lmnecppFsd \ + -lmnecppUtilsd \ + -lmnecppTimeFrequencyd \ +} else { + LIBS += -lmnecppDisp \ + -lmnecppEvents \ + -lmnecppRtProcessing \ + -lmnecppConnectivity \ + -lmnecppInverse \ + -lmnecppFwd \ + -lmnecppMne \ + -lmnecppFiff \ + -lmnecppFs \ + -lmnecppUtils \ + -lmnecppTimeFrequency \ +} + +SOURCES += main.cpp + +INCLUDEPATH += $${EIGEN_INCLUDE_DIR} +INCLUDEPATH += $${MNE_INCLUDE_DIR} + +unix:!macx { + QMAKE_RPATHDIR += $ORIGIN/../lib +} + +macx { + QMAKE_LFLAGS += -Wl,-rpath,@executable_path/../lib +} + +# Activate FFTW backend in Eigen for non-static builds only +contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { + DEFINES += EIGEN_FFTW_DEFAULT + INCLUDEPATH += $$shell_path($${FFTW_DIR_INCLUDE}) + LIBS += -L$$shell_path($${FFTW_DIR_LIBS}) + + win32 { + # On Windows + LIBS += -llibfftw3-3 \ + -llibfftw3f-3 \ + -llibfftw3l-3 \ + } + + unix:!macx { + # On Linux + LIBS += -lfftw3 \ + -lfftw3_threads \ + } +} diff --git a/examples/ex_time_frequency/main.cpp b/examples/ex_time_frequency/main.cpp index 470a0307e24..432d94d540a 100644 --- a/examples/ex_time_frequency/main.cpp +++ b/examples/ex_time_frequency/main.cpp @@ -1,8 +1,140 @@ -#include + +//============================================================================================================= +// INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// Eigen +//============================================================================================================= + +#include + +//============================================================================================================= +// QT INCLUDES +//============================================================================================================= + +#include +#include + +//============================================================================================================= +// MAIN +//============================================================================================================= int main(int argc, char *argv[]) { - QCoreApplication a(argc, argv); + QApplication app(argc, argv); + + QCommandLineParser parser; + parser.setApplicationDescription("TF Example"); + parser.addHelpOption(); + + QCommandLineOption inputOption("fileIn", "The input file .", "in", QCoreApplication::applicationDirPath() + "/MNE-sample-data/MEG/sample/sample_audvis_raw.fif"); + parser.addOption(inputOption); + + QCommandLineOption fromOption("from", "Read data from (in seconds).", "from", "42.956"); + parser.addOption(fromOption); + + QCommandLineOption toOption("to", "Read data from (in seconds).", "to", "320.670"); + parser.addOption(toOption); + + parser.process(app); + + QFile t_fileRaw(parser.value(inputOption)); + + float from = parser.value(fromOption).toFloat(); + float to = parser.value(toOption).toFloat(); + + bool in_samples = false; + bool keep_comp = false; + + + FIFFLIB::FiffRawData raw(t_fileRaw); + + // + // Set up pick list: MEG + STI 014 - bad channels + // + // + QStringList include; + include << "STI 014"; + bool want_meg = true; + bool want_eeg = false; + bool want_stim = false; + + Eigen::RowVectorXi picks = raw.info.pick_types(want_meg, want_eeg, want_stim, include, raw.info.bads); + + // + // Set up projection + // + qint32 k = 0; + if (raw.info.projs.size() == 0) + qInfo("No projector specified for these data\n"); + else + { + // + // Activate the projection items + // + for (k = 0; k < raw.info.projs.size(); ++k) + raw.info.projs[k].active = true; + + qInfo("%d projection items activated\n",raw.info.projs.size()); + // + // Create the projector + // + FIFFLIB::fiff_int_t nproj = raw.info.make_projector(raw.proj); + + if (nproj == 0) + qWarning("The projection vectors do not apply to these channels\n"); + else + qInfo("Created an SSP operator (subspace dimension = %d)\n",nproj); + } + + // + // Set up the CTF compensator + // + qint32 current_comp = raw.info.get_current_comp(); + qint32 dest_comp = 0; + + if (current_comp > 0) + qInfo("Current compensation grade : %d\n",current_comp); + + if (keep_comp) + dest_comp = current_comp; + + if (current_comp != dest_comp) + { + if(MNELIB::MNE::make_compensator(raw.info, current_comp, dest_comp, raw.comp)) + { + raw.info.set_current_comp(dest_comp); + qInfo("Appropriate compensator added to change to grade %d.\n",dest_comp); + } + else + { + qWarning("Could not make the compensator\n"); + return -1; + } + } + // + // Read a data segment + // times output argument is optional + // + bool readSuccessful = false; + Eigen::MatrixXd data; + Eigen::MatrixXd times; + if (in_samples) + readSuccessful = raw.read_raw_segment(data, times, (qint32)from, (qint32)to, picks); + else + readSuccessful = raw.read_raw_segment_times(data, times, from, to, picks); + + if (!readSuccessful) + { + qWarning("Could not read raw segment.\n"); + return -1; + } + + //data. - return a.exec(); + return app.exec(); } From 8f37dfdc0a8ad0d2c7242f3dcdbc74b8011bd74f Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Tue, 18 May 2021 11:10:54 -0400 Subject: [PATCH 54/57] ENH: more superlet work --- .../methods/helpers/analysisIO.h | 5 + libraries/timefrequency/methods/superlets.cpp | 97 +++++++++++++++++++ libraries/timefrequency/methods/superlets.h | 9 ++ .../timefrequency/timefrequencyanalyzer.cpp | 1 - .../timefrequency/timefrequencyanalyzer.h | 2 - 5 files changed, 111 insertions(+), 3 deletions(-) diff --git a/libraries/timefrequency/methods/helpers/analysisIO.h b/libraries/timefrequency/methods/helpers/analysisIO.h index 0000bcedaac..9190c2a373d 100644 --- a/libraries/timefrequency/methods/helpers/analysisIO.h +++ b/libraries/timefrequency/methods/helpers/analysisIO.h @@ -15,6 +15,11 @@ struct AnalysisSettings int input_size; }; +class TimeFrequencyInput +{ + TimeFrequencyInput(Eigen::MatrixXd); +}; + class TimeFrequencyResult { template diff --git a/libraries/timefrequency/methods/superlets.cpp b/libraries/timefrequency/methods/superlets.cpp index 0b94e0e7e30..801d2fcbffb 100644 --- a/libraries/timefrequency/methods/superlets.cpp +++ b/libraries/timefrequency/methods/superlets.cpp @@ -1,5 +1,7 @@ #include "superlets.h" +#include + using namespace TIMEFREQUENCYLIB; Superlets::Superlets(SuperletSettings& settings) @@ -7,3 +9,98 @@ Superlets::Superlets(SuperletSettings& settings) { } + +bool Superlets::validateSettings() +{ + +} + +bool Superlets::compute() +{ + size_t input_size = m_settings.input_size; + + for (size_t i_freq = 0; i_freq < m_superlets.size(); ++i_freq) + { + // initialize the pooling buffer + std::fill(m_pooling_buffer.begin(), m_pooling_buffer.end(), 1.0); + + if (m_superlets[i_freq].size() > 1) + { + // superresolution + size_t n_wavelets = size_t(std::floor(m_orders[i_freq])); + double r_factor = 1.0 / n_wavelets; + + for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) + { + // perform R2C convolution + m_filters[i_freq][i_wave]->conv_r2c_same(input, m_conv_buffer.data()); + + // pool with exponent = 1 + for (size_t i = 0; i < input_size; ++i) + { + m_pooling_buffer[i] *= 2.0 * mag_sqr(m_conv_buffer[i]); + } + } + + // determine if fractional superlet should be used + if (fractional(m_orders[i_freq]) != 0 && // order is fractional + m_set.fractional && // we are allowed to use it + m_superlets[i_freq].size() == n_wavelets + 1 ) // we really have a wavelet available for it + { + double exponent = fractional(m_orders[i_freq]); + r_factor = 1.0 / (n_wavelets + exponent); + + // perform convolution with the last wavelet + m_filters[i_freq].back()->conv_r2c_same(input, m_conv_buffer.data()); + + // pool with fractional exponent + for (size_t i = 0; i < input_size; ++i) + { + m_pooling_buffer[i] *= std::pow(2.0 * mag_sqr(m_conv_buffer[i]), exponent); + } + } + + // perform geometric mean and save to output buffer + for (size_t i = 0; i < input_size; ++i) + { + output[i] += float(std::pow(m_pooling_buffer[i], r_factor)); + } + } + else + { + // standard CWT + m_filters[i_freq].front()->conv_r2c_same(input, m_conv_buffer.data()); + + for (size_t i = 0; i < input_size; ++i) + output[i] += float(2.0 * mag_sqr(m_conv_buffer[i])); + } + + output += input_size; + } +} + +void Superlets::initFromSettings() +{ + m_filters.resize(m_settings.freq_count); + m_superlets.resize(m_settings.freq_count); + m_conv_buffer.resize(m_settings.input_size); + m_pooling_buffer.resize(m_settings.input_size); + + m_frequencies = linspace(m_settings.freq_low, m_settings.freq_high, m_settings.freq_count); + m_orders = linspace(m_settings.resolution_low, m_settings.resolution_high, m_settings.freq_count); +} + +std::vector Superlets::linspace(float from, float to, int n) +{ + +} + +float Superlets::mag_sqr(const std::complex& z) +{ + +} + +float Superlets::fractional(float x) +{ + +} diff --git a/libraries/timefrequency/methods/superlets.h b/libraries/timefrequency/methods/superlets.h index 68434d8a7d5..d8403532715 100644 --- a/libraries/timefrequency/methods/superlets.h +++ b/libraries/timefrequency/methods/superlets.h @@ -30,6 +30,15 @@ class Superlets : public AnalysisMethod virtual bool validateSettings(); protected: + + void initFromSettings(); + + std::vector linspace(float from, float to, int n); + + float mag_sqr(const std::complex& z); + + float fractional(float x); + SuperletSettings& m_settings; std::vector m_filters; std::vector m_superlets; diff --git a/libraries/timefrequency/timefrequencyanalyzer.cpp b/libraries/timefrequency/timefrequencyanalyzer.cpp index a94b48a874b..538450ac684 100644 --- a/libraries/timefrequency/timefrequencyanalyzer.cpp +++ b/libraries/timefrequency/timefrequencyanalyzer.cpp @@ -6,7 +6,6 @@ TimeFrequencyAnalyzer::TimeFrequencyAnalyzer(AnalysisMethod& method) : m_method(method) { - } bool TimeFrequencyAnalyzer::run() diff --git a/libraries/timefrequency/timefrequencyanalyzer.h b/libraries/timefrequency/timefrequencyanalyzer.h index d3d0a5d17e6..4689c4d49f9 100644 --- a/libraries/timefrequency/timefrequencyanalyzer.h +++ b/libraries/timefrequency/timefrequencyanalyzer.h @@ -11,8 +11,6 @@ namespace TIMEFREQUENCYLIB { class TimeFrequencyAnalyzer { public: - TimeFrequencyAnalyzer(); - TimeFrequencyAnalyzer(AnalysisMethod& method); bool run(); From 242b5c74cc87041f8a35764e984e1109631a19a9 Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Thu, 20 May 2021 10:06:59 -0400 Subject: [PATCH 55/57] moving functions to superlets class --- examples/examples.pro | 4 ++-- .../methods/helpers/analysisIO.h | 8 +++----- libraries/timefrequency/methods/superlets.cpp | 20 +++++++++++++++++++ libraries/timefrequency/methods/superlets.h | 3 +++ .../timefrequency/timefrequencyanalyzer.cpp | 3 ++- .../timefrequency/timefrequencyanalyzer.h | 6 +++++- 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/examples/examples.pro b/examples/examples.pro index c5090fc120c..364dbf651f8 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -62,8 +62,8 @@ SUBDIRS += \ ex_read_evoked \ ex_read_fwd \ ex_read_raw \ - ex_read_write_raw \ \ - ex_time_frequency + ex_read_write_raw \ + ex_time_frequency \ qtHaveModule(charts) { SUBDIRS += \ diff --git a/libraries/timefrequency/methods/helpers/analysisIO.h b/libraries/timefrequency/methods/helpers/analysisIO.h index 9190c2a373d..bd796cf3213 100644 --- a/libraries/timefrequency/methods/helpers/analysisIO.h +++ b/libraries/timefrequency/methods/helpers/analysisIO.h @@ -6,7 +6,6 @@ namespace TIMEFREQUENCYLIB { -} struct AnalysisSettings { float sampling_rate; @@ -15,18 +14,17 @@ struct AnalysisSettings int input_size; }; -class TimeFrequencyInput +struct TimeFrequencyInput { TimeFrequencyInput(Eigen::MatrixXd); }; -class TimeFrequencyResult +struct TimeFrequencyResult { template std::complex getArray(); Eigen::MatrixXcd getEigenMatrix(); }; - -//namespace +}//namepace #endif // ANALYSISSETTINGS_H diff --git a/libraries/timefrequency/methods/superlets.cpp b/libraries/timefrequency/methods/superlets.cpp index 801d2fcbffb..f5d9e6bb735 100644 --- a/libraries/timefrequency/methods/superlets.cpp +++ b/libraries/timefrequency/methods/superlets.cpp @@ -88,6 +88,26 @@ void Superlets::initFromSettings() m_frequencies = linspace(m_settings.freq_low, m_settings.freq_high, m_settings.freq_count); m_orders = linspace(m_settings.resolution_low, m_settings.resolution_high, m_settings.freq_count); + + if (!m_settings.fractional) + std::transform(m_orders.begin(), m_orders.end(), m_orders.begin(), std::roundf); + + for (size_t i_freq = 0; i_freq < m_settings.freq_count; ++i_freq) + { + float center_freq = m_frequencies[i_freq]; + int n_wavelets = int(std::ceil(m_orders[i_freq])); + + for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) + { + float ncyc = m_settings.multiplicative + ? (i_wave + 1) * m_settings.wavelet_cycles + : m_settings.wavelet_cycles + i_wave; + + m_superlets[i_freq] .emplace_back(center_freq, ncyc, m_settings.sampling_rate); + m_filters[i_freq] .push_back(new convolver(m_settings.input_size, m_superlets[i_freq].back().size())); + m_filters[i_freq] .back()->assign_kernel(m_superlets[i_freq].back().data(), m_superlets[i_freq].back().size()); + } + } } std::vector Superlets::linspace(float from, float to, int n) diff --git a/libraries/timefrequency/methods/superlets.h b/libraries/timefrequency/methods/superlets.h index d8403532715..1bd9dcd70d9 100644 --- a/libraries/timefrequency/methods/superlets.h +++ b/libraries/timefrequency/methods/superlets.h @@ -16,6 +16,9 @@ struct SuperletSettings : public AnalysisSettings{ float wavelet_cycles; float resolution_low; float resolution_high; + + bool multiplicative; + bool fractional; }; class Superlets : public AnalysisMethod diff --git a/libraries/timefrequency/timefrequencyanalyzer.cpp b/libraries/timefrequency/timefrequencyanalyzer.cpp index 538450ac684..a8b356a8869 100644 --- a/libraries/timefrequency/timefrequencyanalyzer.cpp +++ b/libraries/timefrequency/timefrequencyanalyzer.cpp @@ -20,7 +20,8 @@ bool TimeFrequencyAnalyzer::run() return validRun; } -TimeFrequencyResult TimeFrequencyAnalyzer::getResult() +TimeFrequencyResult TimeFrequencyAnalyzer::getResult() const { return m_method.getResult(); } + diff --git a/libraries/timefrequency/timefrequencyanalyzer.h b/libraries/timefrequency/timefrequencyanalyzer.h index 4689c4d49f9..a3252cba99d 100644 --- a/libraries/timefrequency/timefrequencyanalyzer.h +++ b/libraries/timefrequency/timefrequencyanalyzer.h @@ -15,7 +15,11 @@ class TimeFrequencyAnalyzer bool run(); - TimeFrequencyResult getResult(); + TimeFrequencyResult compute(TimeFrequencyInput input); + + bool setInput(const TimeFrequencyInput& data); + + TimeFrequencyResult getResult() const; private: AnalysisMethod& m_method; From dca3670cdb0776769d973aca4b8d5fc2ab039f0a Mon Sep 17 00:00:00 2001 From: gabrielbmotta Date: Mon, 24 May 2021 10:28:14 -0400 Subject: [PATCH 56/57] change input --- examples/ex_time_frequency/main.cpp | 5 +++++ libraries/timefrequency/methods/analysismethod.h | 3 +-- libraries/timefrequency/methods/superlets.cpp | 4 ++-- libraries/timefrequency/methods/superlets.h | 2 +- libraries/timefrequency/timefrequencyanalyzer.cpp | 15 ++++----------- libraries/timefrequency/timefrequencyanalyzer.h | 6 ------ 6 files changed, 13 insertions(+), 22 deletions(-) diff --git a/examples/ex_time_frequency/main.cpp b/examples/ex_time_frequency/main.cpp index 432d94d540a..cda8169808a 100644 --- a/examples/ex_time_frequency/main.cpp +++ b/examples/ex_time_frequency/main.cpp @@ -19,6 +19,9 @@ #include #include +#include +#include + //============================================================================================================= // MAIN //============================================================================================================= @@ -134,6 +137,8 @@ int main(int argc, char *argv[]) return -1; } + + TIMEFREQUENCYLIB::TimeFrequencyAnalyzer analyzer(TIMEFREQUENCYLIB::SuperletSettings); //data. return app.exec(); diff --git a/libraries/timefrequency/methods/analysismethod.h b/libraries/timefrequency/methods/analysismethod.h index ea55d23ac53..c4f801d6a77 100644 --- a/libraries/timefrequency/methods/analysismethod.h +++ b/libraries/timefrequency/methods/analysismethod.h @@ -10,10 +10,9 @@ class AnalysisMethod public: AnalysisMethod() = default; - virtual bool compute() = 0; + virtual bool compute(TimeFrequencyInput input, TimeFrequencyResult output) = 0; virtual bool validateSettings() = 0; virtual TimeFrequencyResult getResult() = 0; - }; }//namespace #endif // ANALYSISMETHOD_H diff --git a/libraries/timefrequency/methods/superlets.cpp b/libraries/timefrequency/methods/superlets.cpp index f5d9e6bb735..9c0530c3bcb 100644 --- a/libraries/timefrequency/methods/superlets.cpp +++ b/libraries/timefrequency/methods/superlets.cpp @@ -15,7 +15,7 @@ bool Superlets::validateSettings() } -bool Superlets::compute() +bool Superlets::compute(TimeFrequencyInput* input, TimeFrequencyResult* output) { size_t input_size = m_settings.input_size; @@ -44,7 +44,7 @@ bool Superlets::compute() // determine if fractional superlet should be used if (fractional(m_orders[i_freq]) != 0 && // order is fractional - m_set.fractional && // we are allowed to use it + m_settings.fractional && // we are allowed to use it m_superlets[i_freq].size() == n_wavelets + 1 ) // we really have a wavelet available for it { double exponent = fractional(m_orders[i_freq]); diff --git a/libraries/timefrequency/methods/superlets.h b/libraries/timefrequency/methods/superlets.h index 1bd9dcd70d9..9e77f71c113 100644 --- a/libraries/timefrequency/methods/superlets.h +++ b/libraries/timefrequency/methods/superlets.h @@ -29,7 +29,7 @@ class Superlets : public AnalysisMethod Superlets() = delete; Superlets(SuperletSettings& settings); - virtual bool compute(); + virtual bool compute(TimeFrequencyInput input, TimeFrequencyResult output); virtual bool validateSettings(); protected: diff --git a/libraries/timefrequency/timefrequencyanalyzer.cpp b/libraries/timefrequency/timefrequencyanalyzer.cpp index a8b356a8869..6f7d7b256cc 100644 --- a/libraries/timefrequency/timefrequencyanalyzer.cpp +++ b/libraries/timefrequency/timefrequencyanalyzer.cpp @@ -8,20 +8,13 @@ TimeFrequencyAnalyzer::TimeFrequencyAnalyzer(AnalysisMethod& method) } -bool TimeFrequencyAnalyzer::run() +TimeFrequencyResult TimeFrequencyAnalyzer::compute(TimeFrequencyInput input) { - bool validRun = false; bool validSettings = m_method.validateSettings(); + TimeFrequencyResult output; + if(validSettings){ - validRun = m_method.compute(); + m_method.compute(input, output); } - - return validRun; -} - -TimeFrequencyResult TimeFrequencyAnalyzer::getResult() const -{ - return m_method.getResult(); } - diff --git a/libraries/timefrequency/timefrequencyanalyzer.h b/libraries/timefrequency/timefrequencyanalyzer.h index a3252cba99d..f700ab77ab3 100644 --- a/libraries/timefrequency/timefrequencyanalyzer.h +++ b/libraries/timefrequency/timefrequencyanalyzer.h @@ -13,14 +13,8 @@ class TimeFrequencyAnalyzer public: TimeFrequencyAnalyzer(AnalysisMethod& method); - bool run(); - TimeFrequencyResult compute(TimeFrequencyInput input); - bool setInput(const TimeFrequencyInput& data); - - TimeFrequencyResult getResult() const; - private: AnalysisMethod& m_method; }; From ac8d2d8f6071df393d29167baa312c9be53650a9 Mon Sep 17 00:00:00 2001 From: Gabriel B Motta Date: Mon, 24 May 2021 14:40:40 -0400 Subject: [PATCH 57/57] remove tracer and unused sections of supelets to get project to build. --- applications/mne_analyze/mne_analyze/main.cpp | 3 - .../plugins/timefrequency/timefrequency.cpp | 3 +- libraries/rtprocessing/timefrequency.cpp | 7 - libraries/timefrequency/interface.cpp | 402 +++++++++--------- .../methods/helpers/convolver.cpp | 6 +- libraries/timefrequency/methods/superlets.cpp | 139 +++--- libraries/timefrequency/timefrequency.pro | 5 +- .../wavelet_spectrum_analyzer.cpp | 298 ++++++------- .../timefrequency/wavelet_spectrum_analyzer.h | 88 ++-- libraries/utils/spectrogram.cpp | 8 - libraries/utils/utils.pro | 2 - 11 files changed, 475 insertions(+), 486 deletions(-) diff --git a/applications/mne_analyze/mne_analyze/main.cpp b/applications/mne_analyze/mne_analyze/main.cpp index 26a31309f3f..9d8b5825102 100644 --- a/applications/mne_analyze/mne_analyze/main.cpp +++ b/applications/mne_analyze/mne_analyze/main.cpp @@ -42,7 +42,6 @@ #include "info.h" #include "analyzecore.h" -#include "utils/tracer.h" //============================================================================================================= // Qt INCLUDES @@ -89,7 +88,6 @@ Q_IMPORT_PLUGIN(TimeFrequency) int main(int argc, char *argv[]) { - __TRACER_ENABLE // When building a static version of MNE Analyze we have to init all resource (.qrc) files here manually #ifdef STATICBUILD #ifndef WASMBUILD @@ -113,7 +111,6 @@ int main(int argc, char *argv[]) pAnalyzeCore->showMainWindow(); int main_return_value(app.exec()); - __TRACER_DISABLE return main_return_value; } diff --git a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp index e326a9c22b8..6b017b4e60c 100644 --- a/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp +++ b/applications/mne_analyze/plugins/timefrequency/timefrequency.cpp @@ -56,7 +56,7 @@ #include #include -#include + //============================================================================================================= // USED NAMESPACES //============================================================================================================= @@ -267,7 +267,6 @@ void TimeFrequency::setChannelSelection(const QVariant &data) void TimeFrequency::computeTimeFreqency() { - __TRACE_FUNC(); qDebug() << "[TimeFrequency::computeTimeFreqency]"; if (!m_pFiffRawModel){ return; diff --git a/libraries/rtprocessing/timefrequency.cpp b/libraries/rtprocessing/timefrequency.cpp index f5a3a59442c..5a4acf52f4f 100644 --- a/libraries/rtprocessing/timefrequency.cpp +++ b/libraries/rtprocessing/timefrequency.cpp @@ -46,7 +46,6 @@ #include #include -#include //============================================================================================================= // QT INCLUDES @@ -68,7 +67,6 @@ using namespace RTPROCESSINGLIB; std::vector TimeFrequencyData::computeEpochListTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { - __TRACE_FUNC(); qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; int a = 0; @@ -97,7 +95,6 @@ std::vector TimeFrequencyData::computeEpochListTimeFrequency(co std::vector TimeFrequencyData::computeComplexTimeFrequency(const FIFFLIB::FiffEvokedSet& evokedSet) { - __TRACE_FUNC(); qDebug() << "[RTPROCESSINGLIB::computeTimeFreqency]"; auto& evoked = evokedSet.evoked.first(); @@ -121,7 +118,6 @@ std::vector> TimeFrequencyData::computeEpochListTi float fTMinS, float fTMaxS) { - __TRACE_FUNC(); QMap mapReject; mapReject.insert("eog", 300e-06); int iType = 1; @@ -149,7 +145,6 @@ std::vector> TimeFrequencyData::computeEpochListTi std::vector TimeFrequencyData::computeEpochTimeFrequency(const QSharedPointer& epoch, float sampleFrequency) { - __TRACE_FUNC(); int numChannels(epoch->epoch.rows()); std::vector channelTimeFrequencyList; @@ -169,7 +164,6 @@ std::vector TimeFrequencyData::computeEpochTimeFrequency(const Eigen::MatrixXcd TimeFrequencyData::averageEpochTimeFrequency(const std::vector& epochTimeFrequency) { - __TRACE_FUNC(); if (epochTimeFrequency.empty()){ return Eigen::MatrixXcd(); } @@ -187,7 +181,6 @@ Eigen::MatrixXcd TimeFrequencyData::averageEpochTimeFrequency(const std::vector< std::vector TimeFrequencyData::averageEpochListTimeFrequency(const std::vector >& epochListTimeFrequency) { - __TRACE_FUNC(); int numFreqs(epochListTimeFrequency.front().front().rows()); int numSamples(epochListTimeFrequency.front().front().cols()); diff --git a/libraries/timefrequency/interface.cpp b/libraries/timefrequency/interface.cpp index 161dc3c2ceb..0602746f19f 100644 --- a/libraries/timefrequency/interface.cpp +++ b/libraries/timefrequency/interface.cpp @@ -1,221 +1,215 @@ -#include "wavelet_spectrum_analyzer.h" +//#include "wavelet_spectrum_analyzer.h" -using namespace TIMEFREQUENCYLIB; +//using namespace TIMEFREQUENCYLIB; -#define P_INPUT_DATA 0 -#define P_SAMPLING_RATE 1 -#define P_FREQ_INTERVAL 2 -#define P_FREQ_COUNT 3 -#define P_CYCLE_COUNT 4 -#define P_SUPERRESOLUTION 5 -#define P_MULTIPLICATIVE 6 -#define P_FRACTIONAL 7 +//#define P_INPUT_DATA 0 +//#define P_SAMPLING_RATE 1 +//#define P_FREQ_INTERVAL 2 +//#define P_FREQ_COUNT 3 +//#define P_CYCLE_COUNT 4 +//#define P_SUPERRESOLUTION 5 +//#define P_MULTIPLICATIVE 6 +//#define P_FRACTIONAL 7 -bool is_integer(double x) -{ - return x - (long long)x == 0; -} +//bool is_integer(double x) +//{ +// return x - (long long)x == 0; +//} -int mxGetSize(mxArray* arr) -{ - return arr - ? (int)(mxGetM(arr) * mxGetN(arr)) - : 0; -} +//int mxGetSize(mxArray* arr) +//{ +// return arr +// ? (int)(mxGetM(arr) * mxGetN(arr)) +// : 0; +//} -//void validate_params(int nrhs, mxArray** prhs) +////void validate_params(int nrhs, mxArray** prhs) +////{ +//// // check params +//// if (nrhs < 6) +//// mexErrMsgTxt("Parameter count not met! faslt expects at least 6 parameters! See below...\n \ +//// 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ +//// 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ +//// 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ +//// 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ +//// 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ +//// 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ +//// 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ +//// 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); +//// if (nrhs > 8) +//// mexErrMsgTxt("Parameter count exceeded! faslt expects at most 8 parameters! See below...\n \ +//// 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ +//// 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ +//// 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ +//// 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ +//// 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ +//// 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ +//// 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ +//// 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); + +//// // check data +//// if (!mxIsDouble(prhs[P_INPUT_DATA])) +//// mexErrMsgTxt("input_data needs to be a real-valued (double) matrix"); + +//// // check input size +//// if (!mxGetN(prhs[P_INPUT_DATA]) == 1) +//// mexErrMsgTxt("input_data is a column vector. faslt only accepts row vectors."); + +//// // check FS +//// if (mxGetScalar(prhs[P_SAMPLING_RATE]) <= 0.0) +//// mexErrMsgTxt("sampling_rate needs to be a positive non-zero scalar representing the sampling frequency of the input in Hz"); + +//// // check freq interval +//// if (!mxIsDouble(prhs[P_FREQ_INTERVAL]) || mxGetSize(prhs[P_FREQ_INTERVAL]) != 2) +//// mexErrMsgTxt("frequency_interval needs to be a tuple containing the lower and upper frequency bounds in Hz"); +//// else +//// { +//// double lower = mxGetPr(prhs[P_FREQ_INTERVAL])[0]; +//// double upper = mxGetPr(prhs[P_FREQ_INTERVAL])[1]; +//// double fs = mxGetScalar(prhs[P_SAMPLING_RATE]); + +//// if (lower <= 0 || lower >= fs / 2 || +//// upper <= 0 || upper >= fs / 2) +//// mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); +//// } + +//// // check frequency count +//// if (!is_integer(mxGetScalar(prhs[P_FREQ_COUNT])) || mxGetScalar(prhs[P_FREQ_COUNT]) <= 0) +//// mexErrMsgTxt("frequency_count needs to be a positive non-zero integer"); + +//// // check cycle count +//// if (mxGetScalar(prhs[P_CYCLE_COUNT]) <= 0.0) +//// mexErrMsgTxt("cycle_count needs to be a positive non-zero scalar representing the number of cycles of the shortest wavelets"); + +//// // check resolution +//// if (!mxIsDouble(prhs[P_SUPERRESOLUTION]) || mxGetSize(prhs[P_SUPERRESOLUTION]) != 2) +//// mexErrMsgTxt("superresolution needs to be a tuple containing the lower and upper frequency bounds in Hz"); +//// else +//// { +//// if (mxGetPr(prhs[P_SUPERRESOLUTION])[0] <= 0 || mxGetPr(prhs[P_SUPERRESOLUTION])[1] <= 0) +//// mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); +//// } + +//// // check multiplicative +//// if (nrhs > P_MULTIPLICATIVE && mxGetSize(prhs[P_MULTIPLICATIVE]) != 1) +//// mexErrMsgTxt("multiplicative needs to be a scalar (0 - false, !0 otherwise)"); + +//// // check fractional +//// if (nrhs > P_FRACTIONAL && mxGetSize(prhs[P_FRACTIONAL]) != 1) +//// mexErrMsgTxt("fractional needs to be a scalar (0 - false, !0 otherwise)"); +////} + + + +////void print_settings(wavelet_analyzer_settings& set) +////{ +//// mexPrintf("wavelet_analyzer_settings:\n\ +//// sampling_rate: %f\n\ +//// freq_low: %f\n\ +//// freq_high: %f\n\ +//// freq_count: %d\n\ +//// input_size: %d\n\ +//// wavelet_cycles: %f\n\ +//// resolution_low: %f\n\ +//// resolution_high: %f\n\ +//// multiplicative: %s\n\ +//// fractional: %s\n", +//// set.sampling_rate, +//// set.freq_low, +//// set.freq_high, +//// set.freq_count, +//// set.input_size, +//// set.wavelet_cycles, +//// set.resolution_low, +//// set.resolution_high, +//// set.multiplicative ? "true" : "false", +//// set.fractional ? "true" : "false"); +////} + + +//void mexFunction(int nlhs, mxArray** plhs, int nrhs, mxArray** prhs) //{ -// // check params -// if (nrhs < 6) -// mexErrMsgTxt("Parameter count not met! faslt expects at least 6 parameters! See below...\n \ -// 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ -// 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ -// 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ -// 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ -// 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ -// 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ -// 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ -// 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); -// if (nrhs > 8) -// mexErrMsgTxt("Parameter count exceeded! faslt expects at most 8 parameters! See below...\n \ -// 1. input_data - Scalar Matrix - Input buffers (row major) - each row is a trial\n \ -// 2. sampling_rate - Scalar Number - The sampling frequency in Hz\n \ -// 3. frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency\n \ -// 4. frequency_count - Scalar Number - the number of frequency bins in the interval\n \ -// 5. cycle_count - Scalar Number - the number of cycles of the shortest wavelets\n \ -// 6. superresolution_order - Scalar Vector - tuple (vector of size 2) containing the lowest and the highest superresolution orders\n \ -// 7. multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true)\n \ -// 8. fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true)"); - -// // check data -// if (!mxIsDouble(prhs[P_INPUT_DATA])) -// mexErrMsgTxt("input_data needs to be a real-valued (double) matrix"); - -// // check input size -// if (!mxGetN(prhs[P_INPUT_DATA]) == 1) -// mexErrMsgTxt("input_data is a column vector. faslt only accepts row vectors."); - -// // check FS -// if (mxGetScalar(prhs[P_SAMPLING_RATE]) <= 0.0) -// mexErrMsgTxt("sampling_rate needs to be a positive non-zero scalar representing the sampling frequency of the input in Hz"); - -// // check freq interval -// if (!mxIsDouble(prhs[P_FREQ_INTERVAL]) || mxGetSize(prhs[P_FREQ_INTERVAL]) != 2) -// mexErrMsgTxt("frequency_interval needs to be a tuple containing the lower and upper frequency bounds in Hz"); -// else +// // Parameter Name - Parameter Type - Description +// // +// // input_data - Scalar Matrix - Input buffers (row major) - each row is a trial +// // sampling_rate - Scalar Number - The sampling frequency in Hz +// // frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency +// // frequency_count - Integer Number - the number of frequency bins in the interval +// // cycle_count - Scalar Number - the number of cycles of the shortest wavelets +// // superresolution_order - Scalar Vector - tuple containing the lowest and the highest superresolution orders +// // multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true) +// // fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true) +// // +// //Return values +// // S - Scalar Matrix - A matrix of size length(frequencies) x size(input_data, 2) + +// validate_params(nrhs, prhs); + +// // read parameters +// wavelet_analyzer_settings set; + +// // input dimensions +// int input_count = (int)mxGetM(prhs[P_INPUT_DATA]); +// set.input_size = (int)mxGetN(prhs[P_INPUT_DATA]); + +// // sampling rate +// set.sampling_rate = (float)mxGetScalar(prhs[P_SAMPLING_RATE]); + +// // frequencies +// set.freq_low = (float)mxGetPr(prhs[P_FREQ_INTERVAL])[0]; +// set.freq_high = (float)mxGetPr(prhs[P_FREQ_INTERVAL])[1]; +// set.freq_count = (int)mxGetScalar(prhs[P_FREQ_COUNT]); + +// // res order +// set.wavelet_cycles = (float)mxGetScalar(prhs[P_CYCLE_COUNT]); +// set.resolution_low = (float)mxGetPr(prhs[P_SUPERRESOLUTION])[0]; +// set.resolution_high = (float)mxGetPr(prhs[P_SUPERRESOLUTION])[1]; + +// // flags +// set.multiplicative = nrhs > P_MULTIPLICATIVE ? (bool)mxGetScalar(prhs[P_MULTIPLICATIVE]) : true; +// set.fractional = nrhs > P_FRACTIONAL ? (bool)mxGetScalar(prhs[P_FRACTIONAL]) : true; + +// // create output +// nlhs = 1; +// plhs[0] = mxCreateDoubleMatrix(set.freq_count, set.input_size, mxREAL); + +// // alloc temporary buffers (for float conversion and IO) +// float *flt_input_data = static_cast(mxCalloc(set.input_size, sizeof(float))); +// float *flt_result = static_cast(mxCalloc(size_t(set.freq_count) * set.input_size, sizeof(float))); +// double* in_ptr = mxGetPr(prhs[P_INPUT_DATA]); +// double* out_ptr = mxGetPr(plhs[0]); + +// // check buffers +// if (!flt_input_data || !flt_result) // { -// double lower = mxGetPr(prhs[P_FREQ_INTERVAL])[0]; -// double upper = mxGetPr(prhs[P_FREQ_INTERVAL])[1]; -// double fs = mxGetScalar(prhs[P_SAMPLING_RATE]); - -// if (lower <= 0 || lower >= fs / 2 || -// upper <= 0 || upper >= fs / 2) -// mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); +// mexErrMsgTxt("Internal error!"); +// return; // } -// // check frequency count -// if (!is_integer(mxGetScalar(prhs[P_FREQ_COUNT])) || mxGetScalar(prhs[P_FREQ_COUNT]) <= 0) -// mexErrMsgTxt("frequency_count needs to be a positive non-zero integer"); +// // create analyzer +// wavelet_spectrum_analyzer anl(set); -// // check cycle count -// if (mxGetScalar(prhs[P_CYCLE_COUNT]) <= 0.0) -// mexErrMsgTxt("cycle_count needs to be a positive non-zero scalar representing the number of cycles of the shortest wavelets"); - -// // check resolution -// if (!mxIsDouble(prhs[P_SUPERRESOLUTION]) || mxGetSize(prhs[P_SUPERRESOLUTION]) != 2) -// mexErrMsgTxt("superresolution needs to be a tuple containing the lower and upper frequency bounds in Hz"); -// else +// // perform analysis +// for (int i = 0; i < input_count; ++i) // { -// if (mxGetPr(prhs[P_SUPERRESOLUTION])[0] <= 0 || mxGetPr(prhs[P_SUPERRESOLUTION])[1] <= 0) -// mexErrMsgTxt("frequency interval must not include DC (0) and Nyquist (sampling_rate / 2) frequencies"); -// } - -// // check multiplicative -// if (nrhs > P_MULTIPLICATIVE && mxGetSize(prhs[P_MULTIPLICATIVE]) != 1) -// mexErrMsgTxt("multiplicative needs to be a scalar (0 - false, !0 otherwise)"); - -// // check fractional -// if (nrhs > P_FRACTIONAL && mxGetSize(prhs[P_FRACTIONAL]) != 1) -// mexErrMsgTxt("fractional needs to be a scalar (0 - false, !0 otherwise)"); -//} +// for (int j = 0; j < set.input_size; ++j) +// flt_input_data[j] = (float)in_ptr[i + j * input_count]; +// anl.analyze(flt_input_data, flt_result); +// } +// // normalize and copy output +// double idiv = 1.0 / input_count; +// for (int i = 0; i < set.freq_count; ++i) +// { +// for (int j = 0; j < set.input_size; ++j) +// { +// out_ptr[i + j * set.freq_count] = flt_result[i * set.input_size + j] * idiv; +// } +// } -//void print_settings(wavelet_analyzer_settings& set) -//{ -// mexPrintf("wavelet_analyzer_settings:\n\ -// sampling_rate: %f\n\ -// freq_low: %f\n\ -// freq_high: %f\n\ -// freq_count: %d\n\ -// input_size: %d\n\ -// wavelet_cycles: %f\n\ -// resolution_low: %f\n\ -// resolution_high: %f\n\ -// multiplicative: %s\n\ -// fractional: %s\n", -// set.sampling_rate, -// set.freq_low, -// set.freq_high, -// set.freq_count, -// set.input_size, -// set.wavelet_cycles, -// set.resolution_low, -// set.resolution_high, -// set.multiplicative ? "true" : "false", -// set.fractional ? "true" : "false"); +// mxFree(flt_input_data); +// mxFree(flt_result); //} - - -void mexFunction(int nlhs, mxArray** plhs, int nrhs, mxArray** prhs) -{ - // Parameter Name - Parameter Type - Description - // - // input_data - Scalar Matrix - Input buffers (row major) - each row is a trial - // sampling_rate - Scalar Number - The sampling frequency in Hz - // frequency_interval - Scalar Vector - tuple (vector of size 2) containing the lowest and highest frequency - // frequency_count - Integer Number - the number of frequency bins in the interval - // cycle_count - Scalar Number - the number of cycles of the shortest wavelets - // superresolution_order - Scalar Vector - tuple containing the lowest and the highest superresolution orders - // multiplicative - Scalar Number - 0 to use additive superresolution, multiplicative otherwise (default: true) - // fractional - Scalar Number - 0 to use integral ASLT, uses fractional otherwise (default: true) - // - //Return values - // S - Scalar Matrix - A matrix of size length(frequencies) x size(input_data, 2) - - validate_params(nrhs, prhs); - - // read parameters - wavelet_analyzer_settings set; - - // input dimensions - int input_count = (int)mxGetM(prhs[P_INPUT_DATA]); - set.input_size = (int)mxGetN(prhs[P_INPUT_DATA]); - - // sampling rate - set.sampling_rate = (float)mxGetScalar(prhs[P_SAMPLING_RATE]); - - // frequencies - set.freq_low = (float)mxGetPr(prhs[P_FREQ_INTERVAL])[0]; - set.freq_high = (float)mxGetPr(prhs[P_FREQ_INTERVAL])[1]; - set.freq_count = (int)mxGetScalar(prhs[P_FREQ_COUNT]); - - // res order - set.wavelet_cycles = (float)mxGetScalar(prhs[P_CYCLE_COUNT]); - set.resolution_low = (float)mxGetPr(prhs[P_SUPERRESOLUTION])[0]; - set.resolution_high = (float)mxGetPr(prhs[P_SUPERRESOLUTION])[1]; - - // flags - set.multiplicative = nrhs > P_MULTIPLICATIVE ? (bool)mxGetScalar(prhs[P_MULTIPLICATIVE]) : true; - set.fractional = nrhs > P_FRACTIONAL ? (bool)mxGetScalar(prhs[P_FRACTIONAL]) : true; - - // create output - nlhs = 1; - plhs[0] = mxCreateDoubleMatrix(set.freq_count, set.input_size, mxREAL); - - // alloc temporary buffers (for float conversion and IO) - float *flt_input_data = static_cast(mxCalloc(set.input_size, sizeof(float))); - float *flt_result = static_cast(mxCalloc(size_t(set.freq_count) * set.input_size, sizeof(float))); - double* in_ptr = mxGetPr(prhs[P_INPUT_DATA]); - double* out_ptr = mxGetPr(plhs[0]); - - // check buffers - if (!flt_input_data || !flt_result) - { - mexErrMsgTxt("Internal error!"); - return; - } - - // create analyzer - wavelet_spectrum_analyzer anl(set); - - // perform analysis - for (int i = 0; i < input_count; ++i) - { - for (int j = 0; j < set.input_size; ++j) - flt_input_data[j] = (float)in_ptr[i + j * input_count]; - - anl.analyze(flt_input_data, flt_result); - } - - // normalize and copy output - double idiv = 1.0 / input_count; - for (int i = 0; i < set.freq_count; ++i) - { - for (int j = 0; j < set.input_size; ++j) - { - out_ptr[i + j * set.freq_count] = flt_result[i * set.input_size + j] * idiv; - } - } - - mxFree(flt_input_data); - mxFree(flt_result); -} - - - - - - diff --git a/libraries/timefrequency/methods/helpers/convolver.cpp b/libraries/timefrequency/methods/helpers/convolver.cpp index 5718f601bca..278f548ac66 100644 --- a/libraries/timefrequency/methods/helpers/convolver.cpp +++ b/libraries/timefrequency/methods/helpers/convolver.cpp @@ -3,6 +3,7 @@ #include #include +#include using namespace TIMEFREQUENCYLIB; @@ -22,8 +23,7 @@ int nextpow2(int x) return x + 1; } - -__forceinline std::complex conj(const std::complex& z) + std::complex conj(const std::complex& z) { return std::complex(z.real(), -z.imag()); } @@ -136,7 +136,7 @@ void convolver::alloc_fft_buffers(int fft_size) if (!_signal_buffer || !_fft_fwd || !_fft_rev) exit(-1); - memset(_signal_buffer, 0, size_t(_fft_size) * 3 * sizeof(std::complex)); + std::memset(_signal_buffer, 0, size_t(_fft_size) * 3 * sizeof(std::complex)); } diff --git a/libraries/timefrequency/methods/superlets.cpp b/libraries/timefrequency/methods/superlets.cpp index 9c0530c3bcb..45a04fa694a 100644 --- a/libraries/timefrequency/methods/superlets.cpp +++ b/libraries/timefrequency/methods/superlets.cpp @@ -15,68 +15,70 @@ bool Superlets::validateSettings() } -bool Superlets::compute(TimeFrequencyInput* input, TimeFrequencyResult* output) +bool Superlets::compute(TimeFrequencyInput input, TimeFrequencyResult output) { - size_t input_size = m_settings.input_size; - - for (size_t i_freq = 0; i_freq < m_superlets.size(); ++i_freq) - { - // initialize the pooling buffer - std::fill(m_pooling_buffer.begin(), m_pooling_buffer.end(), 1.0); - - if (m_superlets[i_freq].size() > 1) - { - // superresolution - size_t n_wavelets = size_t(std::floor(m_orders[i_freq])); - double r_factor = 1.0 / n_wavelets; - - for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) - { - // perform R2C convolution - m_filters[i_freq][i_wave]->conv_r2c_same(input, m_conv_buffer.data()); - - // pool with exponent = 1 - for (size_t i = 0; i < input_size; ++i) - { - m_pooling_buffer[i] *= 2.0 * mag_sqr(m_conv_buffer[i]); - } - } - - // determine if fractional superlet should be used - if (fractional(m_orders[i_freq]) != 0 && // order is fractional - m_settings.fractional && // we are allowed to use it - m_superlets[i_freq].size() == n_wavelets + 1 ) // we really have a wavelet available for it - { - double exponent = fractional(m_orders[i_freq]); - r_factor = 1.0 / (n_wavelets + exponent); - - // perform convolution with the last wavelet - m_filters[i_freq].back()->conv_r2c_same(input, m_conv_buffer.data()); - - // pool with fractional exponent - for (size_t i = 0; i < input_size; ++i) - { - m_pooling_buffer[i] *= std::pow(2.0 * mag_sqr(m_conv_buffer[i]), exponent); - } - } - - // perform geometric mean and save to output buffer - for (size_t i = 0; i < input_size; ++i) - { - output[i] += float(std::pow(m_pooling_buffer[i], r_factor)); - } - } - else - { - // standard CWT - m_filters[i_freq].front()->conv_r2c_same(input, m_conv_buffer.data()); - - for (size_t i = 0; i < input_size; ++i) - output[i] += float(2.0 * mag_sqr(m_conv_buffer[i])); - } - - output += input_size; - } +// size_t input_size = m_settings.input_size; + +// for (size_t i_freq = 0; i_freq < m_superlets.size(); ++i_freq) +// { +// // initialize the pooling buffer +// std::fill(m_pooling_buffer.begin(), m_pooling_buffer.end(), 1.0); + +// if (m_superlets[i_freq].size() > 1) +// { +// // superresolution +// size_t n_wavelets = size_t(std::floor(m_orders[i_freq])); +// double r_factor = 1.0 / n_wavelets; + +// for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) +// { +// // perform R2C convolution +// m_filters[i_freq][i_wave]->conv_r2c_same(input, m_conv_buffer.data()); + +// // pool with exponent = 1 +// for (size_t i = 0; i < input_size; ++i) +// { +// m_pooling_buffer[i] *= 2.0 * mag_sqr(m_conv_buffer[i]); +// } +// } + +// // determine if fractional superlet should be used +// if (fractional(m_orders[i_freq]) != 0 && // order is fractional +// m_settings.fractional && // we are allowed to use it +// m_superlets[i_freq].size() == n_wavelets + 1 ) // we really have a wavelet available for it +// { +// double exponent = fractional(m_orders[i_freq]); +// r_factor = 1.0 / (n_wavelets + exponent); + +// // perform convolution with the last wavelet +// m_filters[i_freq].back()->conv_r2c_same(input, m_conv_buffer.data()); + +// // pool with fractional exponent +// for (size_t i = 0; i < input_size; ++i) +// { +// m_pooling_buffer[i] *= std::pow(2.0 * mag_sqr(m_conv_buffer[i]), exponent); +// } +// } + +// // perform geometric mean and save to output buffer +// for (size_t i = 0; i < input_size; ++i) +// { +// output[i] += float(std::pow(m_pooling_buffer[i], r_factor)); +// } +// } +// else +// { +// // standard CWT +// m_filters[i_freq].front()->conv_r2c_same(input, m_conv_buffer.data()); + +// for (size_t i = 0; i < input_size; ++i) +// output[i] += float(2.0 * mag_sqr(m_conv_buffer[i])); +// } + +// output += input_size; +// } + + return false; } void Superlets::initFromSettings() @@ -112,15 +114,26 @@ void Superlets::initFromSettings() std::vector Superlets::linspace(float from, float to, int n) { + if (n <= 0) return { }; + else if (n == 1) return { from }; + else + { + std::vector result(n); + + float dv = (to - from) / (n - 1); + for (size_t i = 0; i < result.size(); ++i) + result[i] = from + i * dv; + return result; + } } float Superlets::mag_sqr(const std::complex& z) { - + return z.real() * z.real() + z.imag() * z.imag(); } float Superlets::fractional(float x) { - + return x - (int)x; } diff --git a/libraries/timefrequency/timefrequency.pro b/libraries/timefrequency/timefrequency.pro index ec48d9c7339..e9fe36a250a 100644 --- a/libraries/timefrequency/timefrequency.pro +++ b/libraries/timefrequency/timefrequency.pro @@ -35,7 +35,6 @@ CONFIG(debug, debug|release) { SOURCES += \ methods/helpers/convolver.cpp \ interface.cpp \ - methods/helpers/morlet.cpp \ methods/superlets.cpp \ timefrequencyanalyzer.cpp \ wavelet_spectrum_analyzer.cpp @@ -71,9 +70,13 @@ macx { QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/ } +contains(MNECPP_CONFIG, useFFTW):!contains(MNECPP_CONFIG, static) { win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -llibfftw3f-3 + else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -llibfftw3f-3d + else:unix: LIBS += -L$$PWD/lib/ -llibfftw3f-3 +} INCLUDEPATH += $$PWD/include DEPENDPATH += $$PWD/include diff --git a/libraries/timefrequency/wavelet_spectrum_analyzer.cpp b/libraries/timefrequency/wavelet_spectrum_analyzer.cpp index 4c85d223427..413e25b6f40 100644 --- a/libraries/timefrequency/wavelet_spectrum_analyzer.cpp +++ b/libraries/timefrequency/wavelet_spectrum_analyzer.cpp @@ -1,152 +1,152 @@ -#include "wavelet_spectrum_analyzer.h" -#include - -using namespace TIMEFREQUENCYLIB; - -std::vector linspace(float from, float to, int n) -{ - if (n <= 0) return { }; - else if (n == 1) return { from }; - else - { - std::vector result(n); - - float dv = (to - from) / (n - 1); - for (size_t i = 0; i < result.size(); ++i) - result[i] = from + i * dv; - - return result; - } -} - - -__forceinline float mag_sqr(const std::complex& z) -{ - return z.real() * z.real() + z.imag() * z.imag(); -} - -__forceinline float fractional(float x) -{ - return x - (int)x; -} - - - - -wavelet_spectrum_analyzer::wavelet_spectrum_analyzer(wavelet_analyzer_settings set) -{ - _set = set; - _filters .resize(_set.freq_count); - _superlets .resize(_set.freq_count); - _conv_buffer .resize(_set.input_size); - _pooling_buffer .resize(_set.input_size); - _frequencies = linspace(_set.freq_low, _set.freq_high, _set.freq_count); - _orders = linspace(_set.resolution_low, _set.resolution_high, _set.freq_count); - - if (!_set.fractional) - std::transform(_orders.begin(), _orders.end(), _orders.begin(), std::roundf); - - for (size_t i_freq = 0; i_freq < _set.freq_count; ++i_freq) - { - float center_freq = _frequencies[i_freq]; - int n_wavelets = int(std::ceilf(_orders[i_freq])); - - for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) - { - float ncyc = _set.multiplicative - ? (i_wave + 1) * _set.wavelet_cycles - : _set.wavelet_cycles + i_wave; - - _superlets[i_freq] .emplace_back(center_freq, ncyc, _set.sampling_rate); - _filters[i_freq] .push_back(new convolver(_set.input_size, _superlets[i_freq].back().size())); - _filters[i_freq] .back()->assign_kernel(_superlets[i_freq].back().data(), _superlets[i_freq].back().size()); - } - } -} - -wavelet_spectrum_analyzer::~wavelet_spectrum_analyzer() -{ - for (auto& fb : _filters) - { - for (auto& conv : fb) - delete conv; - fb.clear(); - } - - _filters .clear(); - _superlets .clear(); - _pooling_buffer .clear(); - _frequencies .clear(); - _orders .clear(); - _conv_buffer .clear(); - _set = wavelet_analyzer_settings(); -} - - - -void wavelet_spectrum_analyzer::analyze(float* input, float* output) -{ - size_t input_size = _set.input_size; - - for (size_t i_freq = 0; i_freq < _superlets.size(); ++i_freq) - { - // initialize the pooling buffer - std::fill(_pooling_buffer.begin(), _pooling_buffer.end(), 1.0); - - if (_superlets[i_freq].size() > 1) - { - // superresolution - size_t n_wavelets = size_t(std::floorf(_orders[i_freq])); - double r_factor = 1.0 / n_wavelets; - - for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) - { - // perform R2C convolution - _filters[i_freq][i_wave]->conv_r2c_same(input, _conv_buffer.data()); - - // pool with exponent = 1 - for (size_t i = 0; i < input_size; ++i) - { - _pooling_buffer[i] *= 2.0 * mag_sqr(_conv_buffer[i]); - } - } - - // determine if fractional superlet should be used - if (fractional(_orders[i_freq]) != 0 && // order is fractional - _set.fractional && // we are allowed to use it - _superlets[i_freq].size() == n_wavelets + 1 ) // we really have a wavelet available for it - { - double exponent = fractional(_orders[i_freq]); - r_factor = 1.0 / (n_wavelets + exponent); - - // perform convolution with the last wavelet - _filters[i_freq].back()->conv_r2c_same(input, _conv_buffer.data()); - - // pool with fractional exponent - for (size_t i = 0; i < input_size; ++i) - { - _pooling_buffer[i] *= std::pow(2.0 * mag_sqr(_conv_buffer[i]), exponent); - } - } - - // perform geometric mean and save to output buffer - for (size_t i = 0; i < input_size; ++i) - { - output[i] += float(std::pow(_pooling_buffer[i], r_factor)); - } - } - else - { - // standard CWT - _filters[i_freq].front()->conv_r2c_same(input, _conv_buffer.data()); - - for (size_t i = 0; i < input_size; ++i) - output[i] += float(2.0 * mag_sqr(_conv_buffer[i])); - } - - output += input_size; - } -} +//#include "wavelet_spectrum_analyzer.h" +//#include + +//using namespace TIMEFREQUENCYLIB; + +//std::vector linspace(float from, float to, int n) +//{ +// if (n <= 0) return { }; +// else if (n == 1) return { from }; +// else +// { +// std::vector result(n); + +// float dv = (to - from) / (n - 1); +// for (size_t i = 0; i < result.size(); ++i) +// result[i] = from + i * dv; + +// return result; +// } +//} + + +//__forceinline float mag_sqr(const std::complex& z) +//{ +// return z.real() * z.real() + z.imag() * z.imag(); +//} + +//__forceinline float fractional(float x) +//{ +// return x - (int)x; +//} + + + + +//wavelet_spectrum_analyzer::wavelet_spectrum_analyzer(wavelet_analyzer_settings set) +//{ +// _set = set; +// _filters .resize(_set.freq_count); +// _superlets .resize(_set.freq_count); +// _conv_buffer .resize(_set.input_size); +// _pooling_buffer .resize(_set.input_size); +// _frequencies = linspace(_set.freq_low, _set.freq_high, _set.freq_count); +// _orders = linspace(_set.resolution_low, _set.resolution_high, _set.freq_count); + +// if (!_set.fractional) +// std::transform(_orders.begin(), _orders.end(), _orders.begin(), std::roundf); + +// for (size_t i_freq = 0; i_freq < _set.freq_count; ++i_freq) +// { +// float center_freq = _frequencies[i_freq]; +// int n_wavelets = int(std::ceilf(_orders[i_freq])); + +// for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) +// { +// float ncyc = _set.multiplicative +// ? (i_wave + 1) * _set.wavelet_cycles +// : _set.wavelet_cycles + i_wave; + +// _superlets[i_freq] .emplace_back(center_freq, ncyc, _set.sampling_rate); +// _filters[i_freq] .push_back(new convolver(_set.input_size, _superlets[i_freq].back().size())); +// _filters[i_freq] .back()->assign_kernel(_superlets[i_freq].back().data(), _superlets[i_freq].back().size()); +// } +// } +//} + +//wavelet_spectrum_analyzer::~wavelet_spectrum_analyzer() +//{ +// for (auto& fb : _filters) +// { +// for (auto& conv : fb) +// delete conv; +// fb.clear(); +// } + +// _filters .clear(); +// _superlets .clear(); +// _pooling_buffer .clear(); +// _frequencies .clear(); +// _orders .clear(); +// _conv_buffer .clear(); +// _set = wavelet_analyzer_settings(); +//} + + + +//void wavelet_spectrum_analyzer::analyze(float* input, float* output) +//{ +// size_t input_size = _set.input_size; + +// for (size_t i_freq = 0; i_freq < _superlets.size(); ++i_freq) +// { +// // initialize the pooling buffer +// std::fill(_pooling_buffer.begin(), _pooling_buffer.end(), 1.0); + +// if (_superlets[i_freq].size() > 1) +// { +// // superresolution +// size_t n_wavelets = size_t(std::floorf(_orders[i_freq])); +// double r_factor = 1.0 / n_wavelets; + +// for (size_t i_wave = 0; i_wave < n_wavelets; ++i_wave) +// { +// // perform R2C convolution +// _filters[i_freq][i_wave]->conv_r2c_same(input, _conv_buffer.data()); + +// // pool with exponent = 1 +// for (size_t i = 0; i < input_size; ++i) +// { +// _pooling_buffer[i] *= 2.0 * mag_sqr(_conv_buffer[i]); +// } +// } + +// // determine if fractional superlet should be used +// if (fractional(_orders[i_freq]) != 0 && // order is fractional +// _set.fractional && // we are allowed to use it +// _superlets[i_freq].size() == n_wavelets + 1 ) // we really have a wavelet available for it +// { +// double exponent = fractional(_orders[i_freq]); +// r_factor = 1.0 / (n_wavelets + exponent); + +// // perform convolution with the last wavelet +// _filters[i_freq].back()->conv_r2c_same(input, _conv_buffer.data()); + +// // pool with fractional exponent +// for (size_t i = 0; i < input_size; ++i) +// { +// _pooling_buffer[i] *= std::pow(2.0 * mag_sqr(_conv_buffer[i]), exponent); +// } +// } + +// // perform geometric mean and save to output buffer +// for (size_t i = 0; i < input_size; ++i) +// { +// output[i] += float(std::pow(_pooling_buffer[i], r_factor)); +// } +// } +// else +// { +// // standard CWT +// _filters[i_freq].front()->conv_r2c_same(input, _conv_buffer.data()); + +// for (size_t i = 0; i < input_size; ++i) +// output[i] += float(2.0 * mag_sqr(_conv_buffer[i])); +// } + +// output += input_size; +// } +//} diff --git a/libraries/timefrequency/wavelet_spectrum_analyzer.h b/libraries/timefrequency/wavelet_spectrum_analyzer.h index 128bc3aad25..f903c2711e1 100644 --- a/libraries/timefrequency/wavelet_spectrum_analyzer.h +++ b/libraries/timefrequency/wavelet_spectrum_analyzer.h @@ -1,46 +1,46 @@ #pragma once -#include "morlet.h" -#include "convolver.h" - - -namespace TIMEFREQUENCYLIB { - -struct wavelet_analyzer_settings -{ - float sampling_rate; - float freq_low; - float freq_high; - int freq_count; - int input_size; - float wavelet_cycles; - float resolution_low; - float resolution_high; - bool multiplicative; - bool fractional; -}; - - -class wavelet_spectrum_analyzer -{ - using filter_bank = std::vector; - using superlet = std::vector; - -public: - wavelet_spectrum_analyzer(wavelet_analyzer_settings set); - ~wavelet_spectrum_analyzer(); - - void analyze(float* input, float* output); - -protected: - wavelet_analyzer_settings _set; - std::vector _filters; - std::vector _superlets; - std::vector> _conv_buffer; - std::vector _pooling_buffer; - std::vector _frequencies; - std::vector _orders; - -}; - -} +//#include "morlet.h" +//#include "convolver.h" + + +//namespace TIMEFREQUENCYLIB { + +//struct wavelet_analyzer_settings +//{ +// float sampling_rate; +// float freq_low; +// float freq_high; +// int freq_count; +// int input_size; +// float wavelet_cycles; +// float resolution_low; +// float resolution_high; +// bool multiplicative; +// bool fractional; +//}; + + +//class wavelet_spectrum_analyzer +//{ +// using filter_bank = std::vector; +// using superlet = std::vector; + +//public: +// wavelet_spectrum_analyzer(wavelet_analyzer_settings set); +// ~wavelet_spectrum_analyzer(); + +// void analyze(float* input, float* output); + +//protected: +// wavelet_analyzer_settings _set; +// std::vector _filters; +// std::vector _superlets; +// std::vector> _conv_buffer; +// std::vector _pooling_buffer; +// std::vector _frequencies; +// std::vector _orders; + +//}; + +//} diff --git a/libraries/utils/spectrogram.cpp b/libraries/utils/spectrogram.cpp index 4ea6022a481..9a02e1fd102 100644 --- a/libraries/utils/spectrogram.cpp +++ b/libraries/utils/spectrogram.cpp @@ -36,7 +36,6 @@ //============================================================================================================= #include "spectrogram.h" -#include "utils/tracer.h" //============================================================================================================= // EIGEN INCLUDES //============================================================================================================= @@ -69,7 +68,6 @@ MatrixXd Spectrogram::makeSpectrogram(const VectorXd& signal, qint32 windowSize) { //QElapsedTimer timer; //timer.start(); - __TRACE_FUNC(); // signal.array() -= signal.mean(); QList lData; int iThreadSize = QThread::idealThreadCount()*2; @@ -110,7 +108,6 @@ MatrixXcd Spectrogram::makeComplexSpectrogram(const VectorXd& signal, qint32 win { //QElapsedTimer timer; //timer.start(); - __TRACE_FUNC(); // signal.array() -= signal.mean(); QList lData; int iThreadSize = QThread::idealThreadCount(); @@ -147,7 +144,6 @@ MatrixXcd Spectrogram::makeComplexSpectrogram(const VectorXd& signal, qint32 win VectorXd Spectrogram::gaussWindow(qint32 sample_count, qreal scale, quint32 translation) { - __TRACE_FUNC(); VectorXd gauss = VectorXd::Zero(sample_count); for(qint32 n = 0; n < sample_count; n++) @@ -166,7 +162,6 @@ MatrixXd Spectrogram::compute(const SpectogramInputData& inputData) #ifdef EIGEN_FFTW_DEFAULT fftw_make_planner_thread_safe(); #endif - __TRACE_FUNC(); MatrixXd tf_matrix; // Eigen::FFT fft; // MatrixXd tf_matrix = MatrixXd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows()); @@ -199,7 +194,6 @@ MatrixXcd Spectrogram::computeComplex(const SpectogramInputData& inputData) #ifdef EIGEN_FFTW_DEFAULT fftw_make_planner_thread_safe(); #endif - __TRACE_FUNC(); Eigen::FFT fft; MatrixXcd tf_matrix = MatrixXcd::Zero(inputData.vecInputData.rows()/2, inputData.vecInputData.rows()); VectorXd envelope, windowed_sig; @@ -229,7 +223,6 @@ MatrixXcd Spectrogram::computeComplex(const SpectogramInputData& inputData) void Spectrogram::reduce(MatrixXd &resultData, const MatrixXd &data) { - __TRACE_FUNC(); if(resultData.size() == 0) { resultData = data; } else { @@ -242,7 +235,6 @@ void Spectrogram::reduce(MatrixXd &resultData, void Spectrogram::reduceComplex(MatrixXcd &resultData, const MatrixXcd &data) { - __TRACE_FUNC(); if(resultData.size() == 0) { resultData = data; } else { diff --git a/libraries/utils/utils.pro b/libraries/utils/utils.pro index aa7a8bc10af..6f00878640e 100644 --- a/libraries/utils/utils.pro +++ b/libraries/utils/utils.pro @@ -70,7 +70,6 @@ SOURCES += \ layoutmaker.cpp \ selectionio.cpp \ spectrogram.cpp \ -# tracer.cpp \ warp.cpp \ sphere.cpp \ generics/observerpattern.cpp \ @@ -79,7 +78,6 @@ SOURCES += \ HEADERS += \ kmeans.h\ -# tracer.h \ utils_global.h \ mnemath.h \ ioutils.h \