0

Say I have a one-dimensional array of size NxN in C which I think of as a two-dimensional array, i.e. every N entries, a new row begins.

I would like to visualise this array by laying it onto a plane and then treating every entry as the height of the array above the plane, thereby creating a surface.

How would I go about transferring the data from C to Python in such a way that Python can read it in as a two-dimensional array and then plot it in three dimensions?


Update

Writing the data to a CSV file, as suggested in barny's answer and by joao in the comments, worked well:

FILE *datafile = fopen("data.csv", "w");
for(int i = 0; i < N; i++) {
    for(int j = 0; j < N; j++) {
        fprintf(datafile, "%g, ", data[i * N + j]);
    }
    fprintf(datafile, "\n");
}

Reading it into a list in python was easy too:

import csv
data = list(csv.reader(open("data.csv")))

Unfortunately, outputting this data into a surface plot is causing problems. My python script reads

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

import csv
data = list(csv.reader(open("data.csv")))

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = y = np.arange(0, 1, 1.0/len(data))
X, Y = np.meshgrid(x, y)
data = np.array(data).reshape(Y.size,X.size)

ax.plot_surface(X, Y, data)

plt.show

If I try to run it, I get an error on line 12 (data = np.array(data).reshape(Y.size,X.size) ) saying ValueError: total size of new array must be unchanged. I tried np.sqrt(len(data)) instead of len(data) as well 256which happens to be the value of N in my case. However, the error persisted in every case.


Update 2

What finally worked for me was the suggestion by Emilie to simply write the C array out linearly, i.e.

FILE *datafile = fopen("data.dat", "w");
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++) {
    fwrite(&array[i * N + j], sizeof(double), 1, datafile);
}

and then read it in via

data = np.fromfile('data.dat', dtype=float, count=-1, sep='')

in Python followed by

array = data.reshape((np.sqrt(len(data)), np.sqrt(len(data))))

to give the array its required shape. (Note: This step will likely cause problems if your array length is not a square number.)

The complete working plotting script is

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

data = np.fromfile('data.dat', dtype=float, count=-1, sep='')

array = data.reshape((np.sqrt(len(data)), np.sqrt(len(data))))

fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
x = y = np.arange(0, 1, 1.0/np.sqrt(len(data)))
X, Y = np.meshgrid(x, y)
array = np.array(data)

ax.plot_surface(X, Y, array)

plt.show()
9
  • The question is quite vague, but here is one option - in your C program save the array into a csv file (xml, json, or whatever open format you prefer). In your python code read the file and then plot it. Commented Nov 26, 2015 at 14:52
  • "transferring the data from C to Python" -- you likely have some constraints here that are not explicit. Can you just write the values to a file in C and read them back in python? Commented Nov 26, 2015 at 14:55
  • @BrianCain Not really. I actually thought about including in my question that writing the data into a file and reading it back in python would be the preferred method. Commented Nov 26, 2015 at 14:57
  • @Casimir, yes, far and away it's the simplest IMO. There's some simple text formats like json that python handles well. Otherwise you can write integers or floats in your machine's representation and read them back into python using the struct module. Commented Nov 26, 2015 at 15:00
  • Also swig (swig.org) can be used to interface python and C/C++ modules, bit the file approach is surely simpler. Commented Nov 26, 2015 at 15:01

2 Answers 2

1

The reshape error yields because when you read the csv, your data is already a list of lists, which you can simply transform to a numpy array with np.array(data).

For instance if I have this file:

/tmp$ cat foo.csv 
1,2,3
4,5,6

I can do:

>>> import csv
>>> data = list(csv.reader(open("foo.csv")))
>>> data
[['1', '2', '3'], ['4', '5', '6']]
>>> import numpy as np
>>> np.array(data)
array([['1', '2', '3'],
       ['4', '5', '6']], 
      dtype='|S1')

Depending on what you want to do with this numpy array, you may also need to change the types of the elements. You could also write your data linearly and then use np.reshape. I'm not sure csv is the most elegant way of doing this, but probably a simple solution.

Sign up to request clarification or add additional context in comments.

2 Comments

I'll look into np.reshape. However, I don' think it is correctly shaped. If I remove .reshape(Y.size,X.size), I get an error on line 14, i.e. where I write the plot command, saying ValueError: shape mismatch: two or more arrays have incompatible dimensions on axis 1..
Wow! Writing the array out linearly and using numpy.reshape worked immediately. I'm a beginner with python and didn't know about this. Thanks for the tip.
0

You could print the data as a python expression like this:

printf( "data2d = [\n" );
for ( y = 0; y < N ; y++ ) {
    printf( "  [" );
    for ( x = 0 ; x < n ; x++ ) {
        printf( " %d,", datalist[y*N+x] );
    }
    printf( " ],\n" );
}
printf( "]\n" );

Haven't tested this, while since I did any C, but it will be something like that.

(I don't think the trailing commas will matter - if they do, don't print them on the last entries of each row)

Or, perhaps easier, print it as a plain csv file - each line a row of the array with , between the values, then use the csv module to read it.

HTH Barny

1 Comment

This is way too hackish, code and data should be separated if possible, here they clearly can be.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.