Page 1 of 2

Stacked Bar Chart

Posted: Thu Feb 13, 2014 5:46 am
by 16566546
I wish to use the Stacked Bar Chart to draw lithology columns direct from a table of data in a database. I also want to use as much of existing line chart code as possible, which uses a custom TLineSeries to convert data from the underlying SI values to user units (for instance, m to ft).

The line series code is as follows, using fields in the table such as Depth on Independent Axis, and Temperature and Pressure on two independent axes:
ChangeNode Move to a different header/detail table
GenerateGraph Set up the graph to be drawn
ClearAll Remove all series from chart, clear datasources, clear series from collections (for each dependent axis)
InsertSeries Insert UnitLineSeries (with unit conversion code) into a collection for each dependent axis.
Set X/Y ValueSource Fields in the table
Set DataSource Detail table query based on header record
RefreshAllSeries Calls TChartSeries.RefreshSeries for each collection.
Chart.RefreshData Calls TCustomDBChart.RefreshData

When I move to another record in the header table, the program simply Calls RefreshAllSeries and Chart.RefreshData.

This works fine, but when I apply the same technique to a stacked bar chart, I have a lot of problems. Typical fields in table are Strata Top, Strata Bottom, Rock Type, Pattern, Foreground, Background. In this case, the InsertSeries step has to carry out calculations to calculate the depth increments, insert missing sections, so I need to call it again every time I move from record to record. I am having trouble with the following:
1. Coloring the foreground and background of the selected patterns. I set ColorSource = 'Foreground' which doesn't seem to color the foreground correctly - it starts of well but for repeat rock types the pattern is correct but the color has changed. And how can I use the Background values to color the background.
2. Legend. Rocktypes are repeated but I want only one instance of each rocktype in the legend (and preferably in alphabetical order). Is there any easy way to do this (remember I am sending a BarSeries to the chart, not drawing the chart record by record.
3. Labels. I want to label each strata with a comment from the table that stays with the bar chart when I zoom. I don't seem to have much success here.
3. How can I control the position of the bar chart on the chart. I have used a dummy numeric x-axis (Depth is on the y-axis) and the bar chart is located at the value zero. in the middle of the chart window. When I zoom (vertical only) the chart jumps to the left-hand axis.
4. Multiple bar charts. If I select a number of sets of lithology data, I want to place them side by side on a common y-axis, at user-specified positions. Any ideas on how to do this?

I look forward to any comments and suggestions.

Re: Stacked Bar Chart

Posted: Fri Feb 14, 2014 12:08 pm
by narcis
Hello Errol,

Thanks for the explanation. It's difficult to be able to provide accurate replies without seeing how do you exactly implement such functionality with TeeChart though. To be able to help you and give effective suggestions and solutions, it would be very helpful if you arranged a simple example project we can run "as-is" to reproduce those issues here.

Thanks in advance.

Re: Stacked Bar Chart

Posted: Wed Feb 19, 2014 6:14 am
by 16566546
Lithology_Chart.png
Lithology_Chart.png (16.93 KiB) Viewed 19516 times
I have made some progress with the stacked bar chart. I use two procedures, firstly InsertGeologicalSeries which puts the data queried from the database in a memory table, and calculates depth increments. The program then creates a unit bar series and links the DataSource to the memory table. TUnitBarSeries.DrawBar overrides Series.TBarSeries.DrawBar.

I am now able to colour the foreground and background, but I am unable to draw a legend apart from one showing the Name of the TUnitBarSeries and a random colour. (see attachment). I have searched the entire TeeChart Help and am unable to find out how to do this. Any suggestions welcome.

Code: Select all

procedure TQSCollection.InsertGeologicalSeries(aCodeFld,aFld:string);

var
  iIndex,k : integer;
  stitle,sxfield,syfield : string;
  tmpHorizAxis: TChartAxis;
  sDepField : string; 

begin
  self.Owner.Chart.LeftAxis.Inverted := True;
  self.Owner.IndependentField := 'Depth';
  self.owner.IntervalQuery := TkbmMemTable.Create(self.Owner);
  self.owner.IntervalQuery.FieldDefs.Assign(self.Owner.UnitDataSet.GetDataSet.FieldDefs);
  self.owner.IntervalQuery.FieldDefs.Add(self.Owner.IndependentField, ftFloat, 0, false);
  self.owner.IntervalQuery.Open;
  self.Owner.UnitDataSet.GetDataSet.First;

  while not self.Owner.UnitDataSet.GetDataSet.Eof do
  begin
    self.owner.IntervalQuery.Append;
    self.owner.IntervalQuery.CopyFields(self.Owner.UnitDataSet.GetDataSet);
    self.owner.IntervalQuery.FieldByName('Depth').asFloat :=
      self.owner.IntervalQuery.FieldByName('Strata Bottom').asFloat
       - self.Owner.IntervalQuery.FieldByName('Strata Top').asFloat;
    self.owner.IntervalQuery.Post;
    self.Owner.UnitDataSet.GetDataSet.Next;
  end;

  self.owner.IntervalQuery.First;
  sTitle := 'Lithology Profile';

  SeriesListB.AddObject(sTitle, TUnitBarSeries.Create(Owner));
    iIndex := SeriesListB.IndexOf(sTitle);
    with TUnitBarSeries(SeriesListB.Objects[iIndex]) do
    begin
      FirstDraw := true;
      MultiBar := mbSelfStack;
      CustomBarWidth := 80;
      ParentChart := self.Owner.Chart;
      ShowInLegend := true;   //self.Owner.EnableLinerLegend;
      Name := GetValidName(sTitle);  // removes spaces

      ColorSource := 'Foreground';
      YValues.ValueSource := self.Owner.IndependentField;  // Depth increments
      XValues.ValueSource := sDepField;   // an attempt to place the bar chart in a defined position        
      DataSource := self.Owner.IntervalQuery; 
      HorizAxis := aBottomAxis;
      VertAxis := aLeftAxis;

      sxField := sDepField;
      syField := Self.Owner.IndependentField;
      XUnitType := self.Owner.UnitSystem.GetFieldType(sxfield);  // for unit changing
      YUnitType := self.Owner.UnitSystem.GetFieldType(syfield);  // for unit changing
  end; 

procedure TUnitBarSeries.DrawBar(BarIndex, StartPos, EndPos: Integer);
begin
  // go to dataset record for this index
  TkbmMemTable(self.DataSource).RecNo := BarIndex + 1;
  Brush.Style := TBrushStyle(TkbmMemTable(self.DataSource).FieldByName('Pattern').asInteger);  // hard-coded pattern field name
  Brush.Color := TColor(TkbmMemTable(self.DataSource).FieldByName('Background').asInteger);
  ShowInLegend := True;
  inherited DrawBar(BarIndex,StartPos,EndPos);
end;


Re: Stacked Bar Chart

Posted: Thu Feb 20, 2014 9:21 am
by narcis
Hi Errol,
Errol wrote:I am unable to draw a legend apart from one showing the Name of the TUnitBarSeries and a random colour. (see attachment).
I'm not sure about how you'd like the legend to be. According to your previous post:
Errol wrote: 2. Legend. Rocktypes are repeated but I want only one instance of each rocktype in the legend (and preferably in alphabetical order). Is there any easy way to do this (remember I am sending a BarSeries to the chart, not drawing the chart record by record.
So I assume you'd like to have all values in the series being represented in the legend. You can do that using default legend style:

Code: Select all

  Chart1.Legend.LegendStyle:=lsAuto;
Or force that setting it like this:

Code: Select all

  Chart1.Legend.LegendStyle:=lsValues;
If that's not what you are looking for, please provide more information with a simple code example we can run here to reproduce the problem.

Thanks in advance.

Re: Stacked Bar Chart

Posted: Thu Feb 20, 2014 11:30 pm
by 16566546
Hi Narcis

Thanks for your reply and pointing me to your previous post that I had somehow overlooked. However, I have had no success with your suggestions. I have attached a code snippet below - but all this does is draw a legend with a random pattern and the name of the bar series. Clearly I am not pointing the Legend at the correct field in the DataSource but I cannot find out how to do this.

Code: Select all

procedure TQSCollection.InsertGeologicalSeries(aCodeFld,aFld:string);

begin

// code to populate IntervalQuery, a kbmMemTable, from the database table

  self.owner.IntervalQuery.First;

// construct title
  sTitle := self.Owner.UnitSystem.GetPreferredName('Lithology Profile'); 

  SeriesListB.AddObject(sTitle, TUnitBarSeries.Create(Owner));
  iIndex := SeriesListB.IndexOf(sTitle);
  with TUnitBarSeries(SeriesListB.Objects[iIndex]) do
  begin
    MultiBar := mbSelfStack;
    CustomBarWidth := 80;

    self.Owner.Chart.Legend.Visible := True;
    self.Owner.Chart.Legend.LegendStyle := lsAuto;

    Name := GetValidName(sTitle);

    ColorSource := 'Foreground';
    XLabelsSource := 'Rock Type Code';
    YValues.ValueSource := self.Owner.IndependentField;
    XValues.ValueSource := sDepField;
    DataSource := self.Owner.IntervalQuery; // assumes query is active

    YLabelDisplay := ldUnit;
    HorizAxis := aBottomAxis;
    VertAxis := aLeftAxis;
    sxField := sDepField;
    syField := Self.Owner.IndependentField;
    active := true;
  end;
end;

Re: Stacked Bar Chart

Posted: Fri Feb 21, 2014 10:13 am
by narcis
Hi Errol,

What about setting LegendStyle to lsValues? Does it make any difference?

Could you please arrange a simple example project we can run "as-is" to reproduce the problem here? You could use random/manual data simulating your real environment.

Thanks in advance.

Re: Stacked Bar Chart

Posted: Mon Feb 24, 2014 5:54 am
by 16566546
Hi Narcis

Thank you for your suggestion. I set LegendStyles to lsValues and sure enough I obtained a legend (see attachment). However, there are a couple of issues:
1. The legend symbols show only the foreground colour of the corresponding bar, not the whole pattern. Can the symbol be modified to duplicate the bar pattern, foreground and background? I draw the pattern by using ColorSource, Brush.Style and Vrush.Color.
2. The legend text gives both the incremental depth and the Rock Type Code. I see that XLabelsSource controls the text field (in this case Rock Type Code). How do I suppress the incremental depth value?
3. Can I turn individual items of the legend on and off?

Thanks in advance

Errol
Lithology_Chart_Labels003.png
Lithology_Chart_Labels003.png (21.75 KiB) Viewed 19394 times

Re: Stacked Bar Chart

Posted: Mon Feb 24, 2014 12:58 pm
by narcis
Hi Errol,
1. The legend symbols show only the foreground colour of the corresponding bar, not the whole pattern. Can the symbol be modified to duplicate the bar pattern, foreground and background? I draw the pattern by using ColorSource, Brush.Style and Vrush.Color.
In that case I recommend you to use the legend Picture property as explained here. Notice this is included with the version we published earlier today. This might not be suitable for different symbol pictures in a single series, in which case you could do as in the All Features\Welcome!\Miscellaneous\Legend\Symbol OnDraw example in the new features demo, available at TeeChart's program group.
2. The legend text gives both the incremental depth and the Rock Type Code. I see that XLabelsSource controls the text field (in this case Rock Type Code). How do I suppress the incremental depth value?
You can either set the LegendStyle property or use the OnGetLegendText event to parse and remove it or Chart1.Legend.Items list as in the All Features\Welcome!\Miscellaneous\Legend\Items property.
3. Can I turn individual items of the legend on and off?
This can only be done with legend checkboxes or using the ShowInLegend property with multiple series.

Re: Stacked Bar Chart

Posted: Tue Feb 25, 2014 4:02 am
by 16566546
Hi Narcis

Thanks for your reply. However, I am stuck on one thing - you refer to "All Features\Welcome!\Miscellaneous\Legend\... in the new features demo, available at TeeChart's program group". However, I have no idea of how to find this new features demo. Is it on your website or is it part of my TeeChart installation? I have installed the binary version and see a file called Tee9New.exe but this doesn't run (an entry point cannot be found in Tee911.bpl). Please advise.

Many thanks

Errol

Re: Stacked Bar Chart

Posted: Tue Feb 25, 2014 8:09 am
by narcis
Hi Errol,

Yes, that's Tee9New.exe. Given the error message you mentioned, you should open the demo project and compile it at your end.

Re: Stacked Bar Chart

Posted: Tue Feb 25, 2014 9:46 pm
by 16566546
Hi Narcis

Thanks for your suggestions regarding the Steema demo project. I opened C:\Program Files (x86)\Steema Software\TeeChart 2013 for Delphi 2007\Examples\Features\Tee9New.dpr. This failed to compile with the following error:
[DCC Error] Tee9new.dpr(639): F2063 Could not compile used unit 'Tools_Clustering.pas'

I then downloaded and installed TeeChart2012_Examples.zip from the Steema website. TeeChart2010_Examples\Tee9new.exe runs without problems. The file date is 29/01/2013 so I presume it is up-to-date even though it is located in TeeChart2010_Examples folder.

Regards

Errol

Re: Stacked Bar Chart

Posted: Tue Feb 25, 2014 10:07 pm
by 16566546
I have a query about patterns used to fill bar charts. At present I use the standard Windows patterns (bsSolid, bdDiagonal, etc). These have the advantage of displaying with a constant pattern size (no stretching or compressing to fit the bar rectangle) and auto-clipping at the bar boundaries. I understand that any bitmap can be used as a pattern. Are these bitmaps displayed at a constant pattern size (using some auto-repeat to fill large bars) or are they stretched to fit? Also is there a library of well-behaved patterns available (for instance thick diagonal, brick, etc) so I do not have to create these.

Thanks in advance

Errol

Re: Stacked Bar Chart

Posted: Wed Feb 26, 2014 12:36 pm
by yeray
Hi Errol
Errol wrote:Thanks for your suggestions regarding the Steema demo project. I opened C:\Program Files (x86)\Steema Software\TeeChart 2013 for Delphi 2007\Examples\Features\Tee9New.dpr. This failed to compile with the following error:
[DCC Error] Tee9new.dpr(639): F2063 Could not compile used unit 'Tools_Clustering.pas'

I then downloaded and installed TeeChart2012_Examples.zip from the Steema website. TeeChart2010_Examples\Tee9new.exe runs without problems. The file date is 29/01/2013 so I presume it is up-to-date even though it is located in TeeChart2010_Examples folder.
We'll try to update the precompiled examples as soon as possible. In the meanwhile note you can also find an up to date version of the versions in the v2014.10 installers recently published.

Re: Stacked Bar Chart

Posted: Wed Feb 26, 2014 3:37 pm
by yeray
Hi Errol,
Yeray wrote: We'll try to update the precompiled examples as soon as possible. In the meanwhile note you can also find an up to date version of the versions in the v2014.10 installers recently published.
Just done!
http://www.steema.com/download/vcl

Re: Stacked Bar Chart

Posted: Wed Feb 26, 2014 3:59 pm
by yeray
Hi again Errol,
Errol wrote:I have a query about patterns used to fill bar charts. At present I use the standard Windows patterns (bsSolid, bdDiagonal, etc). These have the advantage of displaying with a constant pattern size (no stretching or compressing to fit the bar rectangle) and auto-clipping at the bar boundaries. I understand that any bitmap can be used as a pattern. Are these bitmaps displayed at a constant pattern size (using some auto-repeat to fill large bars) or are they stretched to fit? Also is there a library of well-behaved patterns available (for instance thick diagonal, brick, etc) so I do not have to create these.
You can set any image you like as a brush:

Code: Select all

Series1.Brush.Image.LoadFromFile('E:\tmp\flower.jpg');
The same can be done through the editor at the Series/Pattern/Custom tab