-
-
Notifications
You must be signed in to change notification settings - Fork 122
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
Feature coordinates accept numpy float64 but float32 is "not a JSON compliant number" #173
Comments
I've been staring at this behavior for a bit. I would like to take this on. However, this is my first time tackling an issue. At the very minimum, I would like to advance the conversation around whether what @60south saw was expected behavior and is compliant with RFC 7946. |
Thanks @trcmohitmandokhot In defense of the GeoJSON module, the problem appears related to the cpython 'isinstance' function which is used on line 50 of the GeoJSON geometry.py function. Specifically, there is an inconsistency in how isinstance() treats numpy floats:
returns True, even though it's actually of type <class 'numpy.float64'>, not 'float', whereas:
returns False. Ditto for isinstance(np.float128(1), float), which should also be True. I'm too new at this to say whether this is a problem with isinstance() or the numpy implementation of floats, or not really a problem at all and I'm just a whiner, but it does seem kinda bogus: a float is a float, we're just dickering over precision. It would be easy enough to import numpy into GeoJSON and test for those types, but then that adds numpy as a dependency to GeoJSON which it shouldn't need. Ugh. The best suggestion I have is to use the numbers module, i.e., instead of:
do this:
If a Decimal is a Number, then the statement could be shortened even further. I'm sure someone with more knowledge than I will shred this idea, but it's the best I got. thanx. |
@60south. |
There appear to be some previous interesting numpy issues, which also relate to this dtype inconsistency topic. I am attaching links here for some side-reading. |
Thanks for reporting this, @60south. In section 3.1.1 of RFC 7946 it says (emphasis added):
This implies that checking that the coordinates are decimal numbers is the intended behavior for this logic. @trcmohitmandokhot I encourage you to submit a PR to resolve this bug, which I'd be happy to review. Here are some breadcrumbs:
|
Thank you for the guidance. I will take this up. |
One other note on the proposed solution, @trcmohitmandokhot. It uses numpy. We would rather not add numpy as a dependency. Let's try to find a way to fix it without numpy. |
@rayrrr, thanks. I agree that numpy should not be a dependency. Rather, we need an expansive, holistic solution where any Real floating point number passes the test, as it should. I am cautious about equating the traditional RFC 7946 definition of decimal (i.e., not a fraction) with the python Decimal class, since I don't think they mean the same thing. In fact, looking at the Decimal class definition, I see they actually warn against treating Decimals as Real numbers:
That shouldn't preclude their use as coordinates, of course. After some further testing, it looks like any numpy.floatXX, numpy.intXX, and numpy.uintXX, etc., do pass the isinstance(x, numbers.Real) test, so they apparently inherit from the Numbers abstract base class, but not the Decimal class. Complex numbers fail the isinstance() test, as they should. Seems like: Regardless, I'm very happy to see this issue getting some attention! |
I agree with @60south's and @rayrrr's analysis and suggestions. PEP 3141 lays out a really nice Type Hierarchy for Numbers, where
Results of testing are tabulated below.
|
Fix included in version 3.0.0 |
Hi. I'm new to GeoJSON and still learning Python.
I'm reading in coordinate data from various sources. Some arrives as numpy float32 type. Attempting to create a geojson point or polygon using float64 works fine, while float32 produces an error: "ValueError: 1.0 is not a JSON compliant number" (see example below).
The error is very confusing, and it took a long time to figure out what it was complaining about. It's easy enough to convert, but any floating point number should be valid. Thanks.
The text was updated successfully, but these errors were encountered: