6
$\begingroup$

In

tensor = {{
             {0.00350361663652802, 0.001969775251872901}, 
             {0.00182446396280031, 0.001170563161973650}
            },{
             {0.00293044432963058, 0.0011301989150090416}, 
             {0.00200206664944458, 0.0045369413588220095}
         }}

Out

numpyArray =  array([[
             [0.00350361663652802, 0.001969775251872901], 
             [0.00182446396280031, 0.001170563161973650]
            ],[
             [0.00293044432963058, 0.0011301989150090416], 
             [0.00200206664944458, 0.0045369413588220095]
         ]])

I want to export the above (2,2,2) tensor out of Mathematica into python and convert it into a numpy array.

Edit: I actually want to export ten thousand (20, 288, 288) tensors. The above one is a minimalist example.

$\endgroup$
  • 1
    $\begingroup$ Does it work for you: StringTemplate["`` = array(``)"][HoldForm[tensor], ExportString[tensor, "RawJSON", "Compact" -> True]]? $\endgroup$ – Kuba Jan 15 '18 at 8:02
  • $\begingroup$ @Kuba yes it works, but it takes 1.7 seconds per (20,288,288) tensor. But it allows me to save the tensor as a python program. $\endgroup$ – Conor Cosnett Jan 15 '18 at 12:54
  • 1
    $\begingroup$ Wow, on my machine it takes even more for 100x smaller one ;p Yes I was afraid RawJSON is to high level. $\endgroup$ – Kuba Jan 16 '18 at 7:20
10
$\begingroup$

.fits method


One possible way is to use the .fits format...

Export["~/Dropbox/tensor.fits", tensor]

enter image description here

from astropy.io import fits
hdul= fits.open("/home/cosnett/Dropbox/tensor.fits")
np.array([hdul[i].data for i in range(1)])

.hdf5 method

as suggested below

Export["~/Dropbox/planet.hdf5", tensor, "HDF5"]

enter image description here

from numpy import *
import h5py
filename = '/home/conor/Dropbox/planet.hdf5'

def import_hdf5(file):
    f = h5py.File(filename, 'r')
    a_group_key = list(f.keys())[0]
    data = list(f[a_group_key])
    return array(data)

import_hdf5(filename)
$\endgroup$
  • 3
    $\begingroup$ I would also suggest to try one of the formats designed for such data. An alternative which I think is also supported by both Mathematica and python would be hdf5... $\endgroup$ – Albert Retey Jan 15 '18 at 8:13
5
$\begingroup$

For your simple case, I'm sure it is faster to create it by hand. However, in the general case you can use something related to a visitor pattern. What it does is that it inspects expressions and handles specific cases differently. In your situation, you only need to take care that lists are converted and numbers are converted and maybe a highlevel case to create your array:

SetAttributes[toPyArray, {HoldFirst}];
toPyArray[s_Symbol /; Head[s] === List] := With[
  {name = SymbolName[Unevaluated[s]]},
    StringJoin[name, " = np.array(", toPy[s], ")"]
];

toPy[l_List] := StringJoin["[", StringRiffle[toPy /@ l, ", "], "]"];
toPy[n_?NumericQ] := ToString[N[n]];

toPyArray[tensor]
(* "tensor = array([[[0.00350362, 0.00196978], [0.00182446, 
0.00117056]], [[0.00293044, 0.0011302], [0.00200207, 0.00453694]]])" *)

This string can simply be exported as text and hopefully re-imported into Python.

$\endgroup$
  • 1
    $\begingroup$ using this method, one can turn data directly into a python program and run it. Export["~/Dropbox/plan001.py", "import numpy as np \n"~~toPyArray[tensor], "String"] $\endgroup$ – Conor Cosnett Jan 15 '18 at 12:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.