Python GDAL – How to Loop for Creating a Multi-Page TIFF (Layer Stack)

gdalpython

So far I use python to create a layer stack for each pair of TIF files now l am looking for the solution to loop this process.

This is my code for creating a layer stack.

import os
from osgeo import gdal
imgB01Path = "E:/eyerStack/Raw2Tif_2016/tif16/2016.01.01.Smb01.tif"
imgB02Path = "E:/eyerStack/Raw2Tif_2016/tif16/2016.01.01.Smb02.tif"
outImgPath = "E:/LeyerStack2016/2016.01.01.tif"

oB01Band = gdal.Open(imgB01Path)
oB02Band = gdal.Open(imgB02Path)

gDriver = oB01Band.GetDriver()
outImg = gDriver.Create(outImgPath, oB01Band.RasterXSize,oB01Band.RasterYSize, 2, gdal.GDT_UInt16, ["PHOTOMETRIC=RGB"])

outImg.SetGCPs(tuple(oB01Band.GetGCPs()),oB01Band.GetGCPProjection()) #Set GCPs
outImg.SetGeoTransform(tuple(oB01Band.GetGeoTransform())) #Set GeoTransform
outImg.SetProjection(oB01Band.GetProjection()) #Set Projection

B01 = oB01Band.GetRasterBand(1).ReadAsArray()
B02 = oB02Band.GetRasterBand(1).ReadAsArray()

outImg.GetRasterBand(1).WriteArray(B01)
outImg.GetRasterBand(2).WriteArray(B02)

oB01Band = None #Clear Memory
oB02Band = None #Clear Memory
outImg = None #Clear Memory

The example file name of band1

2015.01.01.Smb01.tif
2015.01.09.Smb01.tif
2015.01.17.Smb01.tif
2015.01.25.Smb01.tif
2015.02.02.Smb01.tif

The example file name of band2

2015.01.01.Smb02.tif
2015.01.09.Smb02.tif
2015.01.17.Smb02.tif
2015.01.25.Smb02.tif
2015.02.02.Smb02.tif

This is the complete adapted code.

import os
from osgeo import gdal

tifFolder = r'E:/ProcessNdvi2015_2021/05LayerStack/tif/'

tifs = [os.path.join(root, file) for root, folder, files in os.walk(tifFolder) for file in files if file.endswith('tif') and 'smb' in file.lower()]
tifs.sort()
count = 0
for t1, t2 in zip(tifs[::2], tifs[1::2]):
    ##print(t1,t2)
    oB01Band = gdal.Open(tifs[count])
    oB02Band = gdal.Open(tifs[count+1])
    filename = tifs[count].split("/")[-1]
    
    outImgPath = "E:/ProcessNdvi2015_2021/05LayerStack/LayerStack2/" + filename 

    gDriver = oB01Band.GetDriver()
    outImg = gDriver.Create(outImgPath, oB01Band.RasterXSize,oB01Band.RasterYSize, 2, gdal.GDT_Int16, ["PHOTOMETRIC=RGB"])

    outImg.SetGCPs(tuple(oB01Band.GetGCPs()),oB01Band.GetGCPProjection()) #Set GCPs
    outImg.SetGeoTransform(tuple(oB01Band.GetGeoTransform())) #Set GeoTransform
    outImg.SetProjection(oB01Band.GetProjection()) #Set Projection

    B01 = oB01Band.GetRasterBand(1).ReadAsArray()
    B02 = oB02Band.GetRasterBand(1).ReadAsArray()

    outImg.GetRasterBand(1).WriteArray(B01)
    outImg.GetRasterBand(2).WriteArray(B02)

    oB01Band = None #Clear Memory
    oB02Band = None #Clear Memory
    outImg = None #Clear Memory
    count = count+2

Best Answer

I like os walk in combination with collections defaultdict list for problems like this. You can store each date as a key, and the two files as values:

import os
from collections import defaultdict

tifFolder = r'/home/bera/Desktop/GIStest/input_files/'

tifs = defaultdict(list)

for root, folders, files in os.walk(tifFolder): #Find all tif files with smb in filename in the tifFolder
    for file in files:
        if 'smb' in file.lower() and file.endswith('tif'):
            tifs[file.split('.S')[0]].append(os.path.join(root, file)) #Add the full path to the file as value and date as key to the defaultdict
           
#defaultdict(list,
            #{'2015.01.01': ['/home/bera/Desktop/GIStest/input_files/2015.01.01.Smb01.tif', '/home/bera/Desktop/GIStest/input_files/2015.01.01.Smb02.tif'],
             #'2015.01.09': ['/home/bera/Desktop/GIStest/input_files/2015.01.09.Smb01.tif', '/home/bera/Desktop/GIStest/input_files/2015.01.09.Smb02.tif'],
             #'2015.01.17': ['/home/bera/Desktop/GIStest/input_files/2015.01.17.Smb02.tif', '/home/bera/Desktop/GIStest/input_files/2015.01.17.Smb01.tif']})

for date, tiffiles in tifs.items():
    smb01, smb02 = sorted(tiffiles) #You will get ValueError here if there's missing files
    print(date)
    print(smb01)
    print(smb02)
    #oB01Band = gdal.Open(smb01)
    #oB02Band = gdal.Open(smb02)
    # ...
    

#2015.01.01
#/home/bera/Desktop/GIStest/input_files/2015.01.01.Smb01.tif
#/home/bera/Desktop/GIStest/input_files/2015.01.01.Smb02.tif

#2015.01.09
#/home/bera/Desktop/GIStest/input_files/2015.01.09.Smb01.tif
#/home/bera/Desktop/GIStest/input_files/2015.01.09.Smb02.tif

#2015.01.17
#/home/bera/Desktop/GIStest/input_files/2015.01.17.Smb01.tif
#/home/bera/Desktop/GIStest/input_files/2015.01.17.Smb02.tif

You can also try something like this, which is easier:

import os

tifFolder = r'C:\Users\jksdhfd\Desktop\Temp'

tifs = [os.path.join(root, file) for root, folder, files in os.walk(tifFolder) for file in files if file.endswith('tif') and 'smb' in file.lower()]
tifs.sort()

for t1, t2 in zip(tifs[::2], tifs[1::2]):
    print(t1, t2)