QCustomPlot Discussion and Comments

log scale on color map yields unexpected resultReturn to overview

While it is great to see that QCustomPlot supports on the fly scaling the result is a bit unexpected. In this "heatmap" i expect the center to remain at 5, yet in the graph with the log x-Axis the the center moved left (not expected) instead of right (expected).


As can be seen in the image, the scatter plot behaves differently and as expected. As can also be seen, there are issues with the scales.

For convenience, here the url in a clickable form.

I think I understand what is going wrong. There is no intention of scaling the data, it is just that QCPColorMap::draw calls coordsToPixels which returns the wrong values when the scale is not linear. This can be fixed by storing the scale type, temporarily setting it to linear, and then resetting them at the end. This yields a log scale on the graph without changing the image, which is probably what was intended.

see: https://ibb.co/H7j53Yp

void QCPColorMap::draw(QCPPainter *painter)
  auto keyScaleType = keyAxis()->scaleType();
  auto valueScaleType = valueAxis()->scaleType();

  keyAxis()->setScaleType( QCPAxis::ScaleType::stLinear );
  valueAxis()->setScaleType( QCPAxis::ScaleType::stLinear );

  QRectF imageRect = QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower),
                            coordsToPixels(mMapData->keyRange().upper, mMapData->valueRange().upper)).normalized();
  keyAxis()->setScaleType( keyScaleType );
  valueAxis()->setScaleType( valueScaleType );

Hi Thomas,
Is it possible that the range of your color map starts at (0, 0)? In this case QCustomPlot realizes that this is not displayable on a log scale, and fails gracefully by just painting it a couple of hundred pixels outside the axis range. For example, this mechanism allows it to plot a sine which has positive and negative half-waves on a logarithmic y-Axis, while keeping the line continuous and as natural as possible. I agree that in your case with a QColorMap the result is not as graceful indeed, but I'm not sure what the correct way to handle the situation would be. The input is simply incorrect, there is no zero on a logarithmic plot.

A side note: I recommend using the logarithmic axis tickers if you switch the scale to logarithmic. (See QCPAxisTickerLog)

In general The usage of QColorMap with a log axis is not quite as foolproof as with normal curves and graphs. Also see the note of warning of the setData method. For performance reasons and to reduce the complexity of QColorMap, it does not transform the bins logarithmically. This makes sense for most applications, since data that is inherently suited for logarithmic display, is usually also acquired in a logarithmic fashion (i.e. more sparse at higher key intervals), and thus an equally spaced binning in display-space is adequate. Compare this to the alternative: A QColorMap would quickly grow beyond any computer's working memory if it did space its bins according to the coordinate axes of a log-log-plot. Further, drawing a QColorMap with log-spaced bins would require a true pixel-by-pixel rendering in display-space and couldn't use regular graphics scaling routines for speedup.

My bad for the bad scale, but I don"t think that was the cause of the problem. I removed my changes and changed the scale to something valid

    customPlot->xAxis->setRange( 0.001, 10.0 );
    customPlot->yAxis->setRange( 0.001, 10.0 );

The error is exactly the same. The cause, imho, is that the calls to `coordsToPixels` mess up the coordinate calculations when the scale is logarithmic.

PS: It's totally fine by me (and expected) that the color map does not modify the data. It's just that initially (and surprisingly) it looked as thought it did, because that what the effect looked like to a certain degree.