I'm working on a generative art generator library for python called Samila based on the matplotlib scatter plot. It gets two functions and maps a square space into a arbitrary shape. We want the generated shape to be the same for given functions and given random seed in order to be reproducible.
Recently we were working on functions with complex values and notified that scatter plot output is not the same in different versions on matplotlib.
I wanted to know why is it like this and what's the problem with matplotlib. If this is a bug it could be horrible for matplotlib to plot different figures for a specific code in its different versions.
What you have left out is that both versions return:
ComplexWarning: Casting complex values to real discards the imaginary part
offsets = np.asanyarray(offsets, float)
Please cast data1 and data2 to float as you see fit - scatter cannot handle complex values, and passing them is undefined. Clearly some details of where in the plotting chain the bad values are dealt with has changed, but I don't feel it is worth chasing down for poorly formed inputs.
Observation: I can get both versions of your plot (more or less) out of the same version of matplotlib by rewriting the math using numpy (which is both clearer and more performant):
Your data-generating functions have a bunch of numerical issues (which numpy warns about but math silently ignores). I doubt this has anything to do with a change in the drawing logic of matplotlib per se, but maybe a change in the way that invalid/complex pure-python (i.e. not numpy) dytpes are handled?
What you have left out is that both versions return:
ComplexWarning: Casting complex values to real discards the imaginary part
offsets = np.asanyarray(offsets, float)
Please cast data1 and data2 to float as you see fit - scatter cannot handle complex values, and passing them is undefined. Clearly some details of where in the plotting chain the bad values are dealt with has changed, but I don't feel it is worth chasing down for poorly formed inputs.
I don't think that's the issue. I try casting the data before plotting by np.real and float like bellow:
@sadrasabouri please indicate if the current version of Matplotlib has a bug, preferably with a minimal example that demonstrates the issue, and explicitly says what you expect is correct result.
I'm also not clear why you are double casting above.
Matplotlib changes its plotting strategy from 3.0.3 which ignores points with negative radius to 3.4.3 in which they're plotted.
I couldn't find this using compare release notes and it was so confusing for me. Hope there will be an warning for this situation avoiding future issues. (I can work on this if you think it's a bug)
Ah OK, that makes sense. Thanks for digging up the minimal example!
This project predates GitHub, let alone release notes, so you will have to read the documentation which have API changes. I'm not 100% sure when this came in.
@QuLogic right, but think something must have happened with the axes limits as well. Probably #13980.
I think the current behaviour is desired, and we have explained the difference in versions, so lets close this. @sadrasabouri if you need deterministic behaviour between versions, I think setting the r-limits explicitly is your best bet. Thanks....
Activity
jklymak commented on Oct 28, 2021
What you have left out is that both versions return:
Please cast data1 and data2 to float as you see fit - scatter cannot handle complex values, and passing them is undefined. Clearly some details of where in the plotting chain the bad values are dealt with has changed, but I don't feel it is worth chasing down for poorly formed inputs.
mwaskom commented on Oct 28, 2021
Observation: I can get both versions of your plot (more or less) out of the same version of matplotlib by rewriting the math using numpy (which is both clearer and more performant):
Your data-generating functions have a bunch of numerical issues (which numpy warns about but math silently ignores). I doubt this has anything to do with a change in the drawing logic of matplotlib per se, but maybe a change in the way that invalid/complex pure-python (i.e. not numpy) dytpes are handled?
sadrasabouri commented on Oct 28, 2021
I don't think that's the issue. I try casting the data before plotting by np.real and float like bellow:
unfortunately no difference.
jklymak commented on Oct 28, 2021
@sadrasabouri please indicate if the current version of Matplotlib has a bug, preferably with a minimal example that demonstrates the issue, and explicitly says what you expect is correct result.
I'm also not clear why you are double casting above.
sadrasabouri commented on Oct 28, 2021
Minimal Example Saved Me 😄
Matplotlib changes its plotting strategy from 3.0.3 which ignores points with negative radius to 3.4.3 in which they're plotted.
I couldn't find this using compare release notes and it was so confusing for me. Hope there will be an warning for this situation avoiding future issues. (I can work on this if you think it's a bug)
data1 = [-2, -5, 2, 2] data2 = [-2, 2, -2, 2] fig = plt.figure() ax = fig.add_subplot(111, projection="polar") ax.scatter( data2, data1, s=30) plt.show()in matplotlib.__version__ == 3.0.3 we got:
while in matplotlib.__version__ == 3.4.3:
jklymak commented on Oct 28, 2021
Ah OK, that makes sense. Thanks for digging up the minimal example!
This project predates GitHub, let alone release notes, so you will have to read the documentation which have API changes. I'm not 100% sure when this came in.
QuLogic commented on Oct 29, 2021
That was #4699, added in 2.1.0.
jklymak commented on Oct 29, 2021
@QuLogic right, but think something must have happened with the axes limits as well. Probably #13980.
I think the current behaviour is desired, and we have explained the difference in versions, so lets close this. @sadrasabouri if you need deterministic behaviour between versions, I think setting the r-limits explicitly is your best bet. Thanks....