Commit 54cabbdd authored by Janet Barrett's avatar Janet Barrett
Browse files

A new program, kaguyasp2isis, was developed to import Kaguya Spectral Profiler...

A new program, kaguyasp2isis, was developed to import Kaguya Spectral Profiler data to a tab delimited text file.

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/trunk@5784 41f8697f-d340-4b68-9986-7bafba869bb8
parent 1cce488e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
ifeq ($(ISISROOT), $(BLANK))
.SILENT:
error:
	echo "Please set ISISROOT";
else
	include $(ISISROOT)/make/isismake.apps
endif
 No newline at end of file
+310 −0
Original line number Diff line number Diff line
#include "Isis.h"

#include <bitset>
#include <cstdio>
#include <QString>

#include "ProcessImportPds.h"

#include "UserInterface.h"
#include "FileName.h"
#include "iTime.h"

using namespace std;
using namespace Isis;

void IsisMain() {
  ProcessImportPds p;
  UserInterface &ui = Application::GetUserInterface();

  FileName inFile = ui.GetFileName("FROM");
  Pvl lab(inFile.expanded());

  ofstream os;
  QString outFile = FileName(ui.GetFileName("TO")).expanded();
  os.open(outFile.toAscii().data(), ios::out);

  int minobs = 1;
  int maxobs = 1000000;
  if (ui.WasEntered("MINOBS")) {
    QString keyval = ui.GetString("MINOBS");
    minobs = toInt(keyval);
    if (minobs < 1) {
      minobs = 1;
    }
  } 
  if (ui.WasEntered("MAXOBS")) {
    QString keyval = ui.GetString("MAXOBS");
    maxobs = toInt(keyval);
  }
  if (maxobs < minobs) {
    int temp = minobs;
    minobs = maxobs;
    maxobs = temp;
  }

  int wavptr = 0;
  int rawptr = 0;
  int radptr = 0;
  int refptr = 0;
  int qaptr = 0;

  if (lab.hasKeyword("^SP_SPECTRUM_WAV")) {
    wavptr = toInt(lab.findKeyword("^SP_SPECTRUM_WAV")[0]) - 1;
  }
  if (lab.hasKeyword("^SP_SPECTRUM_RAW")) {
    rawptr = toInt(lab.findKeyword("^SP_SPECTRUM_RAW")[0]) - 1;
  }
  if (lab.hasKeyword("^SP_SPECTRUM_RAD")) {
    radptr = toInt(lab.findKeyword("^SP_SPECTRUM_RAD")[0]) - 1;
  }
  if (lab.hasKeyword("^SP_SPECTRUM_REF")) {
    refptr = toInt(lab.findKeyword("^SP_SPECTRUM_REF")[0]) - 1;
  }
  if (lab.hasKeyword("^SP_SPECTRUM_QA")) {
    qaptr = toInt(lab.findKeyword("^SP_SPECTRUM_REF")[0]) - 1;
  }

  FILE *spcptr;
  if ((spcptr = fopen(inFile.expanded().toAscii().data(),"rb")) == 0) {
    QString msg = "Error opening input Kaguya SP file [" + inFile.expanded() + "]";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  union {
    unsigned char ichar[2];
    unsigned short iword;
  } ibuf;

  union {
    unsigned char ichar[2];
    unsigned short iword;
  } obuf;

  if (!lab.hasObject("SP_SPECTRUM_WAV") || !lab.hasObject("SP_SPECTRUM_QA") ||
      !lab.hasObject("SP_SPECTRUM_RAD") || !lab.hasObject("SP_SPECTRUM_REF")) {
    QString msg = "Input file [" + inFile.expanded() + "] is not a valid ";
    msg += "Kaguya Spectral Profiler file";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  PvlObject wavobj = lab.findObject("SP_SPECTRUM_WAV");
  int wavlines = toInt(wavobj.findKeyword("LINES")[0]);
  int wavsamps = toInt(wavobj.findKeyword("LINE_SAMPLES")[0]);
  QString wavtype = wavobj.findKeyword("SAMPLE_TYPE");
  int wavbits = toInt(wavobj.findKeyword("SAMPLE_BITS")[0]);
  if (wavlines != 1 || wavsamps != 296 || wavtype != "MSB_UNSIGNED_INTEGER" ||
      wavbits != 16) {
    QString msg = "Wavelength data in input file does not meet the following ";
    msg += "requirements: Size=1 row x 296 columns, DataType=MSB_UNSIGNED_INTEGER, ";
    msg += "BitType: 16";
    throw IException(IException::User, msg, _FILEINFO_);
  }
  QString keyval = wavobj.findKeyword("SCALING_FACTOR")[0];
  bool ok;
  double wavscale = keyval.toDouble(&ok);
  if (!ok) {
    wavscale = 1.0;
  }
  keyval = wavobj.findKeyword("OFFSET")[0];
  double wavoffset = keyval.toDouble(&ok);
  if (!ok) {
    wavoffset = 0.0;
  }

  double wavelength[296];
  fseek(spcptr,wavptr,SEEK_SET);
  for (int i=0; i<wavlines; i++) {
    for (int j=0; j<wavsamps; j++) {
      size_t results = fread((void *)ibuf.ichar,2,1,spcptr);
      if (results != 1) {
        QString msg = "Error reading wavelength data from input file";
        throw IException(IException::User, msg, _FILEINFO_);
      }
      obuf.ichar[0] = ibuf.ichar[1];
      obuf.ichar[1] = ibuf.ichar[0];
      wavelength[j] = (float)obuf.iword * wavscale + wavoffset;
    }
  }

  PvlObject rawobj = lab.findObject("SP_SPECTRUM_RAW");
  int rawlines = toInt(rawobj.findKeyword("LINES")[0]);
  int rawsamps = toInt(rawobj.findKeyword("LINE_SAMPLES")[0]);
  QString rawtype = rawobj.findKeyword("SAMPLE_TYPE");
  int rawbits = toInt(rawobj.findKeyword("SAMPLE_BITS")[0]);
  if (rawsamps != 296 || rawtype != "MSB_UNSIGNED_INTEGER" ||
      rawbits != 16) {
    QString msg = "Raw 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 = rawobj.findKeyword("SCALING_FACTOR")[0];
  double rawscale = keyval.toDouble(&ok);
  if (!ok) {
    rawscale = 1.0;
  }
  keyval = rawobj.findKeyword("OFFSET")[0];
  double rawoffset = keyval.toDouble(&ok);
  if (!ok) {
    rawoffset = 0.0;
  }

  double raw[296*rawlines];
  fseek(spcptr,rawptr,SEEK_SET);
  for (int i=0; i<rawlines; i++) {
    for (int j=0; j<rawsamps; j++) {
      size_t results = fread((void *)ibuf.ichar,2,1,spcptr);
      if (results != 1) {
        QString msg = "Error reading raw data from input file";
        throw IException(IException::User, msg, _FILEINFO_);
      }
      obuf.ichar[0] = ibuf.ichar[1];
      obuf.ichar[1] = ibuf.ichar[0];
      raw[j+i*296] = (float)obuf.iword * rawscale + rawoffset;
    }
  }

  PvlObject qaobj = lab.findObject("SP_SPECTRUM_QA");
  int qalines = toInt(qaobj.findKeyword("LINES")[0]);
  int qasamps = toInt(qaobj.findKeyword("LINE_SAMPLES")[0]);
  QString qatype = qaobj.findKeyword("SAMPLE_TYPE");
  int qabits = toInt(qaobj.findKeyword("SAMPLE_BITS")[0]);
  if (qalines != rawlines || qasamps != 296 || qatype != "MSB_UNSIGNED_INTEGER" ||
      qabits != 16) {
    QString msg = "Quality Assessment data in input file does not meet the ";
    msg += "following requirements: Size=296 columns, DataType=MSB_UNSIGNED_INTEGER, ";
    msg += "BitType=16";
    throw IException(IException::User, msg, _FILEINFO_);
  }
  keyval = qaobj.findKeyword("SCALING_FACTOR")[0];
  double qascale = keyval.toDouble(&ok);
  if (!ok) {
    qascale = 1.0;
  }
  keyval = qaobj.findKeyword("OFFSET")[0];
  double qaoffset = keyval.toDouble(&ok);
  if (!ok) {
    qaoffset = 0.0;
  }

  double qa[296*qalines];
  fseek(spcptr,qaptr,SEEK_SET);
  for (int i=0; i<qalines; i++) {
    for (int j=0; j<qasamps; j++) {
      size_t results = fread((void *)ibuf.ichar,2,1,spcptr);
      if (results != 1) {
        QString msg = "Error reading quality assessment data from input file";
        throw IException(IException::User, msg, _FILEINFO_);
      }
      obuf.ichar[0] = ibuf.ichar[1];
      obuf.ichar[1] = ibuf.ichar[0];
      qa[j+i*296] = (float)obuf.iword * qascale + qaoffset;
    }
  }

  PvlObject radobj = lab.findObject("SP_SPECTRUM_RAD");
  int radlines = toInt(radobj.findKeyword("LINES")[0]);
  int radsamps = toInt(radobj.findKeyword("LINE_SAMPLES")[0]);
  QString radtype = radobj.findKeyword("SAMPLE_TYPE");
  int radbits = toInt(radobj.findKeyword("SAMPLE_BITS")[0]);
  if (radlines != qalines || radsamps != 296 || radtype != "MSB_UNSIGNED_INTEGER" ||
      radbits != 16) {
    QString msg = "Radiance 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 = radobj.findKeyword("SCALING_FACTOR")[0];
  double radscale = keyval.toDouble(&ok);
  if (!ok) {
    radscale = 1.0;
  }
  keyval = radobj.findKeyword("OFFSET")[0];
  double radoffset = keyval.toDouble(&ok);
  if (!ok) {
    radoffset = 0.0;
  }

  double rad[296*radlines];
  fseek(spcptr,radptr,SEEK_SET);
  for (int i=0; i<radlines; i++) {
    for (int j=0; j<radsamps; j++) {
      size_t results = fread((void *)ibuf.ichar,2,1,spcptr);
      if (results != 1) {
        QString msg = "Error reading radiance data from input file";
        throw IException(IException::User, msg, _FILEINFO_);
      }
      obuf.ichar[0] = ibuf.ichar[1];
      obuf.ichar[1] = ibuf.ichar[0];
      rad[j+i*296] = (float)obuf.iword * radscale + radoffset;
    }
  }

  PvlObject refobj = lab.findObject("SP_SPECTRUM_REF");
  int reflines = toInt(refobj.findKeyword("LINES")[0]);
  int refsamps = toInt(refobj.findKeyword("LINE_SAMPLES")[0]);
  QString reftype = refobj.findKeyword("SAMPLE_TYPE");
  int refbits = toInt(refobj.findKeyword("SAMPLE_BITS")[0]);
  if (reflines != radlines || refsamps != 296 || reftype != "MSB_UNSIGNED_INTEGER" ||
      refbits != 16) {
    QString msg = "Reflectance 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 = refobj.findKeyword("SCALING_FACTOR")[0];
  double refscale = keyval.toDouble(&ok);
  if (!ok) {
    refscale = 1.0;
  }
  keyval = refobj.findKeyword("OFFSET")[0];
  double refoffset = keyval.toDouble(&ok);
  if (!ok) {
    refoffset = 0.0;
  }

  double ref[296*reflines];
  fseek(spcptr,refptr,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);
      if (results != 1) {
        QString msg = "Error reading reflectance data from input file";
        throw IException(IException::User, msg, _FILEINFO_);
      }
      obuf.ichar[0] = ibuf.ichar[1];
      obuf.ichar[1] = ibuf.ichar[0];
      ref[j+i*296] = (float)obuf.iword * refscale + refoffset;
    }
  }

  if (wavsamps != rawsamps || wavsamps != radsamps || wavsamps != refsamps ||
      wavsamps != qasamps || wavsamps != 296) {
    QString msg = "Number of columns in input file must be 296";
    throw IException(IException::User, msg, _FILEINFO_);
  }

  if (rawlines < maxobs) {
    maxobs = rawlines;
  }
  if (rawlines < minobs) {
    minobs = rawlines;
  }

  os << "WaveLength,";
  for (int i=minobs; i<=maxobs; i++) {
    os << "Raw" << i << ",Rad" << i << ",Ref" << i << ",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();
}
+97 −0
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">

  <brief>
    Imports a Kaguya SP (Spectral Profiler) 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.
  </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.
  </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.
  </p>
  </description>

  <history>
    <change name="Janet Barrett" date="2014-02-19">
      Original version. This program imports binary data
      from a Kaguya Spectral Profiler file and puts the 
      data into a tab delimited table.
    </change>
  </history>

  <category>
    <categoryItem>Utility</categoryItem>
  </category>

  <groups>
    <group name="Files">
      <parameter name="FROM">
        <type>filename</type>
        <fileMode>input</fileMode>
        <brief>
          Input Kaguya SP file
        </brief>
        <description>
          This is the input Kaguya SP file
        </description>
        <filter>
          *.spc
        </filter>
      </parameter>
      <parameter name="TO">
        <type>filename</type>
        <fileMode>output</fileMode>
        <brief>
          Output Kaguya text file
        </brief>
        <description>
          The output file will be formatted as a tab delimited
          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.
        </description>
      </parameter>
    </group>

    <group name="Limit Parameters">
      <parameter name="MINOBS">
        <type>string</type>
        <brief>Minimum observation</brief>
        <description>
          This is the minimum observation of the observation range
          for which information will be obtained from the input
          file. If no value is specified, then the minimum will be
          set to 1.
        </description>
        <default><item>None</item></default>
      </parameter>
      <parameter name="MAXOBS">
        <type>string</type>
        <brief>Maximum observation</brief>
        <description>
          This is the maximum observation of the observation range
          for which information will be obtained from the input 
          file. If no value is specified, then the maximum will be
          set to the maximum observation in the input file.
        </description>
        <default><item>None</item></default>
      </parameter>
    </group>
  </groups>
</application>
Loading