klayout icon indicating copy to clipboard operation
klayout copied to clipboard

numpy.int64 is not seen as int

Open olcc opened this issue 6 years ago • 8 comments

Hello, Operations with the numpy module sometimes return integers of type numpy.int64. These integers are not accepted by some KLayout functions, for example pya.Trans(). It would be nice if such integers could be accepted. Olivier (KLayout 0.25.8, Debian Linux)

olcc avatar Mar 19 '19 20:03 olcc

Hi Olivier,

I'm relying on the Python C API - I guess this does something like "int(...)" would do. Are you implying that "int(...)" works on a numpy.int64 while KLayout doesn't?

Matthias

klayoutmatthias avatar Mar 21 '19 00:03 klayoutmatthias

An example that illustrates my comment is the following:

import pya
import numpy

a = 1                                 # a = int(1)
pya.Trans(a, 0)       # works

b = (numpy.ones(3)).astype(int)[0]    # b = numpy.int64(1)
pya.Trans(int(b), 0)  # works
pya.Trans(b,0)        # fails!

It appears that astype(int) does not return an int but a numpy.int64 (at least on my Linux system). And it appears that the Klayout functions only accept the int integers. I thinks that the second type casting int(b) is ugly and should not be needed, but I don't know how it can be avoided and which program should be responsible of this.

olcc avatar Mar 21 '19 00:03 olcc

May be this helps:

>>> import numpy

>>> b = (numpy.ones(3)).astype(int)[0]
>>> type(b)
numpy.int32

>>> c = (numpy.ones(3)).astype(int).tolist()[0]
>>> type(c)
int

dimapu avatar Mar 21 '19 07:03 dimapu

Ah, on your system you have int32, while I have int64 on mine. Your trick of creating a list indeed works, but it uses memory unnecessarily.

olcc avatar Mar 21 '19 11:03 olcc

One particularly dangerous behavior is this one:

> pya.Trans(numpy.int64(1), 1)
No overload with matching arguments in Trans.new    # an error is triggered

> pya.Trans(1, numpy.int64(1))      
m45 0,0                 # no error triggered, but the values are changed to 0

olcc avatar May 04 '19 14:05 olcc

Hi olcc,

the whole thing is actually difficult to fix ... type deduction isn't straightforward. The two-argument overload is actually Trans(rotation_in_units_of_90_degree, mirror_flag). The first argument is an int, the second a boolean. Python gives me ways to check whether an object is an int (numpy.int64 isn't, because it's not a known type built into Python) and another way to get the boolean value of any object (supported by every object). That's why the first form fails and the second one evaluates to Trans(1, false) which is m45 (90 degree rotation after mirror at x axis is a mirror at the 45 degree axis).

I can't check for numpy types because as Python itself, these classes aren't known to me inside the code. All I could do is to ask these types to convert them into int (like "int(numpy.int64(1))"). But this creates an ambiguity between float and int as almost all scalar numeric types are convertible to double and int.

Bottom line is that Python itself does not give me the tools to implement this consistently and without introducing side effects in other places.

Matthias

klayoutmatthias avatar Jul 24 '19 19:07 klayoutmatthias

Did you consider b.item() when bis a numpy object? it returns a python builtin ìnt or float, depending on the type of b (numpy.int* or numpy.float*).

olcc avatar Jul 24 '19 21:07 olcc

Hello,

I faced the same problem again when wanting to create a pya.Box() with numpy.int64 coordinates... Such type comes very soon when working with numpy arrays.

As said in the previous message, if Klayout knows that some variable b is a numpy scalar, the base type can be obtained with b.item(). In the meantime, I will use type casting with int(...), a.tolist() or b.item() where necessary.

Best regards, Olivier (with Klayout 0.26.2 on Debian Linux)

olcc avatar Jan 26 '21 23:01 olcc