Commit 84b50230 authored by Summer Stapleton's avatar Summer Stapleton
Browse files

Merge branch 'CaSSIS_Pipeline' of github.com:USGS-Astrogeology/ISIS3 into iTime

parents fdcc0e18 7fd9ea88
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -49,16 +49,27 @@ namespace Isis {
  /**
   * Constructs a iTime object and initializes it to the time from the argument.
   *  
   * This constructor will (temporarily) strip the Z off of the end of an input UTC-formatted time 
   * if it is present. This time format is used by PDS4, but not presently supported by NAIF calls, 
   * in particular str2et_c, which is used by this class.  
   *  
   * @param time A time string formatted in standard UTC or similar format.
   *             Example:"2000/12/31 23:59:01.6789" or "2000-12-31T23:59:01.6789"
   *             Example:"2000/12/31 23:59:01.6789" or "2000-12-31T23:59:01.6789" or
   *             "2000-12-31T23:59:01.6789Z"
   */
  iTime::iTime(const QString &time) {
    LoadLeapSecondKernel();
    
    QString tempTime = time; 
    if (QString::compare(time.at(time.size() - 1), "Z", Qt::CaseInsensitive) == 0) {
      tempTime = time.left(time.size() - 1);
    }

    NaifStatus::CheckErrors();

    // Convert the time string to a double ephemeris time
    SpiceDouble et;
    str2et_c(time.toLatin1().data(), &et);
    str2et_c(tempTime.toLatin1().data(), &et);

    p_et = et;
    NaifStatus::CheckErrors();
+2 −0
Original line number Diff line number Diff line
@@ -72,6 +72,8 @@ namespace Isis {
   *           were signaled. References #2248.
   *  @history 2018-03-15 Adam Goins - Removed deprecated function iTime::UnloadLeapSecondKernel().
   *                          Fixes #5325.
   *  @history 2018-05-11 Kristin Berry and Makayla Shepherd - Added UTC time format that ends in Z,
   *                          as this format is used by PDS4 (and the TGO CaSSIS mission.) 
   */
  class iTime {
    public:
+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
+270 −0
Original line number Diff line number Diff line
#include "Isis.h"

#include "Application.h"
#include "Camera.h"
#include "Cube.h"
#include "FileList.h"
#include "IException.h"
#include "Pvl.h"
#include "IString.h"
#include "Longitude.h"
#include "OriginalLabel.h"
#include "Process.h"
#include "ProgramLauncher.h"
#include "TProjection.h"
#include "UserInterface.h"


using namespace std;
using namespace Isis;

#include <vector>

//functions in the code
void CompareLabels(Pvl &match, Pvl &comp);


void IsisMain() {

  // Get the list of cubes to mosaic

  UserInterface &ui = Application::GetUserInterface();
  FileList flist(ui.GetFileName("FROMLIST"));

  vector<Cube *> clist;
  try {
    if(flist.size() < 1) {
      QString msg = "the list file [" + ui.GetFileName("FROMLIST") +
                    "does not contain any data";
      throw IException(IException::User, msg, _FILEINFO_);
    }

    // open all the cube and place in vector clist

    for(int i = 0; i < flist.size(); i++) {
      Cube *c = new Cube();
      clist.push_back(c);
      c->open(flist[i].toString());
    }



    // run the compare function here.  This will conpare the
    // labels of the first cube to the labels of each following cube.
//     PvlKeyword sourceProductId("SourceProductId");
    QString ProdId;
    Pvl *pmatch = clist[0]->label();
    for(int i = 0; i < (int)clist.size(); i++) {
      Pvl *pcomp = clist[i]->label();
      CompareLabels(*pmatch, *pcomp);
      ProdId = (QString)pmatch->findGroup("Archive", Pvl::Traverse)["UniqueIdentifier"];
      QString bandname = (QString)pmatch->findGroup("BandBin", Pvl::Traverse)["FilterName"];
      bandname = bandname.toUpper();
      ProdId = ProdId + "_" + bandname;
    }
    
    bool runXY = true;

    //calculate the min and max lon
    double minLat = DBL_MAX;
    double maxLat = -DBL_MAX;
    double minLon = DBL_MAX;
    double maxLon = -DBL_MAX;
    double avgLat;
    double avgLon;
    for(int i = 0; i < (int)clist.size(); i++) {
      TProjection *proj = (TProjection *) clist[i]->projection();
      if(proj->MinimumLatitude() < minLat) minLat = proj->MinimumLatitude();
      if(proj->MaximumLatitude() > maxLat) maxLat = proj->MaximumLatitude();
      if(proj->MinimumLongitude() < minLon) minLon = proj->MinimumLongitude();
      if(proj->MaximumLongitude() > maxLon) maxLon = proj->MaximumLongitude();
    }
    avgLat = (minLat + maxLat) / 2;
    avgLon = (minLon + maxLon) / 2;
    TProjection *proj = (TProjection *) clist[0]->projection();
    proj->SetGround(avgLat, avgLon);
    avgLat = proj->UniversalLatitude();
    avgLon = proj->UniversalLongitude();
    // Use camera class to get Inc., emi., phase, and other values
    double Cemiss;
    double Cphase;
    double Cincid;
    double ClocalSolTime;
    double CsolarLong;
    double CsunAzimuth;
    double CnorthAzimuth;
    for(int i = 0; i < (int)clist.size(); i++) {
      Camera *cam = clist[i]->camera();
      if(cam->SetUniversalGround(avgLat, avgLon)) {
        Cemiss = cam->EmissionAngle();
        Cphase = cam->PhaseAngle();
        Cincid = cam->IncidenceAngle();
        ClocalSolTime = cam->LocalSolarTime();
        CsolarLong = cam->solarLongitude().degrees();
        CsunAzimuth = cam->SunAzimuth();
        CnorthAzimuth = cam->NorthAzimuth();
        runXY = false;
        break;
      }
    }

    //The code within the if runXY was added in 10/07 to find an intersect with
    //pole images that would fail when using projection set universal ground.
    // This is run if no intersect is found when using lat and lon in
    // projection space.
    if(runXY) {
      double startX = DBL_MAX;
      double endX = DBL_MIN;
      double startY = DBL_MAX;
      double endY =  DBL_MIN;
      for(int i = 0; i < (int)clist.size(); i++) {
        TProjection *proj = (TProjection *) clist[i]->projection();
        proj->SetWorld(0.5, 0.5);
        if(i == 0) {
          startX = proj->XCoord();
          endY = proj->YCoord();
        }
        else {
          if(proj->XCoord() < startX) startX =  proj->XCoord();
          if(proj->YCoord() > endY) endY = proj->YCoord();
        }
        Pvl *p = clist[i]->label();
        double nlines = p->findGroup("Dimensions", Pvl::Traverse)["Lines"];
        double nsamps = p->findGroup("Dimensions", Pvl::Traverse)["Samples"];

        proj->SetWorld((nsamps + 0.5), (nlines + 0.5));
        if(i == 0) {
          endX = proj->XCoord();
          startY = proj->YCoord();
        }
        else {
          if(proj->XCoord() > endX) endX =  proj->XCoord();
          if(proj->YCoord() < startY) startY = proj->YCoord();
        }
      }

      double avgX = (startX + endX) / 2;
      double avgY = (startY + endY) / 2;
      double sample = proj->ToWorldX(avgX);
      double line = proj->ToWorldY(avgY);

      for(int i = 0; i < (int)clist.size(); i++) {
        Camera *cam = clist[i]->camera();
        if(cam->SetImage(sample, line)) {
          Cemiss = cam->EmissionAngle();
          Cphase = cam->PhaseAngle();
          Cincid = cam->IncidenceAngle();
          ClocalSolTime = cam->LocalSolarTime();
          CsolarLong = cam->solarLongitude().degrees();
          CsunAzimuth = cam->SunAzimuth();
          CnorthAzimuth = cam->NorthAzimuth();
          runXY = false;
          break;
        }
      }
    }
    if(runXY) {
      QString msg = "Camera did not intersect images to gather stats";
      throw IException(IException::User, msg, _FILEINFO_);
    }

    // get the min SCLK values ( do this with QString comp.)
    // get the value from the original label blob
    QString startClock;
    QString startTime;
    for(int i = 0; i < (int)clist.size(); i++) {
      // himos used original label here. 

      Pvl *origLab = clist[i]->label();
      PvlGroup timegrp = origLab->findGroup("Instrument", Pvl::Traverse);

      if(i == 0) {
        startClock = (QString)timegrp["SpacecraftClockStartCount"];
        startTime = (QString)timegrp["StartTime"];
      }
      else {
        QString testStartTime = (QString)timegrp["StartTime"];
        if(testStartTime < startTime) {
          startTime = testStartTime;
          startClock = (QString)timegrp["SpacecraftClockStartCount"];
        }
      }
    }

    // Get the blob of original labels from first image in list
   // Pvl *org = clist[0]->label();

    //close all cubes
    for(int i = 0; i < (int)clist.size(); i++) {
      clist[i]->close();
      delete clist[i];
    }
    clist.clear();

    // automos step
    QString list = ui.GetFileName("FROMLIST");
    QString toMosaic = ui.GetFileName("TO");
    QString MosaicPriority = ui.GetString("PRIORITY");

    QString parameters = "FROMLIST=" + list + " MOSAIC=" + toMosaic + " PRIORITY=" + MosaicPriority;
    ProgramLauncher::RunIsisProgram("automos", parameters);

    // write out new information to new group mosaic


    PvlGroup mos("Mosaic");
    mos += PvlKeyword("ProductId ", ProdId);
//     mos += PvlKeyword(sourceProductId);
    mos += PvlKeyword("StartTime ", startTime);
    mos += PvlKeyword("SpacecraftClockStartCount ", startClock);
    mos += PvlKeyword("IncidenceAngle ", toString(Cincid), "DEG");
    mos += PvlKeyword("EmissionAngle ", toString(Cemiss), "DEG");
    mos += PvlKeyword("PhaseAngle ", toString(Cphase), "DEG");
    mos += PvlKeyword("LocalTime ", toString(ClocalSolTime), "LOCALDAY/24");
    mos += PvlKeyword("SolarLongitude ", toString(CsolarLong), "DEG");
    mos += PvlKeyword("SubSolarAzimuth ", toString(CsunAzimuth), "DEG");
    mos += PvlKeyword("NorthAzimuth ", toString(CnorthAzimuth), "DEG");

    Cube mosCube;
    mosCube.open(ui.GetFileName("TO"), "rw");
    PvlObject &lab = mosCube.label()->findObject("IsisCube");
    lab.addGroup(mos);
    //add orginal label blob to the output cube
//    mosCube.write(org);
    mosCube.close();

  }
  catch(IException &e) {
    for(int i = 0; i < (int)clist.size(); i++) {
      clist[i]->close();
      delete clist[i];
    }
    QString msg = "The mosaic [" + ui.GetFileName("TO") + "] was NOT created";
    throw IException(IException::User, msg, _FILEINFO_);
  }
} // end of isis main

//Function to compare label - CompareLabels
void CompareLabels(Pvl &pmatch, Pvl &pcomp) {
  // test of the ObservationId
//   PvlGroup matchgrp = pmatch.findGroup("Archive", Pvl::Traverse);
//   PvlGroup compgrp = pcomp.findGroup("Archive", Pvl::Traverse);
//   QString obsMatch = matchgrp["ObservationId"];
//   QString obsComp = compgrp["ObservationId"];
// 
//   if(obsMatch != obsComp) {
//     QString msg = "Images not from the same observation";
//     throw IException(IException::User, msg, _FILEINFO_);
//   }

  // Test of the BandBin filter name
  PvlGroup bmatchgrp = pmatch.findGroup("BandBin", Pvl::Traverse);
  PvlGroup bcompgrp = pcomp.findGroup("BandBin", Pvl::Traverse);
  QString bandMatch = bmatchgrp["FilterName"];
  QString bandComp = bcompgrp["FilterName"];

  if(bandMatch != bandComp) {
    QString msg = "Images not the same filter";
    throw IException(IException::User, msg, _FILEINFO_);
  }
}
+100 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="UTF-8"?>

<application name="tgocassismos" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://isis.astrogeology.usgs.gov/Schemas/Application/application.xsd">
  <brief>
    Produce an output mosaic of TGO CaSSIS images from the same observation and filter.
  </brief>

  <description>
    <p>
  If the final product wil not be an RDR, mapmos or automos can be used to produce a mosaic.  
  This program produces a mosaic and adds keywords to the label group "Mosaic" that are required 
  by hirdrgen. <br/>

  The  input cubes  to this program must be from the same observation, same filter, and map projected.<br/>  

   A new label group, required by tgocassisrdrgen, called "Mosaic"  is added to the image labels of 
   the output cube.  The original label blob is also propagated from the first file in the input list.<br/>
   </p>

<p>
  <b> processing sequence for single filter products that will become RDRs </b><br/>
         <b>cam2map</b> - project the cube.<br/>
         <b>tgocassismos</b> - mosaic files and add keywords to the mosaic group.<br/>
         <b>tgocassisrdrgen</b> - produce a RDR product.<br/>
</p>

 </description>

  <category>
    <missionItem>Trace Gas Orbiter</missionItem>
  </category>

  <history>
    <change name="Makayla Shepherd" date="2018-05-09">
      Original version.
    </change>
  </history>

  <groups>
    <group name="Files">
      <parameter name="FROMLIST">
        <type>filename</type>
        <fileMode>input</fileMode>
        <brief>
          Input list of files
        </brief>
        <description>
          A single colume list of TGO CaSSIS files that will be mosaiced together.  The input
          files must be from the some observation and be from the same filter.  The files must also
          be map projected.
        </description>
        <filter>
          *.lis *.lst *.txt
        </filter>
      </parameter>

      <parameter name="TO">
        <type>cube</type>
        <fileMode>output</fileMode>
        <brief>
          Output mosaic
        </brief>
        <description>
          The output mosaic cube with the new mosaic label group added.
        </description>
        <filter>
          *.cub
        </filter>
      </parameter>

      <parameter name="PRIORITY">
        <type>string</type>
        <default>
          <item>ONTOP</item>
        </default>
        <brief>The priority of pixel placement</brief>
        <description>
          This parameter is used to select one of two ways to masaic the
          pixels in areas of overlap.
        </description>

        <list>
          <option value="ONTOP">
            <brief>Input cube will be placed on top of the mosaic </brief>
            <description>
              When the input pixel is not Null, the input pixel
              value will be written to the output cube.
            </description>
          </option>
          <option value="BENEATH">
            <brief>Input cube will be placed beneath the mosaic</brief>
            <description>
              When the mosaic pixel is not Null it will be left unchanged.
            </description>
          </option>
        </list>
      </parameter>
    </group>
  </groups>
</application>
Loading