Working with Composite UltraCharts

Posted by ChUIMonster on 17-Mar-2009 13:30

Not having learned when enough is enough I've embarked on an adventure to try to get a composite UltraChart working.

So I have spent a good chunk of yesterday and today grinding through the documentation, the samples and the infragistics forums and stuff.

Step 1 was to simply replace an ordinary chart with a composite chart with just one layer. This, sort of, works.

However I wouldn't be posting if it worked perfectly And I'm posting here, rather than at infragistics because 1) I don't speak VB or C# particularly well and 2) I think my issues are largely a result of cognitive dissonance between my data oriented Progress 4GL mindset and the controls oriented VB/C# mindset.

I think that the core problem is that I don't grok the concept of a NumericSeries as it relates to a chart. I keep trying to think of it as a temp-table but that is clearly wrong. It doesn't really seem to be an array either. In particular it bothers me that:

series1:DataBind( dTable, dValue, dLabel ).

is supposed to mean something. "series1" is a NumericSeries. "dTable" is a "DataTable" which I have converted from a Progress temp-table (thanks to Haavard's help from the last go-roubnd with UltraCharts!). The DataTable at least makes sense to me. dTable has 20 rows and 2 columns, a label column and a data column. (The underlying temp-table has 4 colums -- 1 labels, 3 data.)

I can apparently add as many "series" to a chart as I'd like. But I do not really understand their function and how they are to be used and, from my perspective, the infragistics documentation seems very circular in terms of defining the term.

One theory that I've formed is that I need a data series for:

a) The x axis labels

b) The y values for anything that I want to chart

If that is correct then I would need to create a "series" for every column in the DataTable. And add each series to the UltraChart. Is that right? I don't think that it is quite right because it doesn't explain the 2 columns provided to Bind() nor does it work if I arbitrarily Add() additional series -- odd things happen then. So my conceptual model seems to be flawed.

This attached code, sort of works in a limited way. It displays a nice column chart.

But the idea is to have two layers and show two column charts super-imposed on one another. It seems to me that if I just uncomment the two lines down towards the bottom that that should happen. But instead the chart heads off into the twilight zone...

Ultimately I'm trying to get to a point where I can have one of the charts be a StackColumnChart and the other a LineChart. But neither of those chart types will work for me with my understanding of series right now.

Can anyone educate me?

[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/myCompositeChart.cls:550:0]

All Replies

Posted by ChUIMonster on 17-Mar-2009 15:50

Well one problem turns out to be the the dolt who wrote the code above forgot to reopen the query between binding it to various sessions. Fixing that helps but it doesn't explain everything.

It's getting better but I still think I'm missing a clear understanding of what "series" are all about.

Posted by Håvard Danielsen on 18-Mar-2009 07:08

> Well one problem turns out to be the the dolt who wrote the code above forgot to reopen the query between binding it to various sessions. Fixing that helps but it doesn't explain everything.

Reposition-to-row(1) before the do while get-next seems to help also. Or change it to a do while with a get-first before and the get-next at bottom.

> It's getting better but I still think I'm missing a clear understanding of what "series" are all about.

The two following settings probably throws you off.

x2Axis:AxisNumber = AxisNumber:X2_Axis

y2Axis:AxisNumber = AxisNumber:Y2_Axis

This is moving the axis to the other (2) side and changes the position of the data area of the chart.

Try:

x2Axis:AxisNumber = AxisNumber:X_Axis

y2Axis:AxisNumber = AxisNumber:Y_Axis

Posted by ChUIMonster on 18-Mar-2009 07:22

Those were making the 2nd chart offset from the 1st but I had a couple of work-arounds for that.

Poking around last night on the IG boards I found an example that clarified a few minor points like that. One key thing is that I only need a single chartArea -- not two. So I cleaned that up which makes the code a bit smaller and easier to read.

I now have an example that reliably super-imposes one chart over the other (attached). But I still haven't figured out how to make the first chart a StackColumnChart and the second a LineChart. I'm clearly still missing something regarding the interactions between the chart and its data.

[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/7318.myCompositeChart.cls:550:0]

Posted by ChUIMonster on 18-Mar-2009 07:26

Oops -- slightly wrong version of code. To get the layered charts change the bit at the bottom to look like this:

Posted by Håvard Danielsen on 18-Mar-2009 08:40

One key thing is that I only need a single chartArea

-- not two. So I cleaned that up which makes the

code a bit smaller and easier to read.

I'm not sure about that.

In any case I'm attaching the example changed to super-impose a PieChart and ColumnChart on top of each other by ensuring that the Bounds of the ChartAreas are the same.

A LineChart is quite different according to Infragistics doc: Each row is drawn as a single line (or area) on the chart, with a number of points in the line equal to the count of numeric columns in the data set.

So you need at least two numeric columns for a line chart to show a line.

[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/5875.myCompositeChart.cls:550:0]

Posted by ChUIMonster on 18-Mar-2009 14:15

The single ChartArea approach does seem to work. It makes sense to me and simplified things quite nicely too. Plus it came from one of the IG guys who seems to know what he's talking about

Getting at least two numeric columns (series?) seems to be at the root of all of my current issues.

When I add 2 or more series to a chart they appear next to each other. (I can understand that that might sometimes be the desired behavior but, to me, it seems like it ought to be the exception rather than the rule.) This leads me to believe that adding additional "series" is not the right way to go. I suspect that I need a way to add more values to a series.

Specifically I think that my use of:

is the problem. I may be out in left field but I'm thinking that perhaps I need to make multiple passes through the DataTable? One to set it up like above and then another for each additional column of data? Maybe something like this:

Posted by ChUIMonster on 18-Mar-2009 14:31

Nope, that looks like a dead-end

For one things the 2nd form is subtly different -- the 1st parameter is a DataSet not a DataTable. The 2nd parameter is the index of the desired Table within the Set rather than the column.

But why have a method to bind a DataTable if it is only going to use a limited number of columns? That just doesn't seem sensible.

What is left of my brain is turning to mush and dribbling out my ears...

Posted by Håvard Danielsen on 18-Mar-2009 15:42

The single ChartArea approach does seem to work. It

makes sense to me and simplified things quite

nicely too. Plus it came from one of the IG guys who

seems to know what he's talking about

I certainly won't argue with that, but the WinChart/Composite/DataBind sample that we ship uses two ChartAreas and was transformed from an IG sample.

Getting at least two numeric columns (series?) seems to be at the root of all of my current issues.

You need to completely twist/invert the data to make them meaningful for the LineChart.

If you have two rows A and B with columns X, Y, Z a column chart shows it like this The graph height (y-axis) is set from the value of the column.

X

Y

Z

X

Y

Z

Row A Row B

In a LineChart the same data is shown like this.

The y-axis position of the points is decided by the value of the columns

RowA XYZ

RowB XYZ

In your case you have many rows with one column (X)

|X|      |X|      |X|      |X|

RowA RowB RowC RowD

If you want a LineChart to show the same data super imposed so that it matches the column chart, you need a column for each row, so to speak.

LineRow

- Column1 = RowA:X

- Column2 = RowB:X

- Column3 = RowC:X

- Column4 = RowD:X

Posted by ChUIMonster on 18-Mar-2009 16:07

I'm guessing that the same sort of "logic" applies to StackColumnChart.

That seems like what SwapRowsAndColumns does with a DataTable when you use a non-composite chart. But, so far as i can tell, there is nothing similar available when dealing with layers and series?

So the questions is... how do you make that happen? In good old 4GL code

It sort of sounds like I'm going to have to dynamically create a series that corresponds to every row in the data table? And an entry in the series for each column?

The mush is no longer dribbling -- it's gushing

Posted by Thomas Mercer-Hursh on 18-Mar-2009 16:11

The mush is no longer dribbling -- it's gushing

I guess that is what one has to expect when that which used to be ChUI is now GUI!

Posted by ChUIMonster on 18-Mar-2009 16:14

This little nugget from the IG docs looks promising:

I think that GetXYSeriesUnBound() is creating the sort of structure that I need... I'll have to fiddle with it later tonight.

Posted by ChUIMonster on 18-Mar-2009 16:15

Where is the Groan feedback button when I need it?

Posted by Thomas Mercer-Hursh on 18-Mar-2009 16:19

Probably hiding under some of that mush ...

Posted by Håvard Danielsen on 18-Mar-2009 17:21

The mush is no longer dribbling -- it's

gushing

I guess that is what one has to expect when that

which used to be ChUI is now GUI!

I guess the problem is amplified by the fact that you (and I) have to learn the components, but the core issue here is charting or reporting.

The reason why I tried to illustrate the 3 column sample case earlier was to illustrate why a column chart and line chart needs to be different.

In your case you have one column per row. This makes it possible to show the data as a line chart, but a line chart is really a single row of data.

Here's the important part; If you break your data down to satisfy the line chart then you can use the data to also feed a column chart in this case. You really do not need the column chart capability to show multiple rows when you have a single column in each row. You can show it as a single row and it should appear exactly as it currently does.

When this is said, I would look for options or settings for this particular one column per row situation. The SwapRowsAndColumns certainly sounds promising, or maybe a line chart can be shown as single column chart or something, or maybe there is a simpler type of column chart. Or it might be as simple as just feeding the data column by column to the chart while you traverse the rows. Tom's last posting might also be onto something .

Message was edited by:

Havard Danielsen

Posted by ChUIMonster on 19-Mar-2009 07:27

I guess the problem is amplified by the fact that you

(and I) have to learn the components, but the core

issue here is charting or reporting.

There is definitely an issue with vocabulary. I really don't think that I understand what they mean when they say "series". It almost seems like a one dimensional array or a column from a table but I don't think that either of those is really right because when I try to apply that idea I get burned. Repeatedly. (And how can it be either when the methods for building them take at least two and sometimes 3 data values?)

The reason why I tried to illustrate the 3 column

sample case earlier was to illustrate why a column

chart and line chart needs to be different.

Going back to that...

I'm not sure that I agree that they need to be different. They clearly are different but to my way of thinking the difference is entirely specious and quite antagonistic to mapping database tables (or temp tables) onto the chart.

In your case you have one column per row. This makes

it possible to show the data as a line chart, but a

line chart is really a single row of data.

In my mind a line chart and a column chart are (or should be) just two different ways of visualizing the same data. One draws columns from the X-Axis to the point, the other connects the points.

That is not, however, the way that IG controls seem to see the world. It may be that "reporting" people agree with IG. I wouldn't know. I do know that have had similar bouts of head banging and hair pulling with Excel charts so it probably isn't just IG that thinks in this messed up way.

Here's the important part; If you break your data down

to satisfy the line chart

I wish I could figure out how to do that...

... then you can use the data

to also feed a column chart in this case. You really

do not need the column chart capability to show

multiple rows when you have a single column in each

row. You can show it as a single row and it should

appear exactly as it currently does.

What? I completely lost you.

When this is said, I would look for options or

settings for this particular one column per row

situation. The SwapRowsAndColumns certainly sounds

promising,

It doesn't exist at this level. Or if it does exist it is very well hidden from me.

... or maybe a line chart can be shown as

single column chart or something, or maybe there is a

simpler type of column chart. Or it might be as

simple as just feeding the data column by column to

the chart while you traverse the rows. Tom's last

posting might also be onto something .

That seems to have turned out to be another rat-hole of circular logic and definitions

I am currently at a complete loss with no ideas for moving forward

Posted by Håvard Danielsen on 19-Mar-2009 14:23

I do not have the answer to how to make the line chart visible (yet), but it's not like we're not getting anywhere. We do have a layered chart working with different chart types.

> > I guess the problem is amplified by the fact that

you

(and I) have to learn the components, but the core

issue here is charting or reporting.

There is definitely an issue with vocabulary. I

really don't think that I understand what they mean

when they say "series". It almost seems like a one

dimensional array or a column from a table but I

don't think that either of those is really right

because when I try to apply that idea I get burned.

Repeatedly. (And how can it be either when the

methods for building them take at least two and

sometimes 3 data values?)

I see it as a a row with columns (different than an array as each column has a name)

The constructors provide a way to tell the chart which fields are the value field and the text field, basically making each row into a virtual name/value pair list. (3 parameters: table, valuefield, textfield)

You can also just describe only the value column. (2 parameters - no text field)

I think the confusion is that:

1. These constructors do not support more than one value column, while the chart is designed for and defaults to support multiple value columns.

Possible explanation:

- The default is to include all columns in the row in the chart.

- You use other methods like IncludeColumns to control which columns to chart

2. When there is obvious name/value pair support then one would expect it to work with a line chart. However, the line chart expects one row per line with a column for each value (like an array).

Possible explanation:

- The default makes sense if you want more than one line charted!

- I am 99% sure the SwapRowsAndColumns is for this case where you have a value in each row and only need a single line, but maybe it does not work with layers or series or something.

> Going back to that...

I'm not sure that I agree that they need to be

different. They clearly are different but to

my way of thinking the difference is entirely

specious and quite antagonistic to mapping database

tables (or temp tables) onto the chart.

They are kind of the same for all charts, but the Line chart is special since you need at least two column per line (row), since the line is drawn from one value to the other.

> > In your case you have one column per row. This

makes

it possible to show the data as a line chart, but

a

line chart is really a single row of data.

In my mind a line chart and a column chart are (or

should be) just two different ways of visualizing the

same data. One draws columns from the X-Axis to the

point, the other connects the points.

This is right, but the default is that each row is a chart item and with only one value there is nothing to draw. I'm sure it's there, just not visible...

> That is not, however, the way that IG controls seem

to see the world. It may be that "reporting" people

agree with IG. I wouldn't know. I do know that have

had similar bouts of head banging and hair pulling

with Excel charts so it probably isn't just IG

that thinks in this messed up way

The data requirements for 2D charting are based on laws of nature almost. Easy to use manually often, but tough to program generically.

Here's the important part; If you break your data

down

to satisfy the line chart

I wish I could figure out how to do that...

You can try to make a version of the DataTable method that adds the columns to a single row, but I still don't know how/if that would work with the current chart.

The SwapRowsAndColumns certainly sounds

promising,

It doesn't exist at this level. Or if it does exist

it is very well hidden from me.

Maybe not supported for layers or something?

> > ... or maybe a line chart can be shown as

single column chart or something, or maybe there is

a

simpler type of column chart. Or it might be as

simple as just feeding the data column by column

to

the chart while you traverse the rows. Tom's last

posting might also be onto something .

That seems to have turned out to be another rat-hole

of circular logic and definitions :(

> I am currently at a complete loss with no ideas for

moving forward :(

I would have tried to make a line chart work in a very simple case. (no layering or multiple areas.

Try the data you have and see if the SwapRowsAndColumns setting does some magic.

Try to create data in a single row instead and see if that works. (You can make a version of DataTable that does this, with some changes.

Posted by Thomas Mercer-Hursh on 19-Mar-2009 15:40

I haven't fiddled with this stuff at all, but just as an outsider observer, I wonder about:

They are kind of the same for all charts, but the Line chart is special since you need at least two column per line (row), since the line is drawn from one value to the other.

Seems to me that for any chart type which happens on an X-Y axis display, what one actually needs is N+1 sets of data for each indicator. For most chart types, one set provides the categories on the X axis (or vice versa if one flips the chart type) where each category occupies the same amount of space. For scatter plots this first set would be the distance along the X axis. The remaining sets represent values. In a non-stacked bar chart, each is a separate bar in the category. In a stacked bar chart each is drawn on top of the prior. In a line chart, the value designates a point above the X axis and a line is drawn from one to the next.

For all except the scatter plot, it is immaterial whether the values in the X-axis are uniformly distributed or not because they will be displayed uniformly regardless. They don't even have to be ordered or orderable. Only the scatter plot comes to mind where the X values have metric quality and where it might help to put them in in order if one wanted to connect them with lines.

Posted by Håvard Danielsen on 20-Mar-2009 07:12

Seems to me that for any chart type which happens on

an X-Y axis display, what one actually needs is N+1

sets of data for each indicator. For most chart

types, one set provides the categories on the X axis

(or vice versa if one flips the chart type) where

each category occupies the same amount of space. For

scatter plots this first set would be the distance

along the X axis.

The remaining sets represent

values. In a non-stacked bar chart, each is a

separate bar in the category. In a stacked bar chart

each is drawn on top of the prior. In a line chart,

the value designates a point above the X axis and a

line is drawn from one to the next.

For all except the scatter plot, it is immaterial

whether the values in the X-axis are uniformly

distributed or not because they will be displayed

uniformly regardless. They don't even have to be

ordered or orderable. Only the scatter plot comes to

mind where the X values have metric quality and where

it might help to put them in in order if one wanted

to connect them with lines.

I was pretty wrong about my assumption about a Line chart. It is actually not a point, but an area. So the x-axis distribution/ordering is thus very different from a column chart.

If one want to have a line chart or area chart in a composite chart then one need to set the x-axis to use continuousData, otherwise the chart wont render.

The only change needed to make the second chart show up in the previously attached sample (in addition to setting the ChartType to LineChart) is to:

x2Axis:SetLabelAxisType = SetLabelAxisType:ContinuousData

Tom's assumption about how this should work was thus quite right and the data can remain as is with one column per row and there is no need to use SwapRowsAndColumns, even if it actually is possible to set this on composite charts on the ChartLayoutAppearance. It does what it says, with quite different effect than I assumed.

Infragistics Online documentation Axis Requirements for Composite Charts has a table that outlines the requirements for each axis in a chart that is used as a layer of a Composite chart. It also says If any of the requirements are not met, the Composite chart will not render.

Posted by ChUIMonster on 20-Mar-2009 07:52

I still find the IG documentation to be fairly opaque I had found the table that you refer to but it really wasn't very helpful to me.

I heartily agree with Thomas regarding the nature of charts. This bizarre terminology seems, to me, to be a Windows thing. It sure isn't related to anything that was taught back in my school days. Other charting tools, like GnuPlot for example, use a much more straight-forward nomenclature that is a far better match for my vocabulary. Just guessing at the history but this feels like a group of people were building charting functionality in a spreadsheet program and adding features and making stuff up ad-hoc over a long period of time and without ever talking to each other nor ever stopping to refactor. And whatever they did was then copied by a couple of generations of similarly uncoordinated teams working on different projects and it has now become enshrined as "the windows way". Sort of reminds me of the UNIX vi editor.

On the bright side I posted a question on the IG forums yesterday seeking a simple example using a StackColumnChart and I have managed to translate the reply into working Progress code. I should have something ready to post here in a little bit.

Posted by Håvard Danielsen on 20-Mar-2009 08:11

I still find the IG documentation to be fairly opaque

I had found the table that you refer to but it

really wasn't very helpful to me.

Maybe it could have used better graphics and highlighted or underlined the "will not render", but it explains exactly why the line chart did not render.

I'm attaching the working version of this thread's chart.

[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/myCompositeChart2.cls:550:0]

Posted by ChUIMonster on 20-Mar-2009 08:20

The attached class works!

I think that we all sort of knew that the data needed to be "rotated" but getting there was difficult. The key was to abandon the DataTable, construct a NumericSeries for each row in the query and add each series to the ChartLayer.

So, as I said, the attached class does the job and displays what I had hoped for as a simple example.

For bonus points though I do have a few open items associated with this task:

1) I'd like to get the columns spaced out. In an non-composite chart "ultraChart1:ColumnChart:ColumnSpacing = 1." would do the trick. I'm not seeing how to translate that.

2) I'd like to get the 2nd layer's columns centered within the 1st layer's stacked columns. That might magically happen if the spacing above can get worked out but it might not. Any ideas on ways to accomplish that?

3) Making the 2nd layer's columns some other color.

[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/1200.myCompositeChart.cls:550:0]

Posted by ChUIMonster on 20-Mar-2009 09:11

Setting the color turns out to be easy. Just add a PaintElement to the series and set its color:

Setting the spacing still has me puzzled though.

Posted by Håvard Danielsen on 20-Mar-2009 09:28

I think that we all sort of knew that the data needed

to be "rotated" but getting there was difficult. The

key was to abandon the DataTable, construct a

NumericSeries for each row in the query and add each

series to the ChartLayer.

This is kind of the way I thought it needed to be, but it's actually not necessary to rotate the data.

The only problem with the original sample was that it did not render a LineChart. It seems you need to use continousData to make it work with a LineChart also with this approach.

Also note that with the extra rotated data you now actually need to use SwapRowsAndColumns on the ChartLayer to make the LineChart make sense.

Posted by Håvard Danielsen on 20-Mar-2009 10:18

1) I'd like to get the columns spaced out. In an

non-composite chart

"ultraChart1:ColumnChart:ColumnSpacing = 1." would do

the trick. I'm not seeing how to translate that.

The ColumnChartAppearance that controls this is accessible through the ChartTypeAppearance on the ChartLayer. You would need to cast it down to get the ColumnSpacing attribute.

Something like this should do the trick:

cast(ultraChart1:CompositeChart:ChartLayers:Item[0]:ChartTypeAppearance,ColumnChartAppearance):ColumnSpacing = 1.

On could possibly also new a ColumnChartAppearance with this and other settings and add it to the ChartLayer when you create it.

Posted by ChUIMonster on 20-Mar-2009 10:50

Ok, that works!

I'm starting to understand why it was so hard to find -- you have to know where to look first (You need to know what to cast it to.)

Would "other settings" also include things like the width of the column? How can I figure out what "other settings" are available?

Posted by ChUIMonster on 20-Mar-2009 10:56

I could never find a SwapRowsAndColumns at the ChartLayer level. This whole thing probably would have been solved 3 days ago if I had It would be nice to know, for reference, where that is if it exists.

Is that another one of those you've got to know what to cast() in order to know what to cast() circular documentation things?

In the end though I'm pretty happy with my addQuery2Layer() method. Eliminating that DataTable mapping is a big plus.

Posted by Håvard Danielsen on 20-Mar-2009 12:18

I could never find a SwapRowsAndColumns at the

ChartLayer level. This whole thing probably would

have been solved 3 days ago if I had It would be

nice to know, for reference, where that is if it

exists.

SwapRowsAndColumn would not have helped 3 days ago as the LineChart would have remained invisible.

The property is on the actual ChartLayerAppearance.

chartLayer2 = new ChartLayerAppearance().

...

chartLayer2:SwapRowsAndColumns = true.

You can also access the chart layer through the chart layer collection on the UltraChart as follows:

ultraChart1:CompositeChart:ChartLayers:Item[0]:SwapRowsAndColumns = true.

In the end though I'm pretty happy with my

addQuery2Layer() method. Eliminating that DataTable

mapping is a big plus.

I'm pretty sure it is a plus performance wise to eliminate the DataTable. But you might loose some advanced behavior by not using data binding. You probably do not need this in most of cases, but try the WinCharts/Composite/DataBind.cls example in our samples and edit something in the grid and the data in the chart will be refreshed. This happens automatically through data binding.

Posted by Håvard Danielsen on 20-Mar-2009 15:05

Ok, that works!

I'm starting to understand why it was so hard to find

-- you have to know where to look first (You need

to know what to cast it to.)

Yes, you need to know what to look for, but I had that information when you said that the non layered case used "ultraChart1:ColumnChart:ColumnSpacing = 1.

So I just needed to find the same type of appearance somewhere on the layer. (I also looked at the area, since I'm still a bit hazy on the chart concepts) Given that the layer is for all types, I did not expect an exact match to the ColumnChartAppearance, but looked at all appearances.

Would "other settings" also include things like the

width of the column? How can I figure out what

"other settings" are available?

I was mainly referring to the properties at the ColumnChartAppearance without really knowing what was there, but the use of appearance objects is very central in Infragistics and controls almost everything layout/appearance related.

Take a look at the ColumnChartAppearance in the documentation or object type browser.

Posted by ChUIMonster on 20-Mar-2009 15:23

I did. I somehow managed to miss ColumnSpacing. Or maybe I just couldn't get the cast() to work, I dunno, it's all becoming a haze... Even though there isn't actually much there. (I was really hoping for a ColumnWidth field somewhere -- but no luck :-(.) I looked in a million or so other places too. I get very lost searching for this stuff -- something leads to something else and before too long I've lost track of how I got to wherever I am... and the back button isn't very helpful.

In cases like this it would be really helpful if the class browser supported searching for properties and methods rather than just class names. (Or maybe it does and I'm just not aware of it?)

Posted by Peter Judge on 20-Mar-2009 15:28

In cases like this it would be really helpful if the

class browser supported searching for properties and

methods rather than just class names. (Or maybe it

does and I'm just not aware of it?)

Unfortunately, it doesn't. I logged a bug for that : please feel free to have your name added to bug OE00175205

-- peter

This thread is closed