Why are all my bands called Band_1 when using arcpy.CompositeBands_management?

6986
11
Jump to solution
11-25-2019 02:25 PM
Heidi_Kristenson
Occasional Contributor

I have a script that combines three singe-band rasters into an RGB raster. Everything works fine, except that the bands in the output raster are all called Band_1. The data is from the three different bands I used as inputs, and they are assigned to the correct RGB bands, but they're all called Band_1, which is very confusing. If I use the Composite Bands tool in ArcMap with the same input files, they are named appropriately. Does anyone know why this is happening and/or what needs to happen to have the bands named Band_1, Band_2 and Band_3 in the symbology? I'm working in ArcGIS 10.6.1.

This is what the outputs look like in the TOC. The top one is the raster generated by the script, the bottom one was generated manually using the tool interface in ArcMap. The rasters are identical in terms of pixel values in the RGB bands.

If you open the properties of the composite raster, you can see that there are 3 different bands to choose from, but they're all called Band_1. If you change the green band to the first Band_1 listed instead of the second, the image behaves as you would expect if you changed the green band (Band_2 in a the tool-generated output) to the red band (Band_1 in the tool-generated output). Likewise, the statistics for each layer (Red, Green, Blue) match those for the appropriate input single-band raster. It really does appear to be only the naming that's off.

I've even tried naming my variables Band_1, Band_2, Band_3, but, as expected, that didn't make any difference.

Here's the relevant part of the code:

# Generate Red Band
rband = (2*rp*(1-blue_mask) + zp*blue_mask)*255
Band_1 = rband*mask
bandList.append(Band_1)

# Generate Green Band
gband = (3*SquareRoot(xp)*(1-blue_mask) + 2*zp*blue_mask)*255
Band_2 = gband*mask
bandList.append(Band_2)

# Generate Blue Band
bband = (2*bp*(1-blue_mask) + 5*zp*blue_mask)*255
Band_3 = bband*mask
bandList.append(Band_3)

# Combine the bands into an RGB raster
outpath = outdir+'\\'+outname
arcpy.CompositeBands_management(bandList, outpath)

11 Replies
Don_Bayles
New Contributor

Thank you!

0 Kudos
Heidi_Kristenson
Occasional Contributor

I find myself revisiting this issue in the process of working on another project, which is timely considering another comment was just added today. 

It looks like the crux of the issue is the use of virtual rasters. 

  • If I actually save the input rasters to a .tif file, and then generate my band list with the path for each of the band .tif files, the bands are labeled correctly. 
  • If I just use the variables for the virtual outputs (there are a long series of processing steps in the script, all done in memory, resulting in the three single-band rasters that I want to combine to an RGB image), I consistently get the problem where all of the bands are labeled as band_1. This will happen even if I use the Composite Bands tool manually, and select the virtual rasters as the input bands. 

Here is the workflow I was using with the virtual rasters as inputs (note that many processing steps came before the final step where values greater than 255 are set to 255 and the values are converted to integers using the Con and Int tools):

# Create empty list for RGB bands
bandList = []

# Remove negative values and convert each band to an integer raster
aR = arcpy.sa.Int(arcpy.sa.Con(iR, "255", iR, "VALUE > 255"))
bandList.append(aR)
aG = arcpy.sa.Int(arcpy.sa.Con(iG, "255", iG, "VALUE > 255"))
bandList.append(aG)
aB = arcpy.sa.Int(arcpy.sa.Con(iB, "255", iB, "VALUE > 255"))
bandList.append(aB)

# Combine the aRGB bands into a composite raster
outpath = os.path.join(outdir, outname)
arcpy.CompositeBands_management(bandList, outpath)

And this is the amended workflow, where I actually save the raster objects to a file before combining them:

# Create empty list for RGB bands
bandList = []

# Remove negative values and convert each band to an integer raster
aR = arcpy.sa.Int(arcpy.sa.Con(iR, "255", iR, "VALUE > 255"))
aG = arcpy.sa.Int(arcpy.sa.Con(iG, "255", iG, "VALUE > 255"))
aB = arcpy.sa.Int(arcpy.sa.Con(iB, "255", iB, "VALUE > 255"))

# Save bands as GeoTIFF rasters in the scratch folder
aRpath = os.path.join(scratchpath, "aR.tif")
aR.save(aRpath)
bandList.append(aRpath)

aGpath = os.path.join(scratchpath, "aG.tif")
aG.save(aGpath)
bandList.append(aGpath)

aBpath = os.path.join(scratchpath, "aB.tif")
aB.save(aBpath)
bandList.append(aBpath)

# Combine the aRGB bands into a composite raster
outpath = os.path.join(outdir, outname)
arcpy.CompositeBands_management(bandList, outpath)

The output RGB rasters look pretty similar. When the virtual input bands are used there are more NoData pixels, however - some of the individual bands contain NoData values where there should be values of 1; I'm not sure what's going on there, but that's a problem for another day. The important thing to note is that the one generated with the virtual rasters as inputs lists all bands as Band_1 (even though they're clearly not), while the one generated with the saved GeoTIFF rasters lists the bands correctly.

Note that the same behavior occurs when using the Toolbox manually or using the script. When the virtual rasters are used for the input bands, all the bands are listed as Band_1. When the saved rasters are used for the input bands, the band numbers are correct.

0 Kudos