GetAxisLabel always passes -1 for ValueIndex - teechart

I need to be able to format the X Axis labels on a TeeChart Standard 2012 chart. I’m handling the GetAxisLabel event, but the ValueIndex is always -1.
I found this bit of documentation:
Axis Labels are Values.
In this case, the Series parameter will be nil, and the ValueIndex will be -1.
Axis Labels are Series points.
The Series parameter will be a valid TChartSeries, and the ValueIndex will be the current Series point position.
The problem is that I can find no way to set the Axis Labels to series points.
Can someone help me out?

You need to set LabelStyle to be:
Chart1.Axes.Bottom.LabelStyle:=talPointValue;
or
Chart1.Axes.Bottom.LabelStyle:=talText;
in your chart. Then you'll be able to do something like this:
procedure TForm2.Chart1GetAxisLabel(Sender: TChartAxis; Series: TChartSeries;
ValueIndex: Integer; var LabelText: string);
begin
if ((Series <> nil) and (ValueIndex <> -1)) then
begin
LabelText:=FormatFloat('#.00', Series.XValue[ValueIndex]);
end;
end;
However, it's much easier to achieve what the method above does using AxisValuesFormat property:
Chart1.Axes.Bottom.AxisValuesFormat:='#.00';

Related

TeeChart Firemonkey LineSeries NULL Points

I am creating a Firemonkey (FMX) application. I use TChart with a Line Series (TLineSeries). I need to draw a chart line that is not continuous. The x-axis is date time and I want the line to be drawn say between 10 and 11AM and then again between 3PM and 4PM. I tried the following but it always draws a continuous line from the first point (X1) to the last point (X4):
Series.TreatNulls:=TTreatNullsStyle.tnDontPaint;
Series.AddXY(X1,1);
Series.AddXY(X2,1);
Series.AddNullXY(X2,1);
Series.AddNullXY(X3,1);
Series.AddXY(X3,1);
Series.AddXY(X4,1);
Where
X1=date value at 10AM
X2=date value at 11AM
X3=date value at 3PM
X4=date value at 4PM
I tried various combinations of TreatNulls but still no success. I am using TeeChart Version 2021.32
Any suggestions would be appreciated.
I've given it a try and it seems to work fine for me here with the code below.
Note a single null point is enough to avoid drawing two sectors (A-null-B)
uses Series, Constants;
procedure TForm1.FormCreate(Sender: TObject);
var X1, X2, X3, X4: TDateTime;
begin
Caption:=TeeMsg_Version;
X1:=Date+DateTimeStep[dtOneHour]*10;
X2:=Date+DateTimeStep[dtOneHour]*11;
X3:=Date+DateTimeStep[dtOneHour]*15;
X4:=Date+DateTimeStep[dtOneHour]*16;
with Chart1.AddSeries(TLineSeries) do
begin
XValues.DateTime:=True;
AddXY(X1,1);
AddXY(X2,1);
//AddNullXY(X2,1);
AddNullXY(X3,1);
AddXY(X3,1);
AddXY(X4,1);
end;
Chart1.Legend.Hide;
//Chart1.View3D:=False;
Chart1.Axes.Left.SetMinMax(0,2);
Chart1.Axes.Left.Increment:=0.5;
Chart1.Axes.Bottom.Increment:=DateTimeStep[dtOneHour];
end;

Usage of pascal variant record

I need help from those who know the pascal very well.
I need (teachers requirement) to use a variant record. Those variant record are defined like this:
Temperature = record
case scale : TemperatureScale of
celsius : (celsius_value : ScaleCelsius);
kelvin : (kelvin_value : ScaleKelvin);
end;
According to primary sources I found during my research about this topic, I could not find how to use variant record, only how to declare it.
My primary sources: google search(found nothing), Case-Freepascal and Record-Freepascal
Edit for those who wonder what i must use in implementation it is exacly this:
type
UkPolozka = ^Polozka;
UkHodnota = ^Hodnota;
TypUdaj=(typretez, typcele, typrealne, typlogik, typpole, typobjekt);
VarZaznam = record
case Udaj: TypUdaj of
typretez: (retez: string);
typcele: (cele: word);
typrealne: (realne: single);
typlogik: (logik: boolean);
typpole: (pole: UkHodnota);
typobjekt: (objekt: UkPolozka);
end;
Polozka = record
Nazev: string;
Hodn: VarZaznam;
Dalsi: UkPolozka
end;
Hodnota = record
Hodn: VarZaznam;
Dalsi: UkHodnota
end;
Consider example record from Delphi Help. I modified it with tag.
Tag usage is optional and usually is not used and doesn't provide useful information.
Note that the first line outputs radius with the same value as height - they share the same memory.
Then I explicitly set tag (but fields stay the same)
Also note size difference for no-tag record and tagged one.
Note again - in most cases programmers don't define or use tag value. It might be unsafe to rely on tag (until you follow strict rules in assigning tags). I did not set rectangle tag, but program consider zero tag as the first variant.
Just assign needed field by name. Just read needed field by name. For your example varVarZaznam.retez:= 'test';
type
TShapeList = (Rectangle, Triangle, Circle, Ellipse, Other);
TFigure = record
case shape: TShapeList of
Rectangle: (Height, Width: Real);
Triangle: (Side1, Side2, Angle: Real);
Circle: (Radius: Real);
Ellipse, Other: ();
end;
TFigureNoTag = record
case TShapeList of
Rectangle: (Height, Width: Real);
Triangle: (Side1, Side2, Angle: Real);
Circle: (Radius: Real);
Ellipse, Other: ();
end;
var
Fig: TFigure;
begin
Fig.Height := 5;
Fig.Width := 3;
//default tag is zero = Rectangle
if Fig.shape = Rectangle then
Writeln('Rect ', Fig.Height:3:0, Fig.Width:3:0, Fig.Radius:3:0)
else
Writeln('not Rect');
Fig.shape := Circle;
if Fig.shape <> Rectangle then
Writeln('not Rect');
Writeln('Fig size ', SizeOf(TFigure), ' noTag size ', SizeOf(TFigureNoTag));
Readln;
output in Delphi:
Rect 5 3 5
not Rect
Fig size 32 noTag size 24

How to generate line chart with discrete value, not time serial, as x-axis

Sorry for this silly question, but I am lost and hope any other expert can help me.
I need to draw a bar chart, but the x axis is NOT time series, it is discrete values.
var ndx = crossfilter( self.getStatus( contracts ));
var skuDim = ndx.dimension( function(d){
return d.sku;
});
var skuDimCount = skuDim.group().reduceCount();
var chartLineContractSku= dc.barChart("#chart-line-contract-sku");
chartLineContractSku
.width(500)
.height(200)
.dimension(skuDim)
.group(skuDimCount)
.x(d3.scale.linear().domain(skus))
.legend(dc.legend());
the skus is:
array of sku:
["PAR-ND-SRX1-SPCNPC", "SVC-ND-M10i", "SVC-CP-SRX3400", "SVC-ND-SRX3400", "SVC-ND-SRX3-IOC", "SVC-CP-SRX3-IOC", "SVC-CP-SRX3-NPC", "SVC-3-ND-SRX3-IOC", "SVC-CP-SRX3-SPC", "SVC-ND-SRX3-SPC"]
which is used to group dimension the input data.
But the output graph is always empty.
Can anyone tell me how to fix this? And how to generate the barChart with discrete value? Also, another question is how to make the label vertical? as we have quite a lot skus.
Thanks
Gordon is correct in saying that you should use ordinal scale to get your desired result. Replace your d3.scale.linear code with
x(d3.scale.ordinal().domain(skus))
Look at this as an example
http://bost.ocks.org/mike/bar/3/

Independent Component Analysis as Images

I have applied Independent Component Analysis on set of face images using FastICA. I have successfully retrieved independent components and mixing matrix. The values of independent components are in double and I want to display these components as images like available on web, e.g., http://research.ics.aalto.fi/ica/imageica/. I don't know how to show this.
One way you might do this more automatically is with the montage function. Or you can look at subimage. See also this StackOverflow question and answer.
Try the follwing function
function [XX,fh]=dispImgs(X,cols,gap,ihw,fh)
% Courtesy A. Leonardis, D. Skocaj
% see http://vicos.fri.uni-lj.si/danijels/downloads
[M,N]=size(X);
if nargin<2 cols=floor(sqrt(N)); end;
if nargin<3 gap=0; end;
if nargin<4 ihw=[sqrt(M),sqrt(M)]; end;
if nargin<5 fh = figure; end; % new figure
ih=ihw(1);iw=ihw(2);
maxv=max(X(:));
rows=floor(N/cols);
XX=zeros((rows*ih)+(rows-1)*gap,(cols*iw)+(cols-1)*gap)+maxv;
for i=1:N
a=(iw+gap)*mod(i-1,cols)+1;
b=(iw+gap)*mod(i-1,cols)+iw;
c=(ih+gap)*(floor((i-1)/cols))+1;
d=(ih+gap)*(floor((i-1)/cols))+ih;
XX(c:d,a:b)=reshape(X(:,i)',ih,iw);
end;
xxmax=max(XX(:));
xxmin=min(XX(:));
fh = figure(fh);
imshow((XX-xxmin)/(xxmax-xxmin));
axis off;
Example:
X: imsize by N
dispImgs( X, 8, 4, imsize );%show all N images in 8 columns with Gap=4

Get X and Y values under mouse pointer

I have a simple chart using only TLineSeries with a single Y axis. As the mouse pointer moves over the chart, I’d like to get the X and Y values associated with the pointer’s position independent of any series.
I can handle the MouseMove event and get the screen X and Y coordinates, but the only way I’ve found to convert them is via the Series->XValues->Locate and Series->YValue->Locate methods.
There are two problems with this:
1 - The value returned from Series->YValue->Locate is always -1 regardless of whether the pointer is over a series line or not.
2 – The value returned from Series->XValue->Locate is -1 unless the pointer is over a part of the chart containing a series line.
Why does Series->YValue->Locate always return -1?
More importantly, how can I get the values regardless of whether the pointer is over a part of the chart with series lines or not?
I’m using the version of TeeChart that ships with Rad Studio XE3.
Why does Series->YValue->Locate always return -1?
That's because Locate uses a series value and returns its point index in the series. OnMouseMove provides screen pixel coordinates, not series values.
More importantly, how can I get the values regardless of whether the
pointer is over a part of the chart with series lines or not?
You can use axes as a reference instead of series, for example:
procedure TForm2.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
XVal: double;
YVal: double;
begin
XVal:=Chart1.Axes.Bottom.CalcPosPoint(X);
YVal:=Chart1.Axes.Left.CalcPosPoint(Y);
Chart1.Title.Text[0]:=FormatFloat('#.##', XVal) + ' - ' + FormatFloat('#.##', YVal);
end;

Resources