ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  frmContourZoomScroll
Posted by KeithB on Mar-19-2024 22:55
I am trying to "promote" the FrmCountourZoomScroll example to a main form, so that I don't need a shell program to run it.

I have it running, and can put my own data in the loadData() function - which works fine, but I would like to load a new dataset on the fly. Since loadData() only gets called once, I can't put my new data there, but when I create a new button and try to load the data, I can't get the main chart and thumbnail to show my new data correctly.

Is there a special incantation?

I have tried adding drawFullChart(), drawChart() and updateViewPort(), but nothing seems to work - the thumbnail never gets redrawn, and my data does not show up in the main chart.

  Re: frmContourZoomScroll
Posted by KeithB on Mar-19-2024 22:56
This is in windows forms C#, btw.

  Re: frmContourZoomScroll
Posted by Peter Kwan on Mar-20-2024 03:07
Hi KeithB,

You can always change the data. In fact, we include a number of real time zoom/scroll examples in which the data changes all the time. Whether you use a button to update the data or a timer to update the data, it is the same to ChartDirector.

As in the real time chart example, when the data change, the x-axis scale, y-axis scale, zoom/scroll positions, etc., may remain stable and do not change. In your case, your new data may not be a real time update of your previous data, but ChartDirector cannot know. If your new data are outside the axes range of the old data, it will fall outside the chart and will not be plotted.

To address this problem, you can reinitialize the viewport and the Form variables to its  initial state. I have tried myself with the following code with the frmContourZoomScroll.cs, and it works in my case:


private void loadNewData_Click(object sender, EventArgs e)
{
    loadData2();

    WinChartViewer viewer = winChartViewer1;

    // reset form variables
    firstChart = null;
    firstColorAxis = null;

    // reset viewport
    viewer.setFullRange("x", 0, 0);
    viewer.setFullRange("y", 0, 0);
    viewer.ViewPortLeft = 0;
    viewer.ViewPortTop = 0;
    viewer.ViewPortWidth = 1;
    viewer.ViewPortHeight = 1;

    // redraw the chart
    viewer.updateViewPort(true, true);
    drawFullChart(viewPortControl1, viewer);
}

// Some test data
private void loadData2()
{
    // The x and y coordinates of the grid
    dataX = new double[] { 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };
    dataY = new double[] { 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 };

    // The values at the grid points. In this example, we will compute the values using the
    // formula z = sin((x - 0.5) * 2 * pi) * sin((y - 0.5) * 2 * pi)
    dataZ = new double[dataX.Length * dataY.Length];
    for (int yIndex = 0; yIndex < dataY.Length; ++yIndex)
    {
        double y = (dataY[yIndex] - 0.5) * 2 * 3.1416;
        for (int xIndex = 0; xIndex < dataX.Length; ++xIndex)
        {
            double x = (dataX[xIndex] - 0.5) * 2 * 3.1416;
            dataZ[yIndex * dataX.Length + xIndex] = Math.Sin(x) * Math.Sin(y);
        }
    }
}


Best Regards
Peter Kwan

  Re: frmContourZoomScroll
Posted by KeithB on Mar-20-2024 03:26
Thanks, that did it.

This is temperature data I am plotting, I would like to filter it, to say focus on the area of 300 to 400 degrees. I would like to set the filtered data to Chart.NoValue, but the contour map, takes that in stride and simply interpolates around it.

Ah, I thought, I will just create a discrete heat map, like the wafer map I did earlier! Your sin+cos example works fine, But when I use my data with 27,315 points, nothing gets displayed. Is there a limit to the number of discretes in a discrete heat map?

  Re: frmContourZoomScroll
Posted by Peter Kwan on Mar-20-2024 04:52
Hi KeithB,

If the invisible part is defined by data values, you can try to set a color scale such that those data values use the transparent color. An example is:

// color scale from 300 to 400
layer.colorAxis().setLinearScale(300, 400, 10);

// set overflow and underflow color to transparent
layer.colorAxis().setColorGradient(false, null, Chart.Transparent, Chart.Transparent);

The ColorAxis.setColorScale API allows more flexibility, such as when you want to display the opposite (the part that is <300 and >400). The following is a setColorScale example that comes with ChartDirector, You can set some colors to transparent to hide those data ranges.

https://www.advsofteng.com/doc/cdnet.htm#contourcolor.htm

Best Regards
Peter Kwan

  Re: frmContourZoomScroll
Posted by KeithB on Mar-20-2024 23:44
Great thanks.

As I said, I could not get a discrete heatmap to plot with the 37,000 points I had, I just got a blank form.

How does the discrete heatmap handle oversampling?

Can I switch from contour to discrete on the fly when I get to a reasonable number of points?

  Re: frmContourZoomScroll
Posted by Peter Kwan on Mar-21-2024 02:22
Attachments:
Hi KeithB,

I have just tried to modify the discrete heat map sample code that comes with ChartDirector so that it plots over 90000 points, and it works normally. Note that when each cell becomes very small, the cell border, which is 1 pixel wide, will become a significant part of the cell. So the cell are mostly filled with the border color, which is black, and the chart looks dark. That's why in my modified code, I set the cell border color to the same as the fill color.


The original sample code is:

https://www.advsofteng.com/doc/cdnet.htm#discreteheatmap.htm


The modified code with 301 x 301 points is as follows:

public void createChart(WinChartViewer viewer, int chartIndex)
{
    // Random data for the 10 x 10 cells
    RanSeries r = new RanSeries(2);
    double[] zData = r.get2DSeries(301, 301, 0, 100);

    // Create an XYChart object of size 520 x 470 pixels.
    XYChart c = new XYChart(520, 470);

    // Set the plotarea at (50, 30) and of size 400 x 400 pixels.
    PlotArea p = c.setPlotArea(50, 30, 400, 400);

    // Create a discrete heat map with 10 x 10 cells
    DiscreteHeatMapLayer layer = c.addDiscreteHeatMapLayer(zData, 301);
    layer.setBorderColor(Chart.SameAsMainColor);

    // Set the x-axis labels. Use 8pt Arial Bold font. Set axis stem to transparent, so only
    // the labels are visible. Set 0.5 offset to position the labels in between the grid
    // lines.
    //c.xAxis().setLabels(xLabels);
    c.xAxis().setLabelStyle("Arial Bold", 8);
    c.xAxis().setColors(Chart.Transparent, Chart.TextColor);
    c.xAxis().setLabelOffset(0.5);
    c.xAxis().setTitle("X Axis Title Placeholder", "Arial Bold", 12);

    // Set the y-axis labels. Use 8pt Arial Bold font. Set axis stem to transparent, so only
    // the labels are visible. Set 0.5 offset to position the labels in between the grid
    // lines.
    // c.yAxis().setLabels(yLabels);
    c.yAxis().setLabelStyle("Arial Bold", 8);
    c.yAxis().setColors(Chart.Transparent, Chart.TextColor);
    c.yAxis().setLabelOffset(0.5);
    c.yAxis().setTitle("Y Axis Title Placeholder", "Arial Bold", 12);

    // Position the color axis 20 pixels to the right of the plot area and of the same
    // height as the plot area. Put the labels on the right side of the color axis. Use 8pt
    // Arial Bold font for the labels.
    ColorAxis cAxis = layer.setColorAxis(p.getRightX() + 20, p.getTopY(), Chart.TopLeft,
        p.getHeight(), Chart.Right);
    cAxis.setLabelStyle("Arial Bold", 8);

    // Output the chart
    viewer.Chart = c;
}


If the above still cannot solve the problem, is it possible to provide a hard coded example that can illustrate the problem you see?


Best Regards
Peter Kwan
discrete_heat_map_301x301.png

  Re: frmContourZoomScroll
Posted by Peter Kwan on Mar-21-2024 02:26
Hi KeithB,

For switching between contour and discrete heat map, you can always plot any chart you want. In the original sample code, the main window has 8 chart viewer controls, and we can switch them to any chart type based on user selection on the left side.

Basically, you can have a subroutine that plots the data as a contour chart, and another subroutine that plots the data as a discrete heat map, and you can call either one to draw the chart you want.

Best Regards
Peter Kwan

  Re: frmContourZoomScroll
Posted by KeithB on Mar-23-2024 00:28
I think I found my problem.
(Oh, there is a documentation error on the web. It shows a .addDiscreteHeatMapLayer2(), while actually, there are only overloads of .addDiscreteHeatMapLayer())

My data is formatted like this:
X    Y       Z
0 -1800 393.51
25.75 -1800 393.585
51.5 -1800 393.808
77.25 -1800 394.172
103 -1800 394.662
131.5 -1800 395.32
160 -1800 396.076
188.125 -1800 396.888
216.25 -1800 397.731
// skip a bunch to show Y spacing

0 -1750 393.733
25.75 -1750 393.814
51.5 -1750 394.054
77.25 -1750 394.454
103 -1750 395.092
131.5 -1750 395.774
160 -1750 396.603
188.125 -1750 397.498
216.25 -1750 398.414
217 -1750 398.439
223 -1750 398.631
251 -1750 399.509
279 -1750 400.37
// and so on

As you can see, my X's and Y's are not evenly spaced. I guess I need to pass addDiscreteHeatMapLayer() a list of X's and Y's, and then a list of Z's in the correct order. (First making sure that each X,Y pair has a Z!)

Also, as you can also see the Y value (in microns) is negative which means that I cannot easily .syncAxis. Is there a "Get Max Axis Value" method so that I can sync the axes? Also, when you sync axes, does it take proportion into account. for example if Y is half of X and X goes to 1000, will Y go to 500?

  Re: frmContourZoomScroll
Posted by Peter Kwan on Mar-23-2024 03:24
Hi KeithB,

Thanks for pointing the doc error for addDiscreteHeatMapLayer2. It should be an overloaded addDiscreteHeatMapLayer in code.


If your x coordinates are unevenly spaced, it can mean one of the following two things:

(a) The cells are of different sizes in the x-direction. For example, if the x values are {12, 20, 30, 80}, the cell at 20 will be smaller than the cell at 30.

or

(b) All cells are of the same size. The x values are just "names" for display. In this case, the x/y values are treated as axis labels (configured using Axis.setLabels), and only the z values are passed to addDiscreteHeatMapLayer. This is demonstrated in the ChartDirector sample code.


For syncAxis, do you mean you want to synchronize the x-axis with the y-axis scale in some way? Normally, the axis should use a scale that is most appropriate to the data. Synchronize the x and y axes may cause one of the axis to use a scale not based on the data, so it may not be a good idea. If you really want to sync the axis, you can use Axis.syncAxis or Axis.syncScale. Negative values should not cause any issue. We often synchronize temperature in Celsius and Fahrenheit in which the temperature can be positive or negative.

You mentioned "X goes to 1000, will Y go to 500"? Do you mean the horizontal length (in pixels) of 1000 x-units axis should be the same as the vertical length of 500 y-units? The length depends on the axis scale and the plot area width/height. The axis scale depends on your data, while the plot area width/height are the parameters you can freely choose.

If the axis scale is automtically determined by ChartDirector, you can ask ChartDirector to determine the axis scale immediately by using XYChart.layoutAxes. After that, you can use Axis.getMaxValue and Axis.getMinValue to determine the axis scale, and you can use XYChart.packPlotArea to modify the plot area size to get your preferred display ratio.

Best Regards
Peter Kwan

  Re: frmContourZoomScroll
Posted by KeithB on Mar-23-2024 03:28
The output is from a 3D thermal simulation, and I think the spacing comes about from the meshing, which is not uniform.

Sorry if my explanation is not clear. Both X and Y are distance units, but what I am graphing is rectangular: about 6000 units in X and 1800 in Y. I would like the proportions to be the same.

  Re: frmContourZoomScroll
Posted by Peter Kwan on Mar-25-2024 16:28
Hi KeithB,

From your data, you can obtain the minimum and maximum values of the x and y coordinates. Then you can determine the exact proportion you need. For example, if you want the plot area to be 400 pixels wide, then the height must be:

int width = 400;
int height = (int)(width * (maxY - minY) / (maxX - minX) + 0.5);

c.setPlotArea(50, 30, width, height);

The x-axis and y-axis scales should be:

c.xAxis().setLinearScale(minX, maxX);
c.xAxis().setRouinding(false, false);

c.yAxis().setLinearScale(minY, maxY);
c.yAxis().setRouinding(false, false);

This should provide the proportion you want.

Best Regards
Peter Kwan

  Re: frmContourZoomScroll
Posted by KeithB on Mar-26-2024 01:49
Thanks, this all works great.

Is there a way to get at the color scale?

Given my uneven XY spacing, it might be best to plot the X,Y points with a marker that is the color of the Z value. (Like the xyline example, but without the lines.)

The only downside, is that I might have a lot of layers - one layer for each point.

So:
Is there a way to color each datasymbol in a line a different color?

Or, I can also group each Z value to a color range so that all the "red" points are on the same layer.

  Re: frmContourZoomScroll
Posted by Peter Kwan on Mar-26-2024 04:56
Hi KeithB,

If you have a lot of symbols, you would need to group the symbols of the same shape and color into a single layer. Symbols in a layer must have the same shape and color.

In practice, there is not a lot colors in a color scale. Most color scales only have a few colors, so only a few layers are needed. Even if you use continuous smooth coloring (like https://www.advsofteng.com/doc/cdnet.htm#smoothcontour.htm), if the color axis is 400 pixels long, it is not possible to contain more than 400 colors. It is OK to have a few hundred layers in ChartDirector.

You mentioned "Is there a way to get at the color scale?". You can ask the ColorAxis what is the color for a certain z value. See:

https://www.advsofteng.com/doc/cdnet.htm#ColorAxis.getColor.htm

However, before your code can ask the ColorAxis for the color, it needs to define the color scale first. such as using ColorAxis.setColorScale.

https://www.advsofteng.com/doc/cdnet.htm#ColorAxis.setColorScale.htm

Best Regards
Peter Kwan

  Re: frmContourZoomScroll
Posted by KeithB on Mar-26-2024 22:28
Attachments:
Thanks for the idea:

As you can see, the tooltip shows the range of the temperature -which is the name of the scatter layer. Is there any way to put my actual temperature value there?

The tooltip is only slightly modified from the example:
winChartViewer1.ImageMap = c.getHTMLImageMap("clickable", "",
    "title='[{dataSetName}] X = {x}, Y = {value}'");

I would like to be able to put arbitrary text in place of the dataSetName. (I can of course set up an array of values corresponding to x,y.)
Untitled.jpg

  Re: frmContourZoomScroll
Posted by Peter Kwan on Mar-27-2024 04:49
Hi KeithB,

Yes, you can provide the z value to the scatter layer as an extra field. Then you can configure the tooltip to display the extra field instead of the dataSetName. It is like:

myScatterLayer.addExtraField(zDataArray);

.....

winChartViewer1.ImageMap = c.getHTMLImageMap("clickable", "",
    "title='[{field0}] X = {x}, Y = {value}'");


See:

https://www.advsofteng.com/doc/cdnet.htm#Layer.addExtraField.htm
https://www.advsofteng.com/doc/cdnet.htm#paramsub.htm

Best Regards
Peter Kwan