1

These are the operations I am doing in my code:

  1. reading an existing raster (tif)
  2. creating a in memory raster object
  3. reading the existing raster object in chunk as array
  4. making some calculations
  5. writing the array to my in memory object

What I want to do now is, with the in memory raster object ready to be used, feed it to gdal warp, which should also output an intermediate raster object that I'll be use afterwards.

However, when I try to GetRasterBand() out of this latter raster object, I receive an error because it is actually equal to None:

AttributeError: 'NoneType' object has no attribute 'GetRasterBand'

I am pretty sure it is about saving/updating/flushing the status of the raster object after the calculations but I could not find out if this is the actual problem.

How can I use in memory (intermediate) files in my script?

from osgeo import gdal, gdalconst
import numpy as np

in_raster = gdal.Open(r'/my/raster.tif', gdalconst.GA_ReadOnly)
in_b = in_r.GetRasterBand(1)

b1 = in_raster.GetRasterBand(1)
xsize = b1.XSize
ysize = b1.YSize
step = 10  # THIS IS THE CHUNK SIZE!
ystep = ysize / step
ystep = int(ystep)
yresidual = ysize - (ystep * step)

driver = gdal.GetDriverByName("MEM")
temp_calc = driver.Create('',
                          xsize,
                          ysize,
                          1,
                          gdal.GDT_Float32)

temp_b = temp_calc.GetRasterBand(1)

for i in range(step):
    if i != step-1:
        arr_part = in_b.ReadAsArray(
            0, ystep * i, xsize, ystep).astype('float32')

        data = np.nan_to_num(arr_part)

        temp_b.WriteArray(data, 0, ystep * i)
    else:
        arr_part = in_b.ReadAsArray(
            0, ystep * i, xsize, ystep + yresidual).astype('float32')

        # replace nan with zeros
        # https://docs.scipy.org/doc/numpy/reference/generated/numpy.nan_to_num.html
        data = np.nan_to_num(arr_part)

        # write array chunk to (in memory) file
        # https://gdal.org/python/osgeo.gdal.Band-class.html#WriteArray
        temp_b.WriteArray(data, 0, ystep * i)

# get raster resolution
in_gt = in_raster.GetGeoTransform()
in_x = in_gt[1]
in_y = -in_gt[5]

kwargs = {'xRes': in_x,
          'yRes': in_y,
          'targetAlignedPixels': True,
          'resampleAlg': 'average',
          'format': 'MEM'
          }

ds = gdal.Warp('',
               temp_calc,
               **kwargs)
b1 = ds.GetRasterBand(1)
# ds is None and the above line throws the exception
2
  • Just a thought here. What happens if you give a filename as the first argument of gdal.Warp() instead of an empty string? Commented Feb 21, 2020 at 16:11
  • @MarceloVilla Sorry for the late reply. It was probably a problem of CRS. I used CreateCopy() instead of just Create() to make a copy of in_raster and work directoy on it and it worked. I'll post the solution as soon as I can.
    – umbe1987
    Commented Feb 24, 2020 at 9:48

1 Answer 1

0

Not sure if the problem was the wrong CRS when I created the raster object in memory (step 2 of my question), but using CreateCopy() instead of Create() to create a new raster object which is a copy of the input existing raster seems to have solved my problem.

temp_calc = driver.Create('',
                          xsize,
                          ysize,
                          1,
                          gdal.GDT_Float32)

has changed to

temp_calc = driver.CreateCopy(r'/my/copy.tif', in_raster)

The rest of the code is pretty much the same.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.