PDA

View Full Version : Any examples of different color tables with Qwt?



bigjoeystud
10th September 2014, 04:58
Hello all,

Has anyone done a GUI for Qwt and making/setting new color tables with Qwt plots such as spectrograms?

Ideally, I'd like to default to a "standard" color bar and let the user switch it to some other predefined ones and/or modify the color table somehow to add more blue/red/purple/etc.

I'd like to match IDL's color tables somehow if possible if you are familiar with that piece of software.

I'm not sure where to start so I thought if anyone had an example of something they've done or seen somewhere, that would help!

Thanks!

Uwe
10th September 2014, 08:55
You could have a look at the rasterview example - but in the end setting the color steps is so simple, that I'm not sure if this is all you are looking for.

Uwe

bigjoeystud
16th September 2014, 21:11
I saw that, and I use a similar color bar; however, how did you know what color stops to add where?

That plus, designing a reasonable GUI for creating/changing color tables seems outside my expertise... I was thinking sliders above/below a color bar which changes on the fly based on user interaction, and then apply that to the existing spectrogram?

If you have other suggestions, I'm open!

Joey

Uwe
17th September 2014, 09:05
I saw that, and I use a similar color bar; however, how did you know what color stops to add where?
The range of a color map is - independent from any data - always from 0.0->1.0. Like percentage (%) is always 0-100.
So when the color map is used for diplaying raster data with a given range of 0-2000 ( = QwtRasterData::interval( Qt::ZAxis ) ) a value of 1000 would be mapped to the color at 0.5 in the color map.

Uwe

bigjoeystud
23rd September 2014, 03:51
Yes, I get this; but I was asking more about the color tables themselves.

Say I want a black and white color table and/or a "hot" color table (different shades of red), a "cold" color tables (different shades of blue). Then you have to add color stops. I was wanting a selection of different color bars. Could I mix/match them?

Initially, someone was complaining that the color bar I use (identical to the color spectrogram example) didn't have enough contrast at the low end, and honestly, I had no idea how to fix that!

Thanks,
Joey

Uwe
23rd September 2014, 08:10
Initially, someone was complaining that the color bar I use (identical to the color spectrogram example) didn't have enough contrast at the low end, and honestly, I had no idea how to fix that!

This color map interpolates for the lower 10% of the values between dark cyan to cyan - what are indeed colors with almost no contrast. In the example this is done intentionally as this range is considered as "noise" - instead this color map is using high contrasting colors for the top most 5% for emphasizing them.

When having too many stops with contrasting colors you will be able to identify the value of each position easily, but the over all readability might get lost. F.e when when 60° is a significant temperature, where something gets damaged, you probably want to have a color map with several stops with high contrasts between 40°-60° not distracted by many colors for values between 0°-10°.

But often you can't know in advance what information a user is interested in, when inspecting a particular survey, and it might be best to offer a small editor, where the user can modify the color map himself.

Uwe

bigjoeystud
3rd October 2014, 00:42
But often you can't know in advance what information a user is interested in, when inspecting a particular survey, and it might be best to offer a small editor, where the user can modify the color map himself.


This is a case where I wish I had an example color bar editor to model from! I'm not sure what would be good.

In the mean time, how could I develop a color bar like the one attached? This comes from the GMT documentation. Right now, I would just guess how much color I have where and add a stop for that color, but that seems wrong?

In their code, they are go over the entire HSV spectrum but I'm not sure how to convert that to a colorStop.

Joey

Uwe
3rd October 2014, 07:21
In their code, they are go over the entire HSV spectrum but I'm not sure how to convert that to a colorStop.
If you need to do the same and you already have the code, why trying to emulate it with something else.

Derive from QwtColorMap ( not using QwtLinearColorMap ! ) and implement HSVColorMap::rgb() using the code you have.
When you don't have to deal with QImage::Format_Indexed8 images HSVColorMap:colorIndex() can be implemented as a no operation.

If all you need to do is to interpolate between hsv instead of rgb you could also overload QwtLinearColorMap::rgb() replacing the 3 lines interpolating rgb by doing the same with hsv. ( I would be interested in your patch adding HSV interpolation as an option of QwtLinearColorMap ). Guess in your case min/max of the color map would cover the complete HSV spectrum - without having any other color stops.

But be careful as HSVColorMap::rgb() will be called very often and needs to implemented as fast as possible !

Uwe

bigjoeystud
3rd October 2014, 16:15
I got somewhere... Not sure how I did since I'm not sure I totally understand color scales. Anyway, I modified the spectrogram example and got something interesting.

Thanks!
Joey



Index: plot.cpp
================================================== =================
--- plot.cpp (revision 2046)
+++ plot.cpp (working copy)
@@ -8,6 +8,8 @@
#include <qwt_plot_panner.h>
#include <qwt_plot_layout.h>
#include <qwt_plot_renderer.h>
+#include <qnumeric.h> // for qIsNan
+#include <qglobal.h> // for qAbs
#include "plot.h"

class MyZoomer: public QwtPlotZoomer
@@ -63,13 +65,43 @@
}
};

+class HSVColorMap : public QwtColorMap
+{
+public:
+ HSVColorMap( QwtColorMap::Format format = QwtColorMap::RGB ) : QwtColorMap (format), _from (Qt::blue), _to (Qt::red) {}
+ HSVColorMap( const QColor &from, const QColor &to, QwtColorMap::Format format = QwtColorMap::RGB ) : QwtColorMap (format), _from (from), _to (to) {}
+ ~HSVColorMap () {}
+ QRgb rgb( const QwtInterval &interval, double value ) const
+ {
+ if (qIsNaN (value)) return qRgba (0, 0, 0, 0);
+
+ const double width = interval.width();
+
+ double ratio = 0.0;
+ if ( width > 0.0 )
+ ratio = ( value - interval.minValue() ) / width;
+
+ if ( ratio < 0.0 ) ratio = 0.0; // under lowest end of min!
+ if ( ratio > 1.0 ) ratio = 1.0; // over highest end of max!
+
+ if (_from.hsvHueF () > _to.hsvHueF ())
+ return QColor::fromHsvF ((_from.hsvHueF () - _to.hsvHueF ()) * (1.0 - ratio), 1.0, 1.0).rgb ();
+ else return QColor::fromHsvF ((_to.hsvHueF () - _from.hsvHueF ()) * ratio, 1.0, 1.0).rgb ();
+ }
+
+ void setColorInterval( const QColor &from, const QColor &to )
+ {
+ _from = from;
+ _to = to;
+ }
+ unsigned char colorIndex (const QwtInterval &, double) const { return 0; } // nop
+
+private:
+ QColor _from;
+ QColor _to;
+};
+
Plot::Plot( QWidget *parent ):
QwtPlot( parent )
{
d_spectrogram = new QwtPlotSpectrogram();
d_spectrogram->setRenderThreadCount( 0 ); // use system specific thread count

- d_spectrogram->setColorMap( new ColorMap() );
+ d_spectrogram->setColorMap( new HSVColorMap(QColor::fromHsv (300, 255, 255), QColor::fromHsv (1, 255, 255)));
d_spectrogram->setCachePolicy( QwtPlotRasterItem::PaintCache );

d_spectrogram->setData( new SpectrogramData() );
@@ -85,7 +117,7 @@
QwtScaleWidget *rightAxis = axisWidget( QwtPlot::yRight );
rightAxis->setTitle( "Intensity" );
rightAxis->setColorBarEnabled( true );
- rightAxis->setColorMap( zInterval, new ColorMap() );
+ rightAxis->setColorMap( zInterval, new HSVColorMap(QColor::fromHsv (300, 255, 255), QColor::fromHsv (1, 255, 255)) );

setAxisScale( QwtPlot::yRight, zInterval.minValue(), zInterval.maxValue() );
enableAxis( QwtPlot::yRight );

Uwe
24th October 2014, 19:03
As was interested myself I implemented a color map that interpolates between hue values. The implementation can be found in the spectrogram example in the 6.1 branch - in trunk it can be found as QwtHueColorMap.
Note that this implementation is way faster than yours, as it calculates the rgb values, that correspond with the possible 360 hue values, in advance.

I will also play with color maps that interpolate value or saturation if something useful can be done with them.

Uwe