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$
3
  • 2
    $\begingroup$ Does it work for you: StringTemplate["`` = array(``)"][HoldForm[tensor], ExportString[tensor, "RawJSON", "Compact" -> True]]? $\endgroup$ Commented Jan 15, 2018 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$ Commented Jan 15, 2018 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$ Commented Jan 16, 2018 at 7:20

2 Answers 2

14
$\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

# source file
filename = '/home/conor/Dropbox/planet.hdf5'

def import_hdf5(filename):
    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$
1
  • 4
    $\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$ Commented Jan 15, 2018 at 8:13
6
$\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
  • 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$ Commented Jan 15, 2018 at 12:59

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.