0

I would like to save a matrix to a file in python and retain the matrix structure in the output file.

For example:

#Program to test the output of an array to a file 
import numpy as np
from mpmath import mp,mpf,matrix
# Set precision to 32 digits
mp.dps=32

#Define array
out=matrix(3,2)
for j in range(3):
    out[j,0]=mpf(j+1)*mpf('1.73')
    out[j,1]=mp.sin(mpf(j))

filout="test_out.txt"
np.savetxt(filout,out,fmt='%32s')

What I get is:

                               1.73
                                0.0
                               3.46
  0.8414709848078965066525023216303
                               5.19
 0.90929742682568169539601986591174

But, what I would like is:

                       1.73                                0.0
                       3.46  0.8414709848078965066525023216303
                       5.19 0.90929742682568169539601986591174

Has anyone an idea how to do this (I've tried various ways to preserve the matrix structure to no avail)?

Sid
  • 2,174
  • 1
  • 13
  • 29

3 Answers3

0

I believe it’s because you are using mpmath‘s matrix function to create the initial matrix. It appears that matrix shape is not correctly being processed/passed to np.savetxt. Is there a reason mpmath is needed? I.e. can you use numpy functionality to do the same?

I find it best to never mix these kind of modules where possible - as it leads to these kinds of headaches.

If you can get away with using purely numpy functionality, then you could, in this case, make use np.zeros to create the initial matrix. E.g.

import numpy
output_matrix = np.zeros([3,2])
.
.
np.savetxt(filout, output_matrix, fmt='%32s')

If however you do need mpmath, I would look to see if there an mpmath method for saving a matrix to a text file and avoid invoking numpy (I briefly looked and couldn’t see one).

If one is not available, and you must make use of mpmath, then it appear that your only other option is to first convert your mpmath matrix to an np.matrix (ensuing you retain the shape - this will likely involve two separate steps, see How to properly cast mpmath matrix to numpy ndarray ( and mpmath.mpf to float) for the first), and then apply np.savetxt to this new object.

Hashbang
  • 1
  • 1
  • Hashbang: Thanks very much for this advice - I'll follow up on it. I do need mpmath extended precision (perhaps even more than 32 digits). – user22383881 Aug 14 '23 at 13:58
0

Thanks, again, to those who answered. In the meantime, after various additional attempts, I have found an answer (there may be others). The problem, I guess, and as was noted, is in mixing modules (mpmath matrix from mpmath and np.savetxt from numpy).

    # Program to test the output of an array to a file 
    #
    import numpy as np
    from mpmath import mp,mpf
    #
    # Set precision to 32 digits
    mp.dps=32
    #
    # Define array as a list with elements having dynamic dimension
    out=[[] for i in range(3)]
    #
    # Define "columns"
    for j in range(3):
      out[j]=[mpf(j+1)*mpf('1.73'),mp.sin(mpf(j))]
    #
    print(out)
    #
    # Save to text file
    filout="test_out.txt"
    np.savetxt(filout,out,fmt='%35s')
    #

Instead of defining the matrix, "out", using out=matrix(3,2), I now define it as a list with elements having dynamic dimension, interpreted as a column dimension. Thus, in the code, the list is used as a matrix with 3 rows and an unspecified number of columns. Then, in the for loop, the columns are defined for each row. Printing the "list" on the console gives just a list of unformatted elements:

[[mpf('1.7300000000000000000000000000000004'), mpf('0.0')], [mpf('3.4600000000000000000000000000000007'), mpf('0.84147098480789650665250232163029915')], [mpf('5.189999999999999999999999999999998'), mpf('0.90929742682568169539601986591174468')]]

But, the saved text file is just what I need:

                           1.73                                 0.0
                           3.46   0.8414709848078965066525023216303
                           5.19  0.90929742682568169539601986591174

(I don't know why it works this way, but I'm glad it does.)

-2
import numpy as np
from mpmath import mp, matrix

# Set precision to 32 digits
mp.dps = 32

# Create a 3x2 matrix and populate with values
out = matrix(3, 2)
for j in range(3):
    out[j, 0] = (j + 1) * 1.73
    out[j, 1] = mp.sin(j)

np.savetxt("test_out.txt", out, fmt='%32.30f', delimiter=' ')

The key here is to set the correct format (fmt='%32.30f') when saving, and to separate columns using a space (delimiter=' ').

  • biscuit_delicious: Thanks very much. Unfortunately it does not work - I still get just a single column of values. Also, I do need to use the mpf function and string formatting since otherwise matrix "out" will deliver only float precision with garbage appended to get the full 32 digits. – user22383881 Aug 14 '23 at 14:02