# Use GNU parallel call to distribute the work across computers # - This call will wait until all processes are finished IrgPbsFunctions.runInGnuParallel(options.numProcesses, commandString, argumentFilePath, parallelArgs, options.nodesListPath, True)#not options.suppressOutput) # Build a gdal VRT file which is composed of all the processed tiles vrtPath = os.path.join(tempFolder, 'mosaic.vrt') cmd = "gdalbuildvrt -resolution highest " + vrtPath + " " + tempFolder + "*_.tif"; print cmd os.system(cmd) # Convert VRT file to final output file cmd = "gdal_translate -co compress=lzw -co bigtiff=yes " + vrtPath + " " + options.outputPath; print cmd os.system(cmd) #IrgSystemFunctions.executeCommand(cmd, False, True) # Clean up temporary files if not options.keep: IrgFileFunctions.removeFolderIfExists(tempFolder) endTime = time.time() print "Finished in " + str(endTime - startTime) + " seconds." if __name__ == "__main__": sys.exit(main(sys.argv[1:]))
def archiveDataSet(dataSetName, deleteLocalFiles=False, dryRun=False): """Archives a data set to long term storage on Lou""" # The local files to be archived are already in tar files # Make sure the data set is complete before archiving it ds = DataSet(dataSetName) if not ds.isComplete(): raise Exception('Attempting to archive incomplete data set: ' + dataSetName) localFolder = ds.getLocalFolder() resultsFolder = os.path.join(localFolder, 'results/') # In order to archive the file it just has to be moved over to the Lou filesystem. # - Tape archiving is performed automatically when needed. # - All tar files are stored in the same directory filesToArchive = ['output-CompressedOutputs.tar'] for f in filesToArchive: # Get storage name to use archiveName = 'NAC_DTM_' + dataSetName + '_CompressedOutputs.tar' inputPath = os.path.join(resultsFolder, f) outputPath = os.path.join(LOU_STORAGE_PATH, archiveName) # Move the file over to Lou #cmd = ['shiftc', '--wait', '--verify', inputPath, outputPath] cmd = 'shiftc --wait --verify ' + inputPath + ' ' + outputPath print cmd if not dryRun: # Actually transfer the file os.system(cmd) #p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) #textOutput, err = p.communicate() #print textOutput #print 'ppp' #print err #print textOutput.find('done') #if not ('done' in textOutput): # raise Exception('Error transferring file!') # Verify that the file was actually transferred resp = subprocess.call(['ssh', LOU_SSH_TARGET, 'test -e ' + pipes.quote(LOU_LOCAL_STORAGE_PATH)]) if resp == 0: print 'shiftc file transfer confirmed.' else: raise Exception('Failed to transfer file using shiftc!') if deleteLocalFiles: # Remove almost all files # Keep some result files and move them to the main data set directory filesToKeep = ['output-LOLA_diff_stats.txt', 'output-Log.txt', 'output-PcAlignLog.txt', 'output-CompressedInputs.tar.bz2', 'output-CompressedDiagnostics.tar.bz2'] for f in filesToKeep: inputPath = os.path.join(resultsFolder, f) outputPath = os.path.join(localFolder, f) print 'mv ' + inputPath + ' ' + outputPath if not dryRun: # Actually move the files shutil.move(inputPath, outputPath) # Now that we have saved a few files, delete everything else cmdRmImg = 'rm ' + localFolder + '/*.IMG' rdrPath = os.path.join(localFolder, 'lolaRdrPoints.csv') prtPath = os.path.join(localFolder, 'print.prt') #logPath = os.path.join(localFolder, 'stdOutputLog.txt') workDir = os.path.join(localFolder, 'workDir') resultsDir = os.path.join(localFolder, 'results') print cmdRmImg print 'rm ' + rdrPath print 'rm ' + prtPath #print 'rm ' + logPath print 'rm -rf ' + workDir print 'rm -rf ' + resultsDir if not dryRun: # Actually delete the files os.system(cmdRmImg) IrgFileFunctions.removeIfExists(rdrPath) IrgFileFunctions.removeIfExists(prtPath) #IrgFileFunctions.removeIfExists(logPath) IrgFileFunctions.removeFolderIfExists(workDir) IrgFileFunctions.removeFolderIfExists(resultsDir)
def main(argsIn): print '#################################################################################' print "Running makeDemAndCompare.py" try: try: usage = "usage: makeDemAndCompare.py [--output <path>][--manual]\n " parser = optparse.OptionParser(usage=usage) inputGroup = optparse.OptionGroup(parser, 'Input Paths') inputGroup.add_option("--left", dest="leftPath", help="Path to left cube file") inputGroup.add_option("--right", dest="rightPath", help="Path to right cube file") inputGroup.add_option("--lola", dest="lolaPath", help="Path to LOLA DEM") inputGroup.add_option("--asu", dest="asuPath", help="Path to ASU DEM") inputGroup.add_option("--node-file", dest="nodeFilePath", help="Path to file containing list of available nodes") parser.add_option_group(inputGroup) # The default working directory path is kind of ugly... parser.add_option("--workDir", dest="workDir", help="Folder to store temporary files in") parser.add_option("--prefix", dest="prefix", help="Output prefix.") parser.add_option("--log-path", dest="logPath", help="Where to write the output log file.") parser.add_option("--crop", dest="cropAmount", help="Crops the output image to reduce processing time.") parser.add_option("--manual", action="callback", callback=man, help="Read the manual.") parser.add_option("--keep", action="store_true", dest="keep", help="Do not delete the temporary files.") (options, args) = parser.parse_args(argsIn) if not options.leftPath: parser.error("Need left input path") if not options.rightPath: parser.error("Need right input path") if not options.prefix: parser.error("Need output prefix") except optparse.OptionError, msg: raise Usage(msg) print "Beginning processing....." startTime = time.time() # Make sure we have all the functions we need functionStartupCheck() # Set this to true to force steps after it to activate carry = False # Set up the output folders outputFolder = os.path.dirname(options.prefix) inputBaseName = os.path.basename(options.leftPath) tempFolder = outputFolder + '/' + inputBaseName + '_stereoCalibrationTemp/' if (options.workDir): tempFolder = options.workDir if not os.path.exists(outputFolder): os.mkdir(outputFolder) hadToCreateTempFolder = not os.path.exists(tempFolder) if not os.path.exists(tempFolder): os.mkdir(tempFolder) # Set up logging if not options.logPath: options.logPath = options.prefix + '-Log.txt' logging.basicConfig(filename=options.logPath,level=logging.INFO) # Go ahead and set up all the output paths # -- Deliverables demPath = options.prefix + '-DEM.tif' intersectionErrorPath = options.prefix + '-IntersectionErr.tif' hillshadePath = options.prefix + '-Hillshade.tif' colormapPath = options.prefix + '-Colormap.tif' colormapLegendPath = options.prefix + '-ColormapLegend.csv' mapProjectLeftPath = options.prefix + '-MapProjLeft.tif' mapProjectRightPath = options.prefix + '-MapProjRight.tif' confidenceLevelPath = options.prefix + '-Confidence.tif' confidenceLegendPath = options.prefix + '-ConfidenceLegend.csv' # -- Diagnostic intersectionViewPathX = options.prefix + '-IntersectionErrorX.tif' intersectionViewPathY = options.prefix + '-IntersectionErrorY.tif' intersectionViewPathZ = options.prefix + '-IntersectionErrorZ.tif' lolaDiffStatsPath = options.prefix + '-LOLA_diff_stats.txt' lolaDiffPointsPath = options.prefix + '-LOLA_diff_points.csv' lolaAsuDiffStatsPath = options.prefix + '-ASU_LOLA_diff_stats.txt' lolaAsuDiffPointsPath = options.prefix + '-ASU_LOLA_diff_points.csv' mapProjectLeftUint8Path = options.prefix + '-MapProjLeftUint8.tif' mapProjectRightUint8Path = options.prefix + '-MapProjRightUint8.tif' # If specified, crop the inputs that will be passed into the stereo function to reduce processing time mainMosaicCroppedPath = os.path.join(tempFolder, 'mainMosaicCropped.cub') stereoMosaicCroppedPath = os.path.join(tempFolder, 'stereoMosaicCropped.cub') if options.cropAmount and (options.cropAmount > 0): # Verify input files are present if not os.path.exists(options.leftPath): raise Exception('Input file ' + options.leftPath + ' not found!') if not os.path.exists(options.rightPath): raise Exception('Input file ' + options.rightPath + ' not found!') if (not os.path.exists(mainMosaicCroppedPath)) or carry: cmd = ('crop from= ' + options.leftPath + ' to= ' + mainMosaicCroppedPath + ' nlines= ' + str(options.cropAmount))# + ' line=24200') print cmd os.system(cmd) if (not os.path.exists(stereoMosaicCroppedPath) or carry): cmd = ('crop from= ' + options.rightPath + ' to= ' + stereoMosaicCroppedPath + ' nlines= ' + str(options.cropAmount))# + ' line=24200') print cmd os.system(cmd) options.leftPath = mainMosaicCroppedPath options.rightPath = stereoMosaicCroppedPath print '\n-------------------------------------------------------------------------\n' # Call stereo to generate a point cloud from the two images # - This step takes a really long time. stereoOutputPrefix = os.path.join(tempFolder, 'stereoWorkDir/stereo') stereoOutputFolder = os.path.join(tempFolder, 'stereoWorkDir') pointCloudPath = stereoOutputPrefix + '-PC.tif' stereoOptionString = ('--corr-timeout 400 --alignment-method AffineEpipolar --subpixel-mode ' + str(SUBPIXEL_MODE) + ' ' + options.leftPath + ' ' + options.rightPath + ' --job-size-w 4096 --job-size-h 4096 ' + # Reduce number of tile files created ' ' + stereoOutputPrefix + ' --processes 10 --threads-multiprocess 4' + ' --threads-singleprocess 32 --compute-error-vector' + ' --filter-mode 1' + ' --erode-max-size 5000 --subpixel-kernel 35 35 --subpixel-max-levels 0') if (not os.path.exists(pointCloudPath) and not os.path.exists(demPath)) or carry: # Verify input files are present if not os.path.exists(options.leftPath): raise Exception('Input file ' + options.leftPath + ' not found!') if not os.path.exists(options.rightPath): raise Exception('Input file ' + options.rightPath + ' not found!') cmd = ('parallel_stereo ' + stereoOptionString) print cmd os.system(cmd) # Compute percentage of good pixels percentGood = IrgAspFunctions.getStereoGoodPixelPercentage(stereoOutputPrefix) print 'Stereo completed with good pixel percentage: ' + str(percentGood) logging.info('Final stereo completed with good pixel percentage: %s', str(percentGood)) else: print 'Stereo file ' + pointCloudPath + ' already exists, skipping stereo step.' stereoTime = time.time() logging.info('Stereo finished in %f seconds', stereoTime - startTime) # Find out the center latitude of the mosaic if os.path.exists(options.leftPath): centerLat = IrgIsisFunctions.getCubeCenterLatitude(options.leftPath, tempFolder) elif os.path.exists(demPath): # Input file has been deleted but we still have the info demInfo = IrgGeoFunctions.getImageGeoInfo(demPath, False) centerLat = demInfo['standard_parallel_1'] else: raise Exception("Can't delete the input files before creating the DEM!") # Generate a DEM if (not os.path.exists(demPath)) or carry: # Equirectangular style projection # - Latitude of true scale = center latitude = lat_ts # - Latitude of origin = 0 = lat+0 # - Longitude of projection center = Central meridian = lon+0 cmd = ('point2dem --dem-hole-fill-len 15 --remove-outliers --errorimage -o ' + options.prefix + ' ' + pointCloudPath + ' -r moon --tr ' + str(DEM_METERS_PER_PIXEL) + ' --t_srs "+proj=eqc +lat_ts=' + str(centerLat) + ' +lat_0=0 +a='+str(MOON_RADIUS)+' +b='+str(MOON_RADIUS)+' +units=m" --nodata ' + str(DEM_NODATA)) os.system(cmd) else: print 'DEM file ' + demPath + ' already exists, skipping point2dem step.' # Create a hillshade image to visualize the output if (not os.path.exists(hillshadePath)) or carry: cmd = 'hillshade ' + demPath + ' -o ' + hillshadePath print cmd os.system(cmd) else: print 'Output file ' + hillshadePath + ' already exists, skipping hillshade step.' # Create a colorized version of the hillshade # - Uses a blue-red color map from here: http://www.sandia.gov/~kmorel/documents/ColorMaps/ if (not os.path.exists(colormapPath)) or (not os.path.exists(colormapLegendPath)) or carry: # The color LUT is kept with the source code lutFilePath = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'colorProfileBlueRed.csv') # Generate the initial version of colormap colormapTempPath = options.prefix + '-ColormapTemp.tif' cmd = 'colormap ' + demPath + ' -o ' + colormapTempPath + ' -s ' + hillshadePath + ' --lut-file ' + lutFilePath print cmd os.system(cmd) # Now convert to the final output version (remove transparency layer) and remove the temp file IrgFileFunctions.stripRgbImageAlphaChannel(colormapTempPath, colormapPath) os.remove(colormapTempPath) # Generate another file storing the colormap info writeColorMapInfo(colormapPath, lutFilePath, demPath, colormapLegendPath) else: print 'Output file ' + colormapPath + ' already exists, skipping colormap step.' ## Create a 3d mesh of the point cloud #meshPath = os.path.join(outputFolder, 'mesh.ive') #meshPrefix = os.path.join(outputFolder, 'mesh') #cmd = 'point2mesh ' + pointCloudPath + ' ' + options.leftPath + ' -o ' + meshPrefix #if not os.path.exists(meshPath): # print cmd # os.system(cmd) if not options.keep: # Remove stereo folder here to cut down on file count before mapproject calls IrgFileFunctions.removeFolderIfExists(stereoOutputFolder) # Convert the intersection error to a viewable format cmdX = 'gdal_translate -ot byte -scale 0 10 0 255 -outsize 50% 50% -b 1 ' + intersectionErrorPath + ' ' + intersectionViewPathX cmdY = 'gdal_translate -ot byte -scale 0 10 0 255 -outsize 50% 50% -b 2 ' + intersectionErrorPath + ' ' + intersectionViewPathY cmdZ = 'gdal_translate -ot byte -scale 0 10 0 255 -outsize 50% 50% -b 3 ' + intersectionErrorPath + ' ' + intersectionViewPathZ if not os.path.exists(intersectionViewPathX) or carry: print cmdX os.system(cmdX) if not os.path.exists(intersectionViewPathY) or carry: print cmdY os.system(cmdY) if not os.path.exists(intersectionViewPathZ) or carry: print cmdZ os.system(cmdZ) # Generate a confidence plot from the intersection error if not os.path.exists(confidenceLevelPath): thresholdString = str(PIXEL_ACCURACY_THRESHOLDS)[1:-1].replace(',', '') cmd = ('maskFromIntersectError ' + intersectionErrorPath + ' ' + confidenceLevelPath + ' --legend ' + confidenceLegendPath + ' --scaleOutput --thresholds ' + thresholdString) print cmd os.system(cmd) hillshadeTime = time.time() logging.info('DEM and hillshade finished in %f seconds', hillshadeTime - stereoTime) # Call script to compare LOLA data with the DEM if options.lolaPath: compareDemToLola(options.lolaPath, demPath, lolaDiffStatsPath, lolaDiffPointsPath, carry) # Call script to compare LOLA data with the ASU DEM if options.asuPath: compareDemToLola(options.lolaPath, options.asuPath, lolaAsuDiffStatsPath, lolaAsuDiffPointsPath, carry) # Generate a map projected version of the left and right images # - This step is done last since it is so slow! mapProjectImage(options.leftPath, demPath, mapProjectLeftPath, MAP_PROJECT_METERS_PER_PIXEL, centerLat, options.nodeFilePath, carry) mapProjectImage(options.rightPath, demPath, mapProjectRightPath, MAP_PROJECT_METERS_PER_PIXEL, centerLat, options.nodeFilePath, carry) # Generate 8 bit versions of the mapproject files for debugging cmdLeft = 'gdal_translate -scale -ot byte ' + mapProjectLeftPath + ' ' + mapProjectLeftUint8Path cmdRight = 'gdal_translate -scale -ot byte ' + mapProjectRightPath + ' ' + mapProjectRightUint8Path if not os.path.exists(mapProjectLeftUint8Path) or carry: print cmdLeft os.system(cmdLeft) if not os.path.exists(mapProjectRightUint8Path) or carry: print cmdRight os.system(cmdRight) mapProjectTime = time.time() logging.info('Map project finished in %f seconds', mapProjectTime - hillshadeTime) # Clean up temporary files if not options.keep: print 'Removing temporary files' IrgFileFunctions.removeIfExists(mainMosaicCroppedPath) IrgFileFunctions.removeIfExists(stereoMosaicCroppedPath) #IrgFileFunctions.removeIntermediateStereoFiles(stereoOutputPrefix) # Limited clear IrgFileFunctions.removeFolderIfExists(stereoOutputFolder) # Larger clear #if (hadToCreateTempFolder): Not done since stereo output needs to be retained # IrgFileFunctions.removeFolderIfExists(tempFolder) endTime = time.time() logging.info('makeDemAndCompare.py finished in %f seconds', endTime - startTime) print "Finished in " + str(endTime - startTime) + " seconds." print '#################################################################################' return 0