Electrocardiogram plot

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
Yazou
Newbie
Newbie
Posts: 9
Joined: Fri Jan 30, 2009 12:00 am

Electrocardiogram plot

Post by Yazou » Fri Jan 22, 2010 11:55 am

Hi All,
I'm trying to use a chart to plot ECG (cardiac) signals.
The signals are recorded during 24 hours with a sampling frequency of 1 kHz.
I have 12 lineseries. each series has its own YAxis. but they share the same XAxis.
At first I tried loading all the data into the chart and using chart pages to display only a part of the signal but it was too slow.
Then I switched to putting a Tscrollbar (TchartScrollbar is not usefull in my case because it scrolls an already filled chart).
At change of the scrollbar.position I clear the old series and i create new 12 lineseries and I fill them with segment of 10 seconds data:
Here is my code :

Code: Select all

		Screen->Cursor = crHourGlass;
	  int num_leads = ECG->getNumLeads() ;
	  int freq= ECG->getFreq();
	  long M= ECG->getNumSamp();
	  long K = M/num_leads;
	  ScrollBar2->Min = 0;
	  ScrollBar2->Max = floor(1.0*K/(UpDown1->Position*freq));
	  size_t num = freq * UpDown1->Position; // windows size
	  size_t start = ScrollBar2->Position*num; // Page number
	  double Dt = 1.0/freq;
	  double t =0.0;
	  char ld_name[64];
	  for (int j  = 0; j < num_leads; j++) { // plot lead by lead
			ECGPlot[j] = new TFastLineSeries(Chart1);
			ECGPlot[j]->ParentChart = Chart1;
			t=start*Dt;
			double *data = new double[num];
			int read =ECG->getData(j,start,num,data);
			// data table for lead j
			for (int i = 0; i < read ; i++)
			{
				t+=Dt;
				ECGPlot[j]->AddXY(t,data[i]);
			}
			delete [] data;
			sprintf(ld_name, "Lead-%s", ECG->LeadText(j));
			ECGPlot[j]->Title=ld_name;
		}
		Chart1->BottomAxis->SetMinMax(start*Dt, start*Dt+num*Dt);
		Chart1->BottomAxis->Increment=1.0;
		Chart1->CustomAxes->Clear();
	   int n = Chart1->SeriesCount();
	   int D = 100/n;
	   for (int i = 0; i < n; i++) {
		   TChartAxis *Ax = new TChartAxis(Chart1->CustomAxes);
		   Ax->Axis->Color = Chart1->Series[i]->Color;
		   Ax->StartPosition = i*D;
		   Ax->EndPosition = Min(i*D +D-2,100);
		   Ax->PositionPercent = 0;
		   Ax->LabelStyle =talNone;
		   Chart1->Series[i]->CustomVertAxis = Ax;
		   Chart1->Series[i]->Color= clNavy;
	   }
I have some questions about enhancing this code :
1- Can I make the 12 lineseries sharing the same XAxis data with repeating filling and allocating the Xvalues to the 12 series ?
2- I want to control the XAxis scale on the screen and on the printer. Doctors are used to display ECG data with a 25 mm/s.
How can I control the Xasis length to make it equal to 25*10 = 250 mm =25 cm on the screen and on the printer?

Regards

Yeray
Site Admin
Site Admin
Posts: 9601
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Electrocardiogram plot

Post by Yeray » Mon Jan 25, 2010 12:38 pm

Hi Yazou,
Yazou wrote:1- Can I make the 12 lineseries sharing the same XAxis data with repeating filling and allocating the Xvalues to the 12 series ?
I'm not sure to understand what are you exactly trying to do here. Could you please send us a picture showing what you would like to achieve or a simple example project we can run as-is to reproduce the issue here?
Yazou wrote:2- I want to control the XAxis scale on the screen and on the printer. Doctors are used to display ECG data with a 25 mm/s.
How can I control the Xasis length to make it equal to 25*10 = 250 mm =25 cm on the screen and on the printer?
I think you should be able to convert mm to pixels doing something similar to this (and maybe Printer.Handle [uses printers]).
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Yazou
Newbie
Newbie
Posts: 9
Joined: Fri Jan 30, 2009 12:00 am

Re: Electrocardiogram plot

Post by Yazou » Mon Jan 25, 2010 3:36 pm

Hello,
1-As you can see in the attached image I have 8 lineseries sharing the same X axis data.
My data is saved internally as integer (16 bits) without the x axis values. I need to know only the sampling frequency of the data. If I have 24 hours ECG recording with 1000 values/s. This gives 1000*3600*24*(2 bytes) = 172.8 MB for one ECG channel and about 1.4 GB for 8 channel.
If i want to add theses data to a chart then for each value we have (X,Y) on 2 doubles (2x8 bytes = 16 Bytes). This gives 1.38 GB by channel and about 11 GB for 8 channels.
My idea is to to make the 8 lineseries sharing the same Xvalues in order to reduce the memory usage of the chart. Is this possible ?

2- regarding printing with a user defined scale. Is there any example in the demo showing this possibility? I know how to compute the printer pixelperinches informations. But how can I pass these informatiion to the chart ?

best regards,
Yazou
Attachments
sc2.jpg
sc2.jpg (329.26 KiB) Viewed 6202 times

Yeray
Site Admin
Site Admin
Posts: 9601
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Electrocardiogram plot

Post by Yeray » Thu Jan 28, 2010 10:08 am

Hi Yazou,

Excuse us for the delayed reply.
Yazou wrote:1-As you can see in the attached image I have 8 lineseries sharing the same X axis data.
My data is saved internally as integer (16 bits) without the x axis values. I need to know only the sampling frequency of the data. If I have 24 hours ECG recording with 1000 values/s. This gives 1000*3600*24*(2 bytes) = 172.8 MB for one ECG channel and about 1.4 GB for 8 channel.
If i want to add theses data to a chart then for each value we have (X,Y) on 2 doubles (2x8 bytes = 16 Bytes). This gives 1.38 GB by channel and about 11 GB for 8 channels.
My idea is to to make the 8 lineseries sharing the same Xvalues in order to reduce the memory usage of the chart. Is this possible ?
First of all, I recommend you to try to implement as tips as possible from the ones explained in the Real-time Charting article here. In particular you may be interested in the arrays assignment to series' valuelists.

Another suggestion could be using singles instead of doubles as is explained here.

Here is a test I've made that could help you:

Code: Select all

uses series;

procedure TForm1.FormCreate(Sender: TObject);
var i, j, nSeries, nPoints: Integer;
    XValues: array of Single;
    YValues: array of array of Single;
begin
  Chart1.View3D:=false;

  nSeries:=20;
  nPoints:=100000;

  SetLength(XValues,nPoints);
  SetLength(YValues,nSeries);
  for i:=0 to nSeries-1 do
  begin
    SetLength(YValues[i],nPoints);
    YValues[i][0]:=random*100+1000;
  end;
  XValues[0]:=0;
  for j:=Low(XValues)+1 to High(XValues) do
  begin
    XValues[j]:=j*5;
    for i:=Low(YValues) to High(YValues) do
      YValues[i][j]:=YValues[i][j-1] + random*10-5;
  end;


  //option 1: AddXY
  //35 Mb with 20 series and 100.000 pts per series
  //19 Mb with the same data and TEEVALUESINGLE and arrays of singles instead of arrays of doubles
{  for i:=0 to nSeries-1 do
  begin
    Chart1.AddSeries(TLineSeries.Create(self));
    Chart1[i].BeginUpdate;
    for j:=0 to nPoints-1 do
      Chart1[i].AddXY(XValues[j],YValues[i][j]);
    Chart1[i].EndUpdate;
  end;}


  //option 2: Assign Arrays
  //19 Mb with 20 series and 100.000 pts per series
  //11 Mb with the same data and TEEVALUESINGLE and arrays of singles instead of arrays of doubles
  for i:=0 to nSeries-1 do
  begin
    Chart1.AddSeries(TLineSeries.Create(self));
    With Chart1[i].XValues do
    begin
      Value:=TChartValues(XValues);
      Count:=Length(XValues);
      Modified:=True;
    end;
    With Chart1[i].YValues do
    begin
      Value:=TChartValues(YValues[i]);
      Count:=Length(YValues[i]);
      Modified:=True;
    end;
  end;

  Chart1.Axes.Left.Automatic:=true;
end;
Another option could be creating a custom series class that could have a valuelist for each channel and only one more for the X values.
Yazou wrote:2- regarding printing with a user defined scale. Is there any example in the demo showing this possibility? I know how to compute the printer pixelperinches informations. But how can I pass these informatiion to the chart ?
I'd recommend you to take a look at the printing better article here
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Post Reply