Gilfoyle
Gilfoyle

Reputation: 3616

Gnuplot: Reshape Array from Data File to Matrix

I have a program which saves a matrix of size m x n as an array of length L (where L = m x n) in a file.

Example for m = n = 2: The file contains the following numbers (in case of only one matrix in the file):

1
2
3
4

which represents a 2 x 2 matrix:

1 2
3 4

The file contains many matrices. I want to be able to plot specific matrices of this file using the ::start_position::end_position command and converting the array of length L into an m x n matrix such that I can use the command matrix nonuniform.

How can I do that?

Upvotes: 1

Views: 592

Answers (2)

theozh
theozh

Reputation: 25704

Here is a simple gnuplot-only and platform-independent solution without external tools. However, you don't write in your question how or if your "arrays" are separated in your input file. As long as there is no separation line or just a single empty line between the matrices you can use the script below. If you have double empty lines, it needs to be adapted.

Data: SO45225079.dat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Script:

### reshape a single column file to a matrix file
reset session

FILE = "SO45225079.dat"
MAT  = "SO45225079.matrix"

m = 2
n = 3

set print MAT
    mat = ''
    stats FILE u (mat = mat.sprintf(" % 4g",$1).\
          (int($0)%n==n-1? "\n" : "").(int($0)%(m*n)==(m*n-1)?"\n\n":"")) nooutput
    print mat
set print

set tics out
set cbrange[0:25]

set multiplot layout 2,2
    do for [i=0:3] {
        set title sprintf("Matrix %d",i)
        plot MAT matrix index i w image
    }
unset multiplot
### end of script

Result:

SO45225079.matrix

    1    2    3
    4    5    6


    7    8    9
   10   11   12


   13   14   15
   16   17   18


   19   20   21
   22   23   24

enter image description here

Upvotes: 1

ewcz
ewcz

Reputation: 13087

I think that it will be most likely better to delegate the processing to some external tool. For example, this gawk script:

BEGIN{
    #mat_id = 2
    #m = 2
    #n = 3

    mat_size = m * n
    row_lb = ((mat_id-1) * mat_size) + 1
    row_ub = row_lb + mat_size - 1

    curr_row = 0
}

NR >= row_lb && NR <= row_ub{
    col_id = (NR - row_lb) % n
    c = (col_id == (n-1))?"\n":" "
    printf "%d%s", $1, c
}

accepts three variables: mat_id is the 1-based index of the matrix in the file, m denotes the number of rows, and n represents the number of columns. So for example with a data file test.dat as:

1
2
3
4
5
6
10
20
30
40
50
60

a call

gawk -v mat_id=2 -v m=2 -v n=3 -f filter.awk test.dat

yields indeed

10 20 30
40 50 60

In Gnuplot, you can wrap this into a command (assuming that the gawk script is in the same directory from which Gnuplot is invoked):

getMatrix(fName, matId, m, n) = \
    sprintf("<gawk -v mat_id=%d -v m=%d -v n=%d -f filter.awk %s", matId, m, n, fName)

plot getMatrix('test.dat', 2, 2, 3) ... [ rest of the plot command] ...

Upvotes: 1

Related Questions