Friday, February 19, 2010

NSIDC L2_Land Source Code Walkthrough

In this post we're going to take a closer look at the NSIDC source code that produces their Level 2B Land product. For a very brief overview of the Level 2B Land and other NSDIC source see this post.

Inputs
The source code uses the Level 2A Brightness Temperature file as well as several data files as input. The data files are stored in the anc folder that comes with the source.

NOTE: The data files in the anc folder are binary files, so if you want to see what data they contain, you'll need to write a translation program to convert them to ASCII text. See the the Fortran file ancdata.blk in the src/land/level2/common folder for a description of the data in each data file.

Source Code
The source code is located in the src/land/level2 folder. There are three main groups of source code: C code, Fortran code and common code located in the common folder. The C code is used mainly for QA and I/O purposes. It's the Fortran code that does the real work. The code in the common folder is also Fortran code, stored as reusable blocks.

NOTE: Recall from this post that the AMSR-E scans detects both the H and V polarization of light. The H and V values are what allows the source code to detect land, rain, wind, and other characteristics. It's the source code that actually detects these characteristics, not the satellite.

NOTE: You'll see the term TB used throughout the code. This is shorthand for Brightness Temperature.

The main file is amsre_l2main.f. This file will call all the other code as needed. Overall, the program performs the following processes:

  1. Ingest ancillary databases and external parameters.
  2. Ingest AMSR-E Level 2A TB data.
  3. Grid TB data on EASE-grid projection.
  4. Export gridded TB data.
  5. Perform geophysical retrieval.
  6. Export results/flags as Level 2B land product.
Other source files of note are:
  • dobsonv3.f  Compute the dielectric constant of soil as a function of frequency, soil moisture, sand/clay fractions, and surface temperature.
  • fmod_pr3ch.f Compute TB as a function of the 6.9, 10.7, and 18.7 frequencies.
  • fmod_regrs.f Compute vegetation water content and soil moisture as a function of the 10.7, and 18.7 frequencies.
  • fmod_tb4ch.f Compute R squared and Chi values based on the 10.7, and 18.7 frequencies and values calculated in dobsonv3.f.
  • fmod_tb6ch.f Compute R squared and Chi values based on the 6.9, 10.7, and 18.7 frequencies and values calculated in dobsonv3.f.
Execution
AMSRE_L2MAIN() executes with 5 command-line arguments:

                  amsre_l2main.exe INPUT_L2A ANCIL_DIR L2B_DIR GTB_DIR PMC_VER

                INPUT_L2A: Filename of the input Level 2A data file
                ANCIL_DIR: Directory of ancillary databases
                L2B_DIR:   Directory of output Level 2B data files
                GTB_DIR:   Directory of gridded TB data files
                PMC_VER:   Product maturity code and PGE version number

NOTE: This program is designed to execute on big endian machines. If you're using a little endian machine (Intel machines are little endian) you'll need to add code that converts binary data to little endian values. You'll want to change the file l2ard.c and any code that loads ancillary data larger than than one byte. C++ code for swapping bytes is provided here:


inline bool is_bigendian()
{
const int i = 1;
bool bReturn = ( (*(char*)&i) == 0 );
return bReturn;
} // is_bigendian

inline char* reverse_16_bit (char* in16Bit)
{
char aReversed16Bit[2];

aReversed16Bit[0] = in16Bit[1];
aReversed16Bit[1] = in16Bit[0];
in16Bit[0] = aReversed16Bit[0];
in16Bit[1] = aReversed16Bit[1];

return in16Bit;
} // reverse_16_bit

inline char* reverse_16_bit_if_little_endian (char* in16Bit)
{
if (false == is_bigendian())
return reverse_16_bit(in16Bit);
return in16Bit;
} // reverse_16_bit_if_little_endian

inline char* reverse_32_bit(char* in32Bit)
{
char aReversed32Bit[4];

aReversed32Bit[0] = in32Bit[3];
aReversed32Bit[1] = in32Bit[2];
aReversed32Bit[2] = in32Bit[1];
aReversed32Bit[3] = in32Bit[0];
in32Bit[0] = aReversed32Bit[0];
in32Bit[1] = aReversed32Bit[1];
in32Bit[2] = aReversed32Bit[2];
in32Bit[3] = aReversed32Bit[3];

return in32Bit;
} // reverse_32_bit

inline char* reverse_32_bit_if_little_endian (char* in32Bit)
{
if (false == is_bigendian())
return reverse_32_bit(in32Bit);
return in32Bit;
} // reverse_32_bit_if_little_endian

inline char* reverse_64_bit(char* in64Bit)
{
char aReversed64Bit[8];

aReversed64Bit[0] = in64Bit[7];
aReversed64Bit[1] = in64Bit[6];
aReversed64Bit[2] = in64Bit[5];
aReversed64Bit[3] = in64Bit[4];
aReversed16Bit[4] = in64Bit[3];
aReversed64Bit[5] = in64Bit[2];
aReversed64Bit[6] = in64Bit[1];
aReversed64Bit[7] = in64Bit[0];
in64Bit[0] = aReversed64Bit[0];
in64Bit[1] = aReversed64Bit[1];
in64Bit[2] = aReversed64Bit[2];
in64Bit[3] = aReversed64Bit[3];
in64Bit[4] = aReversed64Bit[4];
in64Bit[5] = aReversed64Bit[5];
in64Bit[6] = aReversed64Bit[6];
in64Bit[7] = aReversed64Bit[7];

return in64Bit;
} // reverse_64_bit

inline char* reverse_64_bit_if_little_endian (char* in64Bit)
{
if (false == is_bigendian())
return reverse_32_bit(in64Bit);
return in64Bit;
} // reverse_64_bit_if_little_endian


template<class NUMBER_TYPE>
inline NUMBER_TYPE reverse_bytes(NUMBER_TYPE inValue)
{
if (2 == sizeof(inValue))
return *(reverse_16_bit((char*) &inValue));
if (4 == sizeof(inValue))
return *(reverse_32_bit((char*) &inValue));
if (8 == sizeof(inValue))
return *(reverse_64_bit((char*) &inValue));
return inValue;
} // reverse_bytes

template<class NUMBER_TYPE>
inline NUMBER_TYPE reverse_bytes_if_little_endian(NUMBER_TYPE inValue)
{
if (false == is_bigendian())
return reverse_bytes(inValue);
return inValue;
} // reverse_bytes_if_little_endian


Output
The Level 2B land product contains surface type, surface moisture, and vegetation water content information for the Earth.

Additional Information
Useful documentation on the algorithms is available at AMSR-E/Aqua L2B Surface Soil Moisture, Ancillary Parms, & QC EASE-Grids.

References:

No comments:

Post a Comment