|
Heat maps |
Posted by Herve on Feb-13-2016 04:44 |
|
Hello,
Y am trying to find out how to render this kind of heat map (see my attached screenshot)
with chart director. I saw some contour chart examples but I couldn't make it look like what I
need.
I want to assign to each X,Y location a specific color based on the Z value.
Will you have some advise how to chart this or this is not possible with chart director?
Thanks,
Herv
|
Re: Heat maps |
Posted by Peter Kwan on Feb-15-2016 15:57 |
|
Hi Herve,
This is somewhat similar to a "Wafer Chart". See:
http://www.chartdir.com/forum/download_thread.php?bn=chartdir_support&thread=1317041394#N1353343771
http://www.chartdir.com/forum/download_thread.php?bn=chartdir_support&thread=1340610047#N1340657839
In a heat map or contour chart, the (x, y) location refers to the point at (x, y). For your case, the (x, y) location refers to a rectangle with corners at (x - 0.5, y - 0.5) and (x + 0.5, y + 0.5), which is a region, not a point. So different methods would be needed, such as drawing square cells with colors coming from a "color axis" (the color legend).
If you can inform which programming language you are using, and whether you are writing a web or desktop application, I can create an example for you.
Regards
Peter Kwan |
Re: Heat maps |
Posted by Herve on Feb-15-2016 22:29 |
|
Hi Peter,
Yes, we would like to draw a reticle field which is a part of a wafer map. We usa the C++ version of Chart Director and our application is a desktop one. An example would be greatly appreciated.
Thanks,
Herve |
Re: Heat maps |
Posted by Peter Kwan on Feb-16-2016 04:02 |
|
Hi Herve,
Attached please find an example I have just written by modifying the "Contour Chart" sample code. To try the example, please kindly replace the "contour" function in the mfcdemo (in "mfcdemo/mfcdemo/mfccharts.cpp" for MFC, or "qtdemo/qtdemo/democharts.cpp" for Qt). Apart from displaying the cells, this example also include tooltips for the cells, so the user can read the cell position and value easily.
Hope this can help.
Regards
Peter Kwan
BaseChart *contour(int /* chartIndex */, const char **imageMap)
{
// The number of cells in the x and y direction, and the cell size in pixels
int xCount = 20;
int yCount = 20;
int cellSize = 20;
// Some random data
std::vector<double> dataZ(xCount * yCount);
for(int yIndex = 0; yIndex < yCount; ++yIndex) {
for(int xIndex = 0; xIndex < xCount; ++xIndex) {
dataZ[yIndex * xCount + xIndex] = xIndex * sin((double)yIndex) + yIndex * sin((double)xIndex);
}
}
// Set the chatr size and plot area size based on the number of cells and cell size
XYChart *c = new XYChart((xCount + 1) * cellSize + 180, (yCount + 1) * cellSize + 70);
c->setPlotArea(50, 30, (xCount + 1) * cellSize, (yCount + 1) * cellSize, -1, -1, -1, Chart::Transparent, -1);
// Set up the x-axis and y-axis
c->xAxis()->setLinearScale(1, xCount, 1);
c->yAxis()->setLinearScale(1, yCount, 1);
c->xAxis()->setMargin(cellSize, cellSize);
c->yAxis()->setMargin(cellSize, cellSize);
c->xAxis()->setLabelStyle("arialbd.ttf");
c->yAxis()->setLabelStyle("arialbd.ttf");
// Create a dummy contour layer to use the color axis
ContourLayer *layer = c->addContourLayer(DoubleArray(0, 0), DoubleArray(0, 0), DoubleArray(0, 0));
ColorAxis *cAxis = layer->setColorAxis(c->getPlotArea()->getRightX() + 30,
c->getPlotArea()->getTopY(), Chart::TopLeft, c->getPlotArea()->getHeight(), Chart::Right);
// Specify the color and scale used and the threshold position
double colors[] = { 0, 0x0000ff, 5, 0x008080, 10, 0x00ff00, 15, 0xcccc00, 20, 0xff0000 };
cAxis->setColorGradient(true);
cAxis->setColorScale(DoubleArray(colors, (int)(sizeof(colors) / sizeof(colors[0]))));
cAxis->setLinearScale(0, 20, 20);
cAxis->addMark(15, 0x000000, "Threshold", "arialbd.ttf", 8);
// Set color axis labels to use Arial Bold font
cAxis->setLabelStyle("arialbd.ttf");
cAxis->setLabelFormat("{value}%");
// Add the cells as scatter symbols
double symbolSize = 1;
for (int yIndex = 0; yIndex < yCount; ++yIndex) {
int yOffset = yIndex * xCount;
for (int xIndex = 0; xIndex < xCount; ++xIndex) {
double xCoor = xIndex + 1;
double yCoor = yIndex + 1;
int color = cAxis->getColor(dataZ[yOffset + xIndex]);
c->addScatterLayer(DoubleArray(&xCoor, 1), DoubleArray(&yCoor, 1), "", Chart::SquareSymbol,
cellSize, color, 0x888888)->addExtraField(DoubleArray(&(dataZ[yOffset + xIndex]), 1));
}
}
// Output the chart and the image map
c->makeChart();
*imageMap = c->getHTMLImageMap("", "", "title='({x}, {value}) : {field0|2}%'");
return c;
}
|
Re: Heat maps |
Posted by Herve on Feb-16-2016 21:52 |
|
Thanks Peter.
I am going to try this.
Regards,
Herve |
Re: Heat maps |
Posted by Herve on Feb-16-2016 23:42 |
|
Hi Peter,
We currently use the version V5.1 of CharDirector, and the method Axis::SetColorScale() is only available in V6.0. Is there a way to do the same in V5.x or we need to upgrade to V6.x?
Thanks,
Herve |
Re: Heat maps |
Posted by Herve on Feb-16-2016 23:42 |
|
Hi Peter,
We currently use the version V5.1 of CharDirector, and the method Axis::SetColorScale() is only available in V6.0. Is there a way to do the same in V5.x or we need to upgrade to V6.x?
Thanks,
Herve |
Re: Heat maps |
Posted by Peter Kwan on Feb-17-2016 01:52 |
|
Hi Herve,
May be changed the following lines:
double colors[] = { 0, 0x0000ff, 5, 0x008080, 10, 0x00ff00, 15, 0xcccc00, 20, 0xff0000 };
cAxis->setColorGradient(true);
cAxis->setColorScale(DoubleArray(colors, (int)(sizeof(colors) / sizeof(colors[0]))));
to:
int colors[] = { 0x0000ff, 0x008080, 0x00ff00, 0xcccc00, 0xff0000 };
cAxis->setColorGradient(true, IntArray(colors, (int)(sizeof(colors) / sizeof(colors[0]))));
Hope this can help.
Regards
Peter Kwan |
Re: Heat maps |
Posted by Herve on Feb-17-2016 02:45 |
|
Hi Peter,
I have already tried this (result is attached). The color scale looks good but there is no color in the chart.
Herv
|
Re: Heat maps |
Posted by Peter Kwan on Feb-17-2016 21:37 |
|
Hi Herve,
I have just tried with ChartDirector 5.1, and reproduced the same result as yours. The cause is because the Axis methods can only be used after calling BaseChart::layout. However, we can no longer add any additional scatter layers after BaseChart::layout. To work around, may be you can try the following method:
// Specify the color and scale used and the threshold position
int colors[] = { 0x0000ff, 0x008080, 0x00ff00, 0xcccc00, 0xff0000 };
cAxis->setColorGradient(true, IntArray(colors, (int)(sizeof(colors) / sizeof(colors[0]))));
cAxis->setLinearScale(0, 20);
cAxis->addMark(15, 0x000000, "Threshold", "arialbd.ttf", 8);
// Set color axis labels to use Arial Bold font
cAxis->setLabelStyle("arialbd.ttf");
// Create a dummy chart with the color axis and call BaseChart::layout so that the
// Axis.getColor can be used.
XYChart *c2 = new XYChart(10, 10);
cAxis = c2->addContourLayer(DoubleArray(0, 0), DoubleArray(0, 0), DoubleArray(0, 0))->colorAxis();
cAxis->setColorGradient(true, IntArray(colors, (int)(sizeof(colors) / sizeof(colors[0]))));
cAxis->setLinearScale(0, 20, 5);
c2->layout();
..... add the scatter layers as usual .....
// The dummy chart is no longer needed
delete c2;
Hope this can help.
Regards
Peter Kwan |
Re: Heat maps |
Posted by Peter Kwan on Oct-18-2018 22:17 |
|
Hi,
One of our customers would like a VB version of the code, so I posted it here:
Public Sub createChart(viewer As WinChartViewer)
' The number of cells in the x And y direction, And the cell size in pixels
Dim xCount As Integer = 20
Dim yCount As Integer = 20
Dim cellSize As Integer = 20
' Some random data
Dim dataZ(xCount * yCount - 1) As Double
For yIndex As Integer = 0 To yCount - 1
For xIndex As Integer = 0 To xCount - 1
dataZ(yIndex * xCount + xIndex) = xIndex * Math.Sin(yIndex) + yIndex * Math.Sin(xIndex)
Next
Next
' Set the chatr size and plot area size based on the number of cells and cell size
Dim c As XYChart = New XYChart(xCount * cellSize + 180, yCount * cellSize + 70)
c.setPlotArea(50, 30, xCount * cellSize, yCount * cellSize, -1, -1, Chart.Transparent, &H80FFFFFF, &H80FFFFFF)
' Set up the x-axis and y-axis
c.xAxis().setLinearScale(1, xCount, 1)
c.yAxis().setLinearScale(1, yCount, 1)
c.xAxis().setMargin(cellSize / 2, cellSize / 2)
c.yAxis().setMargin(cellSize / 2, cellSize / 2)
c.xAxis().setLabelStyle("Arial Bold")
c.yAxis().setLabelStyle("Arial Bold")
' Create a dummy contour layer to use the color axis
Dim layer As ContourLayer = c.addContourLayer(Nothing, Nothing, Nothing)
Dim cAxis As ColorAxis = layer.setColorAxis(c.getPlotArea().getRightX() + 30,
c.getPlotArea().getTopY(), Chart.TopLeft, c.getPlotArea().getHeight(), Chart.Right)
' Specify the color and scale used and the threshold position
Dim colors() As Double = {0, &H0000FF, 5, &H008080, 10, &H00FF00, 15, &HCCCC00, 20, &HFF0000}
cAxis.setColorGradient(True)
cAxis.setColorScale(colors)
cAxis.setLinearScale(0, 20, 1)
' Set color axis labels to use Arial Bold font
cAxis.setLabelStyle("Arial Bold")
' Add the cells as scatter symbols
Dim symbolSize As Double = 1
For yIndex As Integer = 0 To yCount - 1
Dim yOffset As Integer = yIndex * xCount
For xIndex As Integer = 0 To xCount - 1
Dim xCoor As Double = xIndex + 1
Dim yCoor As Double = yIndex + 1
Dim color As Integer = cAxis.getColor(dataZ(yOffset + xIndex))
c.addScatterLayer(New Double() {xCoor}, New Double() {yCoor}, "", Chart.SquareSymbol,
cellSize, color, Chart.SameAsMainColor).addExtraField(New Double() {dataZ(yOffset + xIndex)})
Next
Next
c.xAxis().setTickOffset(0.5)
c.yAxis().setTickOffset(0.5)
c.getPlotArea().moveGridBefore(layer)
' Output the chart
viewer.Chart = c
viewer.ImageMap = c.getHTMLImageMap("", "", "title='({x}, {value}) : {field0|2}%'")
End Sub
|
|