Child pages
  • Exercise 2 - Cloud Masking Tool

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

Learning Targets

  • Write a cloud masking tool
    1. Open the AATSR TOA source product
    2. Create a cloud mask target product
    3. Transfer components from source to target product
    4. Create the cloud mask target band instances
    5. Write the cloud mask target product header
    6. Perform scanline-wise processing
      1. Read brightness temperature scanlines
      2. Compute and write the cloud mask scanlines
      3. Write brightness temperature scanlines
    7. Close product I/O
  • Inspect the cloud mask in VISAT
  • Invoke the tool without IDE
    1. Create a JAR
    2. Write a script
    3. Call the script
  • Become acquainted with more BEAM core classes such as
    • ProductWriter
    • RasterDataNode
    • TiePointGrid
    • GeoCoding

Write the cloud masking tool

Challenge: Write a tool which creates cloud masks for an AATSR TOA product. The cloud masks shall be generated from the nadir and forward views of the brightness temperature at 12000 nm by comparing them with a user defined threshold. Your tool will have a command-line interface and the following usage:

Code Block
Usage: cloud_mask <aatsr-file> <cloud-mask-file> [<threshold>]

   <aatsr-file>       The AATSR TOA source product file name
   <cloud-mask-file>  The cloud mask target file name
   <threshold>        The optional threshold in [K], defaults to 270 K

Open the AATSR TOA source product

Create a new project Ex2 as described in the previous exercise. The main class shall be called CloudMask this time.

The initial program structure is the same as in Ex1, but this time you will also evaluate the command-line arguments:

Code Block
java
java
import java.io.File;
import java.io.IOException;
import org.esa.beam.framework.dataio.ProductIO;
import org.esa.beam.framework.datamodel.Product;
import org.esa.beam.util.logging.BeamLogManager;

public class CloudMask {
    public static void main(String[] args) throws IOException {
        String sourceFilename = args[0];
        String targetFilename = args[1];
        if (!targetFilename.endsWith(".dim")) {
            targetFilename += ".dim";
        }
        double btempThreshold = 270.0; // K
        if (args.length > 2) {
            btempThreshold = Double.parseDouble(args[2]);
        }

        BeamLogManager.removeRootLoggerHandlers(); // get rid of BEAM console logging
        Product sourceProduct = ProductIO.readProduct(sourceFilename);
        // more to come...
    }
}

You will have noticed some BEAM logging output in the Console view. You can get rid of this output by calling BeamLogManager.removeRootLoggerHandlers().

Note
titleException handling

For simplicity, the IOException thrown by the readProduct method is declared with the main method in the code above. Production code should always and carefully handle checked exceptions! You can also reuse the exception handling as of Ex1.

Create a target product instance

Append

Code Block
java
java
int rasterWidth = sourceProduct.getSceneRasterWidth();
int rasterHeight = sourceProduct.getSceneRasterHeight();
Product targetProduct = new Product(new File(targetFilename).getName(),
                                    "ATS_CLM_2P", rasterWidth,
                                    rasterHeight);

Transfer components from source to target product

Append

Code Block
java
java
ProductUtils.copyTiePointGrids(sourceProduct, targetProduct);
ProductUtils.copyGeoCoding(sourceProduct, targetProduct);
Band btempNadirTargetBand = ProductUtils.copyBand("btemp_nadir_1200", sourceProduct, targetProduct, false);
Band btempFwardTargetBand = ProductUtils.copyBand("btemp_fward_1200", sourceProduct, targetProduct, false);

Create the cloud mask band instances

Append

Code Block
java
java
Band cloudMaskNadirTargetBand = new Band("cloud_mask_nadir",
                                         ProductData.TYPE_UINT8,
                                         rasterWidth, rasterHeight);
Band cloudMaskFwardTargetBand = new Band("cloud_mask_fward",
                                         ProductData.TYPE_UINT8,
                                         rasterWidth, rasterHeight);
targetProduct.addBand(cloudMaskNadirTargetBand);
targetProduct.addBand(cloudMaskFwardTargetBand);

Write the target product header

Append

Code Block
java
java
ProductWriter productWriter = ProductIO.getProductWriter("BEAM-DIMAP");
productWriter.writeProductNodes(targetProduct, targetFilename);

Perform scanline-wise processing

Read brightness temperature scanlines

Append

Code Block
java
java
Band btempNadirSourceBand = sourceProduct.getBand("btemp_nadir_1200");
Band btempFwardSourceBand = sourceProduct.getBand("btemp_fward_1200");
double[] btempNadirLine = new double[rasterWidth];
double[] btempFwardLine = new double[rasterWidth];
for (int y = 0; y < rasterHeight; y++) {
    btempNadirSourceBand.readPixels(0, y, rasterWidth, 1, btempNadirLine);
    btempFwardSourceBand.readPixels(0, y, rasterWidth, 1, btempFwardLine);

    // todo - compute and write the cloud mask pixels here
}

Compute and write the cloud mask scanlines

Append to loop body

Code Block
java
java
double[] cloudMaskNadirLine = new double[rasterWidth];
double[] cloudMaskFwardLine = new double[rasterWidth];
for (int x = 0; x < rasterWidth; x++) {
    cloudMaskNadirLine[x] = btempNadirLine[x] < btempThreshold ? 1 : 0;
    cloudMaskFwardLine[x] = btempFwardLine[x] < btempThreshold ? 1 : 0;
}

cloudMaskNadirTargetBand.writePixels(0, y, rasterWidth, 1, cloudMaskNadirLine);
cloudMaskFwardTargetBand.writePixels(0, y, rasterWidth, 1, cloudMaskFwardLine);


Write brightness temperature scanlines

Append to loop body

Code Block
languagejava
btempNadirTargetBand.writePixels(0, y, rasterWidth, 1, btempNadirLine);
btempFwardTargetBand.writePixels(0, y, rasterWidth, 1, btempFwardLine);

Close product I/O

Append

Code Block
java
java
sourceProduct.dispose();
targetProduct.dispose();

Class diagram

The following UML class diagram shows the relationships between the BEAM API classes introduced in this exercise:

Invoke the tool without IDE

Create a JAR

Panel
borderColor#ccc
bgColor#FFFFCE
titleBGColor#F7D6C1
titleIntelliJ IDEA
  • Select Ex2 in the Project view
  • Select entry Open Module Settings
  • Select in the upcoming dialog Artifacts on the left and press the plus button in the upper middle region. Select the Jar->Empty entry.
  • Set the name to cloud_mask
  • Set Output directory to %PROJECT_HOME%/Ex2
  • Drag the 'Ex2' compile output entry from the right on the cloud_mask.jar entry on the left and drop it.
  • Click OK

To create the JAR file you can select from the main menu Build/Buld Artifact/cloud_mask.

Panel
borderColor#ccc
bgColor#FFFFCE
titleBGColor#F7D6C1
titleEclipse
  • In the main menu, select File/Export...
  • Select entry Java/JAR file file and click Next >
  • Select in the upcoming dialog the resources to export into the JAR file.
    • Deselect the Eclipse project files .classpath and .project
    • Set export destination JAR file to %PROJECT_HOME%/Ex2/cloud_mask.jar, click Next >
  • Check Save the description of this JAR in the workspace and set Description file to /Ex2/cloud_mask.jardesc. Now we can easily recreate the jar later.
  • Click Finish

Now two files should be generated in the workspace. The JAR Ex2/cloud_mask.jar and JAR description Ex2/cloud_mask.jardesc.
If you now want to recreate the JAR after you've made some changes to the code, you can Create JAR in the context menu for the JAR description file.

Write a script

Next to the generated JAR file, add a new file cloud_mask.bat (Windows), respectively cloud_mask.sh (Unix). The main reason for writing this script is to invoke the Java VM with the correct classpath comprising all the required BEAM libraries. Place following lines into the script and adapt the BEAM4_HOME variable to your local BEAM 4 installation directory.

Windows:

Code Block
titlecloud_mask.bat
@echo off

set BEAM4_HOME=C:\Program Files\beam\beam-4.11

"%BEAM4_HOME%\jre\bin\java.exe" ^
-Xmx1024M ^
-cp ^
"./cloud_mask.jar;^
%BEAM4_HOME%/lib/*;^
%BEAM4_HOME%/modules/*;^
%BEAM4_HOME%/modules/lib-hdf-2.7/lib/*;" CloudMask %*

exit /B 0

Unix:

Code Block
titlecloud_mask.sh
#! /bin/sh

BEAM4_HOME=/opt/Beam/beam-4.11

. "$BEAM4_HOME/bin/detect_java.sh"

"$app_java_home/bin/java" -Xmx1024M \
-cp "./cloud_mask.jar:\
$BEAM4_HOME/lib/*:\
$BEAM4_HOME/modules/*:\
$BEAM4_HOME/modules/lib-hdf-2.7/lib/*" CloudMask "$@"

exit 0

Call the script

Open command shell, cd into Ex2 of your workspace location and invoke the script with the AATSR TOA source product and the brightness temperature threshold:

Windows:

Code Block
> cloud_mask.bat C:\Downloads\ATS_TOA_1CNPDK20030504_111142_000000772016_00080_06146_0157.N1 aatsr-cloud-mask.dim 275.2

Unix:

Code Block
> cloud_mask.sh /Downloads/ATS_TOA_1CNPDK20030504_111142_000000772016_00080_06146_0157.N1 aatsr-cloud-mask.dim 275.2

Inspect the cloud mask product in VISAT

Run the tool in the IDE. Start VISAT and open and inspect the target product just created.