changeset 1392:667e369cfeab

LogRange tests
author Chris Cannam
date Tue, 28 Feb 2017 11:21:49 +0000
parents 2c0e04062a99
children 04abe8f73b22
files base/LogRange.cpp base/LogRange.h base/test/TestLogRange.h base/test/files.pri base/test/svcore-base-test.cpp data/fileio/test/svcore-data-fileio-test.cpp data/model/EditableDenseThreeDimensionalModel.cpp data/model/test/svcore-data-model-test.cpp
diffstat 8 files changed, 357 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/base/LogRange.cpp	Mon Feb 27 16:52:47 2017 +0000
+++ b/base/LogRange.cpp	Tue Feb 28 11:21:49 2017 +0000
@@ -96,7 +96,7 @@
 }
 
 bool
-LogRange::useLogScale(std::vector<double> values)
+LogRange::shouldUseLogScale(std::vector<double> values)
 {
     // Principle: Partition the data into two sets around the median;
     // calculate the standard deviation of each set; if the two SDs
--- a/base/LogRange.h	Mon Feb 27 16:52:47 2017 +0000
+++ b/base/LogRange.h	Tue Feb 28 11:21:49 2017 +0000
@@ -23,14 +23,6 @@
 {
 public:
     /**
-     * Map a linear range onto a logarithmic range.  min and max are
-     * passed as the extents of the linear range and returned as the
-     * extents of the logarithmic range.  thresh is the minimum value
-     * for the log range, to be used if the linear range spans zero.
-     */
-    static void mapRange(double &min, double &max, double thresh = -10);
-
-    /**
      * Map a value onto a logarithmic range.  This just means taking
      * the base-10 log of the absolute value, or using the threshold
      * value if the absolute value is zero.
@@ -44,11 +36,19 @@
     static double unmap(double value);
 
     /**
+     * Map a linear range onto a logarithmic range.  min and max are
+     * passed as the extents of the linear range and returned as the
+     * extents of the logarithmic range.  thresh is the minimum value
+     * for the log range, to be used if the linear range spans zero.
+     */
+    static void mapRange(double &min, double &max, double thresh = -10);
+
+    /**
      * Estimate whether a set of values would be more properly shown
      * using a logarithmic than a linear scale.  This is only ever
      * going to be a rough guess.
      */
-    static bool useLogScale(std::vector<double> values);
+    static bool shouldUseLogScale(std::vector<double> values);
 
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base/test/TestLogRange.h	Tue Feb 28 11:21:49 2017 +0000
@@ -0,0 +1,333 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#ifndef TEST_LOG_RANGE_H
+#define TEST_LOG_RANGE_H
+
+#include "../LogRange.h"
+
+#include <QObject>
+#include <QtTest>
+
+#include <iostream>
+#include <cmath>
+
+using namespace std;
+
+class TestLogRange : public QObject
+{
+    Q_OBJECT
+
+private slots:
+
+    void mapPositiveAboveDefaultThreshold()
+    {
+        QCOMPARE(LogRange::map(10.0), 1.0);
+        QCOMPARE(LogRange::map(100.0), 2.0);
+        QCOMPARE(LogRange::map(0.1), -1.0);
+        QCOMPARE(LogRange::map(1.0), 0.0);
+        QCOMPARE(LogRange::map(0.0000001), -7.0);
+        QCOMPARE(LogRange::map(20.0), log10(20.0));
+    }
+    
+    void mapPositiveAboveSetThreshold()
+    {
+        QCOMPARE(LogRange::map(10.0, -10.0), 1.0);
+        QCOMPARE(LogRange::map(100.0, 1.0), 2.0);
+        QCOMPARE(LogRange::map(0.1, -5.0), -1.0);
+        QCOMPARE(LogRange::map(1.0, -0.01), 0.0);
+        QCOMPARE(LogRange::map(0.0000001, -20.0), -7.0);
+        QCOMPARE(LogRange::map(20.0, 0.0), log10(20.0));
+    }
+
+    void mapZeroDefaultThreshold()
+    {
+        QCOMPARE(LogRange::map(0.0), -10.0);
+    }
+
+    void mapZeroSetThreshold()
+    {
+        QCOMPARE(LogRange::map(0.0, 12.0), 12.0);
+        QCOMPARE(LogRange::map(0.0, -12.0), -12.0);
+        QCOMPARE(LogRange::map(0.0, 0.0), 0.0);
+    }
+    
+    void mapPositiveBelowDefaultThreshold()
+    {
+        // The threshold is used only for zero values, not for very
+        // small ones -- it's arguably a stand-in or replacement value
+        // rather than a threshold. So this should behave the same as
+        // for values above the threshold.
+        QCOMPARE(LogRange::map(1e-10), -10.0);
+        QCOMPARE(LogRange::map(1e-20), -20.0);
+        QCOMPARE(LogRange::map(1e-100), -100.0);
+    }
+
+    void mapPositiveBelowSetThreshold()
+    {
+        // As above
+        QCOMPARE(LogRange::map(10.0, 4.0), 1.0);
+        QCOMPARE(LogRange::map(1e-10, 4.0), -10.0);
+        QCOMPARE(LogRange::map(1e-20, -15.0), -20.0);
+        QCOMPARE(LogRange::map(1e-100, -100.0), -100.0);
+    }
+
+    void mapNegative()
+    {
+        // Should always return map of absolute value. These are
+        // picked from vaarious of the above tests.
+        
+        QCOMPARE(LogRange::map(-10.0), 1.0);
+        QCOMPARE(LogRange::map(-100.0), 2.0);
+        QCOMPARE(LogRange::map(-0.1), -1.0);
+        QCOMPARE(LogRange::map(-1.0), 0.0);
+        QCOMPARE(LogRange::map(-0.0000001), -7.0);
+        QCOMPARE(LogRange::map(-20.0), log10(20.0));
+        QCOMPARE(LogRange::map(-10.0, 4.0), 1.0);
+        QCOMPARE(LogRange::map(-1e-10, 4.0), -10.0);
+        QCOMPARE(LogRange::map(-1e-20, -15.0), -20.0);
+        QCOMPARE(LogRange::map(-1e-100, -100.0), -100.0);
+        QCOMPARE(LogRange::map(-0.0, 12.0), 12.0);
+        QCOMPARE(LogRange::map(-0.0, -12.0), -12.0);
+        QCOMPARE(LogRange::map(-0.0, 0.0), 0.0);
+    }
+
+    void unmap()
+    {
+        // Simply pow(10, x)
+
+        QCOMPARE(LogRange::unmap(0.0), 1.0);
+        QCOMPARE(LogRange::unmap(1.0), 10.0);
+        QCOMPARE(LogRange::unmap(-1.0), 0.1);
+        QCOMPARE(LogRange::unmap(100.0), 1e+100);
+        QCOMPARE(LogRange::unmap(-100.0), 1e-100);
+    }
+
+    void mapRangeAllPositiveDefaultThreshold()
+    {
+        double min, max;
+
+        min = 1.0; max = 10.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
+
+        min = 10.0; max = 1.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
+
+        // if equal, the function uses an arbitrary 1.0 range before mapping
+        min = 10.0; max = 10.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, 1.0); QCOMPARE(max, log10(11.0));
+    }
+
+    void mapRangeAllPositiveSetThreshold()
+    {
+        double min, max;
+
+        min = 1.0; max = 10.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
+
+        min = 10.0; max = 1.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
+
+        // if equal, the function uses an arbitrary 1.0 range before mapping
+        min = 10.0; max = 10.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, 1.0); QCOMPARE(max, log10(11.0));
+    }
+
+    void mapRangeAllNegativeDefaultThreshold()
+    {
+        double min, max;
+
+        min = -1.0; max = -10.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
+
+        min = -10.0; max = -1.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
+
+        // if equal, the function uses an arbitrary 1.0 range before mapping
+        min = -10.0; max = -10.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, log10(9.0)); QCOMPARE(max, 1.0);
+    }
+    
+    void mapRangeAllNegativeSetThreshold()
+    {
+        double min, max;
+
+        min = -1.0; max = -10.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
+
+        min = -10.0; max = -1.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, 0.0); QCOMPARE(max, 1.0);
+
+        // if equal, the function uses an arbitrary 1.0 range before mapping
+        min = -10.0; max = -10.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, log10(9.0)); QCOMPARE(max, 1.0);
+    }
+    
+    void mapRangeAllNonNegativeDefaultThreshold()
+    {
+        double min, max;
+
+        min = 0.0; max = 10.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
+
+        min = 10.0; max = 0.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
+
+        // if equal, the function uses an arbitrary 1.0 range before mapping
+        min = 0.0; max = 0.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 0.0);
+    }
+    
+    void mapRangeAllNonNegativeSetThreshold()
+    {
+        double min, max;
+
+        min = 0.0; max = 10.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
+
+        min = 10.0; max = 0.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
+
+        // if equal, the function uses an arbitrary 1.0 range before mapping
+        min = 0.0; max = 0.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 0.0);
+    }
+    
+    void mapRangeAllNonPositiveDefaultThreshold()
+    {
+        double min, max;
+
+        min = 0.0; max = -10.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
+
+        min = -10.0; max = 0.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
+    }
+    
+    void mapRangeAllNonPositiveSetThreshold()
+    {
+        double min, max;
+
+        min = 0.0; max = -10.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
+
+        min = -10.0; max = 0.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
+    }
+    
+    void mapRangeSpanningZeroDefaultThreshold()
+    {
+        double min, max;
+
+        min = -1.0; max = 10.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
+
+        min = -100.0; max = 1.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 2.0);
+
+        min = -10.0; max = 1e-200;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
+
+        min = 1e-200; max = -10.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
+
+        min = -1e-200; max = 100.0;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 2.0);
+
+        min = 10.0; max = -1e-200;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -10.0); QCOMPARE(max, 1.0);
+
+        // if none of the input range is above the threshold in
+        // magnitude, but it still spans zero, we use the input max as
+        // threshold and then add 1 for range
+        min = -1e-200; max = 1e-300;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -201.0); QCOMPARE(max, -200.0);
+
+        min = 1e-200; max = -1e-300;
+        LogRange::mapRange(min, max);
+        QCOMPARE(min, -201.0); QCOMPARE(max, -200.0);
+    }
+    
+    void mapRangeSpanningZeroSetThreshold()
+    {
+        double min, max;
+
+        min = -1.0; max = 10.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
+
+        min = -100.0; max = 1.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 2.0);
+
+        min = -10.0; max = 1e-200;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
+
+        min = 1e-200; max = -10.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
+
+        min = -1e-200; max = 100.0;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 2.0);
+
+        min = 10.0; max = -1e-200;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -4.0); QCOMPARE(max, 1.0);
+
+        // if none of the input range is above the threshold in
+        // magnitude, but it still spans zero, we use the input max as
+        // threshold and then add 1 for range
+        min = -1e-200; max = 1e-300;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -201.0); QCOMPARE(max, -200.0);
+
+        min = 1e-200; max = -1e-300;
+        LogRange::mapRange(min, max, -4.0);
+        QCOMPARE(min, -201.0); QCOMPARE(max, -200.0);
+    }
+    
+};
+
+#endif
--- a/base/test/files.pri	Mon Feb 27 16:52:47 2017 +0000
+++ b/base/test/files.pri	Tue Feb 28 11:21:49 2017 +0000
@@ -1,10 +1,11 @@
 TEST_HEADERS = \
+	     TestColumnOp.h \
+	     TestLogRange.h \
 	     TestRangeMapper.h \
+	     TestOurRealTime.h \
 	     TestPitch.h \
-	     TestOurRealTime.h \
-	     TestVampRealTime.h \
 	     TestStringBits.h \
-	     TestColumnOp.h
+	     TestVampRealTime.h
 	     
 TEST_SOURCES += \
 	     svcore-base-test.cpp
--- a/base/test/svcore-base-test.cpp	Mon Feb 27 16:52:47 2017 +0000
+++ b/base/test/svcore-base-test.cpp	Tue Feb 28 11:21:49 2017 +0000
@@ -11,6 +11,7 @@
     COPYING included with this distribution for more information.
 */
 
+#include "TestLogRange.h"
 #include "TestRangeMapper.h"
 #include "TestPitch.h"
 #include "TestStringBits.h"
@@ -27,7 +28,7 @@
     int good = 0, bad = 0;
 
     QCoreApplication app(argc, argv);
-    app.setOrganizationName("Sonic Visualiser");
+    app.setOrganizationName("sonic-visualiser");
     app.setApplicationName("test-svcore-base");
 
     {
@@ -60,6 +61,11 @@
 	if (QTest::qExec(&t, argc, argv) == 0) ++good;
 	else ++bad;
     }
+    {
+	TestLogRange t;
+	if (QTest::qExec(&t, argc, argv) == 0) ++good;
+	else ++bad;
+    }
 
     if (bad > 0) {
 	cerr << "\n********* " << bad << " test suite(s) failed!\n" << endl;
--- a/data/fileio/test/svcore-data-fileio-test.cpp	Mon Feb 27 16:52:47 2017 +0000
+++ b/data/fileio/test/svcore-data-fileio-test.cpp	Tue Feb 28 11:21:49 2017 +0000
@@ -43,7 +43,7 @@
     }
 
     QCoreApplication app(argc, argv);
-    app.setOrganizationName("Sonic Visualiser");
+    app.setOrganizationName("sonic-visualiser");
     app.setApplicationName("test-fileio");
 
     {
--- a/data/model/EditableDenseThreeDimensionalModel.cpp	Mon Feb 27 16:52:47 2017 +0000
+++ b/data/model/EditableDenseThreeDimensionalModel.cpp	Tue Feb 28 11:21:49 2017 +0000
@@ -455,7 +455,7 @@
         if (n[j]) sample[j] /= n[j];
     }
     
-    return LogRange::useLogScale(sample);
+    return LogRange::shouldUseLogScale(sample);
 }
 
 void
--- a/data/model/test/svcore-data-model-test.cpp	Mon Feb 27 16:52:47 2017 +0000
+++ b/data/model/test/svcore-data-model-test.cpp	Tue Feb 28 11:21:49 2017 +0000
@@ -24,7 +24,7 @@
     int good = 0, bad = 0;
 
     QCoreApplication app(argc, argv);
-    app.setOrganizationName("Sonic Visualiser");
+    app.setOrganizationName("sonic-visualiser");
     app.setApplicationName("test-model");
 
     {