[gdal-dev] Creating Geotiff with WriteArray in Python

Christopher Barker Chris.Barker at noaa.gov
Thu Mar 20 12:52:41 EDT 2008


Matt Fearon wrote:
> The problem is related to the line
> "dst_ds.GetRasterBand(1).WriteArray(nxarray,0,j)" - I am trying to
> write an imported integer array(y,x) , 13700x13300, to a tif file row
> by row 

> BandWriteArray
>     xsize = array.shape[1]
> IndexError: tuple index out of range

It looks like RasterBand.WriteArray is expecting a 2-d array, and you 
are passing in a 1-d array. This makes sense as you are trying to pass 
in a single row. Do  you need to do it row by row due to memory limitations?

> import Numeric

> import numpy

which version of GDAL are you using? if you use 1.5, you can just use 
numpy, rather than both Numeric and numpy.

> from math import *

Just so you know both Numeric an numpy are essentially supersets of 
math, so you usually don't need the math module. Also, as math and 
Numeric have a lot of overlapping symbols, you generally don't want to 
"import *" both of them

> nxarray=zeros(nx,Float)

> dst_datatype = gdal.GDT_Float32

Another issue here -- I think Numeric.Float is a 64bit float (C double), 
same as the built-in python float. If you want a Float32 array, you need 
something else. In numpy, it's "float32", in Numeric, it's "Float32".

> for j in range(0,ny-1):
>   for i in range(0,nx-1):

I think you want "range(ny)" here:

 >>> range(4)
[0, 1, 2, 3]

There is also room to "vectorize" this operation -- you should be able 
to process a whole row at once, and only loop through y, but not x -- 
that will speed things up a lot (see below). If you have enough memory, 
you could process the whole thing at once with numpy operations -- 
that's the whole point of numpy(and Numeric).

>     nxarray[i]=0.0
>     tmp = array[j,i] * 1.0

why multiply by 1.0 here? that shouldn't do anything.

>     if (tmp > 0):
>       nxarray[i] = 10.0 * log10(pow(tmp,2)) + cal_factor
> 
>   dst_ds.GetRasterBand(1).WriteArray(nxarray,0,j)

Here's the issue. If I have this right, WriteArray is expecting a 2-d 
array, and writing to the RasterBand at the given offsets. So what you 
need to do is convert your (nx,) array to a (nx,1) array, and it should 
work:

nxarray.shape = (-1,1)

This tells Numeric or numpy to set the second dimension to 1, and the 
first to whatever it needs to be to fit. (that could be (nx, 1), but I 
like to be generic when I can.

Now you can call WriteRaster:

dst_ds.GetRasterBand(1).WriteArray(nxarray,0,j)

Also:

dst_ds = None

I think that will delete your destination raster -- has it been written 
to file yet?

Here is my (untested) suggestion to eliminating a loop:

for j in range(ny): # loop though the rows
     nxarray=array[j,:] # note - this is a view into your original array
     nxarray = numpy.where(nxarray > 0,
                           10.0 * log10(pow(tmp,2)) + cal_factor,
                           nxarray)
    nxarray.shape = (-1, 1)
    dst_ds.GetRasterBand(1).WriteArray(nxarray,0,j)


Hope that helps.

-Chris

-- 
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris.Barker at noaa.gov


More information about the gdal-dev mailing list