[Arjen Markus] (16 october 2020) In the Tclers' chat the other day, [Steve Blinkhorn] mentioned an [https://www.nature.com/articles/s41586-020-2649-2%|%article in Nature] on the ''numPy'' package that is used for scientific and technical calculation in [Python]. The question he posed was whether it would be an idea to build an interface to ''numPy'', so that we can use it from a Tcl program. One reason for this: ''numPy'' is a well-respected and well-known package and it would potentially make it easier for Tclers to get their work accepted. [Steve Landers] told me of the [https://github.com/aidanhs/libtclpy%|%tclpy] package that enables you to call [Python] from within Tcl and vice versa (see [Accessing Tcl and Python from one another] for more information, as there are solutions too). So, this provided me a first step towards using ''numPy'' in a Tcl program. Well, "program" is a bit of a big word, as I have not tried anything serious yet. Still, it is a useful first step to investigate how this package can be used. The preparations were simple: build the package and load it into Tcl. My Cygwin environment presented a few problems, though, as the makefile required a file `python-config` to provide the Python include files and libraries. After some experimenting I used the following command to build it: ======none gcc -o libtclpy0.3.so -shared generic/tclpy.c -I/usr/include/tcl8.6 -I/usr/include/python2.7 -ltcl8.6 -lpython2.7 -Wl,--export-all-symbols ====== and introduced a few missing macros in the source code: ======none #define PACKAGE_VERSION "0.3" #define PY_LIBFILE "libpython2.7.dll" ====== Then it was a matter of trying a few commands. Like from the documentation: ======tcl package require tclpy py eval {import numpy as np} py eval {def xx(x,y): return x+y} puts [py call xx string1 string2] ====== which diligently prints `string1string2` Defining an array in the Python interpreter is a trifle more demanding: ======tcl set a [list 4 2 3] py eval "a = np.array(\[[join $a ,]\])" ====== to convert the data in the list into the right format for Python. Now, however, the limitation: the ''tclpy'' package currently passes strings, not variables. This makes it a trifle difficult to manipulate variables on the Python whose names we pass from the Tcl side. For instance: to sort the numbers in the array we just created, this does not work: ======tcl puts [py call np.sort a] ====== Instead we need to convert the string "a" into the Python variable "a". Luckily Python does offer that possibility via the `globals()` and `locals()` function. So what we can do: ======tcl py eval {def tolist(array): var = globals().get(array); return var.tolist()} puts [py call tolist a] ====== This works also with two-dimensional arrays ======tcl set a {[[4,2,3],[1,2,3]]} py eval "z = np.array($a)" puts [py call tolist z] ====== prints: ======none {4 2 3} {1 2 3} ====== Of course, this is not very efficient - with a large array or matrix you would need to convert everything to a long string, pass it to the Python interpreter, do the computations and pass the result back. But the fact that it is so easy to do these first few steps makes it possible to think about the next steps: provide more direct transfer methods to pass large amounts of numerical data to and fro. <>Category Numerical analysis