Skip to content
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

<Error>: CGAffineTransformInvert: singular matrix #802

Closed
klanderson opened this issue Mar 5, 2016 · 37 comments
Closed

<Error>: CGAffineTransformInvert: singular matrix #802

klanderson opened this issue Mar 5, 2016 · 37 comments
Labels

Comments

@klanderson
Copy link

I am getting this error repeatedly with a HorizontalBarChartView:
<Error>: CGAffineTransformInvert: singular matrix.

There is nothing special about my code. I am using a HorizontalBarChartView in OSX that is 175x394 points in size. It is not obstructed by any other views. I initialize the chart with:

@IBOutlet weak var horizontalBarChart: HorizontalBarChartView!
let data = BarChartData(xVals: [1.0, 3.0, 5.0, 7.0, 8.0])
horizontalBarChart.data = data
horizontalBarChart.notifyDataSetChanged()

and then get hit with the error multiple times a second. Any idea what is causing this?

Line 206 in ChartTransformer is the only place the CGAffineTransformInvert is called.

@klanderson
Copy link
Author

This doesn't necessarily address the underlying problem, but a check for matrix singularity avoids the error message. I replaced pixelToValueMatrix in ChartTransformer with this to suppress the error.

public var pixelToValueMatrix: CGAffineTransform
{
  guard valueToPixelMatrix.a*valueToPixelMatrix.d-valueToPixelMatrix.b*valueToPixelMatrix.c != 0 else {
    // Matrix is singular, return the matrix itself
    return valueToPixelMatrix
  }
  return CGAffineTransformInvert(valueToPixelMatrix)
}

@liuxuan30
Copy link
Member

Well, we need to check out the matrix values, why it's singular, that's usually the data has some problems and leads to the matrix calculation goes bad.
You can print out chartXMin, deltaX, deltaY, chartYMin, and _viewPortHandler.contentRect), and the _matrixValueToPx values.
also print out getTransformer(.Left) or getTransformer(.Right) depending on which y axis you are using.
If possible use your data and ChartsDemo to reproduce it

@klanderson
Copy link
Author

I noticed my X axis labels aren't showing up. Maybe that could be the problem?

@liuxuan30
Copy link
Member

can't say for sure right now. Need you to debug to see what's going on. you can try ChartsDemo as well.

@danielgindi
Copy link
Collaborator

You have a transformer with a singular matrix, probably for the X axis. This means that something is your setup went horribly wrong...
But since you haven't answered to @liuxuan30 since March, I'm guessing you've figured it out already and fixed it.

@klanderson
Copy link
Author

Nope, like I said it's a simple HorizontalBarChartView and I'm sure the error could be reproduced. You still have a bug in your code but I just don't have time to help you guys fix it and I found a band-aid workaround.

Closing the issue doesn't fix the bug, but maybe someday someone else will use this Framework and reopen it when they start getting bombarded with error messages.

@danielgindi
Copy link
Collaborator

@Serk1 well, that's not a positive attitude... We're closing issues that people do not respond to for a long time - and @liuxuan30 here was trying to help you.
Like I said - the only case where that message will be spit out - is when your xAxis is invalid, and you shouldn't even see the xAxis labels.
If you are a user of this library, and want to have a better experience you can help this bug get fixed.

@danielgindi
Copy link
Collaborator

The OSX demo is not targeted for iOS devices. Check your configuration again.

@liuxuan30
Copy link
Member

@danielgindi I took a look at the statement again, I found @Serk1 is just feeding barChartData with only x values, no data set at all.
Using ChartsDemo also can print the same error message, and I can just see default y axis labels (0-1), without x axis values.

I looked into the code, it turned out in BarChartView's calcMinMax():

// increase deltax by 1 because the bars have a width of 1
_xAxis.axisRange += 0.5

// extend xDelta to make space for multiple datasets (if ther are one)
_xAxis.axisRange *= Double(data.dataSetCount) <----- BOOM

so _xAxis.axisRange is 0 after this, and leads to the scaleX to 0. then the sigularity triggered when translating to pixelToValueMatrix. Any zooming at this moment has unexpected behaviour.

It seems we support only feed xVals from the API statement. What do you think is a proper fix? We prevent any zoom/scroll in this case, or make a default one (if dataSetCount is 0, just not multiply), or just print warnings?

@liuxuan30 liuxuan30 reopened this Apr 11, 2016
@liuxuan30 liuxuan30 added the bug label Apr 11, 2016
@danielgindi
Copy link
Collaborator

A proper fix might be _xAxis.axisRange *= Double(data.dataSetCount ?? 1)

@liuxuan30
Copy link
Member

oh yeah, I was just editing - the only problem is in this case, the x value labels are a mess. They are rendered in same position.
BTW, it can't be data.dataSetCount ?? 1, ?? is checking nil, not 0:

(lldb) po Double(data.dataSetCount ?? 1)
0.0

@danielgindi
Copy link
Collaborator

Dammit. I'll look into it :-)

@liuxuan30
Copy link
Member

having to eat... I was just thinking handle it like normal bars

@liuxuan30
Copy link
Member

@danielgindi I traced down and manage to get it working. The key is to set step to 1, and groupSpace to 0.8 if data set count is 0. Not sure if you have better ones.
I found

position.x = CGFloat(i * step) + CGFloat(i) * groupSpace + groupSpace / 2.0

is the key part to make sure it is correctly renderered at the right x position, we have to make step = 1 if data set is 0, and groupSpace to 0.8 as well.

This kind of code is distributed in several places, like drawLabels in bar chart x axis renderer, lowestVisibleXIndex/highestVisibleXIndex, calcMinMax in bar chart view.
They have the same pattern but slight differences. Before we fix this, we may want to make it singleton, otherwise we have to change it everywhere.

I just don't know where to put this pattern. If you have time, please help on this. I have to work now.

@chris-gunawardena
Copy link
Contributor

I got the same error when dynamically adding points to a empty dataset and calling addXValue() after calling addEntry() fixed it.

@ghost
Copy link

ghost commented Jul 27, 2016

Got it when sending data array with an value point, [0].

@ghost
Copy link

ghost commented Jul 27, 2016

@klanderson 👍 : your lines solve mine.

@whvandervelde
Copy link

the view's - autoScaleMinMaxEnabled = true - seems to cause this problem for me when redrawing charts, setting to false will not give this issue anymore. Does scaling with empty datasets caus the problem?

@agbb
Copy link

agbb commented Dec 13, 2016

I also have this issue, but debugging it with print statements or breakpoints causes the behaviour to return to normal. Some kind of concurrency issue perhaps?

@liuxuan30
Copy link
Member

Should not be concurrency issues.. I think

@liuxuan30
Copy link
Member

No response for a long time and maybe invalid. Closing

@andreapiso
Copy link

I put some charts in a page view controller and now I get this error on a controller with an empty "No Data" chart simply by linking the view... odd. However the app does not crash and everything seems to be working fine on screen.

Still, maybe this issue should be kept open?

@liuxuan30
Copy link
Member

@AndreaPisoni Not really I guess, as you have no data, it should stop rendering, I tested ChartsDemo bar chart with nil data, it prints nothing

@andreapiso
Copy link

andreapiso commented May 5, 2017 via email

@liuxuan30
Copy link
Member

If you have new issues, open a new thread to track.

@AshishKapoor
Copy link

@klanderson Thanks! Your solution worked for me.

@SiBorya
Copy link

SiBorya commented Aug 21, 2017

Same problem occured to me too. And the solution doesn't fit.
In my case, there is some normal data inside the LineChart, and if I zoom in the chart, it crash.
Seems that it happends at func computeAxis(min: Double, max: Double, inverted: Bool), calculating the p1 and p2. The transformer call produces the error and return NaN, which crash on computeAxisValues afterwards.

@dracoirs
Copy link

dracoirs commented Feb 8, 2018

I am running into a crash at line 117 in AxisRendererBase in computeAxisValues
let intervalMagnitude = pow(10.0, Double(Int(log10(interval)))).roundedToNextSignficant()`
Fatal error: Double value cannot be converted to int because it is either infinite or NaN
p1 and p2 in XAxisRenderer in computeAxis on line 37,38 are returning NaN which changes the min and max values to NaN

`(lldb) po _matrixValueToPx
▿ CGAffineTransform

  • a : 14.2508951822917
  • b : 0.0
  • c : -0.0
  • d : -49.6888020833333
  • tx : 0.0
  • ty : 0.0

(lldb) po _viewPortHandler.touchMatrix
▿ CGAffineTransform

  • a : 1.79769313486232e+308
  • b : 0.0
  • c : 0.0
  • d : 1.0
  • tx : nan
  • ty : nan

(lldb) po _matrixOffset
▿ CGAffineTransform

  • a : 1.0
  • b : 0.0
  • c : 0.0
  • d : 1.0
  • tx : 16.4892578125
  • ty : 159.06640625

(lldb) po _matrixValueToPx.concatenating(_viewPortHandler.touchMatrix).concatenating(_matrixOffset)
▿ CGAffineTransform

  • a : inf
  • b : nan
  • c : -0.0
  • d : -49.6888020833333
  • tx : nan
  • ty : nan`

so min and max are NaN and the call to computeAxisValues crashes

I am able to consistently make this occur if I start with an empty dataset and then quickly add another piece of data before I let the chart finish rendering

@dipesh1604
Copy link

I am getting this error repeatedly with a LineChartView:
<Error>: CGAffineTransformInvert: singular matrix.

I am using it to display speed. But until any movement it will not update or increase my speed any more.That's why my data will not available to display. But after preset timer as my timer ends, it gives this error.

I could not able to find the solution.

@renatamakuch
Copy link

Same problem like @dipesh1604

@Tindi
Copy link

Tindi commented May 24, 2018

After upgrading to Swift 3 I've encountered the same thing. Any luck @xrena , @dipesh1604 ?

@eshirima
Copy link

eshirima commented Jun 20, 2018

Same problem as @dipesh1604
@liuxuan30 @danielgindi Any guidance?

@shvetsjr
Copy link

Same Issue...

@gesabo
Copy link

gesabo commented Jan 31, 2021

Im still seeing this, using Charts wrapped in UIViewRepresentable as per https://medium.com/@zzzzbh/plotting-in-ios-using-charts-framework-with-swiftui-222034a2bea6

@brettfazio
Copy link

I am also getting this issue like @gesabo when using Charts wrapped in UIViewRepresentable

@jawknees
Copy link

Hey! it's 2022. Yeah I know. I'm currently getting this issue on iOS. I'm using the react-native-charts-wrapper which is a bundle of this library for RN.

This was already working properly when I first started, but then I just got this issue recently

@rickymohk
Copy link

rickymohk commented Mar 27, 2023

Having the NaN issue in 2023, with SwiftUI UIViewRepresentable. My App involves repeatedly updating (append dataset, setVisibleXRange, moveViewToAniated) and clearing the chart multiple times. The first plot always has no issue. After clearing and starting the second plot, this issue may occur. There is probably some animation matrix operation freaks out when the dataset entries is empty. My solution is to set the chartView.data to nil when there is no data to display, instead of having an empty dataset.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests