-
-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Logarithmic Axis #109
Comments
Well ios-charts is only about two months old! So I guess there are no new By log scale you mean that you want to have inconsistent x-axis spacing? On Wed, May 27, 2015 at 2:30 PM, zimonjonez notifications@github.com
|
Two months only?! You did a great job! I'll definitely going to spread the word Yes, inconsistent x-axis spacing is what I'm looking for. See images attached. This is what I did earlier using CorePlot. (https://cloud.githubusercontent.com/assets/9811701/7835025/084b718c-04b9-11e5-9ff7-f63e340b69d1.png) |
You can see that it is on the table, it is planned... PhilJay/MPAndroidChart#12 |
From what I'm seeing when reading more on logarithmic axises, it seems like this term refers to an actually logarithmic Y axis - where we would have to logarithmically calculate the value sizes and positions. |
I would love to see logarithmic scaling as well (for both x and y axis). Keep up the good work, this is an awesome project! |
@danielgindi can this be a part of in #194 ? since they are all behaving like y axis |
+1 |
@danielgindi , how to configure Y-axis for using a logarithmic scale? I haven't found any references wither in the github tickets or on the internet (StackOverflow, googling, etc.) As far as I understood your reply earlier in this thread, the library supports log scale for Y axis. Please correct me if I got you wrong. |
@danielgindi , does the library support log scale for Y axis ? |
@xxxrr I suppose current master branch should support both X and Y? |
@liuxuan30 Thanks a lot.. Can you let me know how to configure it ? I am not able to get any references .. |
hmm, I am not familiar with v3 yet.. You can check out v3 ChartsDemo - time line chart. v3 is a big change how x axis values are calculated |
@liuxuan30 Thanks.. But not able to find things related to Logarithmic scale in it..Will look deeper into v3.. Thanks.. |
I mean there is no logarithmic support yet, but seems like v3 can support such type easier than v2. The main difference is for x axis |
Hi, any updates about this ? |
@ThomasGoujon I think this can be solved by Chart 3.0 (except for those axis styles) |
Hi @liuxuan30 @danielgindi, how would I go about plotting Y values logarithmically using Charts 3.0? |
just calculate the x, y and draw it! |
So if I plot a range of x, y values say between 0 and 1000, how to I get the Y axis to draw logarithmically, for example 0, 1, 10, 100, 1000? |
oh I see, you are talking about y axis labels. By default it can't, but you can override |
Can anyone give me a hint on how to get logarithmic axes like the x-axis of @zimonjonez plot? |
@SpaceDuster like I said above, take a look at |
@AshRobinson would you be willing to share how you overrode computeAxisValues() to draw the Y axis logarithmically? |
@danielgindi Great library! Very appreciative! Has the ability to scale the Y axis logarithmically been added yet? |
No, I guess it's not a feature that many people needs. |
@liuxuan30 I overrode computeAxisValues() to show only the values I want to show - log base 10, but the chart is still using a linear scale. Do you know how to go about redrawing the scale - keeping the logarithmic intervals equidistant apart? @SpaceDuster have you had any luck on this? |
@danielgindi could you give me an idea of where to start when trying to rescale the Y axis? |
@brittanygraft screenshot maybe? 'but the chart is still using a linear scale' is not clear to me. Ideally, you should check the data point it using to draw for each label. |
What I figured out so far:
in "open func drawLabels..." after the lines "if xAxis.isWordWrapEnabled { labelMaxSize.width = xAxis.wordWrapWidthPercent * valueToPixelMatrix.a }"
in the same "open func drawLabels" after " if viewPortHandler.isInBoundsX(position.x) {"
in "open override func renderGridLines" after the line "var position = CGPoint(x: 0.0, y: 0.0)"
possible that I forgot a step here. Please let me know if that works for you. |
hello i have some errors on order(input: maxDataNegative) thanks |
OK. There was a big junk of code missing. I updated my previous post. |
i have replace 10 ** ... by and is duplicate |
Deleted the duplicated section. infix operator ** |
I'm almost there but how use dataInput : [([Double], [Double])] ??? |
this are the x and y coordinates of datasets you want to plot: e.g. dataSets = [([1.0, 2.0, 3.0], [-20.0, -10.0, -8.0), ([3.0, 4.0, 5.0, 6.0, 7.0], [0.2, 0.4, 0.6, 6.0, 8.0])] |
another sample for @brittanygraft |
Hello I think it should also change YAxisRenderer as for XAxisrenderer |
@SpaceDuster
How to make changes to YAxisRenderer ?? |
For what it interests |
Hello @SpaceDuster , @brittanygraft I have done cleaning to be able to better integrate in Charts |
For the out of bound issue, you can simply check the lower labels y point is bigger than |
Why not scale your linear data to log using x'i = (log(xi)-log(xmin)) / (log(xmax)-log(xmin)) Then subclass xAxisRenderer to override computeAxisValues and drawLabels for drawing the grid and labels using that formula. I achieved this result for a LPF This is all you need to do to set up your values. XAxisLogRenderer *xAxisRenderer = [[XAxisLogRenderer alloc] initWithViewPortHandler:_lineChart.viewPortHandler
xAxis:_lineChart.xAxis
transformer:[_lineChart getTransformerForAxis:AxisDependencyLeft]];
_lineChart.xAxisRenderer = xAxisRenderer;
values = [NSMutableArray array];
int xMin = 20;
int xMax = 1000;
int scale = xMax - xMin - 1;
for (int i = xMin; i <=xMax; i+=10)
{
[values addObject:[[ChartDataEntry alloc] initWithX:(int)(xMin + ((double)scale * (log10((double)i/(double)xMin)/log10((double)xMax/(double)xMin)))) y:xMin*log10([self lpf:i centerFreq:100])]];
} Save this file in your project, you might want to modify # of labels and interval to your liking. //
// XAxisLogRenderer.swift
// Charts
//
// Created by Marcin Deszczynski on 2/16/17.
//
//
import UIKit
import Foundation
import CoreGraphics
@objc class XAxisLogRenderer: XAxisRenderer {
public var labelInterval: Double = 0.0
open override func computeAxisValues(min: Double, max: Double)
{
guard let axis = self.axis else { return }
let xMin = min
let xMax = max
let range = abs(xMax - xMin)
// let labelCount = Int(floor(range/interval))+1
let labelCount = 18
if labelCount == 0 || range <= 0 || range.isInfinite
{
axis.entries = [Double]()
axis.centeredEntries = [Double]()
return
}
var n = axis.centerAxisLabelsEnabled ? 1 : 0
// Ensure stops contains at least n elements.
axis.entries.removeAll(keepingCapacity: true)
axis.entries.reserveCapacity(labelCount)
var v = xMin
var interval = 20.0;
for _ in 0 ..< labelCount
{
/*
Linear to Log scale
x = fMin * (Log10(f/fMin)/Log10(fMax/fMin))
*/
v = xMin + (Double(range) * (log10(Double(interval) / Double(xMin)) / log10(Double(xMax + 1) / Double(xMin))))
axis.entries.append(v)
if interval < 100 {
interval += 10.0
} else {
interval += 100.0
}
}
n = labelCount
// set decimals
if interval < 1
{
axis.decimals = Int(ceil(-log10(interval)))
}
else
{
axis.decimals = 0
}
if axis.centerAxisLabelsEnabled
{
axis.centeredEntries.reserveCapacity(n)
axis.centeredEntries.removeAll()
let offset: Double = interval / 2.0
for i in 0 ..< n
{
axis.centeredEntries.append(axis.entries[i] + offset)
}
}
computeSize()
}
open override func drawLabels(context: CGContext, pos: CGFloat, anchor: CGPoint)
{
guard
let xAxis = self.axis as? XAxis,
let viewPortHandler = self.viewPortHandler,
let transformer = self.transformer
else { return }
#if os(OSX)
let paraStyle = NSParagraphStyle.default().mutableCopy() as! NSMutableParagraphStyle
#else
let paraStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
#endif
paraStyle.alignment = .center
let labelAttrs = [NSFontAttributeName: xAxis.labelFont,
NSForegroundColorAttributeName: xAxis.labelTextColor,
NSParagraphStyleAttributeName: paraStyle] as [String : NSObject]
let labelRotationAngleRadians = xAxis.labelRotationAngle * ChartUtils.Math.FDEG2RAD
let centeringEnabled = xAxis.isCenterAxisLabelsEnabled
let valueToPixelMatrix = transformer.valueToPixelMatrix
var position = CGPoint(x: 0.0, y: 0.0)
var labelMaxSize = CGSize()
if xAxis.isWordWrapEnabled
{
labelMaxSize.width = xAxis.wordWrapWidthPercent * valueToPixelMatrix.a
}
let entries = xAxis.entries
for i in stride(from: 0, to: entries.count, by: 1)
{
if centeringEnabled
{
position.x = CGFloat(xAxis.centeredEntries[i])
}
else
{
position.x = CGFloat(entries[i])
}
position.y = 0.0
position = position.applying(valueToPixelMatrix)
if viewPortHandler.isInBoundsX(position.x)
{
/*
Log to linear scale
f = fMin * (fMax/fMin)^(x/s)
*/
// let label = xAxis.valueFormatter?.stringForValue(20.0 * pow(1000.0 / 20.0, (xAxis.entries[i] - 20.0) / 979.0), axis: xAxis) ?? ""
let xMax = xAxis.axisMaximum + 1
let xMin = xAxis.axisMinimum
let range = xMax - xMin - 1
print("xMax \(xMax) xMin \(xMin) range \(range)");
let label = xAxis.valueFormatter?.stringForValue(xMin * pow(xMax / xMin, (xAxis.entries[i] - xMin) / range), axis: xAxis) ?? ""
let labelns = label as NSString
if xAxis.isAvoidFirstLastClippingEnabled
{
// avoid clipping of the last
if i == xAxis.entryCount - 1 && xAxis.entryCount > 1
{
let width = labelns.boundingRect(with: labelMaxSize, options: .usesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width
if width > viewPortHandler.offsetRight * 2.0
&& position.x + width > viewPortHandler.chartWidth
{
position.x -= width / 2.0
}
}
else if i == 0
{ // avoid clipping of the first
let width = labelns.boundingRect(with: labelMaxSize, options: .usesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width
position.x += width / 2.0
}
}
drawLabel(context: context,
formattedLabel: label,
x: position.x,
y: pos,
attributes: labelAttrs,
constrainedToSize: labelMaxSize,
anchor: anchor,
angleRadians: labelRotationAngleRadians)
}
}
}
}
|
You are definitely right LineChartView.xAxis.logarithmicEnabled = true / false Optional Possibility of modifying the grid: LineChartView.xAxis.stepsAxis = [1.0, 2.0, 4.0, 6.0, 8.0,]) LineChartView.leftAxis.stepsLabels = [true, false, false, false, false, false, false, false, false] Possibility of modifying the grid with stick LineChartView.xAxis.stick = false or true I just pass the data DataEntriesSet.append (ChartDataEntry (x: log10 (x), y: log10 (y)) |
I'm not clear on this. Is adding log plot capability that "just works" on the road map or not? I just got really excited about moving to Charts from CorePlot, but this excitement came to a screeching halt when I discovered the lack of log plotting capability. Seems like a very basic scientific plotting requirement. I could jump in and try to retrofit it as in all the posts above, but sticking with CorePlot is probably a path of lesser resisistance. Which is too bad, since I really like the look of Charts and that it is pure Swift. |
I gone through your suggestion but while implementing not getting any property for xAxis as you suggest.I have to set xAxis values as log value. |
if I can help you see #3774 https://www.dropbox.com/s/kopkrbad7yu8zsd/Charts-log%20copie%202.zip?dl=0 |
I have tried to implement what ever written in README file. but still having that same problem. |
look at the sample what is your version of chart |
Why not just change the Transformer for a LogTransformer that just applies a log at the end... seems like then everything would just work?! |
Hi
First of all, thank you so much for creating this library. Even if I was working with an Objective C example and Android documentation, I could create something with ios-charts in no time. (Actually I'm surprised this library is not as popular as CorePlot, as ios-charts is much earlier to pick up in my point of view)
Just a quick question/suggestion. One of my projects requires plotting data in Log Scale on the X-Axis. I read through the documentation on MPAndroidChart, but looks like it's not supported.
Is this going to be supported in the near future?
Is there any existing solution that I could work with?
Thanks a lot!
Simon
The text was updated successfully, but these errors were encountered: