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

6952
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)

1 Solution

Accepted Solutions
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.

View solution in original post

0 Kudos
11 Replies
DanPatterson_Retired
MVP Emeritus

In their code example, they used  semicolon delimited list.

"band1.tif;comp.mdb/band2;comp.gdb/bands/Band_3",

I wonder if that makes a difference?

Composite Bands—Data Management toolbox | ArcGIS Desktop 

0 Kudos
Heidi_Kristenson
Occasional Contributor

I had tried a semicolon delimited list in a variety of forms, but it would always error out when using temporary layers. I had tried saving each band and using those paths, and it would still error out. I found this list approach mentioned elsewhere, and it has worked well, save for the band naming problem.

It looks like the issue might be in the use of the Con tool in my workflow. The script I posted was simplified; in my actual script there was a step that used the Con tool to change 0s to 1s. I discovered that if I remove that step, the composite bands function generates an RGB with correctly-named bands. It turns out the output Con raster is changed from the previously signed integer raster to an unsigned integer raster, but there must be something else going on, because even if I convert the Con output back to signed, it still will generate a composite that has all bands listed as Band_1.

0 Kudos
DanPatterson_Retired
MVP Emeritus

Heidi, there doesn't seem to be anything in the Environments that would cause this, other than the inputs are Raster Layers and no mention is made of multiband rasters

Con—Help | ArcGIS Desktop 

Maybe Steve Lynch‌ might know of other restrictions.

0 Kudos
Heidi_Kristenson
Occasional Contributor

It's not just the Con tool, either. I replaced that function with a series of map algebra functions to get to the desired output, and it's still labeling all the bands as Band_1 in the output.

0 Kudos
Heidi_Kristenson
Occasional Contributor

Just to be clear, there's no problem with the actual data output. The bands are being combined appropriately, they're just not being labeled correctly.

DanPatterson_Retired
MVP Emeritus

It is clear, but Steve would know, or know someone who would.

0 Kudos
Heidi_Kristenson
Occasional Contributor

Thanks Dan Patterson for taking time to look at this issue. It turns out that I can use the CopyRaster_management function to save the output of the CompositeBands function as an 8-bit unsigned integer raster. The copied output has correctly-named bands, and the additional benefit of a much-reduced filesize. That approach should get me where I need to be; I can afford to lose some pixel depth, and the product is much tidier.

0 Kudos
KenPierce
New Contributor III

I've been using the additional copy function but it is really slow and now I have a new issue that has arisen where the 8-bit unsigned isn't being respected so I have to 1) composite the bands, 2) copy to get the names right 3) reexport to 8bit unsigned. With big rasters (~100gb+) this adds several hours per raster having to redo the steps. 

0 Kudos
MustafaKhan
New Contributor

Hello to every one,

I had the same error, but what i did to solving this issue that was the use of the arctool box  tool. 

Step 1:  Open your Arcmap and add the Landsat8 or landsat7 tif images to the arcmap, do not use "image Analysis"  instead use the "Composite Bands tool" in the arctoolbox in Data Management. add all your tif images into input and then locate the output folder. it will give you a single composite file with all bands you added.