Batch composite bands using arcpy

3623
11
Jump to solution
12-21-2017 10:28 PM
BrunoDeus1
New Contributor III

Branched from: Help: Batch - composite bands Arc-python 

Hi,

I would like use this script, but it fails. Some hint?

import arcpy, os

arcpy.env.workspace = r'C:\Teste_Auto_CLEIA\Ima_compactadas'

# list all folders in a directory
folders = arcpy.ListWorkspaces("L8*", "Folder") # Inside main directory, already have other folders, but the bands are always inside folders that begin with "L8", e.g. "L8227069".

#The output files place
outws = r'C:\Teste_Auto_CLEIA\Imagem' # Line 9

for folder in folders:
    arcpy.env.workspace = folder
    rasters = arcpy.ListRasters("*.tif") # I already erased the bands which I won't use
    chk4 = ['band{0}.tif'.format(i) for i in range(0, 7)] # I changed the range
    rasters = [a for a in rasters if a[-9:] in chk4]
    name = os.path.join(outws, rasters[1].split("_")[0] + ".tif") # I wrote "outws"
    arcpy.CompositeBands_management(rasters, name) # I put it
    print(rasters)

I'm using ArcMap 10.1 and the bands names aren't the same, for instance, "LO82270682017183CUB00_B1", ... , "LO82270682017183CUB00_B7".

Thanks!

0 Kudos
1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

Can you try this?

import arcpy, os

arcpy.env.workspace = r'C:\Teste_Auto_CLEIA\Ima_compactadas'

# list all folders in a directory
folders = arcpy.ListWorkspaces("L8*", "Folder") # Inside main directory, already have other folders, but the bands are always inside folders that begin with "L8", e.g. "L8227069".
print "folders: "+str(folders) #To see if the search above finds a result

#The output files place
outws = r'C:\Teste_Auto_CLEIA\Imagem' # Line 10

for folder in folders:
    arcpy.env.workspace = folder
    images = arcpy.ListRasters("L*2*0*_B*.tif") #I changed the user word for an exclusive. This line keeps the bands that I will use
    print "images: "+str(images)
##    chk4 = ['band{0}.tif'.format(i) for i in range(0, 7)] # I changed the range
##    print "chk4: "+str(chk4)
##    rasters = [a for a in images if a[-9:] in chk4]
##    print "rasters: "+str(rasters)
    name = os.path.join(outws, images[0].split("_")[0] + ".tif") # I wrote "outws"
    arcpy.CompositeBands_management(images, name) # I put it
    print(rasters)
print "Finished" #23‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Since you already filtered the folder and removed the images that you don't want to use, there is no need to filter them using lines 16 to 19. The error you were receiving was caused due to trying to extract an item with index 1 from an empty list. The list was empty since you were trying to filter the list using a name "band*" when the bands have a different name (there will be no match).

View solution in original post

11 Replies
DanPatterson_Retired
MVP Emeritus

failure is relative... did you get an error message? and if so, what was it?

indentation on what you have posted is completely wrong, so perhaps you could format the code in case there is an issue in the processing because of it

BrunoDeus
New Contributor III

I tried it. I saw that my line #18 was inside "for folder in folders", while the original wasn't, but none change happens when I fix it. 

... print(rasters)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ #18‍‍

The message error still the same.

Runtime error
Traceback (most recent call last):
File "<string>", line 16, in <module>
IndexError: list index out of range

Thanks!

0 Kudos
DanPatterson_Retired
MVP Emeritus

List index out of range means that python was expecting a list of something and the 'index' items in the list are out of range... short translation, list can't list stuff in a folder if you are already in the folder, hence there is nothing to list (ie index is out of range since there is nothing).  If you fed in a folder path into a script then it would look in the folder, retriebve the items and cycle through them one by one (ie index from 0 to X)

0 Kudos
BrunoDeus
New Contributor III

Can you give more instructions?

I inserted some "prints lines" to show the steps executed correctly and I saw the script finds the first folder and him bands. Besides, I don't understand how the original script is fine and this one isn't.

import arcpy, os
... 
... arcpy.env.workspace = r'C:\Teste_Auto_CLEIA\Ima_compactadas'
... 
... # list all folders in a directory
... folders = arcpy.ListWorkspaces("L8*", "Folder") # Inside main directory, already have other folders, but the bands are always inside folders that begin with "L8", e.g. "L8227069".
... print "folders: "+str(folders) #To see if the search above finds a result 
... 
... #The output files place
... outws = r'C:\Teste_Auto_CLEIA\Imagem' # Line 10
... 
... for folder in folders:
...     arcpy.env.workspace = folder
...     images = arcpy.ListRasters("L*2*0*_B*.tif") #I changed the user word for an exclusive. This line keeps the bands that I will use
...     print "images: "+str(images)
...     chk4 = ['band{0}.tif'.format(i) for i in range(0, 7)] # I changed the range
...     print "chk4: "+str(chk4)
...     rasters = [a for a in images if a[-9:] in chk4]
...     print "rasters: "+str(rasters)
...     name = os.path.join(outws, rasters[1].split("_")[0] + ".tif") # I wrote "outws"
...     arcpy.CompositeBands_management(rasters, name) # I put it
...     print(rasters)
... print "Finished" #23
... 

folders: [u'C:\\Teste_Auto_CLEIA\\Ima_compactadas\\L8227068', u'C:\\Teste_Auto_CLEIA\\Ima_compactadas\\L8227069']
images: [u'LO82270682017183CUB00_B1.TIF', u'LO82270682017183CUB00_B2.TIF', u'LO82270682017183CUB00_B3.TIF', u'LO82270682017183CUB00_B4.TIF', u'LO82270682017183CUB00_B5.TIF', u'LO82270682017183CUB00_B6.TIF', u'LO82270682017183CUB00_B7.TIF']
chk4: ['band0.tif', 'band1.tif', 'band2.tif', 'band3.tif', 'band4.tif', 'band5.tif', 'band6.tif']
rasters: []‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Runtime error
Traceback (most recent call last):
File "<string>", line 20, in <module>
IndexError: list index out of range

Kind regards.

0 Kudos
DanPatterson_Retired
MVP Emeritus

This slice fails since non of the rasters have the last 9 characters in chk4 (ie 'band0.tif' etc etc)

What are you trying to do with that line?  You had better write out what you expect since I can't figure out if you are trying to create a new file name or slice a band to use in line 20.  

rasters = [a for a in images if a[-9:] in chk4]

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi BrunodeDeus , I branched your post to a new question and I have a question if you can provided some additional information before I look at the code, You mention that your band are not named the same, but in the example you included the bands seem to have the same name (apart from 1 and 7). Can you list the rasters that you have and post that list here?

Thanks

0 Kudos
BrunoDeus
New Contributor III

Xander Bakker,

I appreciate your help. Right now, I've 2 scenes (some times are more), the folder from a scene (227/068) is showed below.

 *I didn't receive the e-mail about your comments, I will set my account to fix it.

Thankful

0 Kudos
XanderBakker
Esri Esteemed Contributor

Can you try this?

import arcpy, os

arcpy.env.workspace = r'C:\Teste_Auto_CLEIA\Ima_compactadas'

# list all folders in a directory
folders = arcpy.ListWorkspaces("L8*", "Folder") # Inside main directory, already have other folders, but the bands are always inside folders that begin with "L8", e.g. "L8227069".
print "folders: "+str(folders) #To see if the search above finds a result

#The output files place
outws = r'C:\Teste_Auto_CLEIA\Imagem' # Line 10

for folder in folders:
    arcpy.env.workspace = folder
    images = arcpy.ListRasters("L*2*0*_B*.tif") #I changed the user word for an exclusive. This line keeps the bands that I will use
    print "images: "+str(images)
##    chk4 = ['band{0}.tif'.format(i) for i in range(0, 7)] # I changed the range
##    print "chk4: "+str(chk4)
##    rasters = [a for a in images if a[-9:] in chk4]
##    print "rasters: "+str(rasters)
    name = os.path.join(outws, images[0].split("_")[0] + ".tif") # I wrote "outws"
    arcpy.CompositeBands_management(images, name) # I put it
    print(rasters)
print "Finished" #23‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Since you already filtered the folder and removed the images that you don't want to use, there is no need to filter them using lines 16 to 19. The error you were receiving was caused due to trying to extract an item with index 1 from an empty list. The list was empty since you were trying to filter the list using a name "band*" when the bands have a different name (there will be no match).

BrunoDeus
New Contributor III

It works fine!

And the first (and original) script didn't worked to "n" scene(s) just because one line

import arcpy, os
#Define the workspace that contains all of the folders with the Landsat imagery
arcpy.env.workspace = r'C:\Teste_Auto_CLEIA\Ima_compactadas'

#Specify where you would like the output to go
outws = r'C:\Teste_Auto_CLEIA\Imagem'

#List all of the workspaces in the previously defined workspace
folders = arcpy.ListWorkspaces("L8*", "Folder") #Filter to retrieve just the folder(s) with Landsat's bands

#Iterate through this list of workspaces and create a new list within each iteration of unstacked raster bands e.g. ['LC80260272014159LGN00_B1', 'LC80260272014159LGN00_B2',...]
#Landsat files follows this form: LC80260272014159LGN00_B1.tif, so we need to strip off anything after the "_" and use the first basename as the output name. You can do this with various slicing methods and string manipulation in Python.
for folder in folders:
    arcpy.env.workspace = folder
    rasters = arcpy.ListRasters("L*2*0*_B*.tif")# Filter and does that just the Landsat scenes with path/row from my ROI will be used
    name = os.path.join(outws, rasters[1].split("_")[0] + ".tif")
    arcpy.CompositeBands_management(rasters, name)
    print(rasters)#Line which allows composite bands for "n" scene(s)
# Ao completar, por a frase:
print "Processing complete"‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Thank you.

0 Kudos