Commit 20303a8b authored by Kristin Berry's avatar Kristin Berry
Browse files

Updated kaguyasp2isis to work with newer-format data, changed name to...

Updated kaguyasp2isis to work with newer-format data, changed name to kaguyasp2ascii, and made assorted minor format changes to its output file. Fixes #2218

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/trunk@6393 41f8697f-d340-4b68-9986-7bafba869bb8
parent e0fb814d
Loading
Loading
Loading
Loading
(65.6 KiB)

File moved.

(1.48 MiB)

File moved.

+93 −9
Original line number Diff line number Diff line
@@ -46,7 +46,8 @@ void IsisMain() {
  int wavptr = 0;
  int rawptr = 0;
  int radptr = 0;
  int refptr = 0;
  int refptr1 = 0;
  int refptr2 = 0;
  int qaptr = 0;

  if (lab.hasKeyword("^SP_SPECTRUM_WAV")) {
@@ -58,11 +59,19 @@ void IsisMain() {
  if (lab.hasKeyword("^SP_SPECTRUM_RAD")) {
    radptr = toInt(lab.findKeyword("^SP_SPECTRUM_RAD")[0]) - 1;
  }
  //older-format file without calibrated NIR2 data
  if (lab.hasKeyword("^SP_SPECTRUM_REF")) {
    refptr = toInt(lab.findKeyword("^SP_SPECTRUM_REF")[0]) - 1;
    refptr1 = toInt(lab.findKeyword("^SP_SPECTRUM_REF")[0]) - 1;
  }
  //newer-format file with calibrated NIR2 data and 2 different Reflectances
  if (lab.hasKeyword("^SP_SPECTRUM_REF1")) {
    refptr1 = toInt(lab.findKeyword("^SP_SPECTRUM_REF1")[0]) - 1;
  }
  if (lab.hasKeyword("^SP_SPECTRUM_REF2")) {
    refptr2 = toInt(lab.findKeyword("^SP_SPECTRUM_REF2")[0]) - 1;
  }
  if (lab.hasKeyword("^SP_SPECTRUM_QA")) {
    qaptr = toInt(lab.findKeyword("^SP_SPECTRUM_REF")[0]) - 1;
    qaptr = toInt(lab.findKeyword("^SP_SPECTRUM_QA")[0]) - 1;
  }

  FILE *spcptr;
@@ -82,7 +91,8 @@ void IsisMain() {
  } obuf;

  if (!lab.hasObject("SP_SPECTRUM_WAV") || !lab.hasObject("SP_SPECTRUM_QA") ||
      !lab.hasObject("SP_SPECTRUM_RAD") || !lab.hasObject("SP_SPECTRUM_REF")) {
      !lab.hasObject("SP_SPECTRUM_RAD") || !(lab.hasObject("SP_SPECTRUM_REF") || 
      (lab.hasObject("SP_SPECTRUM_REF1") && lab.hasObject("SP_SPECTRUM_REF2")))) {
    QString msg = "Input file [" + inFile.expanded() + "] is not a valid ";
    msg += "Kaguya Spectral Profiler file";
    throw IException(IException::User, msg, _FILEINFO_);
@@ -241,7 +251,16 @@ void IsisMain() {
    }
  }

  PvlObject refobj = lab.findObject("SP_SPECTRUM_REF");
  PvlObject refobj;
  PvlObject refobj2; 
  if (lab.hasKeyword("^SP_SPECTRUM_REF")) {
    refobj = lab.findObject("SP_SPECTRUM_REF");
  } 
  else {
    refobj = lab.findObject("SP_SPECTRUM_REF1"); 
    refobj2 = lab.findObject("SP_SPECTRUM_REF2"); 
  }

  int reflines = toInt(refobj.findKeyword("LINES")[0]);
  int refsamps = toInt(refobj.findKeyword("LINE_SAMPLES")[0]);
  QString reftype = refobj.findKeyword("SAMPLE_TYPE");
@@ -264,8 +283,9 @@ void IsisMain() {
    refoffset = 0.0;
  }

  //import reflectance or "reflectance 1" in newer files
  double ref[296*reflines];
  fseek(spcptr,refptr,SEEK_SET);
  fseek(spcptr,refptr1,SEEK_SET);
  for (int i=0; i<reflines; i++) {
    for (int j=0; j<refsamps; j++) {
      size_t results = fread((void *)ibuf.ichar,2,1,spcptr);
@@ -279,6 +299,48 @@ void IsisMain() {
    }
  }
  
  //import reflectance 2 if it exists
  double *ref2 = NULL; 
  if (lab.hasKeyword("^SP_SPECTRUM_REF2")) {
    int reflines2 = toInt(refobj2.findKeyword("LINES")[0]); 
    int refsamps2 = toInt(refobj2.findKeyword("LINE_SAMPLES")[0]);
    QString reftype2 = refobj2.findKeyword("SAMPLE_TYPE");
    int refbits2 = toInt(refobj2.findKeyword("SAMPLE_BITS")[0]);
    if (reflines2 != radlines || refsamps2 != 296 || reftype2 != "MSB_UNSIGNED_INTEGER" ||
     refbits2 != 16) {
     QString msg = "Reflectance #2 data in input file does not meet the following ";
     msg += "requirements: Size=296 columns, DataType=MSB_UNSIGNED_INTEGER, ";
     msg += "BitType=16";
     throw IException(IException::User, msg, _FILEINFO_);
    }

    keyval = refobj2.findKeyword("SCALING_FACTOR")[0];
    double refscale2 = keyval.toDouble(&ok);
    if (!ok) {
      refscale2 = 1.0;
    }
    keyval = refobj2.findKeyword("OFFSET")[0];
    double refoffset2 = keyval.toDouble(&ok);
    if (!ok) {
      refoffset2 = 0.0;
    }

    ref2 = new double[296*reflines2];
    fseek(spcptr,refptr2,SEEK_SET);
    for (int i=0; i<reflines2; i++) {
      for (int j=0; j<refsamps2; j++) {
        size_t results = fread((void *)ibuf.ichar,2,1,spcptr);
        if (results != 1) {
          QString msg = "Error reading reflectance (Ref2) data from input file";
          throw IException(IException::User, msg, _FILEINFO_);
        }
        obuf.ichar[0] = ibuf.ichar[1];
        obuf.ichar[1] = ibuf.ichar[0];
        ref2[j+i*296] = (float)obuf.iword * refscale2 + refoffset2;
      }
    }
  }

  if (wavsamps != rawsamps || wavsamps != radsamps || wavsamps != refsamps ||
      wavsamps != qasamps || wavsamps != 296) {
    QString msg = "Number of columns in input file must be 296";
@@ -292,19 +354,41 @@ void IsisMain() {
    minobs = rawlines;
  }

  os << "WaveLength,";
  os << "Wavelength";

  //If we have a newer-format file with two Reflectances, output both
  if (ref2 != NULL) { 
    for (int i=minobs; i<=maxobs; i++) {
    os << "Raw" << i << ",Rad" << i << ",Ref" << i << ",QA" << i;
      os << "\t" << "Raw" << i << "\t"<< "Rad" << i << "\t" <<"Ref1_" << i << "\t" << "Ref2_" << i 
          << "\t" << "QA" << i;
    }
    os << endl; 

    for (int j = 0; j < 296; j++) {
      os << wavelength[j];
      for (int i=minobs-1; i<maxobs; i++) {
      os << "\t" << raw[j+i*296] << "\t" << rad[j+i*296] << "\t" << ref[j+i*296] << "\t" << (std::bitset<16>) qa[j+i*296];
        os << "\t" << raw[j+i*296] << "\t" << rad[j+i*296] << "\t" << ref[j+i*296] << "\t" 
            << ref2[j+i*296] << "\t" << (std::bitset<16>) qa[j+i*296];
      }
      os << endl;
     }
     delete ref2; 
  } 
  else {
    for (int i=minobs; i<=maxobs; i++) {
      os << "\t" << "Raw" << i << "\t" << "Rad" << i << "\t" << "Ref" << i << "\t" << "QA" << i;
    }
    os << endl;    

    for (int j = 0; j < 296; j++) {
      os << wavelength[j];
      for (int i=minobs-1; i<maxobs; i++) {
        os << "\t" << raw[j+i*296] << "\t" << rad[j+i*296] << "\t" << ref[j+i*296] << "\t" 
            << (std::bitset<16>) qa[j+i*296];
      }
       os << endl;
    }
  }

  os.close();
}
+48 −14
Original line number Diff line number Diff line
<?xml version="1.0" encoding="UTF-8"?>

<application name="kaguyasp2isis" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://isis.astrogeology.usgs.gov/Schemas/Application/application.xsd">
<application name="kaguyasp2ascii" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://isis.astrogeology.usgs.gov/Schemas/Application/application.xsd">

  <brief>
    Imports a Kaguya SP (Spectral Profiler) file
    Converts Kaguya SP (Spectral Profiler) file to a tab delimited text file 
  </brief>

  <description>
  <p>
    This program will import a Kaguya SP (Spectral Profiler) file to a tab delimited text file.
    The text file will contain one record for each wavelength in the SP file. There are 296
    wavelengths available in an SP file. Each record in the output file will contain all the
    observations for a specific wavelength. The user can limit the number of observations that
    are listed by using the MINOBS and MAXOBS parameters.
    This program will read a binary SELENE Kaguya SP (Spectral Profiler) data file 
    (downloaded as a .spc file from <a href="http://l2db.selene.darts.isas.jaxa.jp/">the archive site</a>) and create a 
    user-specified, tab-delimited text file.

    The multi-column ASCII text file will contain one record for each of the 296 wavelengths (bands or channels) in the SP file. 
    The bands are derived from 3 separate sensors, with wavelengths as follows: UVVIS wavelength = 512.6 -1010.7 nm; NIR1 
    wavelength = 883.5 - 1676.0 nm; NIR2 wavelength = 702.1-2587.9 nm.  Each record in the output file will contain ancillary data 
    and all of the observations for a specific wavelength. You can limit the number of observations that
    are listed by using the MINOBS and MAXOBS parameters. The ancillary data include a quality assessment (QA) parameter, 
    raw DN, radiance, and ref_1 and ref_2 (reflectance  values that have been photometrically corrected using values for
    highlands and mare, respectively) for each wavelength and each observation. SP binary data files can have less than 10 observations
    or more than 50. This program works on both Level 2B and Level 2C products from Kaguya, with two caveats:
    the NIR portions of the Level 2B products are not calibrated or photometrically corrected, but the L2C products have been fully
    calibrated and photometrically corrected. </p>

  <p>
    The documents in the kaguyasp2ascii/assets directory provide information about the Kaguya Spectral 
    Profiler data. The directory also contains a summary of what the different Quality Assessment values 
    mean (from p. 82 of the <a href="http://l2db.selene.darts.isas.jaxa.jp/help/en/LISM_SPICE_Fromat_en_V01-03.pdf">LISM SPICE documentation</a>).
  </p>
  <p>
    The documents in the kaguyasp2isis/assets directory provide information about the Kaguya
    Spectral Profiler data. The directory also contains a cheat sheet to determine what the 
    different Quality Assessment values mean.
    Note that this program does not process the SP data in any way once the binary data is converted to ASCII.
    For example, you likely would not want to work with SP data that have oblique viewing angles or are poorly illuminated 
    (these must be filtered from the archive site), or you may want to remove redundant or erroneous data at the instrument joins 
    (e.g., spikes in DN values at the ends of the VIS, NIR1, NIR2). For the latter, the QA values will help you to identify these.
    QA values with any of the three left-most bits set to 1 can be removed from each spectrum. 
  </p>
  <p>
    Please note that there is no attempt by this program to remove redundant or erroneous
    data at the instrument joins (e.g., VIS, NIR1, NIR2). Also, the data currently available
    do not extend to the NIR2 wavelengths in calibrated form.
    References: 
    <br /> 
     Yamamoto, S. et al. (2011) Preflight and in-flight calibration of the spectral profiler onboard the SELENE (Kaguya). IEEE Trans. Geosci. Remote Sens. 49 (11), p. 4660-4676.
     <br />
     Yamamoto, S. et al. (2014) Calibration of NIR2 of Spectral Profiler onboard Kaguya/SELENE, IEEE Trans. Geosci. Remote Sens. 52 (11), p. 6882-6898.
     <br /> 
     Yokota, Y., et al. (2011) Lunar photometric properties at wavelengths 0.5-1.6mm acquired by SELENE Spectral Profiler and their dependency on local albedo and latitudinal zones. Icarus, 215, 639-660, <a href="http://dx.doi.org/10.1016/j.icarus.2011.07.028">http://dx.doi.org/10.1016/j.icarus.2011.07.028</a>.
  </p>
  </description>

@@ -32,6 +52,19 @@
      from a Kaguya Spectral Profiler file and puts the 
      data into a tab delimited table.
    </change>
    <change name="Kristin Berry" date="2015-08-24">
      Updated to deal with format change for newer files . Now will output both reflectances  
      and calibrated NIR2 data if available. Also, updated to put actual QA information in 
      the output file, which was not happening correctly before, and updated online
      documentation to match Lisa Gaddis's rewrite.
      Additionally, headers are now tab-separated, rather than comma-separated.
      Fixes #2218
    </change>
    <change name="Kristin Berry" date="2015-09-18">
      Backward Compatibility Issue: The application name was changed from kaguyasp2isis to 
      kaguyasp2ascii since this application does not output an ISIS Cube, which could
      impact processing scripts/pipelines which use the old application name. 
    </change>
  </history>

  <category>
@@ -64,7 +97,8 @@
          file and will contain all requested observations for
          a single wavelength in each record of the file. Each
          observation will include the raw, radiance, reflectance,
          and QA information.
          and QA information. If two reflectances are available,
          as in newer-format files, both will be included in the output file.
        </description>
      </parameter>
    </group>
Loading