[gdal-dev] Creating Geotiff with WriteArray in Python

Matt Fearon singlespeed10 at gmail.com
Thu Mar 20 15:14:36 EDT 2008


Thanks Chris, Steve, and Ivan. I have included comments from both of
you. Chris, thank you for the great detail of your response. However,
I still receive trouble with WriteArray and few additional things now.
Below are my errors and updated code. Any thoughts would be
appreciated.

thanks,
Matt


Traceback (most recent call last):
  File "./test.py", line 38, in <module>
    dst_ds.GetRasterBand(1).WriteArray(nxarray,0,j)
  File "/usr/lib/python2.5/site-packages/gdal.py", line 876, in WriteArray
    return gdalnumeric.BandWriteArray( self, array, xoff, yoff )
  File "/usr/lib/python2.5/site-packages/gdalnumeric.py", line 193, in
BandWriteArray
    datatype = NumericTypeCodeToGDALTypeCode( array.typecode() )
AttributeError: 'numpy.ndarray' object has no attribute 'typecode'



#! /usr/bin/env python

import pickle, array, sys, os, shutil
import gdal, gdalnumeric
from gdalconst import *
import numpy
from numpy import *


file = "china/hangzhou/processed/ALPSRP021230580/IMG-HH-ALPSRP021230580-H1.5GUA"

gd=gdal.Open(file)
array=gd.ReadAsArray()
dims = array.shape
nx=dims[1]
ny=dims[0]

nxarray=numpy.zeros(nx, dtype=float32)
cal_factor=-83.0

dst_format = 'GTiff'
dst_datatype = gdal.GDT_Float32
dst_options = ['COMPRESS=LZW']
dst_file='foo.tif'
dst_xsize = nx
dst_ysize = ny
dst_nbands = 1

driver = gdal.GetDriverByName( dst_format )
dst_ds = driver.Create(dst_file, dst_xsize, dst_ysize, dst_nbands,
dst_datatype, dst_options)


for j in range(ny):
    nxarray=array[j,:]
    nxarray = numpy.where(nxarray > 0, 10.0 * log10(pow(nxarray,2)) +
cal_factor, nxarray)
    nxarray.shape = (1,-1)
    print nxarray
    dst_ds.GetRasterBand(1).WriteArray(nxarray,0,j)




On Thu, Mar 20, 2008 at 12:52 PM, Christopher Barker
<Chris.Barker at noaa.gov> wrote:
> 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
>
>
> _______________________________________________
>  gdal-dev mailing list
>  gdal-dev at lists.osgeo.org
>  http://lists.osgeo.org/mailman/listinfo/gdal-dev
>


More information about the gdal-dev mailing list