bool ResamplerPlugIn::execute(PlugInArgList* pInArgList, PlugInArgList* pOutArgList)
{
   VERIFY(pInArgList != NULL && pOutArgList != NULL);
   ProgressTracker progress(pInArgList->getPlugInArgValue<Progress>(Executable::ProgressArg()),
      "Executing Spectral Resampler.", "spectral", "{88CD3E49-A522-431A-AE2A-96A6B2EB4012}");

   Service<DesktopServices> pDesktop;

   const DataElement* pElement(NULL);
   std::string waveFilename;

   // get default resampling options from user config
   std::string resampleMethod = ResamplerOptions::getSettingResamplerMethod();
   double dropOutWindow = ResamplerOptions::getSettingDropOutWindow();
   double fwhm = ResamplerOptions::getSettingFullWidthHalfMax();
   bool useFillValue = ResamplerOptions::getSettingUseFillValue();
   double fillValue = ResamplerOptions::getSettingSignatureFillValue();

   std::vector<Signature*> originalSignatures;
   std::auto_ptr<std::vector<Signature*> > pResampledSignatures(new std::vector<Signature*>);
   std::string errorMsg;

   if (isBatch())
   {
      VERIFY(pInArgList->getPlugInArgValue("Signatures to resample", originalSignatures));
      if (originalSignatures.empty())
      {
         Signature* pSignature = pInArgList->getPlugInArgValue<Signature>("Signature to resample");
         if (pSignature != NULL)
         {
            originalSignatures.push_back(pSignature);
         }
      }
      if (originalSignatures.empty())
      {
         progress.report("No signatures are available to be resampled.", 0, ERRORS, true);
         return false;
      }
      pElement = pInArgList->getPlugInArgValue<DataElement>("Data element wavelength source");
      Filename* pWaveFilename = pInArgList->getPlugInArgValue<Filename>("Wavelengths Filename");
      if (pWaveFilename != NULL)
      {
         waveFilename = pWaveFilename->getFullPathAndName();
      }
      VERIFY(pInArgList->getPlugInArgValue("Resampling Method", resampleMethod));
      VERIFY(pInArgList->getPlugInArgValue("Drop out window", dropOutWindow));
      VERIFY(pInArgList->getPlugInArgValue("FWHM", fwhm));
      VERIFY(pInArgList->getPlugInArgValue("Use fill value", useFillValue));
      VERIFY(pInArgList->getPlugInArgValue("Fill value", fillValue));
   }
   else
   {
      ResamplerPlugInDlg dlg(pDesktop->getMainWidget());
      if (dlg.exec() == QDialog::Rejected)
      {
         progress.report("User canceled resampling.", 0, ABORT, true);
         progress.upALevel();
         return false;
      }
      originalSignatures = dlg.getSignaturesToResample();
      resampleMethod = dlg.getResamplingMethod();
      dropOutWindow = dlg.getDropOutWindow();
      fwhm = dlg.getFWHM();
      useFillValue = dlg.getUseFillValue();
      fillValue = dlg.getFillValue();
      pElement = dlg.getWavelengthsElement();
      waveFilename = dlg.getWavelengthsFilename();
   }

   std::string resampledTo;
   FactoryResource<Wavelengths> pWavelengths;
   if (pElement != NULL)  // try loading wavelengths from user specified data element
   {
      if (getWavelengthsFromElement(pElement, pWavelengths.get(), errorMsg) == false)
      {
         progress.report(errorMsg, 0, ERRORS, true);
         return false;
      }
      resampledTo = pElement->getName();
   }
   else if (waveFilename.empty() == false)  // if no user provided raster, look for a wavelengths file
   {
      if (QFile::exists(QString::fromStdString(waveFilename)))
      {
         if (getWavelengthsFromFile(waveFilename, pWavelengths.get(), errorMsg) == false)
         {
            progress.report(errorMsg, 0, ERRORS, true);
            return false;
         }
      }
      else
      {
         errorMsg = "The wavelengths file \"" + waveFilename + "\" could not be found.";
         progress.report(errorMsg, 0, ERRORS, true);
         return false;
      }
      resampledTo = waveFilename;
   }
   else  // if no wavelength source provided, look for raster in current active spatial data view
   {
      SpatialDataView* pView = dynamic_cast<SpatialDataView*>(pDesktop->getCurrentWorkspaceWindowView());
      if (pView != NULL)
      {
         LayerList* pLayerList = pView->getLayerList();
         if (pLayerList != NULL)
         {
            pElement = pLayerList->getPrimaryRasterElement();
            pWavelengths->initializeFromDynamicObject(pElement->getMetadata(), false);
            if (pWavelengths->isEmpty())
            {
               progress.report("No target wavelengths are available for resampling the signatures.", 0, ERRORS, true);
               return false;
            }
            resampledTo = pElement->getName();
         }
      }
   }

   PlugInResource pPlugIn("Resampler");
   Resampler* pResampler = dynamic_cast<Resampler*>(pPlugIn.get());
   if (pResampler == NULL)
   {
      progress.report("The \"Resampler\" plug-in is not available so the signatures can not be resampled.",
         0, ERRORS, true);
      return false;
   }
   std::string dataName("Reflectance");
   std::string wavelengthName("Wavelength");

   // save user config settings - Resampler doesn't have interface to set them separately from user config
   std::string configMethod = ResamplerOptions::getSettingResamplerMethod();
   ResamplerOptions::setSettingResamplerMethod(resampleMethod);
   double configDropout = ResamplerOptions::getSettingDropOutWindow();
   ResamplerOptions::setSettingDropOutWindow(dropOutWindow);
   double configFwhm = ResamplerOptions::getSettingFullWidthHalfMax();
   ResamplerOptions::setSettingFullWidthHalfMax(fwhm);

   std::vector<double> toWavelengths = pWavelengths->getCenterValues();
   std::vector<double> toFwhm = pWavelengths->getFwhm();
   if (toFwhm.size() != toWavelengths.size())
   {
      toFwhm.clear();  // Resampler will use the default config setting fwhm if this vector is empty
   }

   unsigned int numSigs = originalSignatures.size();
   unsigned int numSigsResampled(0);
   progress.report("Begin resampling signatures...", 0, NORMAL);
   for (unsigned int index = 0; index < numSigs; ++index)
   {
      if (isAborted())
      {
         progress.report("Resampling aborted by user", 100 * index / numSigs, ABORT, true);
         return false;
      }
      if (originalSignatures[index] == NULL)
      {
         continue;
      }

      // check if signature has target wavelength centers and doesn't need to be resampled
      if (needToResample(originalSignatures[index], pWavelengths.get()) == false)
      {
         pResampledSignatures->push_back(originalSignatures[index]);
         ++numSigsResampled;
         continue;
      }

      DataVariant var = originalSignatures[index]->getData(dataName);
      if (var.isValid() == false)
      {
         continue;
      }
      std::vector<double> fromData;
      if (!var.getValue(fromData))
      {
         continue;
      }
      var = originalSignatures[index]->getData(wavelengthName);
      if (var.isValid() == false)
      {
         continue;
      }
      std::vector<double> fromWavelengths;
      if (!var.getValue(fromWavelengths))
      {
         continue;
      }
      std::string resampledSigName = originalSignatures[index]->getName() + "_resampled";
      int suffix(2);
      ModelResource<Signature> pSignature(resampledSigName, NULL);

      // probably not needed but just in case resampled name already used
      while (pSignature.get() == NULL)
      {
         pSignature = ModelResource<Signature>(resampledSigName + StringUtilities::toDisplayString(suffix), NULL);
         ++suffix;
      }
      if (resampledTo.empty() == false)
      {
         DynamicObject* pMetaData = pSignature->getMetadata();
         if (pMetaData != NULL)
         {
            pMetaData->setAttribute(CommonSignatureMetadataKeys::ResampledTo(), resampledTo);
         }
      }
      std::vector<double> toData;
      std::vector<int> toBands;
      if (pResampler->execute(fromData, toData, fromWavelengths, toWavelengths, toFwhm, toBands, errorMsg))
      {
         if (toWavelengths.size() != toBands.size())
         {
            if (toBands.size() < 2)  // no need to try if only one point
            {
               continue;
            }

            if (useFillValue)
            {
               std::vector<double> values(toWavelengths.size(), fillValue);
               for (unsigned int i = 0; i < toBands.size(); ++i)
               {
                  values[static_cast<unsigned int>(toBands[i])] = toData[i];
               }
               toData.swap(values);
               DynamicObject* pMetaData = pSignature->getMetadata();
               if (pMetaData != NULL)
               {
                  pMetaData->setAttribute(CommonSignatureMetadataKeys::FillValue(), fillValue);
               }
            }
            else
            {
               std::vector<double> wavelengths(toBands.size());
               for (unsigned int i = 0; i < toBands.size(); ++i)
               {
                  wavelengths[i] = toWavelengths[static_cast<unsigned int>(toBands[i])];
               }
               toWavelengths.swap(wavelengths);
            }
         }
         pSignature->setData(dataName, toData);
         pSignature->setData(wavelengthName, toWavelengths);
         SignatureDataDescriptor* pDesc = dynamic_cast<SignatureDataDescriptor*>(pSignature->getDataDescriptor());
         if (pDesc == NULL)
         {
            continue;
         }
         pDesc->setUnits(dataName, originalSignatures[index]->getUnits(dataName));
         pResampledSignatures->push_back(pSignature.release());
         ++numSigsResampled;
      }
      std::string progressStr =
         QString("Resampled signature %1 of %2 signatures").arg(index + 1).arg(numSigs).toStdString();
      progress.report(progressStr, (index + 1) * 100 / numSigs, NORMAL);
   }

   // reset config options
   ResamplerOptions::setSettingResamplerMethod(configMethod);
   ResamplerOptions::setSettingDropOutWindow(configDropout);
   ResamplerOptions::setSettingFullWidthHalfMax(configFwhm);

   if (numSigsResampled == numSigs)
   {
      progress.report("Complete", 100, NORMAL);
      progress.upALevel();
   }
   else
   {
      errorMsg = QString("Only %1 of the %2 signatures were successfully resampled.").arg(
         numSigsResampled).arg(numSigs).toStdString();
      progress.report(errorMsg, 100, WARNING, true);
   }

   VERIFY(pOutArgList->setPlugInArgValue("Resampled signatures", pResampledSignatures.release()));
   return true;
}
void SpectralLibraryMatchResults::createAverageSignature()
{
   Service<DesktopServices> pDesktop;

   const RasterElement* pRaster = getRasterElementForCurrentPage();
   if (pRaster == NULL)
   {
      pDesktop->showMessageBox("Spectral Library Match",
         "Unable to determine the RasterElement for the current page.");
      return;
   }

   std::vector<Signature*> signatures = getSelectedSignatures();
   if (signatures.empty())
   {
      pDesktop->showMessageBox("Spectral Library Match",
         "No signatures are selected for use in generating an average signature.");
      return;
   }

   // now need to get the resampled sigs from the library
   SpectralLibraryManager* pLibMgr(NULL);
   std::vector<PlugIn*> plugIns =
      Service<PlugInManagerServices>()->getPlugInInstances(SpectralLibraryMatch::getNameLibraryManagerPlugIn());
   if (!plugIns.empty())
   {
      pLibMgr = dynamic_cast<SpectralLibraryManager*>(plugIns.front());
   }
   if (pLibMgr == NULL)
   {
      pDesktop->showMessageBox("Spectral Library Match",
         "Unable to access the Spectral Library Manager.");
      return;
   }

   const RasterDataDescriptor* pDesc = dynamic_cast<const RasterDataDescriptor*>(pRaster->getDataDescriptor());
   if (pDesc == NULL)
   {
      pDesktop->showMessageBox("Spectral Library Match",
         "Unable to access the RasterDataDescriptor for the RasterElement of the current page.");
      return;
   }

   unsigned int numBands = pDesc->getBandCount();
   std::vector<double> averageValues(numBands, 0);
   std::vector<double> values;
   for (std::vector<Signature*>::iterator it = signatures.begin(); it != signatures.end(); ++it)
   {
      if (pLibMgr->getResampledSignatureValues(pRaster, *it, values) == false)
      {
         pDesktop->showMessageBox("Spectral Library Match",
            "Unable to access the resampled signature values for " + (*it)->getDisplayName(true));
         return;
      }
      for (unsigned int band = 0; band < numBands; ++band)
      {
         averageValues[band] += values[band];
      }
   }
   unsigned int numSigs = signatures.size();
   for (unsigned int band = 0; band < numBands; ++band)
   {
      averageValues[band] /= static_cast<double>(numSigs);
   }

   QString avgName = QInputDialog::getText(pDesktop->getMainWidget(), "Spectral Library Match",
      "Enter the name to use for the average signature:");
   if (avgName.isEmpty())
   {
      return;
   }
   ModelResource<Signature> pAvgSig(avgName.toStdString(), const_cast<RasterElement*>(pRaster));
   pAvgSig->setData("Reflectance", averageValues);

   const DynamicObject* pMetaData = pRaster->getMetadata();
   FactoryResource<Wavelengths> pWavelengths;
   pWavelengths->initializeFromDynamicObject(pMetaData, false);
   const std::vector<double>& centerValues = pWavelengths->getCenterValues();
   pAvgSig->setData("Wavelength", centerValues);
   SignatureDataDescriptor* pSigDesc = dynamic_cast<SignatureDataDescriptor*>(pAvgSig->getDataDescriptor());
   VERIFYNRV(pSigDesc != NULL);
   FactoryResource<Units> pUnits;
   const Units* pRasterUnits = pDesc->getUnits();
   pUnits->setUnitName(pRasterUnits->getUnitName());
   pUnits->setUnitType(pRasterUnits->getUnitType());
   pUnits->setScaleFromStandard(1.0);  // the rescaled values are already corrected for the original scaling factor
   pUnits->setRangeMin(pRasterUnits->getRangeMin());
   pUnits->setRangeMax(pRasterUnits->getRangeMax());
   pSigDesc->setUnits("Reflectance", pUnits.get());
   pAvgSig.release();
}
bool SpectralLibraryManager::generateResampledLibrary(const RasterElement* pRaster)
{
    VERIFY(pRaster != NULL);

    // check that lib sigs are in same units as the raster element
    const RasterDataDescriptor* pDesc = dynamic_cast<const RasterDataDescriptor*>(pRaster->getDataDescriptor());
    VERIFY(pDesc != NULL);
    const Units* pUnits = pDesc->getUnits();
    if (pDesc->getUnits()->getUnitType() != mLibraryUnitType)
    {
        if (Service<DesktopServices>()->showMessageBox("Mismatched Units", "The data are not in the "
                "same units as the spectral library.\n Do you want to continue anyway?", "Yes", "No") == 1)
        {
            return false;
        }
    }

    FactoryResource<Wavelengths> pWavelengths;
    pWavelengths->initializeFromDynamicObject(pRaster->getMetadata(), false);

    // populate the library with the resampled signatures
    PlugInResource pPlugIn("Resampler");
    Resampler* pResampler = dynamic_cast<Resampler*>(pPlugIn.get());
    VERIFY(pResampler != NULL);
    if (pWavelengths->getNumWavelengths() != pDesc->getBandCount())
    {
        mpProgress->updateProgress("Wavelength information in metadata does not match the number of bands "
                                   "in the raster element", 0, ERRORS);
        return false;
    }

    // get resample suitable signatures - leave out signatures that don't cover the spectral range of the data
    std::vector<std::vector<double> > resampledData;
    resampledData.reserve(mSignatures.size());
    std::vector<Signature*> resampledSignatures;
    resampledSignatures.reserve(mSignatures.size());
    std::vector<std::string> unsuitableSignatures;
    std::vector<double> sigValues;
    std::vector<double> sigWaves;
    std::vector<double> rasterWaves = pWavelengths->getCenterValues();
    std::vector<double> rasterFwhm = pWavelengths->getFwhm();
    std::vector<double> resampledValues;
    std::vector<int> bandIndex;
    DataVariant data;
    for (std::vector<Signature*>::const_iterator it = mSignatures.begin(); it != mSignatures.end(); ++it)
    {
        data = (*it)->getData(SpectralLibraryMatch::getNameSignatureWavelengthData());
        VERIFY(data.isValid());
        VERIFY(data.getValue(sigWaves));
        resampledValues.clear();
        data = (*it)->getData(SpectralLibraryMatch::getNameSignatureAmplitudeData());
        VERIFY(data.isValid());
        VERIFY(data.getValue(sigValues));
        double scaleFactor = (*it)->getUnits(
                                 SpectralLibraryMatch::getNameSignatureAmplitudeData())->getScaleFromStandard();
        for (std::vector<double>::iterator sit = sigValues.begin(); sit != sigValues.end(); ++sit)
        {
            *sit *= scaleFactor;
        }

        std::string msg;
        if (pResampler->execute(sigValues, resampledValues, sigWaves, rasterWaves, rasterFwhm, bandIndex, msg) == false
                || resampledValues.size() != rasterWaves.size())
        {
            unsuitableSignatures.push_back((*it)->getName());
            continue;
        }

        resampledData.push_back(resampledValues);
        resampledSignatures.push_back(*it);
    }

    if (resampledSignatures.empty())
    {
        std::string errMsg = "None of the signatures in the library cover the spectral range of the data.";
        if (mpProgress != NULL)
        {
            mpProgress->updateProgress(errMsg, 0, ERRORS);
            return false;
        }
    }
    if (unsuitableSignatures.empty() == false)
    {
        std::string warningMsg = "The following library signatures do not cover the spectral range of the data:\n";
        for (std::vector<std::string>::iterator it = unsuitableSignatures.begin();
                it != unsuitableSignatures.end(); ++it)
        {
            warningMsg += *it + "\n";
        }
        warningMsg += "These signatures will not be searched for in the data.";
        Service<DesktopServices>()->showMessageBox("SpectralLibraryManager", warningMsg);

        StepResource pStep("Spectral LibraryManager", "spectral", "64B6C87A-A6C3-4378-9B6E-221D89D8707B");
        pStep->finalize(Message::Unresolved, warningMsg);
    }

    std::string libName = "Resampled Spectral Library";

    // Try to get the resampled lib element in case session was restored. If NULL, create a new raster element with
    // num rows = num valid signatures, num cols = 1, num bands = pRaster num bands
    RasterElement* pLib = dynamic_cast<RasterElement*>(Service<ModelServices>()->getElement(libName,
                          TypeConverter::toString<RasterElement>(), pRaster));
    if (pLib != NULL)
    {
        // check that pLib has same number of sigs as SpectralLibraryManager
        RasterDataDescriptor* pLibDesc = dynamic_cast<RasterDataDescriptor*>(pLib->getDataDescriptor());
        VERIFY(pLibDesc != NULL);
        if (pLibDesc->getRowCount() != mSignatures.size())
        {
            mpProgress->updateProgress("An error occurred during session restore and some signatures were not restored."
                                       " Check the spectral library before using.", 0, ERRORS);
            Service<ModelServices>()->destroyElement(pLib);
            pLib = NULL;
        }
    }
    bool isNewElement(false);
    if (pLib == NULL)
    {
        pLib = RasterUtilities::createRasterElement(libName,
                static_cast<unsigned int>(resampledData.size()), 1, pDesc->getBandCount(), FLT8BYTES, BIP,
                true, const_cast<RasterElement*>(pRaster));
        isNewElement = true;
    }
    if (pLib == NULL)
    {
        mpProgress->updateProgress("Error occurred while trying to create the resampled spectral library", 0, ERRORS);
        return false;
    }

    RasterDataDescriptor* pLibDesc = dynamic_cast<RasterDataDescriptor*>(pLib->getDataDescriptor());
    VERIFY(pLibDesc != NULL);

    // copy resampled data into new element
    if (isNewElement)
    {
        FactoryResource<DataRequest> pRequest;
        pRequest->setWritable(true);
        pRequest->setRows(pLibDesc->getActiveRow(0), pLibDesc->getActiveRow(pLibDesc->getRowCount()-1), 1);
        DataAccessor acc = pLib->getDataAccessor(pRequest.release());
        for (std::vector<std::vector<double> >::iterator sit = resampledData.begin(); sit != resampledData.end(); ++sit)
        {
            VERIFY(acc->isValid());
            void* pData = acc->getColumn();
            memcpy(acc->getColumn(), &(sit->begin()[0]), pLibDesc->getBandCount() * sizeof(double));
            acc->nextRow();
        }

        // set wavelength info in resampled library
        pWavelengths->applyToDynamicObject(pLib->getMetadata());
        FactoryResource<Units> libUnits;
        libUnits->setUnitType(mLibraryUnitType);
        libUnits->setUnitName(StringUtilities::toDisplayString<UnitType>(mLibraryUnitType));
        pLibDesc->setUnits(libUnits.get());
    }

    pLib->attach(SIGNAL_NAME(Subject, Deleted), Slot(this, &SpectralLibraryManager::resampledElementDeleted));
    mLibraries[pRaster] = pLib;
    mResampledSignatures[pLib] = resampledSignatures;

    const_cast<RasterElement*>(pRaster)->attach(SIGNAL_NAME(Subject, Deleted),
            Slot(this, &SpectralLibraryManager::elementDeleted));

    return true;
}
Beispiel #4
0
bool ImporterShell::validate(const DataDescriptor* pDescriptor, string& errorMessage) const
{
   mValidationError = ValidationTest();

   // Check for no validation
   int validationTest = getValidationTest(pDescriptor);
   if (validationTest == NO_VALIDATION)
   {
      return true;
   }

   // Always validate the data descriptor and file descriptor
   if (pDescriptor == NULL)
   {
      errorMessage = "The data set information is invalid.";
      return false;
   }

   const FileDescriptor* pFileDescriptor = pDescriptor->getFileDescriptor();
   if (pFileDescriptor == NULL)
   {
      errorMessage = "The data set does not contain valid file information.";
      return false;
   }

   // Existing file
   const string& filename = pFileDescriptor->getFilename();
   if (validationTest & EXISTING_FILE)
   {
      // Valid filename
      if (filename.empty() == true)
      {
         errorMessage = "The filename is invalid.";
         mValidationError = EXISTING_FILE;
         return false;
      }

      // Existing file
      LargeFileResource file(true);
      if (!file.open(filename.c_str(), O_RDONLY | O_BINARY, S_IREAD))
      {
         errorMessage = "The file: " + filename + " does not exist.";
         mValidationError = EXISTING_FILE;
         return false;
      }
   }

   // Existing data element
   if (validationTest & NO_EXISTING_DATA_ELEMENT)
   {
      const string& name = pDescriptor->getName();
      const string& type = pDescriptor->getType();
      DataElement* pParent = pDescriptor->getParent();

      Service<ModelServices> pModel;
      if (pModel->getElement(name, type, pParent) != NULL)
      {
         errorMessage = "The data set currently exists.  It may have already been imported.";
         mValidationError = NO_EXISTING_DATA_ELEMENT;
         return false;
      }
   }

   // Valid classification
   Service<UtilityServices> pUtilities;
   if (validationTest & VALID_CLASSIFICATION)
   {
      // Existing Classification object
      const Classification* pClassification = pDescriptor->getClassification();
      if (pClassification == NULL)
      {
         errorMessage = "The required classification does not exist.";
         mValidationError = VALID_CLASSIFICATION;
         return false;
      }

      // Unauthorized classification level on the system - warn the user, but continue to load the file
      FactoryResource<Classification> pSystemClassification;
      pSystemClassification->setLevel(pUtilities->getDefaultClassification());
      if (pClassification->hasGreaterLevel(pSystemClassification.get()) == true)
      {
         errorMessage = "THIS FILE CONTAINS CLASSIFIED INFORMATION WHICH SHOULD NOT BE PROCESSED ON THIS SYSTEM!\n"
            "THIS MAY CONSTITUTE A SECURITY VIOLATION WHICH SHOULD BE REPORTED TO YOUR SECURITY OFFICER!\n";
         StepResource pStep("Validate", "app", "1A881267-6A96-4eb2-A9D3-7D30334B0A0B", errorMessage);
      }
   }

   // Valid metadata
   if (validationTest & VALID_METADATA)
   {
      if (pDescriptor->getMetadata() == NULL)
      {
         errorMessage = "The required metadata does not exist.";
         mValidationError = VALID_METADATA;
         return false;
      }
   }

   // Processing location
   if (validationTest & VALID_PROCESSING_LOCATION)
   {
      if (isProcessingLocationSupported(pDescriptor->getProcessingLocation()) == false)
      {
         errorMessage = "The specified processing location is not supported.";
         mValidationError = VALID_PROCESSING_LOCATION;
         return false;
      }
   }

   // If no RasterDataDescriptor or RasterFileDescriptor tests are performed, end here
   if (validationTest < RASTER_SIZE)
   {
      return true;
   }

   // Since raster tests have been specified, always validate the raster data descriptor and raster file descriptor
   const RasterDataDescriptor* pRasterDescriptor = dynamic_cast<const RasterDataDescriptor*>(pDescriptor);
   if (pRasterDescriptor == NULL)
   {
      errorMessage = "The data set does not contain raster information.";
      return false;
   }

   const RasterFileDescriptor* pRasterFileDescriptor =
      dynamic_cast<const RasterFileDescriptor*>(pRasterDescriptor->getFileDescriptor());
   if (pRasterFileDescriptor == NULL)
   {
      errorMessage = "The file does not contain valid raster data.";
      return false;
   }

   // Raster size
   if (validationTest & RASTER_SIZE)
   {
      // Data set size
      unsigned int loadedRows = pRasterDescriptor->getRowCount();
      unsigned int loadedColumns = pRasterDescriptor->getColumnCount();
      unsigned int loadedBands = pRasterDescriptor->getBandCount();

      if ((loadedRows == 0) || (loadedColumns == 0) || (loadedBands == 0))
      {
         errorMessage = "The data set is empty.  Check the size of the rows, columns, and bands.";
         mValidationError = RASTER_SIZE;
         return false;
      }

      // Pixel size
      if (pRasterFileDescriptor->getBitsPerElement() == 0)
      {
         errorMessage = "The number of bits per element is invalid.";
         mValidationError = RASTER_SIZE;
         return false;
      }
   }

   // Data type
   if (validationTest & VALID_DATA_TYPE)
   {
      const std::vector<EncodingType>& dataTypes = pRasterDescriptor->getValidDataTypes();
      if (std::find(dataTypes.begin(), dataTypes.end(), pRasterDescriptor->getDataType()) == dataTypes.end())
      {
         errorMessage = "The data type is not valid for this data set.";
         mValidationError = VALID_DATA_TYPE;
         return false;
      }
   }

   // Header bytes
   if (validationTest & NO_HEADER_BYTES)
   {
      if (pRasterFileDescriptor->getHeaderBytes() > 0)
      {
         errorMessage = "The file has an invalid number of header bytes.";
         mValidationError = NO_HEADER_BYTES;
         return false;
      }
   }

   // Preline and postline bytes
   if (validationTest & NO_PRE_POST_LINE_BYTES)
   {
      if ((pRasterFileDescriptor->getPrelineBytes() > 0) || (pRasterFileDescriptor->getPostlineBytes() > 0))
      {
         errorMessage = "The file has an invalid number of preline and/or postline bytes.";
         mValidationError = NO_PRE_POST_LINE_BYTES;
         return false;
      }
   }

   // Preband and postband bytes
   if (validationTest & NO_PRE_POST_BAND_BYTES)
   {
      if ((pRasterFileDescriptor->getPrebandBytes() > 0) || (pRasterFileDescriptor->getPostbandBytes() > 0))
      {
         errorMessage = "The file has an invalid number of preband and/or postband bytes.";
         mValidationError = NO_PRE_POST_BAND_BYTES;
         return false;
      }
   }

   // Trailer bytes
   if (validationTest & NO_TRAILER_BYTES)
   {
      if (pRasterFileDescriptor->getTrailerBytes() > 0)
      {
         errorMessage = "The file has an invalid number of trailer bytes.";
         mValidationError = NO_TRAILER_BYTES;
         return false;
      }
   }

   // File size
   int64_t requiredSize = RasterUtilities::calculateFileSize(pRasterFileDescriptor);
   if ((validationTest & FILE_SIZE) == FILE_SIZE)
   {
      // Existing file
      LargeFileResource file;
      VERIFY(file.open(filename, O_RDONLY | O_BINARY, S_IREAD) == true);

      // File size
      if (requiredSize < 0)
      {
         errorMessage = "Unable to determine the required file size.";
         mValidationError = FILE_SIZE;
         return false;
      }

      if (file.fileLength() < requiredSize)
      {
         errorMessage = "The size of the file does not match the current parameters.";
         mValidationError = FILE_SIZE;
         return false;
      }
   }

   // Band files
   const vector<const Filename*>& bandFiles = pRasterFileDescriptor->getBandFiles();
   if (validationTest & NO_BAND_FILES)
   {
      if (bandFiles.empty() == false)
      {
         errorMessage = "This data set cannot have band data in multiple files.";
         mValidationError = NO_BAND_FILES;
         return false;
      }
   }

   // Existing band files and band file sizes
   if (validationTest & EXISTING_BAND_FILES)
   {
      // Enough band files for all bands
      unsigned int numBands = pRasterFileDescriptor->getBandCount();
      if (bandFiles.size() < numBands)
      {
         errorMessage = "The number of band files specified is less than the total number of bands to be loaded.";
         mValidationError = EXISTING_BAND_FILES;
         return false;
      }

      // Invalid file for imported bands
      for (vector<const Filename*>::size_type i = 0; i < bandFiles.size(); ++i)
      {
         const Filename* pFilename = bandFiles[i];
         if (pFilename == NULL)
         {
            stringstream streamMessage;
            streamMessage << "Band filename " << i + 1 << " is missing.";
            errorMessage = streamMessage.str();
            mValidationError = EXISTING_BAND_FILES;
            return false;
         }

         // Invalid filename
         string bandFilename = pFilename->getFullPathAndName();
         if (bandFilename.empty() == true)
         {
            stringstream streamMessage;
            streamMessage << "Band filename " << i + 1 << " is invalid.";
            errorMessage = streamMessage.str();
            mValidationError = EXISTING_BAND_FILES;
            return false;
         }

         // Existing file
         LargeFileResource bandFile;
         if (!bandFile.open(bandFilename, O_RDONLY | O_BINARY, S_IREAD))
         {
            stringstream streamMessage;
            streamMessage << "Band file " << i + 1 << " does not exist.";
            errorMessage = streamMessage.str();
            mValidationError = EXISTING_BAND_FILES;
            return false;
         }

         // File size
         if ((validationTest & BAND_FILE_SIZES) == BAND_FILE_SIZES)
         {
            if (requiredSize < 0)
            {
               errorMessage = "Unable to determine the required band file size.";
               mValidationError = BAND_FILE_SIZES;
               return false;
            }

            if (bandFile.fileLength() < requiredSize)
            {
               stringstream streamMessage;
               streamMessage << "The size of band file " << i + 1 << " does not match the required size "
                  "for the current parameters.";
               errorMessage = streamMessage.str();
               mValidationError = BAND_FILE_SIZES;
               return false;
            }
         }
      }
   }

   // Band names
   const DynamicObject* pMetadata = pRasterDescriptor->getMetadata();
   if ((validationTest & VALID_BAND_NAMES) == VALID_BAND_NAMES)
   {
      VERIFY(pMetadata != NULL);

      string namesPath[] = { SPECIAL_METADATA_NAME, BAND_METADATA_NAME, NAMES_METADATA_NAME, END_METADATA_NAME };

      // If band names are present in the metadata, check the number of names against the number of bands
      // If band names are not present in the metadata, then succeed
      const vector<string>* pBandNames = dv_cast<vector<string> >(&pMetadata->getAttributeByPath(namesPath));
      if (pBandNames != NULL)
      {
         if (pBandNames->size() != pRasterFileDescriptor->getBandCount())
         {
            errorMessage = "The number of band names in the metadata does not match the number of bands.";
            mValidationError = VALID_BAND_NAMES;
            return false;
         }
      }
   }

   // Wavelengths
   if ((validationTest & VALID_WAVELENGTHS) == VALID_WAVELENGTHS)
   {
      VERIFY(pMetadata != NULL);

      // If wavelengths are present in the metadata, check the number of wavelengths against the number of bands
      // If wavelengths are not present in the metadata, then succeed
      FactoryResource<Wavelengths> pWavelengths;
      if (pWavelengths->initializeFromDynamicObject(pMetadata, false) == true)
      {
         if (pWavelengths->getNumWavelengths() != pRasterFileDescriptor->getBandCount())
         {
            errorMessage = "The number of wavelengths in the metadata does not match the number of bands.";
            mValidationError = VALID_WAVELENGTHS;
            return false;
         }
      }
   }

   // Interleave conversions
   if (validationTest & NO_INTERLEAVE_CONVERSIONS)
   {
      InterleaveFormatType dataInterleave = pRasterDescriptor->getInterleaveFormat();
      InterleaveFormatType fileInterleave = pRasterFileDescriptor->getInterleaveFormat();
      if ((pRasterFileDescriptor->getBandCount() > 1) && (dataInterleave != fileInterleave))
      {
         errorMessage = "Interleave format conversions are not supported.";
         mValidationError = NO_INTERLEAVE_CONVERSIONS;
         return false;
      }
   }

   // Skip factors
   if (validationTest & NO_ROW_SKIP_FACTOR)
   {
      if (pRasterDescriptor->getRowSkipFactor() > 0)
      {
         errorMessage = "Row skip factors are not supported.";
         mValidationError = NO_ROW_SKIP_FACTOR;
         return false;
      }
   }

   if (validationTest & NO_COLUMN_SKIP_FACTOR)
   {
      if (pRasterDescriptor->getColumnSkipFactor() > 0)
      {
         errorMessage = "Column skip factors are not supported.";
         mValidationError = NO_COLUMN_SKIP_FACTOR;
         return false;
      }
   }

   // Subsets
   if (validationTest & NO_ROW_SUBSETS)
   {
      if (pRasterDescriptor->getRowCount() != pRasterFileDescriptor->getRowCount())
      {
         errorMessage = "Row subsets are not supported.";
         mValidationError = NO_ROW_SUBSETS;
         return false;
      }
   }

   if (validationTest & NO_COLUMN_SUBSETS)
   {
      if (pRasterDescriptor->getColumnCount() != pRasterFileDescriptor->getColumnCount())
      {
         errorMessage = "Column subsets are not supported.";
         mValidationError = NO_COLUMN_SUBSETS;
         return false;
      }
   }

   if (validationTest & NO_BAND_SUBSETS)
   {
      if (pRasterDescriptor->getBandCount() != pRasterFileDescriptor->getBandCount())
      {
         errorMessage = "Band subsets are not supported.";
         mValidationError = NO_BAND_SUBSETS;
         return false;
      }
   }

   // Available memory
   if (validationTest & AVAILABLE_MEMORY)
   {
      unsigned int loadedRows = pRasterDescriptor->getRowCount();
      unsigned int loadedColumns = pRasterDescriptor->getColumnCount();
      unsigned int loadedBands = pRasterDescriptor->getBandCount();
      unsigned int bytesPerElement = pRasterDescriptor->getBytesPerElement();

      uint64_t dataSize = loadedRows * loadedColumns * loadedBands * bytesPerElement;
      uint64_t maxMemoryAvail = pUtilities->getMaxMemoryBlockSize();
#if PTR_SIZE > 4
      uint64_t totalRam = pUtilities->getTotalPhysicalMemory();
      if (totalRam < maxMemoryAvail)
      {
         maxMemoryAvail = totalRam;
      }
#endif

      if (dataSize > maxMemoryAvail)
      {
         errorMessage = "The data set cannot be loaded into memory.  Use a different "
            "processing location or specify a subset.";
         mValidationError = AVAILABLE_MEMORY;
         return false;
      }
   }

   return true;
}