XAxis entry count is greater than it should be in iOS Charts 3.0.1 in Swift 3 - swift

I have two BarChartDataSets. One of them is always size 3 and the other is either 2 or 3. I tested out the code in version 3.0.0 and everything was working fine. When 3.0.1 came out, it broke my chart. I have the correct number of bars always, but I have six labels instead of 5 when the second dataset is only size 2. It has nothing to do with the stringForValue Delegate function. I set the X values using int's that are associated linearly with the Bar I want represented at that index, so each bar is equally spaced when working properly, but none of them are equally spaced when I have 6 labels and 5 bars.
The one on the left shows the issue and the one on the right shows what it looks like when my BarChartDataSet is size 3. It is duplicating whatever the last value on the chart is and adding it as a 6th label on the left. In 3.0.0 the one on the left would have only had 5 labels.
I dug into their code and where they create the labels in XAxisRendererHorizontalBarChart.swift right before they call drawLabel() I callprint("xAxis entries: \(xAxis.entries.count)")which prints xAxis entries: 6to the console even though right before I call let chartData = BarChartData(dataSets: [chartDataSet1, chartDataSet2])I callprint("dataEntries1 count: \(dataEntries1.count),
dataEntries2 count: (dataEntries2.count)")which prints dataEntries1 count: 3, dataEntries2 count: 2

First, xAxis.entries and dataSet.entries are totally different.
xAxis.entries are the values that being displayed on the axis as labels, while dataSet.entries is the value displayed for the data, e.g. the dot value in line chart, or the bar value for bar chart.
for x axis, it calculate the label count by your data entries min/max value. In Chart 3.0, x axis behaves like y axis, so it calculates x axis entries like y axis, please take a look at computeAxisValues() for details.
So xAxis.entries and dataSet.entries don't have to be equal size.
If you want to set the x axis label count same as your bars count, you can call: setLabelCount(5(6), true):
open func setLabelCount(_ count: Int, force: Bool)
{
self.labelCount = count
forceLabelsEnabled = force
}
Note, don't call the labelCount setter as it's different:
/// the number of label entries the axis should have
/// max = 25,
/// min = 2,
/// default = 6,
/// be aware that this number is not fixed and can only be approximated
open var labelCount: Int
{
get
{
return _labelCount
}
set
{
_labelCount = newValue
if _labelCount > 25
{
_labelCount = 25
}
if _labelCount < 2
{
_labelCount = 2
}
forceLabelsEnabled = false
}
}

Related

how to make horizontal padding in iOS danielgindi charts

I'm using the ios-charts library and I would like to add some horizontal padding to my line charts so that the line does not start immediately at the border of the graph.
This is my current chart:
but I would like the blue line to have some padding as shown below. The rest should remain as it is. The reference gray lines should still take the entire width as they currently do.
I found it. This "padding" is actually ruled by the chart.xAxis.axisMinimum and chart.xAxis.axisMaximum. Those values are automatically set to the data min x and max x.
So if I want a left padding I just have to set a chart.xAxis.axisMinimum
In my case, I want around 10% of the x values to be padded, so I calculate it as
// dates is an array of Date representing my x values
if let maxX = dates
.map(\.timeIntervalSince1970)
.max(),
let minX = dates
.map(\.timeIntervalSince1970)
.min() {
let spanX = maxX - minX
let padding = spanX * 0.1
let axisMinimum = minX - padding
// set the left padding
chart.xAxis.axisMinimum = axisMinimum
}

How do I add a units label to a ILNumerics Colorbar

I would like to display the units in text for the values displayed on the colorbar. I have a colorbar added to my ILSurface and I'd like to show my units in text on the color bar along with the range.
Edit: I want to display text at the bottom of the color bar below the bottom tick just the one label.
I was able to get this to work this way
new ILColorbar()
{
Children = { new ILLabel("nm") {Position = new Vector3(.2f,.98f,0) } }
}
I have to say the Position coordinates are not very intuitive. I had to basically adjust the numbers by trial and error until it fit. I knew that the values range 0..1 so the X value was 1 at the bottom but I wanted it up from the border. And the Y value would need to be indented in some but I wasn't sure what was a good value but .2 works.
You can access the axis of ILColorbar and configure it in the usual way. Use the LabelTransformFunc on the ticks to set your own label text. You can use the default transform func and add your unit string.
Example:
var cb = scene.First<ILColorbar>();
cb.Axis.Ticks.LabelTransformFunc = (ind, val) =>
{
return ILTickCollection.DefaultLabelTransformFunc(ind, val) + "nm";
};
You can read more about the axis configuration here:
Axis Configuration
LabelTransformFunc in ApiDoc
Edit:
If only one label is needed, then add a new ILLabel object in ILColorbar group as follows:
new ILColorbar() {
new ILLabel("z(nm)") {
Position = new Vector3(0.5,1,0),
Anchor = new PointF(0.5f,0)
}
}
The ILColorbar area have the relative coordinates 0..1 over the width and the height of the color bar. So we set position x in the middle of the ILColorbar, and position y at the bottom.
The Anchor position is used as relative position in relation to the Position point.
ILLabel Documentation

How to setup up iOS charts y-axis with min, max value and a fixed step between the grid lines?

I'm just in the learning phase of using ios-charts. I like to change the x-axis grid to fixed values.
My plotted y-values are just int numbers like 1, 2, 3,..., 10. Nevertheless, the left y-axis shows values like 6.3, 9.1, etc., depending on my zoom level.
The second question is, how to set up the x-axis in order to show the labels 1,5,10,15,....40?
Is there any way to influence the step size like e.g. in Excel?
// zoom y-axis to min/max value
lineChart.leftAxis.customAxisMin = max(0.0, lineChart.data!.yMin - 1.0)
lineChart.leftAxis.customAxisMax = min(10.0, lineChart.data!.yMax + 1.0)
lineChart.leftAxis.startAtZeroEnabled = false
Chart (min = 6.0 and max = 10.0): The grid start at 6.3 instead of 6.0.
Chart (min = 7.0 and max = 10.0): The grid starts as expected with 7.0.
What's going wrong here?
I solved the issue just by setting the correct labelCount.
// zoom y-axis to min/max value
lineChart.leftAxis.customAxisMin = max(0.0, lineChart.data!.yMin - 1.0)
lineChart.leftAxis.customAxisMax = min(10.0, lineChart.data!.yMax + 1.0)
lineChart.leftAxis.labelCount = Int(lineChart.leftAxis.customAxisMax lineChart.leftAxis.customAxisMin)
lineChart.leftAxis.startAtZeroEnabled = false
Swift 4.2 and above:
startAtZeroEnabled - This property is deprecated - Use axisMinimum instead.
open var axisMinValue: Double
{
get { return axisMinimum }
set { axisMinimum = newValue }
}
lineChartView.leftAxis.axisMinimum = 0
lineChartView.leftAxis.axisMaximum = 10.0

Changing the axis range dynamically doesnt refresh the lineplot but only the axis labels

I am trying to change the axes Min and Max properties to show only the plot points that lie in a particular range.
say If I have lineplot whose X values are ranging from 0 to 100, I want to display only the values that are greater than 50.However I noticed that the lineplot is drawn using all the position points.Only the x axis ticks got renamed such that they start from 50 and end at 100.
The following is the code I am using
var axes = m_plotCube.First<ILAxisCollection>();
if (axes != null)
{
ILAxis xAxis = axes.Where<ILAxis>(item => item.Label.Text == "X Axis").First();
xAxis.Min = 50;
xAxis.Max = 100;
xAxis.Configure();
}
Am I missing something ?
Use ILPlotCube.Limits instead:
var pc = ilPanel1.Scene.First<ILPlotCube>();
pc.Limits.Set(
new Vector3(50, pc.Limits.YMin, pc.Limits.ZMin),
new Vector3(100, pc.Limits.YMax, pc.Limits.ZMax));
BTW: the axes are accessed much easier: plotcube.Axes.XAxis ...

JfreeChart: Stacked Bar Chart and CategoryAxis showing dates

I have created a stacked bar chart in which I show a count on the y axis and dates on the x axis. The problem is that when I have many dates on the x axis it gets very cluttered and impossible to read. I would like to show only some of the dates, e.g one date per week. Is that possible? I am using ChartFactory.createStackedBarChart() to create the chart, and I have the data in a DefaultCategoryDataSet.
Any input is appreciated!
For a CategoryAxis, which is used the for the domain axis in a StackedBarChart, you have considerable flexility with the method setCategoryLabelPositions(). Typical usage is illustrated in the BarChartDemo1 source, shown here.
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setCategoryLabelPositions(
CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 6.0));
Have you tried overriding the generateLabel methods in the label generator? Something like:
chart.getCategoryPlot().getRenderer().setBaseItemLabelGenerator(
new CategoryItemLabelGenerator() {
public String generateColumnLabel(CategoryDataset dataset, Integer column) {
if(column % 7 == 0)
super.generateColumnLabel(dataset, column)
else
""
}
}
);
I haven't tested the code, but it should only output a label every 7 columns. More info on the label generator is here: http://www.jfree.org/jfreechart/api/javadoc/org/jfree/chart/labels/CategoryItemLabelGenerator.html