Commit 97f8485a authored by Ian Humphrey's avatar Ian Humphrey
Browse files

Added heldList functionality back to jigsaw. Can hold non-overlapping images...

Added heldList functionality back to jigsaw. Can hold non-overlapping images during a bundle adjustment. Turned off solving by sensor (turned off USEPVL, SC_PARAMETERS). Fixes #4293.

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/branches/ipce@7162 41f8697f-d340-4b68-9986-7bafba869bb8
parent 64b5e60c
Loading
Loading
Loading
Loading
+197 −72
Original line number Original line Diff line number Diff line
#include "Isis.h"
#include "Isis.h"


#include <QDir>
#include <QDir>
#include <QObject>
#include <QList>
#include <QList>
#include <QObject>
#include <QObject>
#include <QSharedPointer>
#include <QSharedPointer>
#include <QString>
#include <QString>
#include <QChar>


#include "BundleAdjust.h"
#include "BundleAdjust.h"
#include "BundleResults.h"
#include "BundleObservationSolveSettings.h"
#include "BundleObservationSolveSettings.h"
#include "BundleResults.h"
#include "BundleSettings.h"
#include "BundleSettings.h"
#include "BundleSolutionInfo.h"
#include "BundleSolutionInfo.h"
#include "ControlMeasure.h"
#include "ControlNet.h"
#include "ControlPoint.h"
#include "CubeAttribute.h"
#include "CubeAttribute.h"
#include "IException.h"
#include "IException.h"
#include "iTime.h"
#include "iTime.h"
#include "MaximumLikelihoodWFunctions.h"
#include "MaximumLikelihoodWFunctions.h"
#include "Process.h"
#include "Process.h"
#include "SerialNumber.h"
#include "SerialNumberList.h"
#include "Table.h"
#include "Table.h"


using namespace std;
using namespace std;
using namespace Isis;
using namespace Isis;


BundleSettingsQsp bundleSettings(UserInterface &ui);
BundleSettingsQsp bundleSettings(UserInterface &ui);
void checkImageList(SerialNumberList &heldSerialList, SerialNumberList &cubeSerialList);
QList<BundleObservationSolveSettings> observationSolveSettings(UserInterface &ui);
QList<BundleObservationSolveSettings> observationSolveSettings(UserInterface &ui);
ControlNetQsp fixHeldImages(const QString &cnetFile,
                            const QString &heldList,
                            const QString &imageList);


void IsisMain() {
void IsisMain() {


@@ -46,13 +53,15 @@ void IsisMain() {
  QString cubeList = ui.GetFileName("FROMLIST");
  QString cubeList = ui.GetFileName("FROMLIST");
  
  
  // retrieve settings from jigsaw gui
  // retrieve settings from jigsaw gui
  
  BundleSettingsQsp settings = bundleSettings(ui);
  BundleSettingsQsp settings = bundleSettings(ui);
  BundleAdjust *bundleAdjustment = NULL;
  BundleAdjust *bundleAdjustment = NULL;

  // Get the held list if entered and prep for bundle adjustment
  // Get the held list if entered and prep for bundle adjustment, to determine which constructor to use
  if (ui.WasEntered("HELDLIST")) {
  if (ui.WasEntered("HELDLIST")) {
    QString heldList = ui.GetFileName("HELDLIST");
    QString heldList = ui.GetFileName("HELDLIST");
    bundleAdjustment = new BundleAdjust(settings, cnetFile, cubeList, heldList);
    // Update the control network so that any control points intersecting a held image are fixed
    ControlNetQsp cnet = fixHeldImages(cnetFile, heldList, cubeList);
    bundleAdjustment = new BundleAdjust(settings, cnet, cubeList);
  }
  }
  else {
  else {
    bundleAdjustment = new BundleAdjust(settings, cnetFile, cubeList);
    bundleAdjustment = new BundleAdjust(settings, cnetFile, cubeList);
@@ -116,7 +125,6 @@ void IsisMain() {


          //  Get Kernel group and add or replace LastModifiedInstrumentPointing
          //  Get Kernel group and add or replace LastModifiedInstrumentPointing
          //  keyword.
          //  keyword.
          if (bundleAdjustment->isHeld(i)) continue;   // Don't update held images at all
          Table cmatrix = bundleAdjustment->cMatrix(i);
          Table cmatrix = bundleAdjustment->cMatrix(i);
          QString jigComment = "Jigged = " + Isis::iTime::CurrentLocalTime();
          QString jigComment = "Jigged = " + Isis::iTime::CurrentLocalTime();
          cmatrix.Label().addComment(jigComment);
          cmatrix.Label().addComment(jigComment);
@@ -249,30 +257,41 @@ BundleSettingsQsp bundleSettings(UserInterface &ui) {
}
}




QList<BundleObservationSolveSettings> observationSolveSettings(UserInterface &ui) {
/**
  //************************************************************************************************
 * Checks that all the first serial numbers are in the second serial numbers list (FROMLIST).
  QList<BundleObservationSolveSettings> observationSolveSettingsList;
 *
  bool usePvl = ui.GetBoolean("USEPVL");
 * Note: This function is used for verifying HELDLIST is in the FROMLIST.
  PvlObject obj;
 *
  if (usePvl) {
 * @param imageList List of image serial numbers to check to make sure they're in the second list.
    ui.GetFileName("SC_PARAMETERS");
 * @param fromList List of input image serial numbers to check against.
    Pvl scParPvl(FileName(ui.GetFileName("SC_PARAMETERS")).expanded());
 *
    if (!scParPvl.hasObject("SensorParameters")) {
 * @throws IException::User "The following images are not in the FROMLIST:"
      QString msg = "Input SC_PARAMETERS file missing SensorParameters object";
 */
      throw IException(IException::User, msg, _FILEINFO_);
  void checkImageList(SerialNumberList &imageList, SerialNumberList &fromList) {
  // Keep track of which held images are not in the FROMLIST
  QString imagesNotFound;

  for (int img = 0; img < imageList.size(); img++) {
    // When the FROMLIST does not have the current image, record the image's filename 
    if ( !fromList.hasSerialNumber(imageList.serialNumber(img)) ) {
      imagesNotFound += " [" + imageList.fileName(img) + "]";
    }
  }
  }


    // loop over parameter groups, read settings for each sensor into a
  // Inform the user which images are not in the second list
    // BundleObservationSolveSettings object, and append to observationSolveSettingsList
  if (!imagesNotFound.isEmpty()) {
    obj = scParPvl.findObject("SensorParameters");
    QString msg = "The following images are not in the FROMLIST:";
    PvlObject::PvlGroupIterator g;
    msg += imagesNotFound + ".";
    BundleObservationSolveSettings solveSettings;
    throw IException(IException::User, msg, _FILEINFO_);
    for(g = obj.beginGroup(); g != obj.endGroup(); ++g) {
      solveSettings.setFromPvl(*g);
      observationSolveSettingsList.append(solveSettings);
  }
  }
}
}
  else { // we're not using the pvl, so get what will be solve settings for all images from gui


QList<BundleObservationSolveSettings> observationSolveSettings(UserInterface &ui) {
  //************************************************************************************************
  QList<BundleObservationSolveSettings> observationSolveSettingsList;

  // We are not using the PVL, so get what will be solve settings for all images from gui
  BundleObservationSolveSettings observationSolveSettings;
  BundleObservationSolveSettings observationSolveSettings;


  BundleObservationSolveSettings::InstrumentPointingSolveOption pointingSolveOption =
  BundleObservationSolveSettings::InstrumentPointingSolveOption pointingSolveOption =
@@ -324,8 +343,114 @@ QList<BundleObservationSolveSettings> observationSolveSettings(UserInterface &ui
                                                          positionAprioriSigma,
                                                          positionAprioriSigma,
                                                          positionVelocityAprioriSigma,
                                                          positionVelocityAprioriSigma,
                                                          positionAccelerationAprioriSigma);
                                                          positionAccelerationAprioriSigma);

  // If we are holding any images, then we need a BundleObservationSolveSettings for the held
  // images, and another one for the non-held images
  if (ui.WasEntered("HELDLIST")) {
    // Check that the held images are present in the input image list
    QString heldList = ui.GetFileName("HELDLIST");
    QString fromList = ui.GetFileName("FROMLIST");
    SerialNumberList heldSNs(heldList);
    SerialNumberList cubeSNs(fromList);
    checkImageList(heldSNs, cubeSNs);

    // The settings for the held images will have no pointing or position factors considered
    BundleObservationSolveSettings heldSettings;
    BundleObservationSolveSettings::InstrumentPointingSolveOption noPointing = 
        BundleObservationSolveSettings::stringToInstrumentPointingSolveOption(
            "NoPointingFactors");
    heldSettings.setInstrumentPointingSettings(noPointing,
                                                ui.GetBoolean("TWIST"),
                                                ui.GetInteger("CKDEGREE"),
                                                ui.GetInteger("CKSOLVEDEGREE"),
                                                ui.GetBoolean("OVEREXISTING"),
                                                positionAprioriSigma,
                                                angularVelocityAprioriSigma,
                                                angularAccelerationAprioriSigma);
    BundleObservationSolveSettings::InstrumentPositionSolveOption noPosition =
        BundleObservationSolveSettings::stringToInstrumentPositionSolveOption(
            "NoPositionFactors");
    heldSettings.setInstrumentPositionSettings(noPosition,
                                                ui.GetInteger("SPKDEGREE"),
                                                ui.GetInteger("SPKSOLVEDEGREE"),
                                                ui.GetBoolean("OVERHERMITE"),
                                                positionAprioriSigma,
                                                positionVelocityAprioriSigma,
                                                positionAccelerationAprioriSigma);

    // Add the held images' observationNumbers to the held observation solve settings
    for (int sn = 0; sn < cubeSNs.size(); sn++) {
      if ( heldSNs.hasSerialNumber(cubeSNs.serialNumber(sn)) ) {
        // For held images, we want to set pointing and position settings to NONE, effectively
        // ensuring that the number of pointing and position parameters for the holds are 0
        heldSettings.addObservationNumber(cubeSNs.observationNumber(sn));
      }
      else {
        observationSolveSettings.addObservationNumber(cubeSNs.observationNumber(sn));
      }
    }
    // Add both the non-held and held observation solve settings to the list of solve settings
    // for the BundleAdjust
    observationSolveSettingsList.append(observationSolveSettings);
    observationSolveSettingsList.append(heldSettings);
  }
  // If not using a held list, we just append the GUI acquired solve parameters
  else {
    observationSolveSettingsList.append(observationSolveSettings);
    observationSolveSettingsList.append(observationSolveSettings);
  }
  }
  //************************************************************************************************
  //************************************************************************************************
  return observationSolveSettingsList;
  return observationSolveSettingsList;
}
}


/**
 * Control points that intersect the held images are set to fixed. The points' a priori values
 * are each set to the corresponding surface points of the associated held image's measures.
 * 
 * Note that this returns a ControlNetQsp to the modified input control network.
 * 
 * @param cnetFile QString name of the control network file.
 * @param heldList QString name of the held list file.
 * @param imageLise QString name of the input image list file.
 * 
 * @throws IException::User "Cannot compute surface point for control point [], measure [].
 * 
 * @return @b ControlNetQsp Returns a shared pointer to the modified control network.
 * 
 * @internal
 *   @todo Currently only works for NON-overlapping held images. Any control points that intersect
 *         the held images are set to FIXED and have their apriori surface points set to
 *         corresponding surface points for the held image's measures. 
 */
ControlNetQsp fixHeldImages(const QString &cnetFile, 
                            const QString &heldList, 
                            const QString &snList) {
  ControlNetQsp cnet(new ControlNet(cnetFile));
  // Set up the cameras for all the input images in the control net
  cnet->SetImages(snList);

  // For all held images' measures, set their parent control points' a priori values,
  // and set their types to Fixed
  SerialNumberList heldSNs(heldList);
  for (int sn = 0; sn < heldSNs.size(); sn++) {
    // Get the measures in the held image
    QList<ControlMeasure *> measures = cnet->GetMeasuresInCube(heldSNs.serialNumber(sn));
    
    foreach (ControlMeasure *cm, measures) {
      Camera *cam = cm->Camera();
      ControlPoint *pt = cm->Parent();
      pt->SetType(ControlPoint::Fixed);
      // If possible, set the apriori surface point for the current measure's control point
      if ( cam->SetImage(cm->GetSample(), cm->GetLine()) ) {
        pt->SetAprioriSurfacePoint(cam->GetSurfacePoint());
      }
      else {
        QString msg = "Cannot compute surface point for control point [" + pt->GetId() +
            "], measure [" + cm->GetCubeSerialNumber() + "].";
        throw IException(IException::User, msg, _FILEINFO_);
      }
    }
    
  }
  return cnet;
}
+19 −4
Original line number Original line Diff line number Diff line
@@ -201,7 +201,7 @@
    <change name="Ian Humphrey" date="2016-08-22">
    <change name="Ian Humphrey" date="2016-08-22">
      Reviewed documentation and updated small spelling and grammar errors. References #4226.
      Reviewed documentation and updated small spelling and grammar errors. References #4226.
    </change>
    </change>
    <change name="Adam Paquette" data="2016-08-31">
    <change name="Adam Paquette" date="2016-08-31">
      Updated how jigsaw handles its prefix parameter  along with a small documentation change. Fixes #4309.
      Updated how jigsaw handles its prefix parameter  along with a small documentation change. Fixes #4309.
    </change>
    </change>
    <change name="Ian Humphrey" date="2016-09-22">
    <change name="Ian Humphrey" date="2016-09-22">
@@ -217,6 +217,11 @@
      so that the user can now request the bundleout_images.csv file
      so that the user can now request the bundleout_images.csv file
      in addition to the other output files such as bundleout.txt.  Fixes #4314.
      in addition to the other output files such as bundleout.txt.  Fixes #4314.
    </change>
    </change>
    <change name="Ian Humphrey" date="2016-10-13">
      Implemented HELDLIST functionality for non-overlapping held images. Any control points that 
      intersect the held images are fixed, and a priori surface points for these control points are
      set to the held images' measures' surface points. Disabled USEPVL/SC_PARAMETERS. Fixes #4293.
    </change>
  </history>
  </history>


  <groups>
  <groups>
@@ -241,7 +246,7 @@
        <internalDefault>none</internalDefault>
        <internalDefault>none</internalDefault>
        <fileMode>input</fileMode>
        <fileMode>input</fileMode>
        <brief>
        <brief>
          List of cubes to hold in the adjustment
          List of (non-overlapping) cubes to hold in the adjustment
        </brief>
        </brief>
        <description>
        <description>
          This file contains a list of all <def>cube</def>s whose orientation and position
          This file contains a list of all <def>cube</def>s whose orientation and position
@@ -249,6 +254,7 @@
          in the solution, but their camera orientation and spacecraft position
          in the solution, but their camera orientation and spacecraft position
          will be constrained to keep the values from changing.  This is an
          will be constrained to keep the values from changing.  This is an
          optional parameter and the default is to not hold any of the images.
          optional parameter and the default is to not hold any of the images.
          <i>Note that held images must not overlap each other to work properly.</i>
        </description>
        </description>
        <filter>
        <filter>
          *.txt *.lis
          *.txt *.lis
@@ -286,6 +292,14 @@
        </filter>
        </filter>
      </parameter>
      </parameter>


 <!-- Turning off USEPVL and SC_PARAMETERS for now. Since we are now using observation numbers
      to obtain the BundleObservationSolveSettings for a BundleObservation (instead of inst. id),
      this would require using a PVL that contains names of lists of images to group by.
      E.g. Group = "listA." would create a BundleObservationSolveSettings object that is associated
      with the images' observation numbers. Group = "listB.lis" would create another BOSS object
      that is associated with listB's images' observation numbers. Use of these lists could
      introduce unintended behaviors if not properly verified (e.g. would need to make sure the
      lists are sublists of the FROMLIST, that these sublists are all mutually exclusive ...).
      <parameter name="USEPVL">
      <parameter name="USEPVL">
        <type>boolean</type>
        <type>boolean</type>
        <default><item>false</item></default>
        <default><item>false</item></default>
@@ -296,13 +310,14 @@
          This option indicates that the Camera and Spacecraft parameters are to be
          This option indicates that the Camera and Spacecraft parameters are to be
          obtained from the PVL file specified by SC_PARAMETERS. All of the following
          obtained from the PVL file specified by SC_PARAMETERS. All of the following
          parameters must be entered through the PVL file if this option is chosen:
          parameters must be entered through the PVL file if this option is chosen:
          CKDEGREE, CKSOLVEDEGREE, CAMSOLVE, TWIST, OVEREXISTING, SPKDEGREE,
          HELDLIST, CKDEGREE, CKSOLVEDEGREE, CAMSOLVE, TWIST, OVEREXISTING, SPKDEGREE,
          SPKSOLVEDEGREE, SPSOLVE, OVERHERMITE, SPACECRAFT_POSITION_SIGMA,
          SPKSOLVEDEGREE, SPSOLVE, OVERHERMITE, SPACECRAFT_POSITION_SIGMA,
          SPACECRAFT_VELOCITY_SIGMA, SPACECRAFT_ACCELERATION_SIGMA, CAMERA_ANGLES_SIGMA,
          SPACECRAFT_VELOCITY_SIGMA, SPACECRAFT_ACCELERATION_SIGMA, CAMERA_ANGLES_SIGMA,
          CAMERA_ANGULAR_VELOCITY_SIGMA, CAMERA_ANGULAR_ACCELERATION_SIGMA. An example
          CAMERA_ANGULAR_VELOCITY_SIGMA, CAMERA_ANGULAR_ACCELERATION_SIGMA. An example
          template is located at $base/templates/jigsaw/SC_Parameters.pvl.
          template is located at $base/templates/jigsaw/SC_Parameters.pvl.
        </description>
        </description>
        <exclusions>
        <exclusions>
          <item>HELDLIST</item>
          <item>CKDEGREE</item>
          <item>CKDEGREE</item>
          <item>CKSOLVEDEGREE</item>
          <item>CKSOLVEDEGREE</item>
          <item>CAMSOLVE</item>
          <item>CAMSOLVE</item>
@@ -348,7 +363,7 @@
        <filter>
        <filter>
          *.pvl
          *.pvl
        </filter>
        </filter>
      </parameter>
      </parameter>-->
    </group>
    </group>


    <group name="Solve Options">
    <group name="Solve Options">
+0 −47
Original line number Original line Diff line number Diff line
APPNAME = jigsaw
# This test exercises the bundle adjustment of one image each from the MOC-WA camera 
# and Viking Orbiter-1 B Camera with held image option, solving for position.
#
# The "cat t_bundleout.txt" command in these tests uses sed to do the following (in order):
# 1. remove cube filename paths
# 2. remove net filename paths
# 3. remove digits beyond the fifth decimal place of decimal numbers
# 4. remove date and time
#
# 2014-07-23 Jeannie Backer - Changed method from oldsparse to default (sparse).
#                Commented out references to bundleout_images.csv.
#                Removed default parameters.
# 2016-08-11 Jeannie Backer - Updated documentation

include $(ISISROOT)/make/isismake.tsts

commands:
	$(CP) $(INPUT)/*.cub $(OUTPUT) > /dev/null;
	$(LS) -1 $(OUTPUT)/*.cub > $(OUTPUT)/cub.lis;
	$(LS) -1 $(OUTPUT)/e0400710.lev1.cub > $(OUTPUT)/held.lis;
	$(APPNAME) fromlist=$(OUTPUT)/cub.lis  \
	           heldlist=$(OUTPUT)/held.lis  \
	           cnet=$(INPUT)/mocVik.net \
	           onet=$(OUTPUT)/case2OutNet.net \
	           update=yes \
	           sigma0=1.e-5  \
	           maxits=10 \
	           spsolve=position > /dev/null;
	$(CAT) bundleout.txt  | grep -v "Run Time:" | grep -v "Elapsed Time:" \
	       | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \
	       | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \
	       | $(SED) s/`date +%Y-%m-%dT`\[0-2\]\[0-9\]:\[0-5\]\[0-9\]:\[0-5\]\[0-9\]/date/ \
	       > $(OUTPUT)/bundleout.txt
	$(CAT) residuals.csv \
	       | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \
	       > $(OUTPUT)/residuals.csv
#	$(CAT) bundleout_images.csv \
#	       | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \
#	       > $(OUTPUT)/bundleout_images.csv
#	$(RM) bundleout_images.csv > /dev/null;
	$(RM) residuals.csv > /dev/null;
	$(MV) bundleout_points.csv $(OUTPUT)/bundleout_points.csv > /dev/null;
	$(RM) $(OUTPUT)/cub.lis $(OUTPUT)/held.lis $(OUTPUT)/case2OutNet.bin print.prt > /dev/null;
	$(RM) bundleout.txt print.prt > /dev/null
	cathist from=$(OUTPUT)/vik.cub > $(OUTPUT)/vik.pvl;
	cathist from=$(OUTPUT)/e0400710.lev1.cub > $(OUTPUT)/e0400710.lev1.cub.pvl;
+3 −15
Original line number Original line Diff line number Diff line
@@ -4,9 +4,11 @@
#     TEST B: "Unable to bundle adjust network"
#     TEST B: "Unable to bundle adjust network"
#   TEST C: "Input Target parameters file missing main Target object."
#   TEST C: "Input Target parameters file missing main Target object."
#   TEST D: "Must solve for at least one target body option."
#   TEST D: "Must solve for at least one target body option."
#   TEST E: "Input SC_PARAMETERS file missing SensorParameters object."
#
#
# 2016-08-22 Ian Humphrey - Original version. Fixes #4269.
# 2016-08-22 Ian Humphrey - Original version. Fixes #4269.
# 2016-10-13 Ian Humphrey - Removed TEST E: "Input SC_PARAMETERS file missing SensorParameters
#                object," as USEPVL and SC_PARAMETERS have been turned off. References #4292,
#                #4293."
APPNAME = jigsaw
APPNAME = jigsaw


include $(ISISROOT)/make/isismake.tsts
include $(ISISROOT)/make/isismake.tsts
@@ -53,17 +55,3 @@ commands:
	then \
	then \
	  true; \
	  true; \
	fi;
	fi;
# TEST E: USEPVL=yes and SC_PARAMETERS is missing SensorParameters object
	echo -e "Error Test E:" >> $(OUTPUT)/error.txt;
	if [[ `$(APPNAME) \
	  fromlist=$(INPUT)/empty.lis \
	  cnet=$(INPUT)/empty.net \
	  onet=$(OUTPUT)/out.net \
	  usepvl=yes \
	  sc_parameters=$(INPUT)/invalidSensorParameters.pvl \
	  2>> $(OUTPUT)/error.txt \
	  > /dev/null` ]]; \
	then \
	  true; \
	fi;
	$(RM) $(OUTPUT)/cubes.lis > /dev/null;
+32 −0
Original line number Original line Diff line number Diff line
# This tests the HELDLIST paramater with a single image. We hold a green-filter image,
# N1597182807_2.filtered.cub, effectively setting any control points that intersect
# this image to FIXED, and setting these control points' a priori surface points to the
# corresponding measures' surface points in the held image. See the history of
# N1597182807_2.filtered.cub, as qtie was used before running the jigsaw.
#
# @history 2016-10-13 Ian Humphrey - Original version, adapted from test data provided by
#                         Tammy Becker. References #4293.
APPNAME = jigsaw

include $(ISISROOT)/make/isismake.tsts

commands:
	$(LS) $(INPUT)/*cub > $(OUTPUT)/cubes.lis;
	$(LS) $(INPUT)/N1597182807_2.filtered.cub > $(OUTPUT)/hold-green.lis;
	$(APPNAME) fromlist=$(OUTPUT)/cubes.lis \
	  heldlist=$(OUTPUT)/hold-green.lis \
	  cnet=$(INPUT)/color-tlb.net \
	  onet=$(OUTPUT)/color-tlb-out.net \
	  camera_angles_sigma=10 \
	  > /dev/null;
	$(CAT) bundleout.txt  | grep -v "Run Time:" | grep -v "Elapsed Time:" \
	  | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \
	  | $(SED) 's/\([0-9][0-9]*\.[0-9][0-9][0-9][0-9]\)\([0-9][0-9]*\)/\1/g' \
	  | $(SED) s/`date +%Y-%m-%dT`\[0-2\]\[0-9\]:\[0-5\]\[0-9\]:\[0-5\]\[0-9\]/date/ \
	  > $(OUTPUT)/hold_bundleout.txt;
	$(CAT) residuals.csv \
	  | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \
	  > $(OUTPUT)/hold_residuals.csv;
	$(MV) bundleout_points.csv $(OUTPUT)/hold_bundleout_points.csv;
	$(MV) bundleout_images.csv $(OUTPUT)/hold_bundleout_images.csv;
	$(RM) bundleout.txt residuals.csv $(OUTPUT)/cubes.lis $(OUTPUT)/hold-green.lis;
Loading