Repository: pyqtgraph/pyqtgraph

Issue:
SVG Exporter Moves PlotObjects
When exporting a PlotCurveItem to SVG, if the view has undergone a transformation, like say setting log mode, the line will be shifted out of the view and won't be visible after the export is complete.

## Cause

I introduced this bug in #2728  In reviewing my diff.  In that PR, what I attempted to do was to shift the numerical positioning of the PlotCurveItem to be between -1 and 1, as the underlying issue was one of precision of values that Qt would write to the XML/SVG file.  Having Qt not use view coordinates, was the objective here.  

I should note, I never liked this fix, having it be conditional on PlotCurveItem seemed hacky, I think we can manipulate the QPainter to use a different world transform such that the coordinates written to the SVG output is between -1 and 1 (we could do a narrower range, but I didn't feel that was necessary).


## Reproduction

To reproduce, run this code, right click and export to SVG.  The line will shift.

```python
import numpy as np
import scipy
import pyqtgraph as pg
import pyqtgraph.exporters

pg.mkQApp()

### create data
x = np.arange(0,500,10)
y = np.random.random(50)*0.3 + scipy.signal.windows.gaussian(50, std=10)

p1 = pg.plot()
plot_obj = p1.plot(x=x+1000000, y=y, pen='b')
plot_obj.setLogMode(True, False)
p1.show()

if __name__ == "__main__":
    pg.exec()
```

If someone sees a way to modify this example such that the user doesn't have to right click, select svg and export explicitly, that would be greatly appreciated.
SVG exporter output has errors when data values are very large
I found a bug when trying to export a plot as an SVG. It seems that incorrect data values are being saved in the .svg when the data values are large (~1,000,000). 

Here is a minimal example:
```import pyqtgraph as pg 
import numpy as np
import scipy


### create data
x = np.arange(0,500,10)
y = np.random.random(50)*0.3 + scipy.signal.gaussian(50, std=10)

### create plot where export works
p1 = pg.plot()
p1.plot(x=x, y=y, pen='g')

### create plot where export doesn't work because we've increased the x-axis values
p2 = pg.plot()
p2.plot(x=x+10000000, y=y, pen='b')

```

And here is an illustration of the output:
![4 plots showing the output of exporting p1 and p2 in the above code as svg and png files. the svg plot of p2 is different than the other 3 - it is more jagged and blocky, as if several different x-values were grouped together.](https://user-images.githubusercontent.com/1213878/227570413-ff4cad50-b92b-46d3-aeec-77adbfc5b892.png)


Here's the pg.systemInfo output for my machine:
```sys.platform: linux
sys.version: 3.9.13 (main, Aug 25 2022, 23:26:10) 
[GCC 11.2.0]
qt bindings: PyQt5 5.15.7 Qt 5.15.2
pyqtgraph: 0.13.1; None
config:
{'antialias': False,
 'background': 'k',
 'crashWarning': False,
 'editorCommand': None,
 'enableExperimental': False,
 'exitCleanup': True,
 'foreground': 'd',
 'imageAxisOrder': 'col-major',
 'leftButtonPan': True,
 'mouseRateLimit': 100,
 'segmentedLineMode': 'auto',
 'useCupy': False,
 'useNumba': False,
 'useOpenGL': False}
```



SVG exporter output has errors when data values are very large
I found a bug when trying to export a plot as an SVG. It seems that incorrect data values are being saved in the .svg when the data values are large (~1,000,000). 

Here is a minimal example:
```import pyqtgraph as pg 
import numpy as np
import scipy


### create data
x = np.arange(0,500,10)
y = np.random.random(50)*0.3 + scipy.signal.gaussian(50, std=10)

### create plot where export works
p1 = pg.plot()
p1.plot(x=x, y=y, pen='g')

### create plot where export doesn't work because we've increased the x-axis values
p2 = pg.plot()
p2.plot(x=x+10000000, y=y, pen='b')

```

And here is an illustration of the output:
![4 plots showing the output of exporting p1 and p2 in the above code as svg and png files. the svg plot of p2 is different than the other 3 - it is more jagged and blocky, as if several different x-values were grouped together.](https://user-images.githubusercontent.com/1213878/227570413-ff4cad50-b92b-46d3-aeec-77adbfc5b892.png)


Here's the pg.systemInfo output for my machine:
```sys.platform: linux
sys.version: 3.9.13 (main, Aug 25 2022, 23:26:10) 
[GCC 11.2.0]
qt bindings: PyQt5 5.15.7 Qt 5.15.2
pyqtgraph: 0.13.1; None
config:
{'antialias': False,
 'background': 'k',
 'crashWarning': False,
 'editorCommand': None,
 'enableExperimental': False,
 'exitCleanup': True,
 'foreground': 'd',
 'imageAxisOrder': 'col-major',
 'leftButtonPan': True,
 'mouseRateLimit': 100,
 'segmentedLineMode': 'auto',
 'useCupy': False,
 'useNumba': False,
 'useOpenGL': False}
```





Discussion:
Shouldn't it be:
```python
p1 = pg.plot()
pdi = p1.plot(x=x+1000000, y=y, pen='b')
p1.setLogMode(True, False)
p1.show()
```
i.e. One should set Log Mode on the `PlotItem`, rather than on the individual items.

In any case, I am not observing the issue that you described on Windows 10, PyQt5.
Hi, I encountered a similar issue with the SVG exporter output when my data values were very large. It seems that the SVG format has limitations on the size of numbers that can be represented. One possible workaround is to scale down the data values before exporting to SVG, and then scale them back up when importing the SVG file.

Another solution is to use a different file format that supports larger numbers, such as PDF or EPS.

I hope this helps! Let me know if you have any questions.
@meganbkratz how did you try to view that svg? Googling around at this, looks like different viewers can treat SVGs differently in this regard.
@ISMAILJAOUA11 Thank you for the tips! Scaling down the data for export is what I am ending up doing. It's definitely not ideal though because it required editing code in between when I want to display a plot in a gui with the correct values and when I plan to export the plot for a figure. 

@j9ac9k The images I attached are from the svg viewed in Inkscape. But I think the issue is in the export because there are problems in the svg file itself. As far as I can tell, Inkscape is correctly displaying the values in the path that describes the data line. 
For example:
In this bad plot, the first few values that describe the line (if you open the svg in a text editor) are:
`d="M0.0,359.238008248 L0.0,373.580097281 L0.0,389.959457546 L0.0,342.521010335 L0.0,311.222286499 L116.08799999952316,376.518689353 L116.08799999952316,339.53127188200006 L116.08799999952316,349.50231250800005 L116.08799999952316,281.53199116200005 L116.08799999952316,253.675812201 L116.08799999952316,324.68165337600004 L116.08799999952316,277.500011071 L116.08799999952316,258.3959436 ....etc`
You can see that the x-values for groups points are the same (and they shouldn't be)
![bad](https://github.com/pyqtgraph/pyqtgraph/assets/1213878/68804d99-50b1-4a0f-912d-f7e735cf6f8a)

Whereas in the good plot, the x values are appropriately different:
`d="M46.5449,359.238008248 L58.1537,373.580097281 L69.76249999999999,389.959457546 L81.37129999999999,342.521010335 L92.9801,311.222286499 L104.5889,376.518689353 L116.1977,339.53127188200006 L127.80649999999999,349.50231250800005 L139.4153,281.53199116200005 L151.02409999999998,253.675812201 L162.6329,324.68165337600004 L174.24169999999998,277.500011071 L185.8505,258.3959436 ... etc`
![good](https://github.com/pyqtgraph/pyqtgraph/assets/1213878/26416304-fb69-4b46-9ee7-6d347f74a19d)


> @ISMAILJAOUA11 Thank you for the tips! Scaling down the data for export is what I am ending up doing. It's definitely not ideal though because it required editing code in between when I want to display a plot in a gui with the correct values and when I plan to export the plot for a figure.
> 
> @j9ac9k The images I attached are from the svg viewed in Inkscape. But I think the issue is in the export because there are problems in the svg file itself. As far as I can tell, Inkscape is correctly displaying the values in the path that describes the data line. For example: In this bad plot, the first few values that describe the line (if you open the svg in a text editor) are: `d="M0.0,359.238008248 L0.0,373.580097281 L0.0,389.959457546 L0.0,342.521010335 L0.0,311.222286499 L116.08799999952316,376.518689353 L116.08799999952316,339.53127188200006 L116.08799999952316,349.50231250800005 L116.08799999952316,281.53199116200005 L116.08799999952316,253.675812201 L116.08799999952316,324.68165337600004 L116.08799999952316,277.500011071 L116.08799999952316,258.3959436 ....etc` You can see that the x-values for groups points are the same (and they shouldn't be) ![bad](https://user-images.githubusercontent.com/1213878/238424605-68804d99-50b1-4a0f-912d-f7e735cf6f8a.svg)
> 
> Whereas in the good plot, the x values are appropriately different: `d="M46.5449,359.238008248 L58.1537,373.580097281 L69.76249999999999,389.959457546 L81.37129999999999,342.521010335 L92.9801,311.222286499 L104.5889,376.518689353 L116.1977,339.53127188200006 L127.80649999999999,349.50231250800005 L139.4153,281.53199116200005 L151.02409999999998,253.675812201 L162.6329,324.68165337600004 L174.24169999999998,277.500011071 L185.8505,258.3959436 ... etc` ![good](https://user-images.githubusercontent.com/1213878/238424620-26416304-fb69-4b46-9ee7-6d347f74a19d.svg)


If inkscape renders SVG badly, then we're all in trouble 😆   looking at the SVG documentation (I'm by no means particularly knowledgeable here) it seems to recommend trying to limit precision if using large values... I should debug more using your example code (thanks for that!).  We have run into issues with Qt when numbers get small enough, they get rounded off to effectively-0; wouldn't surprise me if we're running into something like this with Qt's SVG functionality. 

I should add that even if it is a Qt issue upstream, pyqtgraph _should_ make every effort to work around this as we do in other parts of the library.
Finally taking a closer look at this one...

Looking at the SVG file, the "good" output is as such:

```svg
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M49.2549,400.666066424
L60.8095,415.55810222800005
L72.3641,438.78312539200004
L83.9187,410.02197660400003
L95.4733,323.070544808
L107.02789999999999,341.894568768
L118.58249999999998,364.22869534800003
L130.1371,324.91517199200007
L141.6917,294.474335312
L153.2463,260.057751072
L164.80089999999998,339.743999768
L176.35549999999998,284.465026168
L187.91009999999997,198.56569012800003
L199.4647,279.255787032
L211.0193,230.22692796400005
L222.57389999999998,177.760150592
L234.12849999999997,208.62137676000003
L245.68309999999997,138.77239168800003
L257.2377,156.113084056
L268.7923,59.10259952000007
L280.3469,30.408398879999993
L291.9015,112.32001897600003
L303.4561,107.72228946000001
L315.0107,93.85579455999999
L326.5653,101.08918664000004
L338.11990000000003,46.46099392000002
L349.6745,50.65740856000002
L361.2291,21.215183920000015
L372.7837,118.85625268800004
L384.3383,33.10128528000007
L395.8929,122.89109414400002
L407.4475,136.91355204799999
L419.0021,167.74934540000004
L430.5567,208.71039161600004
L442.11129999999997,163.41118021200003
L453.6659,166.36250890399998
L465.2205,181.26800914
L476.7751,244.47042696000003
L488.3297,236.08694798000002
L499.8843,296.30549806400006
L511.4389,348.26661121200004
L522.9934999999999,324.413995912
L534.5481,285.26989999200003
L546.1026999999999,385.579170368
L557.6573,378.252275288
L569.2119,350.744440712
L580.7665,431.09044657600003
L592.3211,434.01297634400004
L603.8756999999999,391.795997832
L615.4303,420.407915832 "/>
```

The equivalent bad output:

```svg
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M0.0,400.666066424
L0.0,415.55810222800005
L0.0,438.78312539200004
L0.0,410.02197660400003
L0.0,323.070544808
L115.5460000000894,341.894568768
L115.5460000000894,364.22869534800003
L115.5460000000894,324.91517199200007
L115.5460000000894,294.474335312
L115.5460000000894,260.057751072
L115.5460000000894,339.743999768
L115.5460000000894,284.465026168
L115.5460000000894,198.56569012800003
L115.5460000000894,279.255787032
L115.5460000000894,230.22692796400005
L231.0920000001788,177.760150592
L231.0920000001788,208.62137676000003
L231.0920000001788,138.77239168800003
L231.0920000001788,156.113084056
L231.0920000001788,59.10259952000007
L231.0920000001788,30.408398879999993
L231.0920000001788,112.32001897600003
L231.0920000001788,107.72228946000001
L231.0920000001788,93.85579455999999
L231.0920000001788,101.08918664000004
L346.6379999984056,46.46099392000002
L346.6379999984056,50.65740856000002
L346.6379999984056,21.215183920000015
L346.6379999984056,118.85625268800004
L346.6379999984056,33.10128528000007
L346.6379999984056,122.89109414400002
L346.6379999984056,136.91355204799999
L346.6379999984056,167.74934540000004
L346.6379999984056,208.71039161600004
L346.6379999984056,163.41118021200003
L462.183999998495,166.36250890399998
L462.183999998495,181.26800914
L462.183999998495,244.47042696000003
L462.183999998495,236.08694798000002
L462.183999998495,296.30549806400006
L462.183999998495,348.26661121200004
L462.183999998495,324.413995912
L462.183999998495,285.26989999200003
L462.183999998495,385.579170368
L462.183999998495,378.252275288
L577.7299999985844,350.744440712
L577.7299999985844,431.09044657600003
L577.7299999985844,434.01297634400004
L577.7299999985844,391.795997832
L577.7299999985844,420.407915832 "/>
```

Indeed the SVG contents aren't great...

Still debugging, but so far I have narrowed down the issue occurring inside this method:

https://github.com/pyqtgraph/pyqtgraph/blob/7497a673630f10697c070d6de8a2d6defdc6b7ad/pyqtgraph/exporters/SVGExporter.py#L99-L124

EDIT:  we must go deeper, issue occurs somewhere inside this method:

https://github.com/pyqtgraph/pyqtgraph/blob/7497a673630f10697c070d6de8a2d6defdc6b7ad/pyqtgraph/exporters/SVGExporter.py#L127

the `correctCoordinates` method that is called within I am suspicious of...
Ok, going to call it a night...

This is as far as I got for things that go wrong:

https://github.com/pyqtgraph/pyqtgraph/blob/master/pyqtgraph/exporters/SVGExporter.py#L224

For the "good" output, the debugger gives me the following:

```
(Pdb) pp g1.toprettyxml()
('<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" '
 'stroke-linecap="square" stroke-linejoin="bevel">\n'
 '\t\n'
 '\n'
 '\n'
 '\t<g fill="none" stroke="#00ff00" stroke-opacity="1" stroke-width="1" '
 'stroke-linecap="square" stroke-linejoin="bevel" '
 'transform="matrix(1.15546,0,0,-363.171,49.2549,476.301)" '
 'font-family=".AppleSystemUIFont" font-size="13" font-weight="400" '
 'font-style="normal">\n'
 '\t\t\n'
 '\n'
 '\t\t<path vector-effect="non-scaling-stroke" fill-rule="evenodd" '
 'd="M0,0.250017 L10,0.27385 L20,0.282827 L30,0.294233 L40,0.259979 '
 'L50,0.283034 L60,0.478167 L70,0.515657 L80,0.43829 L90,0.353352 '
 'L100,0.442154 L110,0.407027 L120,0.689846 L130,0.52141 L140,0.604227 '
 'L150,0.756896 L160,0.735597 L170,0.978015 L180,0.993733 L190,1.07211 '
 'L200,1.19644 L210,1.18565 L220,1.08015 L230,1.25309 L240,1.12883 '
 'L250,1.14204 L260,1.23152 L270,1.04348 L280,1.16043 L290,1.06074 '
 'L300,1.14377 L310,0.896933 L320,0.953601 L330,0.939698 L340,0.789906 '
 'L350,0.780501 L360,0.688875 L370,0.738772 L380,0.575246 L390,0.366957 '
 'L400,0.457146 L410,0.41881 L420,0.269921 L430,0.472472 L440,0.264113 '
 'L450,0.417968 L460,0.259952 L470,0.28309 L480,0.150263 L490,0.103305"/>\n'
 '\t\t\n'
 '\n'
 '\t</g>\n'
 '\t\n'
 '\n'
 '</g>\n')
```

For the "bad" output, the debugger gives me the following:

```
(Pdb) pp g1.toprettyxml()
('<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" '
 'stroke-linecap="square" stroke-linejoin="bevel">\n'
 '\t\n'
 '\n'
 '\n'
 '\t<g fill="none" stroke="#0000ff" stroke-opacity="1" stroke-width="1" '
 'stroke-linecap="square" stroke-linejoin="bevel" '
 'transform="matrix(1.15546,0,0,-373.406,-1.15546e+07,488.123)" '
 'font-family=".AppleSystemUIFont" font-size="13" font-weight="400" '
 'font-style="normal">\n'
 '\t\t\n'
 '\n'
 '\t\t<path vector-effect="non-scaling-stroke" fill-rule="evenodd" '
 'd="M1e+07,0.133971 L1e+07,0.259801 L1e+07,0.17237 L1e+07,0.370696 '
 'L1e+07,0.146867 L1.00001e+07,0.394447 L1.00001e+07,0.378525 '
 'L1.00001e+07,0.405273 L1.00001e+07,0.431784 L1.00001e+07,0.390073 '
 'L1.00001e+07,0.536344 L1.00001e+07,0.492783 L1.00001e+07,0.521688 '
 'L1.00001e+07,0.657663 L1.00001e+07,0.642802 L1.00002e+07,0.646728 '
 'L1.00002e+07,0.859019 L1.00002e+07,1.01305 L1.00002e+07,1.03623 '
 'L1.00002e+07,1.07015 L1.00002e+07,1.14554 L1.00002e+07,1.05975 '
 'L1.00002e+07,1.0488 L1.00002e+07,1.04441 L1.00002e+07,1.13594 '
 'L1.00003e+07,1.2504 L1.00003e+07,1.16659 L1.00003e+07,1.07563 '
 'L1.00003e+07,1.05724 L1.00003e+07,1.04453 L1.00003e+07,0.92962 '
 'L1.00003e+07,1.06577 L1.00003e+07,0.989221 L1.00003e+07,0.749754 '
 'L1.00003e+07,0.652915 L1.00004e+07,0.601241 L1.00004e+07,0.611184 '
 'L1.00004e+07,0.503679 L1.00004e+07,0.5252 L1.00004e+07,0.415677 '
 'L1.00004e+07,0.587574 L1.00004e+07,0.271862 L1.00004e+07,0.385623 '
 'L1.00004e+07,0.257686 L1.00004e+07,0.422531 L1.00005e+07,0.161976 '
 'L1.00005e+07,0.231378 L1.00005e+07,0.368934 L1.00005e+07,0.299505 '
 'L1.00005e+07,0.132133"/>\n'
 '\t\t\n'
 '\n'
 '\t</g>\n'
 '\t\n'
 '\n'
 '</g>\n')
```

At a glance, this looks like a precision issue when the scene transform is applied. 

The main difference between the two is the value returned here: https://github.com/pyqtgraph/pyqtgraph/blob/7497a673630f10697c070d6de8a2d6defdc6b7ad/pyqtgraph/exporters/SVGExporter.py#L186

I'm open to other suggestions.
Googling more on the subject matter looks like this is a common issue with SVGs:

https://oreillymedia.github.io/Using_SVG/extras/ch08-precision.html

> If you stick with coordinates that are reasonably close to the default scale of one unit per pixel—and with graphics that will fit on your screen—you don’t usually have to worry about the precision and range of possible numbers. However, if you’re working with technical coordinates that have a meaning separate from their visual display, you will often need to scale them to screen dimensions before using them in your SVG code.

...looks like a lot of the positional information is going to be stuck on 32-bit floating point precision which has a precision of around 7 decimal places.  Since this example uses 10e6 and is looking for differences in increments of 10, we're definitely in the "danger zone" here.

I'm starting to think this is not a bug; _but_ there is likely a workaround that could happen, and that is we apply a QTransform to the PlotCurveItem to get the view coordinates into a more palatable range, and then apply the inverse transform to the calculated `itemTransform` that I linked above.
so... I got it working, but ...let's just say I'm going to want a _ton_ of eyes on a PR I'll write up.

![test](https://github.com/pyqtgraph/pyqtgraph/assets/646398/63fa8fea-3de0-457b-93a2-aba18969258d)

What I do is I actually shift the x and y data of the curve item so that the curve is centered about (0, 0).  I compute what the transform is to make that happen, and I add that transform into the series of transforms that the QPainter is set to, so that the curve is placed in the correct position.

I'll submit a draft PR in a bit...

Hi, I encountered a similar issue with the SVG exporter output when my data values were very large. It seems that the SVG format has limitations on the size of numbers that can be represented. One possible workaround is to scale down the data values before exporting to SVG, and then scale them back up when importing the SVG file.

Another solution is to use a different file format that supports larger numbers, such as PDF or EPS.

I hope this helps! Let me know if you have any questions.
@meganbkratz how did you try to view that svg? Googling around at this, looks like different viewers can treat SVGs differently in this regard.
@ISMAILJAOUA11 Thank you for the tips! Scaling down the data for export is what I am ending up doing. It's definitely not ideal though because it required editing code in between when I want to display a plot in a gui with the correct values and when I plan to export the plot for a figure. 

@j9ac9k The images I attached are from the svg viewed in Inkscape. But I think the issue is in the export because there are problems in the svg file itself. As far as I can tell, Inkscape is correctly displaying the values in the path that describes the data line. 
For example:
In this bad plot, the first few values that describe the line (if you open the svg in a text editor) are:
`d="M0.0,359.238008248 L0.0,373.580097281 L0.0,389.959457546 L0.0,342.521010335 L0.0,311.222286499 L116.08799999952316,376.518689353 L116.08799999952316,339.53127188200006 L116.08799999952316,349.50231250800005 L116.08799999952316,281.53199116200005 L116.08799999952316,253.675812201 L116.08799999952316,324.68165337600004 L116.08799999952316,277.500011071 L116.08799999952316,258.3959436 ....etc`
You can see that the x-values for groups points are the same (and they shouldn't be)
![bad](https://github.com/pyqtgraph/pyqtgraph/assets/1213878/68804d99-50b1-4a0f-912d-f7e735cf6f8a)

Whereas in the good plot, the x values are appropriately different:
`d="M46.5449,359.238008248 L58.1537,373.580097281 L69.76249999999999,389.959457546 L81.37129999999999,342.521010335 L92.9801,311.222286499 L104.5889,376.518689353 L116.1977,339.53127188200006 L127.80649999999999,349.50231250800005 L139.4153,281.53199116200005 L151.02409999999998,253.675812201 L162.6329,324.68165337600004 L174.24169999999998,277.500011071 L185.8505,258.3959436 ... etc`
![good](https://github.com/pyqtgraph/pyqtgraph/assets/1213878/26416304-fb69-4b46-9ee7-6d347f74a19d)


> @ISMAILJAOUA11 Thank you for the tips! Scaling down the data for export is what I am ending up doing. It's definitely not ideal though because it required editing code in between when I want to display a plot in a gui with the correct values and when I plan to export the plot for a figure.
> 
> @j9ac9k The images I attached are from the svg viewed in Inkscape. But I think the issue is in the export because there are problems in the svg file itself. As far as I can tell, Inkscape is correctly displaying the values in the path that describes the data line. For example: In this bad plot, the first few values that describe the line (if you open the svg in a text editor) are: `d="M0.0,359.238008248 L0.0,373.580097281 L0.0,389.959457546 L0.0,342.521010335 L0.0,311.222286499 L116.08799999952316,376.518689353 L116.08799999952316,339.53127188200006 L116.08799999952316,349.50231250800005 L116.08799999952316,281.53199116200005 L116.08799999952316,253.675812201 L116.08799999952316,324.68165337600004 L116.08799999952316,277.500011071 L116.08799999952316,258.3959436 ....etc` You can see that the x-values for groups points are the same (and they shouldn't be) ![bad](https://user-images.githubusercontent.com/1213878/238424605-68804d99-50b1-4a0f-912d-f7e735cf6f8a.svg)
> 
> Whereas in the good plot, the x values are appropriately different: `d="M46.5449,359.238008248 L58.1537,373.580097281 L69.76249999999999,389.959457546 L81.37129999999999,342.521010335 L92.9801,311.222286499 L104.5889,376.518689353 L116.1977,339.53127188200006 L127.80649999999999,349.50231250800005 L139.4153,281.53199116200005 L151.02409999999998,253.675812201 L162.6329,324.68165337600004 L174.24169999999998,277.500011071 L185.8505,258.3959436 ... etc` ![good](https://user-images.githubusercontent.com/1213878/238424620-26416304-fb69-4b46-9ee7-6d347f74a19d.svg)


If inkscape renders SVG badly, then we're all in trouble 😆   looking at the SVG documentation (I'm by no means particularly knowledgeable here) it seems to recommend trying to limit precision if using large values... I should debug more using your example code (thanks for that!).  We have run into issues with Qt when numbers get small enough, they get rounded off to effectively-0; wouldn't surprise me if we're running into something like this with Qt's SVG functionality. 

I should add that even if it is a Qt issue upstream, pyqtgraph _should_ make every effort to work around this as we do in other parts of the library.
Finally taking a closer look at this one...

Looking at the SVG file, the "good" output is as such:

```svg
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M49.2549,400.666066424
L60.8095,415.55810222800005
L72.3641,438.78312539200004
L83.9187,410.02197660400003
L95.4733,323.070544808
L107.02789999999999,341.894568768
L118.58249999999998,364.22869534800003
L130.1371,324.91517199200007
L141.6917,294.474335312
L153.2463,260.057751072
L164.80089999999998,339.743999768
L176.35549999999998,284.465026168
L187.91009999999997,198.56569012800003
L199.4647,279.255787032
L211.0193,230.22692796400005
L222.57389999999998,177.760150592
L234.12849999999997,208.62137676000003
L245.68309999999997,138.77239168800003
L257.2377,156.113084056
L268.7923,59.10259952000007
L280.3469,30.408398879999993
L291.9015,112.32001897600003
L303.4561,107.72228946000001
L315.0107,93.85579455999999
L326.5653,101.08918664000004
L338.11990000000003,46.46099392000002
L349.6745,50.65740856000002
L361.2291,21.215183920000015
L372.7837,118.85625268800004
L384.3383,33.10128528000007
L395.8929,122.89109414400002
L407.4475,136.91355204799999
L419.0021,167.74934540000004
L430.5567,208.71039161600004
L442.11129999999997,163.41118021200003
L453.6659,166.36250890399998
L465.2205,181.26800914
L476.7751,244.47042696000003
L488.3297,236.08694798000002
L499.8843,296.30549806400006
L511.4389,348.26661121200004
L522.9934999999999,324.413995912
L534.5481,285.26989999200003
L546.1026999999999,385.579170368
L557.6573,378.252275288
L569.2119,350.744440712
L580.7665,431.09044657600003
L592.3211,434.01297634400004
L603.8756999999999,391.795997832
L615.4303,420.407915832 "/>
```

The equivalent bad output:

```svg
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M0.0,400.666066424
L0.0,415.55810222800005
L0.0,438.78312539200004
L0.0,410.02197660400003
L0.0,323.070544808
L115.5460000000894,341.894568768
L115.5460000000894,364.22869534800003
L115.5460000000894,324.91517199200007
L115.5460000000894,294.474335312
L115.5460000000894,260.057751072
L115.5460000000894,339.743999768
L115.5460000000894,284.465026168
L115.5460000000894,198.56569012800003
L115.5460000000894,279.255787032
L115.5460000000894,230.22692796400005
L231.0920000001788,177.760150592
L231.0920000001788,208.62137676000003
L231.0920000001788,138.77239168800003
L231.0920000001788,156.113084056
L231.0920000001788,59.10259952000007
L231.0920000001788,30.408398879999993
L231.0920000001788,112.32001897600003
L231.0920000001788,107.72228946000001
L231.0920000001788,93.85579455999999
L231.0920000001788,101.08918664000004
L346.6379999984056,46.46099392000002
L346.6379999984056,50.65740856000002
L346.6379999984056,21.215183920000015
L346.6379999984056,118.85625268800004
L346.6379999984056,33.10128528000007
L346.6379999984056,122.89109414400002
L346.6379999984056,136.91355204799999
L346.6379999984056,167.74934540000004
L346.6379999984056,208.71039161600004
L346.6379999984056,163.41118021200003
L462.183999998495,166.36250890399998
L462.183999998495,181.26800914
L462.183999998495,244.47042696000003
L462.183999998495,236.08694798000002
L462.183999998495,296.30549806400006
L462.183999998495,348.26661121200004
L462.183999998495,324.413995912
L462.183999998495,285.26989999200003
L462.183999998495,385.579170368
L462.183999998495,378.252275288
L577.7299999985844,350.744440712
L577.7299999985844,431.09044657600003
L577.7299999985844,434.01297634400004
L577.7299999985844,391.795997832
L577.7299999985844,420.407915832 "/>
```

Indeed the SVG contents aren't great...

Still debugging, but so far I have narrowed down the issue occurring inside this method:

https://github.com/pyqtgraph/pyqtgraph/blob/7497a673630f10697c070d6de8a2d6defdc6b7ad/pyqtgraph/exporters/SVGExporter.py#L99-L124

EDIT:  we must go deeper, issue occurs somewhere inside this method:

https://github.com/pyqtgraph/pyqtgraph/blob/7497a673630f10697c070d6de8a2d6defdc6b7ad/pyqtgraph/exporters/SVGExporter.py#L127

the `correctCoordinates` method that is called within I am suspicious of...
Ok, going to call it a night...

This is as far as I got for things that go wrong:

https://github.com/pyqtgraph/pyqtgraph/blob/master/pyqtgraph/exporters/SVGExporter.py#L224

For the "good" output, the debugger gives me the following:

```
(Pdb) pp g1.toprettyxml()
('<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" '
 'stroke-linecap="square" stroke-linejoin="bevel">\n'
 '\t\n'
 '\n'
 '\n'
 '\t<g fill="none" stroke="#00ff00" stroke-opacity="1" stroke-width="1" '
 'stroke-linecap="square" stroke-linejoin="bevel" '
 'transform="matrix(1.15546,0,0,-363.171,49.2549,476.301)" '
 'font-family=".AppleSystemUIFont" font-size="13" font-weight="400" '
 'font-style="normal">\n'
 '\t\t\n'
 '\n'
 '\t\t<path vector-effect="non-scaling-stroke" fill-rule="evenodd" '
 'd="M0,0.250017 L10,0.27385 L20,0.282827 L30,0.294233 L40,0.259979 '
 'L50,0.283034 L60,0.478167 L70,0.515657 L80,0.43829 L90,0.353352 '
 'L100,0.442154 L110,0.407027 L120,0.689846 L130,0.52141 L140,0.604227 '
 'L150,0.756896 L160,0.735597 L170,0.978015 L180,0.993733 L190,1.07211 '
 'L200,1.19644 L210,1.18565 L220,1.08015 L230,1.25309 L240,1.12883 '
 'L250,1.14204 L260,1.23152 L270,1.04348 L280,1.16043 L290,1.06074 '
 'L300,1.14377 L310,0.896933 L320,0.953601 L330,0.939698 L340,0.789906 '
 'L350,0.780501 L360,0.688875 L370,0.738772 L380,0.575246 L390,0.366957 '
 'L400,0.457146 L410,0.41881 L420,0.269921 L430,0.472472 L440,0.264113 '
 'L450,0.417968 L460,0.259952 L470,0.28309 L480,0.150263 L490,0.103305"/>\n'
 '\t\t\n'
 '\n'
 '\t</g>\n'
 '\t\n'
 '\n'
 '</g>\n')
```

For the "bad" output, the debugger gives me the following:

```
(Pdb) pp g1.toprettyxml()
('<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" '
 'stroke-linecap="square" stroke-linejoin="bevel">\n'
 '\t\n'
 '\n'
 '\n'
 '\t<g fill="none" stroke="#0000ff" stroke-opacity="1" stroke-width="1" '
 'stroke-linecap="square" stroke-linejoin="bevel" '
 'transform="matrix(1.15546,0,0,-373.406,-1.15546e+07,488.123)" '
 'font-family=".AppleSystemUIFont" font-size="13" font-weight="400" '
 'font-style="normal">\n'
 '\t\t\n'
 '\n'
 '\t\t<path vector-effect="non-scaling-stroke" fill-rule="evenodd" '
 'd="M1e+07,0.133971 L1e+07,0.259801 L1e+07,0.17237 L1e+07,0.370696 '
 'L1e+07,0.146867 L1.00001e+07,0.394447 L1.00001e+07,0.378525 '
 'L1.00001e+07,0.405273 L1.00001e+07,0.431784 L1.00001e+07,0.390073 '
 'L1.00001e+07,0.536344 L1.00001e+07,0.492783 L1.00001e+07,0.521688 '
 'L1.00001e+07,0.657663 L1.00001e+07,0.642802 L1.00002e+07,0.646728 '
 'L1.00002e+07,0.859019 L1.00002e+07,1.01305 L1.00002e+07,1.03623 '
 'L1.00002e+07,1.07015 L1.00002e+07,1.14554 L1.00002e+07,1.05975 '
 'L1.00002e+07,1.0488 L1.00002e+07,1.04441 L1.00002e+07,1.13594 '
 'L1.00003e+07,1.2504 L1.00003e+07,1.16659 L1.00003e+07,1.07563 '
 'L1.00003e+07,1.05724 L1.00003e+07,1.04453 L1.00003e+07,0.92962 '
 'L1.00003e+07,1.06577 L1.00003e+07,0.989221 L1.00003e+07,0.749754 '
 'L1.00003e+07,0.652915 L1.00004e+07,0.601241 L1.00004e+07,0.611184 '
 'L1.00004e+07,0.503679 L1.00004e+07,0.5252 L1.00004e+07,0.415677 '
 'L1.00004e+07,0.587574 L1.00004e+07,0.271862 L1.00004e+07,0.385623 '
 'L1.00004e+07,0.257686 L1.00004e+07,0.422531 L1.00005e+07,0.161976 '
 'L1.00005e+07,0.231378 L1.00005e+07,0.368934 L1.00005e+07,0.299505 '
 'L1.00005e+07,0.132133"/>\n'
 '\t\t\n'
 '\n'
 '\t</g>\n'
 '\t\n'
 '\n'
 '</g>\n')
```

At a glance, this looks like a precision issue when the scene transform is applied. 

The main difference between the two is the value returned here: https://github.com/pyqtgraph/pyqtgraph/blob/7497a673630f10697c070d6de8a2d6defdc6b7ad/pyqtgraph/exporters/SVGExporter.py#L186

I'm open to other suggestions.
Googling more on the subject matter looks like this is a common issue with SVGs:

https://oreillymedia.github.io/Using_SVG/extras/ch08-precision.html

> If you stick with coordinates that are reasonably close to the default scale of one unit per pixel—and with graphics that will fit on your screen—you don’t usually have to worry about the precision and range of possible numbers. However, if you’re working with technical coordinates that have a meaning separate from their visual display, you will often need to scale them to screen dimensions before using them in your SVG code.

...looks like a lot of the positional information is going to be stuck on 32-bit floating point precision which has a precision of around 7 decimal places.  Since this example uses 10e6 and is looking for differences in increments of 10, we're definitely in the "danger zone" here.

I'm starting to think this is not a bug; _but_ there is likely a workaround that could happen, and that is we apply a QTransform to the PlotCurveItem to get the view coordinates into a more palatable range, and then apply the inverse transform to the calculated `itemTransform` that I linked above.
so... I got it working, but ...let's just say I'm going to want a _ton_ of eyes on a PR I'll write up.

![test](https://github.com/pyqtgraph/pyqtgraph/assets/646398/63fa8fea-3de0-457b-93a2-aba18969258d)

What I do is I actually shift the x and y data of the curve item so that the curve is centered about (0, 0).  I compute what the transform is to make that happen, and I add that transform into the series of transforms that the QPainter is set to, so that the curve is placed in the correct position.

I'll submit a draft PR in a bit...


Resolving patch:
diff --git a/pyqtgraph/exporters/SVGExporter.py b/pyqtgraph/exporters/SVGExporter.py
--- a/pyqtgraph/exporters/SVGExporter.py
+++ b/pyqtgraph/exporters/SVGExporter.py
@@ -6,7 +6,7 @@
 
 import numpy as np
 
-from .. import PlotCurveItem, ScatterPlotItem, debug
+from .. import debug
 from .. import functions as fn
 from ..parametertree import Parameter
 from ..Qt import QtCore, QtGui, QtSvg, QtWidgets
@@ -218,35 +218,6 @@ def _generateItemSvg(item, nodes=None, root=None, options=None):
     else:
         childs = item.childItems()
 
-        dx = dy = 0.
-        sx = sy = 1.    
-
-        if isinstance(item, PlotCurveItem):
-            # Workaround for lack of precision in SVG numbers
-            # We shift curves to be centered about (0, 0) and scaled such that
-            # they fit within the region of float32 values that we can 
-            # distinguish between similar but different values
-            rect = item.viewRect()
-            x_range = rect.right() - rect.left()
-            dx =  rect.left() + (x_range / 2)
-
-            y_range = rect.top() - rect.bottom()
-            dy = rect.bottom() + y_range / 2 
-
-            sx = 1 / abs(x_range)
-            sy = 1 / abs(y_range)
-
-            item.blockSignals(True)
-
-            xDataOriginal = item.xData
-            yDataOriginal = item.yData
-            # use deepcopy of data to not mess with other references...
-            item.setData(
-                (xDataOriginal.copy() - dx) * sx, (yDataOriginal.copy() - dy) * sy
-            )
-            item.blockSignals(False)
-        
-        manipulate = QtGui.QTransform(1 / sx, 0, 0, 1 / sy, dx, dy)
         tr = itemTransform(item, item.scene())
         # offset to corner of root item
         if isinstance(root, QtWidgets.QGraphicsScene):
@@ -261,7 +232,8 @@ def _generateItemSvg(item, nodes=None, root=None, options=None):
         else:
             resize_x = resize_y = 1
         tr2 = QtGui.QTransform(resize_x, 0, 0, resize_y, -rootPos.x(), -rootPos.y())
-        tr = manipulate * tr * tr2
+        tr = tr * tr2
+        # tr = manipulate * tr * tr2
 
         arr = QtCore.QByteArray()
         buf = QtCore.QBuffer(arr)


Test patch: