From 02a4ff509fa23e8c9849b1c0c72f3ef48fc9565e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Offringa?= <offringa@astron.nl>
Date: Tue, 22 Mar 2011 18:59:36 +0000
Subject: [PATCH] Bug 1491: esthetic improvements to the time-frequency window
 of the rfigui: displayment of a colorscale, use of rounded values instead of
 linear interpolated values along axes and other esthetics

---
 .gitattributes                                |   6 +-
 .../include/AOFlagger/CMakeLists.txt          |   4 +-
 .../{horizontaltimescale.h => colorscale.h}   |  79 ++++--
 .../gui/plot/horizontalnumericscale.h         |  51 ----
 .../AOFlagger/gui/plot/horizontalplotscale.h  |  33 +--
 .../include/AOFlagger/gui/plot/tickset.h      | 259 ++++++++++++++++++
 .../AOFlagger/gui/plot/verticalnumericscale.h |  51 ----
 .../AOFlagger/gui/plot/verticalplotscale.h    |  34 +--
 .../AOFlagger/gui/timefrequencywidget.h       |   5 +-
 .../AOFlagger/include/AOFlagger/msio/date.h   |  23 +-
 CEP/DP3/AOFlagger/src/CMakeLists.txt          |   1 +
 CEP/DP3/AOFlagger/src/gui/plot/colorscale.cpp |  78 ++++++
 .../src/gui/plot/horizontalplotscale.cpp      |  95 +++----
 .../src/gui/plot/verticalplotscale.cpp        |  85 +++---
 .../AOFlagger/src/gui/timefrequencywidget.cpp |  81 ++++--
 15 files changed, 559 insertions(+), 326 deletions(-)
 rename CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/{horizontaltimescale.h => colorscale.h} (52%)
 delete mode 100644 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontalnumericscale.h
 create mode 100644 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/tickset.h
 delete mode 100644 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/verticalnumericscale.h
 create mode 100644 CEP/DP3/AOFlagger/src/gui/plot/colorscale.cpp

diff --git a/.gitattributes b/.gitattributes
index 574c170c3d6..66eee21e76c 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -190,16 +190,15 @@ CEP/DP3/AOFlagger/include/AOFlagger/gui/msoptionwindow.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/mswindow.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/newstrategyactionframe.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/numinputdialog.h -text
+CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/colorscale.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/dimension.h -text
-CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontalnumericscale.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontalplotscale.h -text
-CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontaltimescale.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/plot2d.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/plot2dpointset.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/plotable.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/plotwidget.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/system.h -text
-CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/verticalnumericscale.h -text
+CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/tickset.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/verticalplotscale.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/plotframe.h -text
 CEP/DP3/AOFlagger/include/AOFlagger/gui/progresswindow.h -text
@@ -415,6 +414,7 @@ CEP/DP3/AOFlagger/src/gui/imagewidget.cpp -text
 CEP/DP3/AOFlagger/src/gui/msoptionwindow.cpp -text
 CEP/DP3/AOFlagger/src/gui/mswindow.cpp -text
 CEP/DP3/AOFlagger/src/gui/newstrategyactionframe.cpp -text
+CEP/DP3/AOFlagger/src/gui/plot/colorscale.cpp -text
 CEP/DP3/AOFlagger/src/gui/plot/horizontalplotscale.cpp -text
 CEP/DP3/AOFlagger/src/gui/plot/plot2d.cpp -text
 CEP/DP3/AOFlagger/src/gui/plot/plotwidget.cpp -text
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/CMakeLists.txt b/CEP/DP3/AOFlagger/include/AOFlagger/CMakeLists.txt
index 060e44f95f3..1533589e5eb 100644
--- a/CEP/DP3/AOFlagger/include/AOFlagger/CMakeLists.txt
+++ b/CEP/DP3/AOFlagger/include/AOFlagger/CMakeLists.txt
@@ -35,15 +35,13 @@ install(FILES
 
 install(FILES
   gui/plot/dimension.h
-  gui/plot/horizontalnumericscale.h
   gui/plot/horizontalplotscale.h
-  gui/plot/horizontaltimescale.h
   gui/plot/plot2d.h
   gui/plot/plot2dpointset.h
   gui/plot/plotable.h
   gui/plot/plotwidget.h
   gui/plot/system.h
-  gui/plot/verticalnumericscale.h
+  gui/plot/tickset.h
   gui/plot/verticalplotscale.h
   DESTINATION include/${PACKAGE_NAME}/gui/plot)
 
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontaltimescale.h b/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/colorscale.h
similarity index 52%
rename from CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontaltimescale.h
rename to CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/colorscale.h
index 04a72f48985..f36b3e3beba 100644
--- a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontaltimescale.h
+++ b/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/colorscale.h
@@ -17,38 +17,71 @@
  *   Free Software Foundation, Inc.,                                       *
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
-#ifndef HORIZONTALTIMESCALE_H
-#define HORIZONTALTIMESCALE_H
+#ifndef PLOT_COLORSCALE_H
+#define PLOT_COLORSCALE_H
 
 #include <string>
+#include <map>
 
-#include "horizontalplotscale.h"
+#include <gtkmm/drawingarea.h>
 
-#include <AOFlagger/msio/date.h>
+#include <AOFlagger/gui/plot/verticalplotscale.h>
 
-class HorizontalTimeScale : private HorizontalPlotScale
-{
+/**
+	@author A.R. Offringa <offringa@astro.rug.nl>
+*/
+class ColorScale {
 	public:
-		HorizontalTimeScale(Glib::RefPtr<Gdk::Drawable> drawable, double minAipsTime, double maxAipsTime)
-			: HorizontalPlotScale(drawable)
+		ColorScale(Glib::RefPtr<Gdk::Drawable> drawable);
+		
+		virtual ~ColorScale()
 		{
-			for(size_t i=0;i<=10;++i)
-			{
-				double val = ((maxAipsTime - minAipsTime) * i / 10.0 + minAipsTime);
-				std::string s = Date::AipsMJDToTimeString(val);// + "\n" + Date::AipsMJDToDateString(val);
-				if(i % 2 == 0)
-					HorizontalTimeScale::AddLargeTick(i / 10.0, s);
-				else
-					HorizontalTimeScale::AddSmallTick(i / 10.0, s);
-			}
 		}
-		void Draw(Cairo::RefPtr<Cairo::Context> cairo) { HorizontalPlotScale::Draw(cairo); }
-		double GetHeight() { return HorizontalPlotScale::GetHeight(); }
-		double GetRightMargin() { return HorizontalPlotScale::GetRightMargin(); }
-		void SetPlotDimensions(double plotWidth, double plotHeight, double topMargin, double verticalScaleWidth)
+		void SetPlotDimensions(double plotWidth, double plotHeight, double topMargin)
 		{
-			HorizontalPlotScale::SetPlotDimensions(plotWidth, plotHeight, topMargin, verticalScaleWidth);
+			_plotWidth = plotWidth;
+			_plotHeight = plotHeight;
+			_topMargin = topMargin;
+			_width = 0.0;
 		}
+		double GetWidth()
+		{
+			if(_width == 0.0)
+				initWidth();
+			return _width;
+		}
+		void Draw(Cairo::RefPtr<Cairo::Context> cairo);
+		void InitializeNumericTicks(double min, double max)
+		{
+			_min = min;
+			_max = max;
+			_verticalPlotScale.InitializeNumericTicks(min, max);
+		}
+		void SetColorValue(double value, double red, double green, double blue)
+		{
+			ColorValue cValue;
+			cValue.red = red;
+			cValue.green = green;
+			cValue.blue = blue;
+			_colorValues.insert(std::pair<double, ColorValue>(value, cValue));
+		}
+	private:
+		static const double BAR_WIDTH;
+		
+		struct ColorValue
+		{
+			double red, green, blue;
+		};
+		
+		void initWidth();
+		
+		double _plotWidth, _plotHeight, _topMargin;
+		double _scaleWidth, _width;
+		double _min, _max;
+		Glib::RefPtr<Gdk::Drawable> _drawable;
+		Cairo::RefPtr<Cairo::Context> _cairo;
+		class VerticalPlotScale _verticalPlotScale;
+		std::map<double, ColorValue> _colorValues;
 };
 
-#endif // HORIZONTALTIMESCALE_H
+#endif
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontalnumericscale.h b/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontalnumericscale.h
deleted file mode 100644
index 2ed283d54f3..00000000000
--- a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontalnumericscale.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2008 by A.R. Offringa   *
- *   offringa@astro.rug.nl   *
- *                                                                         *
- *   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.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
- ***************************************************************************/
-#ifndef HORIZONTALNUMERICSCALE_H
-#define HORIZONTALNUMERICSCALE_H
-
-#include <sstream>
-
-#include "horizontalplotscale.h"
-
-class HorizontalNumericScale : private HorizontalPlotScale
-{
-	public:
-		HorizontalNumericScale(Glib::RefPtr<Gdk::Drawable> drawable, double min, double max)
-			: HorizontalPlotScale(drawable)
-		{
-			for(size_t i=0;i<=100;++i)
-			{
-				std::stringstream s;
-				s << ((max - min) * i / 100.0 + min);
-				if(i % 10 == 0)
-					HorizontalPlotScale::AddLargeTick(i / 100.0, s.str());
-				else
-					HorizontalPlotScale::AddSmallTick(i / 100.0, s.str());
-			}
-		}
-		void Draw(Cairo::RefPtr<Cairo::Context> cairo) { HorizontalPlotScale::Draw(cairo); }
-		double GetHeight() { return HorizontalPlotScale::GetHeight(); }
-		void SetPlotDimensions(double plotWidth, double plotHeight, double topMargin, double verticalScaleWidth)
-		{
-			HorizontalPlotScale::SetPlotDimensions(plotWidth, plotHeight, topMargin, verticalScaleWidth);
-		}
-};
-
-#endif // HORIZONTALNUMERICSCALE_H
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontalplotscale.h b/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontalplotscale.h
index 5f4c3c754a3..9a3160f0a65 100644
--- a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontalplotscale.h
+++ b/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/horizontalplotscale.h
@@ -32,16 +32,6 @@ class HorizontalPlotScale {
 	public:
 		HorizontalPlotScale(Glib::RefPtr<Gdk::Drawable> drawable);
 		virtual ~HorizontalPlotScale();
-		void AddLargeTick(double normValue, std::string caption)
-		{
-			_largeTicks.push_back(Tick(normValue, caption));
-			_metricsAreInitialized = false;
-		}
-		void AddSmallTick(double normValue, std::string caption)
-		{
-			_smallTicks.push_back(Tick(normValue, caption));
-			_metricsAreInitialized = false;
-		}
 		void SetPlotDimensions(double plotWidth, double plotHeight, double topMargin, double verticalScaleWidth)
 		{
 			_plotWidth = plotWidth;
@@ -53,33 +43,18 @@ class HorizontalPlotScale {
 		double GetHeight();
 		double GetRightMargin();
 		void Draw(Cairo::RefPtr<Cairo::Context> cairo);
+		void InitializeNumericTicks(double min, double max);
+		void InitializeTimeTicks(double timeMin, double timeMax);
 	private:
-		struct Tick {
-			Tick(double _normValue, std::string _caption) :
-				normValue(_normValue), caption(_caption)
-			{ }
-			Tick(const Tick &source) :
-				normValue(source.normValue), caption(source.caption)
-			{ }
-			Tick &operator=(const Tick &rhs)
-			{
-				normValue = rhs.normValue; caption = rhs.caption;
-				return *this;
-			}
-			double normValue;
-			std::string caption;
-		};
-		void setVisibleTicks();
-		bool ticksFit(std::map<double, Tick> &ticks);
+		bool ticksFit();
 		void initializeMetrics(); 
 
 		double _plotWidth, _plotHeight, _topMargin, _verticalScaleWidth;
-		std::vector<Tick> _largeTicks, _smallTicks;
-		std::vector<Tick> _visibleLargeTicks;
 		bool _metricsAreInitialized;
 		double _height, _rightMargin;
 		Glib::RefPtr<Gdk::Drawable> _drawable;
 		Cairo::RefPtr<Cairo::Context> _cairo;
+		class TickSet *_tickSet;
 };
 
 #endif
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/tickset.h b/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/tickset.h
new file mode 100644
index 00000000000..6733a369536
--- /dev/null
+++ b/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/tickset.h
@@ -0,0 +1,259 @@
+
+#include <string>
+#include <vector>
+#include <cmath>
+#include <sstream>
+#include <iostream>
+
+#include <AOFlagger/msio/date.h>
+
+typedef std::pair<double, std::string> Tick;
+
+class TickSet
+{
+	public:
+		TickSet()
+		{
+		}
+		virtual ~TickSet()
+		{
+		}
+		
+		virtual unsigned Size() const = 0;
+		virtual Tick GetTick(unsigned i) const = 0;
+		
+		virtual void DecreaseTicks()
+		{
+			if(Size() > 1)
+			{
+				Reset(Size() - 1);
+			}
+		}
+		virtual void Reset(unsigned sizeRequest) = 0;
+	protected:
+	private:
+		
+};
+
+class NumericTickSet : public TickSet
+{
+	public:
+		NumericTickSet(double min, double max, unsigned sizeRequest) : _min(min), _max(max)
+		{
+			set(sizeRequest);
+		}
+		
+		virtual unsigned Size() const
+		{
+			return _ticks.size();
+		}
+		
+		virtual Tick GetTick(unsigned i) const
+		{
+			std::stringstream tickStr;
+			tickStr << _ticks[i];
+			return Tick((_ticks[i] - _min) / (_max - _min), tickStr.str());
+		}
+		
+		virtual void Reset(unsigned sizeRequest)
+		{
+			_ticks.clear();
+			set(sizeRequest);
+		}
+	private:
+		void set(unsigned sizeRequest)
+		{
+			if(_max == _min)
+				_ticks.push_back(_min);
+			else
+			{
+				if(sizeRequest == 0)
+					sizeRequest = 1;
+				double
+					tickWidth = roundUpToNiceNumber((_max - _min) / (double) sizeRequest);
+				if(tickWidth == 0.0)
+					tickWidth = 1.0;
+				double
+					pos = roundUpToNiceNumber(_min, tickWidth);
+				while(pos <= _max)
+				{
+					std::cout << tickWidth << ' ' << pos << '\n';
+					_ticks.push_back(pos);
+					pos += tickWidth;
+				}
+			}
+		}
+		
+		double roundUpToNiceNumber(double number)
+		{
+			if(!std::isfinite(number))
+				return number;
+			double roundedNumber = 1.0;
+			if(number <= 0.0)
+			{
+				if(roundedNumber == 0.0)
+					return 0.0;
+				else
+				{
+					roundedNumber = -1.0;
+					number *= -1.0;
+				}
+			}
+			while(number > 10)
+			{
+				number /= 10;
+				roundedNumber *= 10;
+			}
+			while(number <= 1)
+			{
+				number *= 10;
+				roundedNumber /= 10;
+			}
+			if(number <= 2) return roundedNumber * 2;
+			else if(number <= 5) return roundedNumber * 5;
+			else return roundedNumber * 10;
+		}
+		double roundUpToNiceNumber(double number, double roundUnit)
+		{
+			return roundUnit * ceil(number / roundUnit);
+		}
+		
+		double _min, _max;
+		std::vector<double> _ticks;
+};
+
+class TimeTickSet : public TickSet
+{
+	public:
+		TimeTickSet(double minTime, double maxTime, unsigned sizeRequest) : _min(minTime), _max(maxTime)
+		{
+			set(sizeRequest);
+		}
+		
+		virtual unsigned Size() const
+		{
+			return _ticks.size();
+		}
+		
+		virtual Tick GetTick(unsigned i) const
+		{
+			double val = _ticks[i];
+			return Tick((val - _min) / (_max - _min), Date::AipsMJDToTimeString(val));
+		}
+		
+		virtual void Reset(unsigned sizeRequest)
+		{
+			_ticks.clear();
+			set(sizeRequest);
+		}
+	private:
+		void set(unsigned sizeRequest)
+		{
+			if(_max == _min)
+				_ticks.push_back(_min);
+			else
+			{
+				if(sizeRequest == 0)
+					sizeRequest = 1;
+			double tickWidth = calculateTickWidth((_max - _min) / (double) sizeRequest);
+				if(tickWidth == 0.0)
+					tickWidth = 1.0;
+				double
+					pos = roundUpToNiceNumber(_min, tickWidth);
+				while(pos < _max)
+				{
+					std::cout << tickWidth << ' ' << pos << '\n';
+					_ticks.push_back(pos);
+					pos += tickWidth;
+				}
+			}
+		}
+		
+		double calculateTickWidth(double lowerLimit) const
+		{
+			// number is in units of seconds
+			
+			// In days?
+			if(lowerLimit >= 60.0*60.0*24.0)
+			{
+				double width = 60.0*60.0*24.0;
+				while(width < lowerLimit)
+					width *= 2.0;
+				return width;
+			}
+			// in hours?
+			else if(lowerLimit > 60.0*30.0)
+			{
+				if(lowerLimit <= 60.0*60.0)
+					return 60.0*60.0; // hours
+				else if(lowerLimit <= 60.0*60.0*2.0)
+					return 60.0*60.0*2.0; // two hours
+				else if(lowerLimit <= 60.0*60.0*3.0)
+					return 60.0*60.0*3.0; // three hours
+				else if(lowerLimit <= 60.0*60.0*4.0)
+					return 60.0*60.0*4.0; // four hours
+				else if(lowerLimit <= 60.0*60.0*6.0)
+					return 60.0*60.0*6.0; // six hours
+				else
+					return 60.0*60.0*12.0; // twelve hours
+			}
+			// in minutes?
+			else if(lowerLimit > 30.0)
+			{
+				if(lowerLimit <= 60.0)
+					return 60.0; // in minutes
+				else if(lowerLimit <= 60.0*2.0)
+					return 60.0*2.0; // two minutes
+				else if(lowerLimit <= 60.0*5.0)
+					return 60.0*5.0; // five minutes
+				else if(lowerLimit <= 60.0*10.0)
+					return 60.0*10.0; // ten minutes
+				else if(lowerLimit <= 60.0*15.0)
+					return 60.0*15.0; // quarter hours
+				else
+					return 60.0*30.0; // half hours
+			}
+			// in seconds?
+			else if(lowerLimit > 0.5)
+			{
+				if(lowerLimit <= 1.0)
+					return 1.0; // in seconds
+				else if(lowerLimit <= 2.0)
+					return 2.0; // two seconds
+				else if(lowerLimit <= 5.0)
+					return 5.0; // five seconds
+				else if(lowerLimit <= 10.0)
+					return 10.0; // ten seconds
+				else if(lowerLimit <= 15.0)
+					return 15.0; // quarter minute
+				else
+					return 30.0; // half a minute
+			}
+			else if(lowerLimit == 0.0)
+				return 0.0;
+			// in 10th of seconds or lower?
+			else
+			{
+				double factor = 1.0;
+				while(lowerLimit < 0.1)
+				{
+					factor *= 0.1;
+					lowerLimit *= 10.0;
+				}
+				if(lowerLimit <= 0.1)
+					return 0.1 * factor;
+				else if(lowerLimit <= 0.2)
+					return 0.2 * factor;
+				else
+					return 0.5 * factor;
+			}
+		}
+		
+		double roundUpToNiceNumber(double number, double roundUnit)
+		{
+			return roundUnit * ceil(number / roundUnit);
+		}
+		
+		double _min, _max;
+		std::vector<double> _ticks;
+};
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/verticalnumericscale.h b/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/verticalnumericscale.h
deleted file mode 100644
index b39f2ed2130..00000000000
--- a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/verticalnumericscale.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2008 by A.R. Offringa   *
- *   offringa@astro.rug.nl   *
- *                                                                         *
- *   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.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
- ***************************************************************************/
-#ifndef VERTICALNUMERICSCALE_H
-#define VERTICALNUMERICSCALE_H
-
-#include <sstream>
-
-#include "verticalplotscale.h"
-
-class VerticalNumericScale : private VerticalPlotScale
-{
-	public:
-		VerticalNumericScale(Glib::RefPtr<Gdk::Drawable> drawable, double min, double max)
-			: VerticalPlotScale(drawable)
-		{
-			for(size_t i=0;i<=100;++i)
-			{
-				std::stringstream s;
-				s << ((max - min) * i / 100.0 + min);
-				if(i % 10 == 0)
-					VerticalPlotScale::AddLargeTick(i / 100.0, s.str());
-				else
-					VerticalPlotScale::AddSmallTick(i / 100.0, s.str());
-			}
-		}
-		void Draw(Cairo::RefPtr<Cairo::Context> cairo) { VerticalPlotScale::Draw(cairo); }
-		double GetWidth() { return VerticalPlotScale::GetWidth(); }
-		void SetPlotDimensions(double plotWidth, double plotHeight, double topMargin)
-		{
-			VerticalPlotScale::SetPlotDimensions(plotWidth, plotHeight, topMargin);
-		}
-};
-
-#endif // VERTICALNUMERICSCALE_H
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/verticalplotscale.h b/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/verticalplotscale.h
index 133c12ab0d0..fd0dae231bb 100644
--- a/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/verticalplotscale.h
+++ b/CEP/DP3/AOFlagger/include/AOFlagger/gui/plot/verticalplotscale.h
@@ -32,16 +32,6 @@ class VerticalPlotScale {
 	public:
 		VerticalPlotScale(Glib::RefPtr<Gdk::Drawable> drawable);
 		virtual ~VerticalPlotScale();
-		void AddLargeTick(double normValue, std::string caption)
-		{
-			_largeTicks.push_back(Tick(normValue, caption));
-			_metricsAreInitialized = false;
-		}
-		void AddSmallTick(double normValue, std::string caption)
-		{
-			_smallTicks.push_back(Tick(normValue, caption));
-			_metricsAreInitialized = false;
-		}
 		void SetPlotDimensions(double plotWidth, double plotHeight, double topMargin)
 		{
 			_plotWidth = plotWidth;
@@ -50,34 +40,18 @@ class VerticalPlotScale {
 			_metricsAreInitialized = false;
 		}
 		double GetWidth();
-		void Draw(Cairo::RefPtr<Cairo::Context> cairo);
+		void Draw(Cairo::RefPtr<Cairo::Context> cairo, double offsetX=0.0, double offsetY=0.0);
+		void InitializeNumericTicks(double min, double max);
 	private:
-		struct Tick {
-			Tick(double _normValue, std::string _caption) :
-				normValue(_normValue), caption(_caption)
-			{ }
-			Tick(const Tick &source) :
-				normValue(source.normValue), caption(source.caption)
-			{ }
-			Tick &operator=(const Tick &rhs)
-			{
-				normValue = rhs.normValue; caption = rhs.caption;
-				return *this;
-			}
-			double normValue;
-			std::string caption;
-		};
-		void setVisibleTicks();
-		bool ticksFit(std::map<double, Tick> &ticks);
+		bool ticksFit();
 		void initializeMetrics(); 
 
 		double _plotWidth, _plotHeight, _topMargin;
-		std::vector<Tick> _largeTicks, _smallTicks;
-		std::vector<Tick> _visibleLargeTicks;
 		bool _metricsAreInitialized;
 		double _width;
 		Glib::RefPtr<Gdk::Drawable> _drawable;
 		Cairo::RefPtr<Cairo::Context> _cairo;
+		class TickSet *_tickSet;
 };
 
 #endif
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/gui/timefrequencywidget.h b/CEP/DP3/AOFlagger/include/AOFlagger/gui/timefrequencywidget.h
index 29ccd96eada..dd40e116636 100644
--- a/CEP/DP3/AOFlagger/include/AOFlagger/gui/timefrequencywidget.h
+++ b/CEP/DP3/AOFlagger/include/AOFlagger/gui/timefrequencywidget.h
@@ -171,8 +171,9 @@ class TimeFrequencyWidget : public Gtk::DrawingArea {
 		size_t _startTime, _endTime;
 		size_t _startFrequency, _endFrequency;
 		SegmentedImageCPtr _segmentedImage;
-		class HorizontalTimeScale *_horiScale;
-		class VerticalNumericScale *_vertScale;
+		class HorizontalPlotScale *_horiScale;
+		class VerticalPlotScale *_vertScale;
+		class ColorScale *_colorScale;
 		num_t _max, _min;
 		enum Range _range;
 
diff --git a/CEP/DP3/AOFlagger/include/AOFlagger/msio/date.h b/CEP/DP3/AOFlagger/include/AOFlagger/msio/date.h
index 97aa98881ad..55005422d76 100644
--- a/CEP/DP3/AOFlagger/include/AOFlagger/msio/date.h
+++ b/CEP/DP3/AOFlagger/include/AOFlagger/msio/date.h
@@ -23,6 +23,7 @@
 
 #include <string>
 #include <sstream>
+#include <cmath>
 
 class Date {
 	public:
@@ -95,12 +96,24 @@ class Date {
 		static std::string ToString(double time)
 		{
 			std::stringstream s;
-			int mins = int(time*60)%60;
-			int secs = int(time*3600)%60;
 			int msec = int(round(time*3600000))%1000;
-			s << floor(time) << ":" << (mins/10) << (mins%10) << ":" << (secs/10) << (secs%10);
-			if(msec != 0)
-				s << "." << msec/100 << (msec/10)%10 << (msec)%10;
+			time -= msec/3600000.0;
+			
+			int secs = int(round(time*3600))%60;
+			time -= secs/3600.0;
+			
+			int mins = int(round(time*60))%60;
+			time -= mins/60.0;
+			
+			int hours = int(round(time));
+			time -= hours;
+			s << hours << ":" << (mins/10) << (mins%10);
+			if(msec != 0 || secs != 0)
+			{
+				s << ":" << (secs/10) << (secs%10);
+				if(msec != 0)
+					s << "." << msec/100 << (msec/10)%10 << (msec)%10;
+			}
 			return s.str();
 		}
 		static std::string ToString(int dayOfMonth, int month, int year)
diff --git a/CEP/DP3/AOFlagger/src/CMakeLists.txt b/CEP/DP3/AOFlagger/src/CMakeLists.txt
index 9e694ad3575..59e02fb1696 100644
--- a/CEP/DP3/AOFlagger/src/CMakeLists.txt
+++ b/CEP/DP3/AOFlagger/src/CMakeLists.txt
@@ -13,6 +13,7 @@ lofar_add_bin_program(aorefscript aorefscript.cpp)
 lofar_add_bin_program(aosynchronisation aosynchronisation.cpp)
 
 set(GUI_PLOT_FILES
+  gui/plot/colorscale.cpp
   gui/plot/horizontalplotscale.cpp
   gui/plot/plot2d.cpp
   gui/plot/plotwidget.cpp
diff --git a/CEP/DP3/AOFlagger/src/gui/plot/colorscale.cpp b/CEP/DP3/AOFlagger/src/gui/plot/colorscale.cpp
new file mode 100644
index 00000000000..ee26096a276
--- /dev/null
+++ b/CEP/DP3/AOFlagger/src/gui/plot/colorscale.cpp
@@ -0,0 +1,78 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by A.R. Offringa   *
+ *   offringa@astro.rug.nl   *
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#include <AOFlagger/gui/plot/colorscale.h>
+
+const double ColorScale::BAR_WIDTH = 15.0;
+
+ColorScale::ColorScale(Glib::RefPtr<Gdk::Drawable> drawable)
+: _width(0.0), _drawable(drawable),  _verticalPlotScale(drawable)
+{
+	_cairo = _drawable->create_cairo_context();
+}
+
+void ColorScale::initWidth()
+{
+	if(_width == 0.0)
+	{
+		_scaleWidth = _verticalPlotScale.GetWidth();
+		_width = _scaleWidth + BAR_WIDTH;
+	}
+}
+
+void ColorScale::Draw(Cairo::RefPtr<Cairo::Context> cairo)
+{
+	_verticalPlotScale.SetPlotDimensions(_plotWidth, _plotHeight, _topMargin);
+	initWidth();
+	_cairo = cairo;
+	ColorValue backValue;
+	if(!_colorValues.empty())
+	{
+		backValue = _colorValues.begin()->second;
+	} else {
+		backValue.red = 1.0;
+		backValue.green = 1.0;
+		backValue.blue = 1.0;
+	}
+	_cairo->rectangle(_plotWidth - _width + _scaleWidth, _topMargin,
+										BAR_WIDTH, _plotHeight);
+	_cairo->set_source_rgb(backValue.red, backValue.green, backValue.blue);
+	_cairo->fill();
+	
+	for(std::map<double, ColorValue>::const_iterator i=_colorValues.begin();
+		i!=_colorValues.end();++i)
+	{
+		double val = (i->first - _min) / (_max - _min);
+		if(val < 0.0) val = 0.0;
+		if(val > 1.0) val = 1.0;
+		double height = _plotHeight * (1.0 - val);
+		const ColorValue &color = i->second;
+		_cairo->set_source_rgb(color.red, color.green, color.blue);
+		_cairo->rectangle(_plotWidth - _width + _scaleWidth, _topMargin,
+											BAR_WIDTH, height);
+		_cairo->fill();
+	}
+	
+	_cairo->rectangle(_plotWidth - _width + _scaleWidth, _topMargin,
+										BAR_WIDTH, _plotHeight);
+	_cairo->set_source_rgb(0.0, 0.0, 0.0);
+	_cairo->stroke();
+	
+	_verticalPlotScale.Draw(cairo, _plotWidth - _width, 0.0);
+}
diff --git a/CEP/DP3/AOFlagger/src/gui/plot/horizontalplotscale.cpp b/CEP/DP3/AOFlagger/src/gui/plot/horizontalplotscale.cpp
index 77ae8ff12ae..63c3a7966d2 100644
--- a/CEP/DP3/AOFlagger/src/gui/plot/horizontalplotscale.cpp
+++ b/CEP/DP3/AOFlagger/src/gui/plot/horizontalplotscale.cpp
@@ -19,15 +19,18 @@
  ***************************************************************************/
 #include <AOFlagger/gui/plot/horizontalplotscale.h>
 
-#include <map>
+#include <AOFlagger/gui/plot/tickset.h>
+
 HorizontalPlotScale::HorizontalPlotScale(Glib::RefPtr<Gdk::Drawable> drawable)
-	: _plotWidth(0), _plotHeight(0), _metricsAreInitialized(false), _drawable(drawable)
+	: _plotWidth(0), _plotHeight(0), _metricsAreInitialized(false), _drawable(drawable), _tickSet(0)
 {
 	_cairo = _drawable->create_cairo_context();
 }
 
 HorizontalPlotScale::~HorizontalPlotScale()
 {
+	if(_tickSet != 0)
+		delete _tickSet;
 }
 
 double HorizontalPlotScale::GetHeight()
@@ -48,15 +51,16 @@ void HorizontalPlotScale::Draw(Cairo::RefPtr<Cairo::Context> cairo)
 	initializeMetrics();
 	_cairo->set_source_rgb(0.0, 0.0, 0.0);
 	_cairo->set_font_size(16.0);
-	for(std::vector<Tick>::const_iterator i=_visibleLargeTicks.begin();i!=_visibleLargeTicks.end();++i)
+	for(unsigned i=0;i!=_tickSet->Size();++i)
 	{
-		double x = i->normValue * (_plotWidth - _verticalScaleWidth) + _verticalScaleWidth;
+		const Tick tick = _tickSet->GetTick(i);
+		double x = tick.first * (_plotWidth - _verticalScaleWidth) + _verticalScaleWidth;
 		_cairo->move_to(x, _topMargin + _plotHeight);
 		_cairo->line_to(x, _topMargin + _plotHeight + 3);
 		Cairo::TextExtents extents;
-		_cairo->get_text_extents(i->caption, extents);
+		_cairo->get_text_extents(tick.second, extents);
 		_cairo->move_to(x - extents.width/2, _topMargin + _plotHeight - extents.y_bearing + extents.height);
-		_cairo->show_text(i->caption);
+		_cairo->show_text(tick.second);
 	}
 	_cairo->stroke();
 }
@@ -65,63 +69,48 @@ void HorizontalPlotScale::initializeMetrics()
 {
 	if(!_metricsAreInitialized)
 	{
-		setVisibleTicks();
-		_cairo->set_font_size(16.0);
-		double maxHeight = 0;
-		for(std::vector<Tick>::const_iterator i=_visibleLargeTicks.begin();i!=_visibleLargeTicks.end();++i)
+		if(_tickSet != 0)
 		{
-			Tick tick = *i;
+			while(!ticksFit())
+			{
+				_tickSet->DecreaseTicks();
+			}
+			_cairo->set_font_size(16.0);
+			double maxHeight = 0;
+			for(unsigned i=0;i!=_tickSet->Size();++i)
+			{
+				const Tick tick = _tickSet->GetTick(i);
+				Cairo::TextExtents extents;
+				_cairo->get_text_extents(tick.second, extents);
+				if(maxHeight < extents.height)
+					maxHeight = extents.height;
+			}
+			_height = maxHeight*2 + 10;
+			
 			Cairo::TextExtents extents;
-			_cairo->get_text_extents(tick.caption, extents);
-			if(maxHeight < extents.height)
-				maxHeight = extents.height;
+			_cairo->get_text_extents(_tickSet->GetTick(_tickSet->Size()-1).second, extents);
+			_rightMargin = extents.width/2+5 > 10 ? extents.width/2+5 : 10;
+			
+			_metricsAreInitialized = true;
 		}
-		_height = maxHeight*2 + 10;
-		_metricsAreInitialized = true;
-		
-		Cairo::TextExtents extents;
-		_cairo->get_text_extents(_visibleLargeTicks.rbegin()->caption, extents);
-		_rightMargin = extents.width/2+5 > 10 ? extents.width/2+5 : 10;
 	}
 } 
 
-void HorizontalPlotScale::setVisibleTicks()
+void HorizontalPlotScale::InitializeNumericTicks(double min, double max)
 {
+	if(_tickSet != 0)
+		delete _tickSet;
+	_tickSet = new NumericTickSet(min, max, 14);
+}
 
-	std::map<double, Tick> ticks;
-	for(std::vector<Tick>::const_iterator i=_largeTicks.begin();i!=_largeTicks.end();++i)
-		ticks.insert(std::pair<double, Tick>(i->normValue, *i));
-
-	if(!ticksFit(ticks))
-	{
-		size_t tryCount = 2;
-	
-		while(tryCount < _largeTicks.size())
-		{
-			tryCount *= 2;
-			ticks.clear();
-			for(size_t i=0;i<tryCount;++i)
-			{
-				size_t index = (i * _largeTicks.size() / tryCount);
-				Tick tick = _largeTicks[index];
-				ticks.insert(std::pair<double, Tick>(tick.normValue, tick));
-			}
-		}
-		tryCount /= 2;
-		ticks.clear();
-		for(size_t i=0;i<tryCount;++i)
-		{
-			size_t index = (i * _largeTicks.size() / tryCount);
-			Tick tick = _largeTicks[index];
-			ticks.insert(std::pair<double, Tick>(tick.normValue, tick));
-		}
-	}
-	_visibleLargeTicks.clear();
-	for(std::map<double, Tick>::const_iterator i=ticks.begin();i!=ticks.end();++i)
-		_visibleLargeTicks.push_back(i->second);
+void HorizontalPlotScale::InitializeTimeTicks(double timeMin, double timeMax)
+{
+	if(_tickSet != 0)
+		delete _tickSet;
+	_tickSet = new TimeTickSet(timeMin, timeMax, 14);
 }
 
-bool HorizontalPlotScale::ticksFit(std::map<double, Tick> &/*ticks*/)
+bool HorizontalPlotScale::ticksFit()
 {
 	/*double pos = 0.0;
 	for(std::map<double, Tick>::const_iterator i= ticks.begin();i!=ticks.end();++i)
diff --git a/CEP/DP3/AOFlagger/src/gui/plot/verticalplotscale.cpp b/CEP/DP3/AOFlagger/src/gui/plot/verticalplotscale.cpp
index a406692ab45..3a36ebbde04 100644
--- a/CEP/DP3/AOFlagger/src/gui/plot/verticalplotscale.cpp
+++ b/CEP/DP3/AOFlagger/src/gui/plot/verticalplotscale.cpp
@@ -19,16 +19,18 @@
  ***************************************************************************/
 #include <AOFlagger/gui/plot/verticalplotscale.h>
 
-#include <map>
+#include <AOFlagger/gui/plot/tickset.h>
 
 VerticalPlotScale::VerticalPlotScale(Glib::RefPtr<Gdk::Drawable> drawable)
-	: _plotWidth(0), _plotHeight(0), _metricsAreInitialized(false), _drawable(drawable)
+	: _plotWidth(0), _plotHeight(0), _metricsAreInitialized(false), _drawable(drawable), _tickSet(0)
 {
 	_cairo = _drawable->create_cairo_context();
 }
 
 VerticalPlotScale::~VerticalPlotScale()
 {
+	if(_tickSet != 0)
+		delete _tickSet;
 }
 
 double VerticalPlotScale::GetWidth()
@@ -37,18 +39,20 @@ double VerticalPlotScale::GetWidth()
 	return _width;
 }
 
-void VerticalPlotScale::Draw(Cairo::RefPtr<Cairo::Context> cairo)
+void VerticalPlotScale::Draw(Cairo::RefPtr<Cairo::Context> cairo, double offsetX, double offsetY)
 {
 	_cairo = cairo;
 	initializeMetrics();
 	_cairo->set_source_rgb(0.0, 0.0, 0.0);
 	_cairo->set_font_size(16.0);
-	for(std::vector<Tick>::const_iterator i=_visibleLargeTicks.begin();i!=_visibleLargeTicks.end();++i)
+	for(unsigned i=0;i!=_tickSet->Size();++i)
 	{
+		const Tick tick = _tickSet->GetTick(i);
 		Cairo::TextExtents extents;
-		_cairo->get_text_extents(i->caption, extents);
-		_cairo->move_to(_width - extents.width - 5, i->normValue * _plotHeight - extents.height/2  - extents.y_bearing + _topMargin);
-		_cairo->show_text(i->caption);
+		_cairo->get_text_extents(tick.second, extents);
+		_cairo->move_to(_width - extents.width - 5 + offsetX,
+										(1.0-tick.first) * _plotHeight - extents.height/2  - extents.y_bearing + _topMargin + offsetY);
+		_cairo->show_text(tick.second);
 	}
 	_cairo->stroke();
 }
@@ -57,59 +61,36 @@ void VerticalPlotScale::initializeMetrics()
 {
 	if(!_metricsAreInitialized)
 	{
-		setVisibleTicks();
-		_cairo->set_font_size(16.0);
-		double maxWidth = 0;
-		for(std::vector<Tick>::const_iterator i=_visibleLargeTicks.begin();i!=_visibleLargeTicks.end();++i)
+		if(_tickSet != 0)
 		{
-			Tick tick = *i;
-			Cairo::TextExtents extents;
-			_cairo->get_text_extents(tick.caption, extents);
-			if(maxWidth < extents.width)
-				maxWidth = extents.width;
+			while(!ticksFit() && _tickSet->Size() > 1)
+			{
+				_tickSet->DecreaseTicks();
+			}
+			_cairo->set_font_size(16.0);
+			double maxWidth = 0;
+			for(unsigned i=0;i!=_tickSet->Size();++i)
+			{
+				Tick tick = _tickSet->GetTick(i);
+				Cairo::TextExtents extents;
+				_cairo->get_text_extents(tick.second, extents);
+				if(maxWidth < extents.width)
+					maxWidth = extents.width;
+			}
+			_width = maxWidth + 10;
+			_metricsAreInitialized = true;
 		}
-		_width = maxWidth + 10;
-		_metricsAreInitialized = true;
 	}
 } 
 
-void VerticalPlotScale::setVisibleTicks()
+void VerticalPlotScale::InitializeNumericTicks(double min, double max)
 {
-
-	std::map<double, Tick> ticks;
-	for(std::vector<Tick>::const_iterator i=_largeTicks.begin();i!=_largeTicks.end();++i)
-		ticks.insert(std::pair<double, Tick>(i->normValue, *i));
-
-	if(!ticksFit(ticks))
-	{
-		size_t tryCount = 2;
-	
-		while(tryCount < _largeTicks.size())
-		{
-			tryCount *= 2;
-			ticks.clear();
-			for(size_t i=0;i<tryCount;++i)
-			{
-				size_t index = (i * _largeTicks.size() / tryCount);
-				Tick tick = _largeTicks[index];
-				ticks.insert(std::pair<double, Tick>(tick.normValue, tick));
-			}
-		}
-		tryCount /= 2;
-		ticks.clear();
-		for(size_t i=0;i<tryCount;++i)
-		{
-			size_t index = (i * _largeTicks.size() / tryCount);
-			Tick tick = _largeTicks[index];
-			ticks.insert(std::pair<double, Tick>(tick.normValue, tick));
-		}
-	}
-	_visibleLargeTicks.clear();
-	for(std::map<double, Tick>::const_iterator i=ticks.begin();i!=ticks.end();++i)
-		_visibleLargeTicks.push_back(i->second);
+	if(_tickSet == 0)
+		delete _tickSet;
+	_tickSet = new NumericTickSet(min, max, 20);
 }
 
-bool VerticalPlotScale::ticksFit(std::map<double, Tick> &/*ticks*/)
+bool VerticalPlotScale::ticksFit()
 {
 	//Cairo::TextExtents extents;
 	//cr->get_text_extents(tick.caption, extents);
diff --git a/CEP/DP3/AOFlagger/src/gui/timefrequencywidget.cpp b/CEP/DP3/AOFlagger/src/gui/timefrequencywidget.cpp
index ff09cbb1cae..4b532c57df9 100644
--- a/CEP/DP3/AOFlagger/src/gui/timefrequencywidget.cpp
+++ b/CEP/DP3/AOFlagger/src/gui/timefrequencywidget.cpp
@@ -28,8 +28,9 @@
 
 #include <iostream>
 
-#include <AOFlagger/gui/plot/horizontaltimescale.h>
-#include <AOFlagger/gui/plot/verticalnumericscale.h>
+#include <AOFlagger/gui/plot/horizontalplotscale.h>
+#include <AOFlagger/gui/plot/verticalplotscale.h>
+#include <AOFlagger/gui/plot/colorscale.h>
 
 TimeFrequencyWidget::TimeFrequencyWidget() :
 	_isInitialized(false), _showOriginalFlagging(true), _showAlternativeFlagging(true), _useColor(true), _colorMap(TFBWMap),
@@ -39,6 +40,7 @@ TimeFrequencyWidget::TimeFrequencyWidget() :
 	_segmentedImage(),
 	_horiScale(0),
 	_vertScale(0),
+	_colorScale(0),
 	_max(1.0), _min(0.0),
 	_range(Winsorized)
 {
@@ -118,17 +120,40 @@ void TimeFrequencyWidget::Update()
 		size_t width = _endTime - _startTime;
 		size_t height = _endFrequency - _startFrequency;
 
+		switch(_visualizedImage)
+		{
+			case TFOriginalImage: _image = _original.GetSingleImage(); break;
+			case TFRevisedImage: _image = _revised.GetSingleImage(); break;
+			case TFContaminatedImage: _image = _contaminated.GetSingleImage(); break;
+			case TFDifferenceImage:
+				_image = Image2D::CreateFromDiff(_original.GetSingleImage(), _revised.GetSingleImage());
+				break;
+		}
+	
+		num_t min, max;
+		Mask2DCPtr mask = GetActiveMask();
+		findMinMax(_image, mask, min, max);
+		
 		if(_horiScale != 0)
 			delete _horiScale;
 		if(_vertScale != 0)
 			delete _vertScale;
+		if(_colorScale != 0)
+			delete _colorScale;
 		if(_metaData != 0) {
-			_vertScale = new VerticalNumericScale(get_window(), _metaData->Band().channels[_startFrequency].frequencyHz / 1e6, _metaData->Band().channels[_endFrequency-1].frequencyHz / 1e6);
-			_horiScale = new HorizontalTimeScale(get_window(), _metaData->ObservationTimes()[_startTime], _metaData->ObservationTimes()[_endTime-1]);
+			_vertScale = new VerticalPlotScale(get_window());
+			_vertScale->InitializeNumericTicks(_metaData->Band().channels[_startFrequency].frequencyHz / 1e6, _metaData->Band().channels[_endFrequency-1].frequencyHz / 1e6);
+			
+			_horiScale = new HorizontalPlotScale(get_window());
+			_horiScale->InitializeTimeTicks(_metaData->ObservationTimes()[_startTime], _metaData->ObservationTimes()[_endTime-1]);
 		} else {
-			_vertScale = new VerticalNumericScale(get_window(), _startFrequency, _endFrequency-1);
-			_horiScale = new HorizontalTimeScale(get_window(), _startTime, _endTime-1);
+			_vertScale = new VerticalPlotScale(get_window());
+			_vertScale->InitializeNumericTicks(_startFrequency, _endFrequency-1);
+			_horiScale = new HorizontalPlotScale(get_window());
+			_horiScale->InitializeNumericTicks(_startTime, _endTime-1);
 		}
+		_colorScale = new ColorScale(get_window());
+		_colorScale->InitializeNumericTicks(min, max);
 
 		_leftBorderSize = _vertScale->GetWidth();
 		_rightBorderSize = _horiScale->GetRightMargin();
@@ -136,25 +161,23 @@ void TimeFrequencyWidget::Update()
 		_bottomBorderSize = _horiScale->GetHeight();
 
 		ColorMap *colorMap = createColorMap();
+		for(unsigned x=0;x<256;++x)
+		{
+			const num_t
+				colorVal = (2.0 / 256.0) * x - 1.0,
+				imageVal = (max-min) * x / 256.0 + min;
+			double
+				r = colorMap->ValueToColorR(colorVal),
+				g = colorMap->ValueToColorG(colorVal),
+				b = colorMap->ValueToColorB(colorVal);
+			_colorScale->SetColorValue(imageVal, r/255.0, g/255.0, b/255.0);
+		}
 		
 		unsigned sampleSize = 8;
 		_pixbuf.clear();
 		_pixbuf =
 			Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, sampleSize, width, height);
 	
-		switch(_visualizedImage)
-		{
-			case TFOriginalImage: _image = _original.GetSingleImage(); break;
-			case TFRevisedImage: _image = _revised.GetSingleImage(); break;
-			case TFContaminatedImage: _image = _contaminated.GetSingleImage(); break;
-			case TFDifferenceImage:
-				_image = Image2D::CreateFromDiff(_original.GetSingleImage(), _revised.GetSingleImage());
-				break;
-		}
-	
-		num_t min, max;
-		Mask2DCPtr mask = GetActiveMask();
-		findMinMax(_image, mask, min, max);
 		guint8* data = _pixbuf->get_pixels();
 		size_t rowStride = _pixbuf->get_rowstride();
 
@@ -167,7 +190,7 @@ void TimeFrequencyWidget::Update()
 		Mask2DCPtr altMask = _contaminated.GetSingleMask();
 		
 		for(unsigned long y=_startFrequency;y<_endFrequency;++y) {
-			guint8* rowpointer = data + rowStride * (y - _startFrequency);
+			guint8* rowpointer = data + rowStride * (_endFrequency - y - 1);
 			for(unsigned long x=_startTime;x<_endTime;++x) {
 				int xa = (x-_startTime) * 4;
 				char r,g,b,a;
@@ -282,12 +305,22 @@ void TimeFrequencyWidget::redraw()
 		cairo->rectangle(0, 0, get_width(), get_height());
 		cairo->fill();
 		
-		_pixbuf->scale_simple(get_width() - (int) floor(_leftBorderSize + _rightBorderSize), get_height() - (int) floor(_topBorderSize + _bottomBorderSize), Gdk::INTERP_BILINEAR)->render_to_drawable(get_window(), get_style()->get_black_gc(),
+		double rightBorder = _rightBorderSize;
+		_colorScale->SetPlotDimensions(get_width() - rightBorder, get_height()-_topBorderSize - _bottomBorderSize - 10.0, _topBorderSize + 10.0);
+		rightBorder += _colorScale->GetWidth() + 5.0;
+		_vertScale->SetPlotDimensions(get_width() - rightBorder, get_height() - _topBorderSize - _bottomBorderSize, _topBorderSize);
+		_horiScale->SetPlotDimensions(get_width() - rightBorder, get_height()-_topBorderSize - _bottomBorderSize, _topBorderSize, _vertScale->GetWidth());
+		
+		int
+			width = get_width() - (int) floor(_leftBorderSize + rightBorder),
+			height = get_height() - (int) floor(_topBorderSize + _bottomBorderSize);
+		_pixbuf->scale_simple(width, height, Gdk::INTERP_BILINEAR)->render_to_drawable(get_window(), get_style()->get_black_gc(),
 		0, 0, (int) round(_leftBorderSize), (int) round(_topBorderSize), -1, -1, Gdk::RGB_DITHER_NONE, 0, 0);
+		cairo->set_source_rgb(0.0, 0.0, 0.0);
+		cairo->rectangle(round(_leftBorderSize), round(_topBorderSize), width, height);
+		cairo->stroke();
 
-		_vertScale->SetPlotDimensions(get_width() - _rightBorderSize, get_height() - _topBorderSize - _bottomBorderSize, _topBorderSize);
-		_horiScale->SetPlotDimensions(get_width() - _rightBorderSize, get_height()-_topBorderSize - _bottomBorderSize, _topBorderSize, _vertScale->GetWidth());
-		
+		_colorScale->Draw(cairo);
 		_vertScale->Draw(cairo);
 		_horiScale->Draw(cairo);
 	}
-- 
GitLab