displaying individual failure marks

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
myghetto
Newbie
Newbie
Posts: 27
Joined: Thu Oct 05, 2006 12:00 am

displaying individual failure marks

Post by myghetto » Wed Dec 13, 2006 1:05 am

Hi,
I am using Borland Delphi 2005 and am currently comparing two series where one will be the default and the other is tested for failures. I would like individual marks to appear at the point of failure and display 'Failed' when it fails compared to the default series. Is this possible? Thank you.
David

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Wed Dec 13, 2006 7:59 am

Hi, David.

Yes, several ways to do it. I'd use TChartSeries OnGetMarkText event to show/hide individual mark text. Something like this:

Code: Select all

procedure TForm1.Series2GetMarkText(Sender: TChartSeries; ValueIndex: Integer;
  var MarkText: string);
begin
  if Sender.MandatoryValueList[ValueIndex] >0 then MarkText := ''
  else MarkText := 'Failure';
end;
In the example above series YValues[ValueIndex] is compared with zero. If false, then a "Failure" mark text is shown, otherwise no mark text is shown. The same approach can be used to check failure/success for individual series points.
Marjan Slatinek,
http://www.steema.com

myghetto
Newbie
Newbie
Posts: 27
Joined: Thu Oct 05, 2006 12:00 am

Post by myghetto » Fri Dec 15, 2006 12:50 am

Hi
Thanks for the reply. How do you do it if you want to activate the failure detection when the checkbox is clicked? I cant seem to get your code working. How does it actually activate?

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Fri Dec 15, 2006 7:33 am

Hi.

How does it work? Well, you're using the TChartSeries OnGetMarkText event, together with failure series values, to "filter" which point marks you want to mark as "failed". Something like this:

Code: Select all

// Enable, disable failure filter
procedure TForm1.CheckBox1Clicked(Sender: TObject);
begin
  if (CheckBox1.Checked) then Series2.OnGetMarkText := Series2GetMarkText;
  else Series2.OnGetMarkText := nil;
end;

// Series "Failure filter" event
procedure TForm1.Series2GetMarkText(Sender: TChartSeries; ValueIndex: Integer; var MarkText: string); 
begin 
  if Not(PointFailed(Series.MandatoryValueList[ValueIndex])) then MarkText := '' 
  else MarkText := 'Failure'; 
end;
where PointFailed is your failure/success boolean function (I don't know your failure criteria so you'll have to code it yourself).
Marjan Slatinek,
http://www.steema.com

myghetto
Newbie
Newbie
Posts: 27
Joined: Thu Oct 05, 2006 12:00 am

Post by myghetto » Tue Dec 19, 2006 4:42 am

Hi,

I have tried out your code. Can't seem to get it working. Below is mine:

Code: Select all

procedure TForm1.openpassfailClick(Sender: TObject);
begin
  if openpassfail.Checked = False then
    begin
      for I:= 16 to 18 do
        Chart3.Series[I].Clear;
        Series1.Clear;
        Series2.OnGetMarkText:= nil;
    end
  else
    begin
      for I:= 16 to 18 do
        Chart3.Series[I].Clear;
      OpenShift:= FloatSpinEdit1.Value;
      Series2.OnGetMarkText:= Series2GetMarkText;
      A:= plotshiftx.Value;
      B:= plotshifty.Value;
      x_axis_multi(x);
      AssignFile(YFile, CDMulti2.Text); //assign filehandle NFile to Edit6.Text
      G:= autofreqmulti(G);
      xfreqmulti:= (0.818/(G*0.4));
      Reset(XFile); //open XFile for read access
        while not Eof(XFile) do //keep looping until the end of XFile
          begin
            Readln(XFile, x); //read line from file to x
            Chart3.Series[16].AddXY((x*xfreqmulti), OpenMaxMinMid + OpenShift, '', clTeeColor); //plot graph
            Chart3.Series[17].AddXY((x*xfreqmulti), OpenMaxMinMid + OpenShift + 0.3, '', clTeeColor); //plot graph
            Chart3.Series[18].AddXY((x*xfreqmulti), OpenMaxMinMid + OpenShift - 0.4, '', clTeeColor); //plot graph
          end;
      for J:= 0 to 400 do
        if (OpenMaxMinMid + OpenShift + 0.3) < (QuickLoadBuffY[J] + B) then
          begin
            Series1.AddXY(QuickLoadBuffX[J] + A, QuickLoadBuffY[J] + B, '', clTeeColor);
          end;
      for J:= OMax to 400 do
        if (OpenMaxMinMid + OpenShift - 0.4) > (QuickLoadBuffY[J] + B) then
          begin
            Series1.AddXY(QuickLoadBuffX[J] + A, QuickLoadBuffY[J] + B, '', clTeeColor);
          end;
      CloseFile(XFile);
    end;
end;

procedure TForm1.Series2GetMarkText(Sender: TChartSeries; ValueIndex: Integer;
  var MarkText: string);
begin
  for ValueIndex:= 0 to 400 do
        if (OpenMaxMinMid + OpenShift + 0.3) < (QuickLoadBuffY[ValueIndex] + B) then
          begin
            MarkText:= 'Failure';
    end;
   for ValueIndex:= OMax to 400 do
        if (OpenMaxMinMid + OpenShift - 0.4) > (QuickLoadBuffY[ValueIndex] + B) then
          begin
            MarkText:= 'Failure';
    end;
end;

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Tue Dec 19, 2006 7:32 am

Hi.

I think the problem is how you use ValueIndex parameter in OnGetMarkText event. In this event ValueIndex is constant parameter and should not be used as variable in for loop.

You should figure out another way to "connect" failure to point ValueIndex (index) parameter. Something like this:

Code: Select all

  if (OpenMaxMinMid + OpenShift + 0.3) < (QuickLoadBuffY[ValueIndex]+ B) or  OpenMaxMinMid + OpenShift - 0.4) > (QuickLoadBuffY[ValueIndex] + B) 
  then MarkText:= 'Failure';
Of course, ValueIndex runs from 0 to number of points in series-1 so perhaps it's a better idea to use Series.YValues[ValueIndex] instead of QuickLoadBuffY[ValueIndex] to check for failure.
Marjan Slatinek,
http://www.steema.com

myghetto
Newbie
Newbie
Posts: 27
Joined: Thu Oct 05, 2006 12:00 am

Post by myghetto » Tue Dec 19, 2006 11:05 pm

Hi,

Thanks for the reply. I was not familiar with the functionality of the ValueIndex and therefore tried to use it as a counter. I initially had

Code: Select all

J:= 0 to 400 
where I had 819 samples. I tried using Series2.YValues instead and nothing shows up. What I am thinking is that the Series2GetmarkText is not being executed. Is

Code: Select all

Series2.OnGetMarkText:= Series2GetMarkText
executing the code? Do you have a simple code or complied file that I can use to test out? If so that would be very helpful. Thank you.

David

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Wed Dec 20, 2006 7:03 am

Hi.

Hmm... Try setting Series2.Marks.Visible property to true:

Code: Select all

Series2.Marks.Visible := True;
Series2.OnGetMarkText := Series2GetMarkText;
If this doesn't work, let me know and I'll prepare a sample test application (D2006) for you.
Marjan Slatinek,
http://www.steema.com

myghetto
Newbie
Newbie
Posts: 27
Joined: Thu Oct 05, 2006 12:00 am

Post by myghetto » Wed Dec 20, 2006 10:51 pm

Hi,

Thanks for that code. It works but it displays 'Failure' at every point, even sections that don't fail. I will continue to try and solve this problem but a sample code would definitely help. Your help is much appreciated. Thank you.

David

myghetto
Newbie
Newbie
Posts: 27
Joined: Thu Oct 05, 2006 12:00 am

Post by myghetto » Tue Jan 09, 2007 12:25 pm

Hi,
Have been trying various different ways but it all end up displayed together. It is operating like the original marks function where it is displayed along the whole line. Maybe you misunderstood. What I am trying to do is actually just display single failure marks where the line has failed, otherwise, other sections of the line will display nothing. I do not want to display failure all over the line whenever there is a failure. Thank you.
David

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Tue Jan 09, 2007 1:03 pm

Hi.
It works but it displays 'Failure' at every point, even sections that don't fail.
This would indicate that the failure check you perfom in series OnGetMarkText always returns true i.e. "Failure" is displayed for every point.
I've prepared a small test application demonstrating how you can test for failure. In the example below Series1 holds default data and Series2 holds actual data which is then compared to default data (Series1.YValues) for failures. In this example a failure occurs only if difference between default and actual value is greater than 2.0.

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Populate series
  // Series1 = default values
  Series1.Add(10);
  Series1.Add(12);
  Series1.Add(3);
  Series1.Add(7);
  Series1.Add(8);
  // Series2 = actual data
  Series2.Add(8);
  Series2.Add(11);
  Series2.Add(7);
  Series2.Add(7);
  Series2.Add(6);
  // Signal failure if difference between
  // default value and actual data is >= 2
  Series2.Marks.Visible := True;

  // The end result
  // Series2 will display three "Failure" marks:
  // fist point (10-8), third point (3-7), fifth point (8-6).
end;

procedure TForm1.Series2GetMarkText(Sender: TChartSeries; ValueIndex: Integer;
  var MarkText: string);
var absdiff: double;
begin
  // Point absolute difference
  // we use this to test for failure
  // NOTE : this will work only if default series and actual series
  // have the same number of points. Otherwise you CAN'T do failure check here.
  absdiff := Abs(Sender.YValues[ValueIndex] - Series1.YValues[ValueIndex]);
  if (absdiff>=2.0) then MarkText := 'Failure' else MarkText := '';
end;
I hope this will clarify what I meant with my original post.
Marjan Slatinek,
http://www.steema.com

myghetto
Newbie
Newbie
Posts: 27
Joined: Thu Oct 05, 2006 12:00 am

Post by myghetto » Tue Jan 09, 2007 11:56 pm

Hi,
From my previous code above

Code: Select all

procedure TForm1.Series2GetMarkText(Sender: TChartSeries; ValueIndex: Integer;
  var MarkText: string);
begin
  for J:= 0 to 400 do
        if (OpenMaxMinMid + OpenShift + 0.3) < (QuickLoadBuffY[J] + B) then
          begin
            MarkText:= 'Failure';
          end
        else
          begin
            MarkText:= '';
          end;
   for J:= OMax to 400 do
        if (OpenMaxMinMid + OpenShift - 0.4) > (QuickLoadBuffY[J] + B) then
          begin
            MarkText:= 'Failure';
     end
        else
          begin
            MarkText:= '';
          end;
end;
 
What I am trying to do is actually check for failures from 0 to 400 and OMax to 400. I am not comparing a series but rather values which are stored in the buffer I called QuickLoadBuffY[J] which is plotted as a series. Basically there are two reference points, one is 0.3 above the mid point and one is o.4 below the mid point. Anything within that reference point will pass, all else will fail within the specified range. I have a total of 818 points and only need to compare up to 400. Is that possible?
David

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Fri Jan 12, 2007 3:15 pm

Hi David,

Could you please send us a simple example project we can run "as-is" to reproduce the problem here? You can post your files at news://www.steema.net/steema.public.attachments newsgroup.

Thanks in advance.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Post Reply