Example #1
0
void IsisMain(){

  const QString hical_program = "hicalbeta";
  const QString hical_version = "5.0";
  const QString hical_revision = "$Revision: 1.15 $";
  const QString hical_runtime = Application::DateTime();

  UserInterface &ui = Application::GetUserInterface();

  QString procStep("prepping phase");
  try {
//  The output from the last processing is the input into subsequent processing
    ProcessByLine p;

    Cube *hifrom = p.SetInputCube("FROM");
    int nsamps = hifrom->sampleCount();
    int nlines = hifrom->lineCount();

//  Initialize the configuration file
    QString conf(ui.GetAsString("CONF"));
    HiCalConf hiconf(*(hifrom->label()), conf);
    DbProfile hiprof = hiconf.getMatrixProfile();

// Check for label propagation and set the output cube
    Cube *ocube = p.SetOutputCube("TO");
    if ( !IsTrueValue(hiprof,"PropagateTables", "TRUE") ) {
      RemoveHiBlobs(*(ocube->label()));
    }

//  Set specified profile if entered by user
    if (ui.WasEntered("PROFILE")) {
      hiconf.selectProfile(ui.GetAsString("PROFILE"));
    }


//  Add OPATH parameter to profiles
    if (ui.WasEntered("OPATH")) {
      hiconf.add("OPATH",ui.GetAsString("OPATH"));
    }
    else {
      //  Set default to output directory
      hiconf.add("OPATH", FileName(ocube->fileName()).path());
    }

//  Do I/F output DN conversions
    QString units = ui.GetString("UNITS");

    //  Allocate the calibration list
    calVars = new MatrixList;

//  Set up access to HiRISE ancillary data (tables, blobs) here.  Note it they
//  are gone, this will error out. See PropagateTables in conf file.
    HiCalData caldata(*hifrom);

////////////////////////////////////////////////////////////////////////////
//  Drift Correction (Zf) using buffer pixels
//    Extracts specified regions of the calibration buffer pixels and runs
//    series of lowpass filters.  Apply spline fit if any missing data
//    remains.  Config file contains parameters for this operation.
    procStep = "ZeroBufferSmooth module";
    hiconf.selectProfile("ZeroBufferSmooth");
    hiprof = hiconf.getMatrixProfile();
    HiHistory ZbsHist;
    ZbsHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      ZeroBufferSmooth zbs(caldata, hiconf);
      calVars->add("ZeroBufferSmooth", zbs.ref());
      ZbsHist = zbs.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        zbs.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      //  NOT RECOMMENDED!  This is required for the next step!
      //  SURELY must be skipped with ZeroBufferSmooth step as well!
      calVars->add("ZeroBufferSmooth", HiVector(nlines, 0.0));
      ZbsHist.add("Debug::SkipModule invoked!");
    }

/////////////////////////////////////////////////////////////////////
// ZeroBufferFit
//  Compute second level of drift correction.  The high level noise
//  is removed from a modeled non-linear fit.
//
    procStep = "ZeroBufferFit module";
    HiHistory ZbfHist;
    hiconf.selectProfile("ZeroBufferFit");
    hiprof = hiconf.getMatrixProfile();
    ZbfHist.add("Profile["+ hiprof.Name()+"]");
    if (!SkipModule(hiprof) ) {
      ZeroBufferFit zbf(hiconf);

      calVars->add(hiconf.getProfileName(),
                   zbf.Normalize(zbf.Solve(calVars->get("ZeroBufferSmooth"))));
      ZbfHist = zbf.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        zbf.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add(hiconf.getProfileName(), HiVector(nlines, 0.0));
      ZbfHist.add("Debug::SkipModule invoked!");
    }


 ////////////////////////////////////////////////////////////////////
 //  ZeroReverse
    procStep = "ZeroReverse module";
    hiconf.selectProfile("ZeroReverse");
    hiprof = hiconf.getMatrixProfile();
    HiHistory ZrHist;
    ZrHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      ZeroReverse zr(caldata, hiconf);
      calVars->add(hiconf.getProfileName(), zr.ref());
      ZrHist = zr.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        zr.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add(hiconf.getProfileName(), HiVector(nsamps, 0.0));
      ZrHist.add("Debug::SkipModule invoked!");
    }

/////////////////////////////////////////////////////////////////
// ZeroDark removes dark current
//
    procStep = "ZeroDark module";
    hiconf.selectProfile("ZeroDark");
    hiprof =  hiconf.getMatrixProfile();
    HiHistory ZdHist;
    ZdHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      ZeroDark zd(hiconf);
      calVars->add(hiconf.getProfileName(), zd.ref());
      ZdHist = zd.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        zd.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add(hiconf.getProfileName(), HiVector(nsamps, 0.0));
      ZdHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
// GainLineDrift correct for gain-based drift
//
    procStep = "GainLineDrift module";
    hiconf.selectProfile("GainLineDrift");
    hiprof = hiconf.getMatrixProfile();
    HiHistory GldHist;
    GldHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      GainLineDrift gld(hiconf);
      calVars->add(hiconf.getProfileName(), gld.ref());
      GldHist = gld.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        gld.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add(hiconf.getProfileName(), HiVector(nlines, 1.0));
      GldHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
//  GainNonLinearity  Correct for non-linear gain
    procStep = "GainNonLinearity module";
    hiconf.selectProfile("GainNonLinearity");
    hiprof =  hiconf.getMatrixProfile();
    HiHistory GnlHist;
    GnlHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      GainNonLinearity gnl(hiconf);
      calVars->add(hiconf.getProfileName(), gnl.ref());
      GnlHist = gnl.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        gnl.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add(hiconf.getProfileName(), HiVector(1, 0.0));
      GnlHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
//  GainChannelNormalize  Correct for sample gain with the G matrix
    procStep = "GainChannelNormalize module";
    hiconf.selectProfile("GainChannelNormalize");
    hiprof =  hiconf.getMatrixProfile();
    HiHistory GcnHist;
    GcnHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      GainChannelNormalize gcn(hiconf);
      calVars->add(hiconf.getProfileName(), gcn.ref());
      GcnHist = gcn.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        gcn.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add(hiconf.getProfileName(), HiVector(nsamps, 1.0));
      GcnHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
//  GainFlatField  Flat field correction with A matrix
    procStep = "GainFlatField module";
    hiconf.selectProfile("GainFlatField");
    hiprof =  hiconf.getMatrixProfile();
    HiHistory GffHist;
    GffHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      GainFlatField gff(hiconf);
      calVars->add(hiconf.getProfileName(), gff.ref());
      GffHist = gff.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        gff.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add(hiconf.getProfileName(), HiVector(nsamps, 1.0));
      GffHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
// GainTemperature -  Temperature-dependant gain correction
    procStep = "GainTemperature module";
    hiconf.selectProfile("GainTemperature");
    hiprof =  hiconf.getMatrixProfile();
    HiHistory GtHist;
    GtHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      GainTemperature gt(hiconf);
      calVars->add(hiconf.getProfileName(), gt.ref());
      GtHist = gt.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        gt.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add(hiconf.getProfileName(), HiVector(nsamps, 1.0));
      GtHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
//  GainUnitConversion converts to requested units
//
    procStep = "GainUnitConversion module";
    hiconf.selectProfile("GainUnitConversion");
    hiprof = hiconf.getMatrixProfile();
    HiHistory GucHist;
    GucHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      GainUnitConversion guc(hiconf, units);
      calVars->add(hiconf.getProfileName(), guc.ref());
      GucHist = guc.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        guc.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add(hiconf.getProfileName(), HiVector(1,1.0));
      GucHist.add("Debug::SkipModule invoked!");
      GucHist.add("Units[Unknown]");
    }

    //  Reset the profile selection to default
    hiconf.selectProfile();

//----------------------------------------------------------------------
//
/////////////////////////////////////////////////////////////////////////
//  Call the processing function
    procStep = "calibration phase";
    p.StartProcess(calibrate);

    // Get the default profile for logging purposes
    hiprof = hiconf.getMatrixProfile();
    const QString conf_file = hiconf.filepath(conf);

    // Quitely dumps parameter history to alternative format file.  This
    // is completely controlled by the configuration file
    if ( hiprof.exists("DumpHistoryFile") ) {
      procStep = "logging/reporting phase";
      FileName hdump(hiconf.getMatrixSource("DumpHistoryFile",hiprof));
      QString hdumpFile = hdump.expanded();
      ofstream ofile(hdumpFile.toAscii().data(), ios::out);
      if (!ofile) {
        QString mess = "Unable to open/create history dump file " +
                      hdump.expanded();
        IException(IException::User, mess, _FILEINFO_).print();
      }
      else {
        ofile << "Program:  " << hical_program << endl;
        ofile << "RunTime:  " << hical_runtime << endl;
        ofile << "Version:  " << hical_version << endl;
        ofile << "Revision: " << hical_revision << endl << endl;

        ofile << "FROM:     " << hifrom->fileName() << endl;
        ofile << "TO:       " << ocube->fileName()  << endl;
        ofile << "CONF:     " << conf_file  << endl << endl;

        ofile << "/* " << hical_program << " application equation */\n"
              << "/* hdn = (idn - ZeroBufferFit(ZeroBufferSmooth) - ZeroReverse - ZeroDark) */\n"
              << "/* odn = hdn / GainLineDrift * GainNonLinearity * GainChannelNormalize */\n"
              << "/*           * GainFlatField  * GainTemperature / GainUnitConversion */\n\n";

        ofile << "****** PARAMETER GENERATION HISTORY *******" << endl;
        ofile << "\nZeroBufferSmooth   = " << ZbsHist << endl;
        ofile << "\nZeroBufferFit   = " << ZbfHist << endl;
        ofile << "\nZeroReverse   = " << ZrHist << endl;
        ofile << "\nZeroDark   = " << ZdHist << endl;
        ofile << "\nGainLineDrift   = " << GldHist << endl;
        ofile << "\nGainNonLinearity   = " << GnlHist << endl;
        ofile << "\nGainChannelNormalize = " << GcnHist << endl;
        ofile << "\nGainFlatField   = " << GffHist << endl;
        ofile << "\nGainTemperature   = " << GtHist << endl;
        ofile << "\nGainUnitConversion = " << GucHist << endl;

        ofile.close();
      }
    }

//  Ensure the RadiometricCalibration group is out there
    const QString rcalGroup("RadiometricCalibration");
    if (!ocube->hasGroup(rcalGroup)) {
      PvlGroup temp(rcalGroup);
      ocube->putGroup(temp);
    }

    PvlGroup &rcal = ocube->group(rcalGroup);
    rcal += PvlKeyword("Program", hical_program);
    rcal += PvlKeyword("RunTime", hical_runtime);
    rcal += PvlKeyword("Version",hical_version);
    rcal += PvlKeyword("Revision",hical_revision);

    PvlKeyword key("Conf", conf_file);
    key.addCommentWrapped("/* " + hical_program + " application equation */");
    key.addComment("/* hdn = idn - ZeroBufferFit(ZeroBufferSmooth) */");
    key.addComment("/*           - ZeroReverse - ZeroDark */");
    key.addComment("/* odn = hdn / GainLineDrift * GainNonLinearity */");
    key.addComment("/*           * GainChannelNormalize * GainFlatField */");
    key.addComment("/*           * GainTemperature / GainUnitConversion */");
    rcal += key;

    //  Record parameter generation history.  Controllable in configuration
    //  file.  Note this is optional because of a BUG!! in the ISIS label
    //  writer as this application was initially developed
    if ( IsEqual(ConfKey(hiprof,"LogParameterHistory",QString("TRUE")),"TRUE")) {
      rcal += ZbsHist.makekey("ZeroBufferSmooth");
      rcal += ZbfHist.makekey("ZeroBufferFit");
      rcal += ZrHist.makekey("ZeroReverse");
      rcal += ZdHist.makekey("ZeroDark");
      rcal += GldHist.makekey("GainLineDrift");
      rcal += GnlHist.makekey("GainNonLinearity");
      rcal += GcnHist.makekey("GainChannelNormalize");
      rcal += GffHist.makekey("GainFlatField");
      rcal += GtHist.makekey("GainTemperature");
      rcal += GucHist.makekey("GainUnitConversion");
    }

    p.EndProcess();
  }
  catch (IException &ie) {
    delete calVars;
    calVars = 0;
    QString mess = "Failed in " + procStep;
    throw IException(ie, IException::User, mess, _FILEINFO_);
  }

// Clean up parameters
  delete calVars;
  calVars = 0;
}
Example #2
0
void IsisMain(){

  const std::string hical_program = "hicalbeta";
  const std::string hical_version = "3.5";
  const std::string hical_revision = "$Revision: 1.14 $";
  const std::string hical_runtime = Application::DateTime();

  UserInterface &ui = Application::GetUserInterface();

  string procStep("prepping phase");
  try {
//  The output from the last processing is the input into subsequent processing
    ProcessByLine p;

    Cube *hifrom = p.SetInputCube("FROM");
    int nsamps = hifrom->Samples();
    int nlines = hifrom->Lines();

//  Initialize the configuration file
    string conf(ui.GetAsString("CONF"));
    HiCalConf hiconf(*(hifrom->Label()), conf);
    DbProfile hiprof = hiconf.getMatrixProfile();

// Check for label propagation and set the output cube
    Cube *ocube = p.SetOutputCube("TO");
    if ( !IsTrueValue(hiprof,"PropagateTables", "TRUE") ) {
      RemoveHiBlobs(*(ocube->Label()));
    }

//  Set specified profile if entered by user
    if (ui.WasEntered("PROFILE")) {
      hiconf.selectProfile(ui.GetAsString("PROFILE"));
    }


//  Add OPATH parameter to profiles
    if (ui.WasEntered("OPATH")) {
      hiconf.add("OPATH",ui.GetAsString("OPATH"));
    }
    else {
      //  Set default to output directory
      hiconf.add("OPATH", Filename(ocube->Filename()).Path());
    }

//  Do I/F output DN conversions
    string units = ui.GetString("UNITS");

    //  Allocate the calibration list
    calVars = new MatrixList;

//  Set up access to HiRISE ancillary data (tables, blobs) here.  Note it they
//  are gone, this will error out. See PropagateTables in conf file.
    HiCalData caldata(*hifrom);

////////////////////////////////////////////////////////////////////////////
//  FixGaps (Z_f) Get buffer pixels and compute coefficients for equation
//     y = a[0] + a[1]*x + a[2] * exp(a[3] * x)
//        where y is the average of the buffer pixel region,
//          and x is the time at each line in electrons/sec/pixel
    procStep = "Zf module";
    hiconf.selectProfile("Zf");
    hiprof = hiconf.getMatrixProfile();
    HiHistory ZfHist;
    ZfHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      DriftBuffer driftB(caldata, hiconf);
      calVars->add("Zf", driftB.ref());
      ZfHist = driftB.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        driftB.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      //  NOT RECOMMENDED!  This is required for the next step!
      //  SURELY must be skipped with Z_d step as well!
      calVars->add("Zf", HiVector(nlines, 0.0));
      ZfHist.add("Debug::SkipModule invoked!");
    }

/////////////////////////////////////////////////////////////////////
// DriftCorrect (Z_d)
//  Now compute the equation of fit
// 
    procStep = "Zd module";
    HiHistory ZdHist;
    hiconf.selectProfile("Zd");
    hiprof = hiconf.getMatrixProfile();
    ZdHist.add("Profile["+ hiprof.Name()+"]");
    if (!SkipModule(hiconf.getMatrixProfile("Zd")) ) { 
      DriftCorrect driftC(hiconf);
      calVars->add("Zd", driftC.Normalize(driftC.Solve(calVars->get("Zf"))));
      ZdHist = driftC.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        driftC.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zd", HiVector(nlines, 0.0));
      ZdHist.add("Debug::SkipModule invoked!");
    }


 ////////////////////////////////////////////////////////////////////
 //  ZeroCorrect (Z_z)  Get reverse clock 
    procStep = "Zz module";
    hiconf.selectProfile("Zz"); 
    hiprof = hiconf.getMatrixProfile();
    HiHistory ZzHist;
    ZzHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      OffsetCorrect zoff(caldata, hiconf);
      calVars->add("Zz", zoff.ref());
      ZzHist = zoff.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        zoff.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zz", HiVector(nsamps, 0.0));
      ZzHist.add("Debug::SkipModule invoked!");
    }

/////////////////////////////////////////////////////////////////
// DarkSubtract (Z_b) Remove dark current
// 
    procStep = "Zb module";
    hiconf.selectProfile("Zb");
    hiprof =  hiconf.getMatrixProfile();
    HiHistory ZbHist;
    ZbHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      DarkSubtractComp dark(hiconf);
      calVars->add("Zb", dark.ref());
      ZbHist = dark.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        dark.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zb", HiVector(nsamps, 0.0));
      ZbHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
// GainVLineCorrect (Z_g) Correct for gain-based drift
// 
    procStep = "Zg module";
    hiconf.selectProfile("Zg");
    hiprof = hiconf.getMatrixProfile();
    HiHistory ZgHist;
    ZgHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      GainVLineComp gainV(hiconf);
      calVars->add("Zg", gainV.ref());
      ZgHist = gainV.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        gainV.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zg", HiVector(nlines, 1.0));
      ZgHist.add("Debug::SkipModule invoked!");
    }


////////////////////////////////////////////////////////////////////
//  GainCorrect (Z_gg)  Correct for gain with the G matrix 
    procStep = "Zgg module";
    hiconf.selectProfile("Zgg"); 
    hiprof =  hiconf.getMatrixProfile();
    HiHistory ZggHist;
    ZggHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      double bin = ToDouble(hiprof("Summing"));
      double tdi = ToDouble(hiprof("Tdi"));
      double factor = 128.0 / tdi / (bin*bin);
      HiVector zgg =  hiconf.getMatrix("G", hiprof);
      for ( int i = 0 ; i < zgg.dim() ; i++ ) { zgg[i] *= factor; }
      calVars->add("Zgg", zgg);;
      ZggHist.add("LoadMatrix(G[" + hiconf.getMatrixSource("G",hiprof) +
                  "],Band[" + ToString(hiconf.getMatrixBand(hiprof)) + 
                  "],Factor[" + ToString(factor) + "])"); 
      if ( hiprof.exists("DumpModuleFile") ) { 
        Component zg("GMatrix", ZggHist);
        zg.Process(zgg);
        zg.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zgg", HiVector(nsamps, 1.0));
      ZggHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
//  FlatField (Z_a)  Flat field correction with A matrix
    procStep = "Za module";
    hiconf.selectProfile("Za"); 
    hiprof =  hiconf.getMatrixProfile();
    HiHistory ZaHist;
    ZaHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      FlatFieldComp flat(hiconf);
      calVars->add("Za", flat.ref());
      ZaHist = flat.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        flat.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Za", HiVector(nsamps, 1.0));
      ZaHist.add("Debug::SkipModule invoked!");
    }

////////////////////////////////////////////////////////////////////
//  FlatField (Z_t)  Temperature-dependant gain correction
    procStep = "Zt module";
    hiconf.selectProfile("Zt"); 
    hiprof =  hiconf.getMatrixProfile();
    HiHistory ZtHist;
    ZtHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      TempGainCorrect tcorr(hiconf);
      calVars->add("Zt", tcorr.ref());
      ZtHist = tcorr.History();
      if ( hiprof.exists("DumpModuleFile") ) {
        tcorr.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof));
      }
    }
    else {
      calVars->add("Zt", HiVector(nsamps, 1.0));
      ZtHist.add("Debug::SkipModule invoked!");
    }


////////////////////////////////////////////////////////////////////
//  I/FCorrect (Z_iof) Conversion to I/F
// 
    procStep = "Ziof module";
    hiconf.selectProfile("Ziof");
    hiprof = hiconf.getMatrixProfile();
    HiHistory ZiofHist;
    ZiofHist.add("Profile["+ hiprof.Name()+"]");
    if ( !SkipModule(hiprof) ) {
      double sed = ToDouble(hiprof("ScanExposureDuration"));  // units = us
      if ( IsEqual(units, "IOF") ) {
        //  Add solar I/F correction parameters
        double au = hiconf.sunDistanceAU();
        ZiofHist.add("SunDist[" + ToString(au) + " (AU)]");
        double suncorr =  1.5 / au;
        suncorr *= suncorr;

        double zbin  = ToDouble(hiprof("ZiofBinFactor"));
        ZiofHist.add("ZiofBinFactor[" + ToString(zbin) + "]");

        double zgain = ToDouble(hiprof("FilterGainCorrection"));
        ZiofHist.add("FilterGainCorrection[" + ToString(zgain) + "]");
        ZiofHist.add("ScanExposureDuration[" + ToString(sed) + "]");
        double ziof = (zbin * zgain) * (sed * 1.0e-6)  * suncorr; 

        calVars->add("Ziof", HiVector(1, ziof));
        ZiofHist.add("I/F_Factor[" + ToString(ziof) + "]");
        ZiofHist.add("Units[I/F Reflectance]");
      }
      else if (  IsEqual(units, "DN/US") ) {
        // Ziof is a divisor in calibration equation
        double ziof = sed;
        calVars->add("Ziof", HiVector(1, ziof));
        ZiofHist.add("ScanExposureDuration[" + ToString(sed) + "]");
        ZiofHist.add("DN/US_Factor[" + ToString(ziof) + "]");
        ZiofHist.add("Units[DNs/microsecond]");
      }
      else {
        // Units are already in DN
        double ziof = 1.0;
        calVars->add("Ziof", HiVector(1, ziof));
        ZiofHist.add("DN_Factor[" + ToString(ziof) + "]");
        ZiofHist.add("Units[DN]");
      }
    }
    else {
      calVars->add("Ziof", HiVector(1,1.0));
      ZiofHist.add("Debug::SkipModule invoked!");
      ZiofHist.add("Units[Unknown]");
    }

    //  Reset the profile selection to default
    hiconf.selectProfile();

//----------------------------------------------------------------------
// 
/////////////////////////////////////////////////////////////////////////
//  Call the processing function
    procStep = "calibration phase";
    p.StartProcess(calibrate);

    // Get the default profile for logging purposes
    hiprof = hiconf.getMatrixProfile();
    const std::string conf_file = hiconf.filepath(conf);

    // Quitely dumps parameter history to alternative format file.  This
    // is completely controlled by the configuration file
    if ( hiprof.exists("DumpHistoryFile") ) {
      procStep = "logging/reporting phase";
      Filename hdump(hiconf.getMatrixSource("DumpHistoryFile",hiprof));
      string hdumpFile = hdump.Expanded();
      ofstream ofile(hdumpFile.c_str(), ios::out);
      if (!ofile) {
        string mess = "Unable to open/create history dump file " + 
                      hdump.Expanded();
        iException::Message(iException::User, mess, _FILEINFO_).Report();
      }
      else {
        ofile << "Program:  " << hical_program << endl;
        ofile << "RunTime:  " << hical_runtime << endl;
        ofile << "Version:  " << hical_version << endl;
        ofile << "Revision: " << hical_revision << endl << endl;

        ofile << "FROM:     " << hifrom->Filename() << endl;
        ofile << "TO:       " << ocube->Filename()  << endl;
        ofile << "CONF:     " << conf_file  << endl << endl;

        ofile << "/* " << hical_program << " application equation */" << endl
              << "/* hdn = (idn - Zd(Zf) - Zz - Zb) */"
              << endl << "/* odn = hdn / Zg * Zgg * Za * Zt / Ziof */" 
              << endl << endl;

        ofile << "****** PARAMETER GENERATION HISTORY *******" << endl;
        ofile << "\nZf   = " << ZfHist << endl;
        ofile << "\nZd   = " << ZdHist << endl;
        ofile << "\nZz   = " << ZzHist << endl;
        ofile << "\nZb   = " << ZbHist << endl;
        ofile << "\nZg   = " << ZgHist << endl;
        ofile << "\nZgg  = " << ZggHist << endl;
        ofile << "\nZa   = " << ZaHist << endl;
        ofile << "\nZt   = " << ZtHist << endl;
        ofile << "\nZiof = " << ZiofHist << endl;

        ofile.close();
      }
    }

//  Ensure the RadiometricCalibration group is out there
    const std::string rcalGroup("RadiometricCalibration");
    if (!ocube->HasGroup(rcalGroup)) {
      PvlGroup temp(rcalGroup);
      ocube->PutGroup(temp);
    }

    PvlGroup &rcal = ocube->GetGroup(rcalGroup);
    rcal += PvlKeyword("Program", hical_program);
    rcal += PvlKeyword("RunTime", hical_runtime);
    rcal += PvlKeyword("Version",hical_version);
    rcal += PvlKeyword("Revision",hical_revision);

    PvlKeyword key("Conf", conf_file);
    key.AddCommentWrapped("/* " + hical_program + " application equation */");
    key.AddComment("/* hdn = (idn - Zd(Zf) - Zz - Zb) */");
    key.AddComment("/* odn = hdn / Zg * Zgg * Za * Zt / Ziof */");
    rcal += key;

    //  Record parameter generation history.  Controllable in configuration
    //  file.  Note this is optional because of a BUG!! in the ISIS label
    //  writer as this application was initially developed
    if ( IsEqual(ConfKey(hiprof,"LogParameterHistory",string("TRUE")),"TRUE")) { 
      rcal += ZfHist.makekey("Zf");
      rcal += ZdHist.makekey("Zd");
      rcal += ZzHist.makekey("Zz");
      rcal += ZbHist.makekey("Zb");
      rcal += ZgHist.makekey("Zg");
      rcal += ZggHist.makekey("Zgg");
      rcal += ZaHist.makekey("Za");
      rcal += ZiofHist.makekey("Ziof");
    }

    p.EndProcess();
  } 
  catch (iException &ie) {
    delete calVars;
    calVars = 0;
    string mess = "Failed in " + procStep;
    ie.Message(iException::User, mess.c_str(), _FILEINFO_);
    throw;
  }
  
// Clean up parameters
  delete calVars;
  calVars = 0;
}