def createSPDPulse(tewHeader, tewPulse, pulseID): """ Create a pulse from TEW-record. """ # Create pulse pulse = spdpy.createSPDPulsePy() pulse.pulseID = pulseID pulse.wavelength = 1550.0 pulse.numberOfReturns = 0 pulse.gpsTime = long(tewPulse.GPSTime*1e9) #Convert to long and store as nanoseconds. # Add origin coordinates pulse.x0 = tewPulse.xyzRelOrigin[0] * tewHeader.xScaleFactor + tewHeader.xOffset pulse.y0 = tewPulse.xyzRelOrigin[1] * tewHeader.yScaleFactor + tewHeader.yOffset pulse.z0 = tewPulse.xyzRelOrigin[2] * tewHeader.zScaleFactor + tewHeader.zOffset range = np.sqrt(tewPulse.outgoingVector[0]**2 + tewPulse.outgoingVector[1]**2 + tewPulse.outgoingVector[2]**2) pulse.azimuth = np.arctan2(tewPulse.outgoingVector[0], tewPulse.outgoingVector[1]) #Should be (y, x), but in SPD it's (x, y). if pulse.azimuth < 0: #It has a value between -pi..pi, but change to a value between 0..2*pi. pulse.azimuth += spdTwoPi pulse.zenith = np.arccos(tewPulse.outgoingVector[2] / range) # Received waveform pulse.rangeToWaveformStart = (tewPulse.recWfOffset - (tewPulse.triggerWfBlockOffset + tewPulse.triggerEchoOffset)) * tewHeader.sampleLength + tewPulse.recWfConstOffset pulse.receiveWaveGain = 1.0 pulse.receiveWaveOffset = 0.0 pulse.numOfReceivedBins = tewPulse.recWfLength pulse.received = [int(i) for i in tewPulse.recWf] # Transmitted waveform pulse.transWaveGain = 1.0 pulse.transWaveOffset = 0.0 pulse.numOfTransmittedBins = tewPulse.triggerWfBlockLength pulse.transmitted = [int(i) for i in tewPulse.triggerWf] # For debugging purpose. if cmdargs.verbosePulses: print "x0: ", pulse.x0 print "y0: ", pulse.y0 print "z0: ", pulse.z0 print "tewPulse.outgoingVector :", tewPulse.outgoingVector print "range:", range print "azimuth:", pulse.azimuth print "zenith:", pulse.zenith print "rangeToWaveformStart:", pulse.rangeToWaveformStart # Return result return pulse
def createSPDPulse(data, wfData, pulseID): """ Create a pulse from LGC record """ # Create pulse pulse = spdpy.createSPDPulsePy() pulse.pulseID = pulseID pulse.wavelength = 1550.0 pulse.numberOfReturns = 0 pulse.GPStime = data[1] # Add coordinates pulse.x0 = data[2] pulse.y0 = data[3] pulse.z0 = data[4] magnitude = np.sqrt(data[5]**2 + data[6]**2 + data[7]**2) pulse.azimuth = np.arctan((data[5]/magnitude) / (data[6]/magnitude)) if pulse.azimuth < 0: pulse.azimuth += 2 * np.pi pulse.zenith = np.arccos(data[7] / magnitude) # Received waveform rwfData = wfData[data[10]:] pulse.rangeToWaveformStart = ((constants.c / 1e9) * data[8]) / 2 pulse.receiveWaveGain = 1.0 pulse.receiveWaveOffset = 0.0 pulse.numOfReceivedBins = data[9] pulse.received = [int(i) for i in rwfData] # Transmitted waveform twfData = wfData[:data[10]] pulse.transWaveGain = 1.0 pulse.transWaveOffset = 0.0 pulse.numOfTransmittedBins = data[10] pulse.transmitted = [int(i) for i in twfData] # Return result return pulse
def txt2UPD(Input, Output, Header, separator, x_col, y_col, z_col, r_col, g_col, b_col): ''' A function to convert a text file into the UPD format. Input: input text file path. Output: output UPD file path. separator: column separator/delimiter for the input text file. x_col: column index of the x coordinates. y_col: column index of the y coordinates. z_col: column index of the z coordinates. r_col: column index of the red color channel. g_col: column index of the green color channel. b_col: column index of the blue color channel. ''' # try to open the input text file: try: f = open(Input, 'r') n_points = sum([1 for line in f]) f.seek(0) if Header == True: f.readline() except Exception: sys.exit('Error: unable to read input text file.') print('Creating the output file: '+os.path.basename(Output)) UPD = spdpy.createSPDFile(Output) spdWriter = spdpy.SPDPyNoIdxWriter() spdWriter.open(UPD, Output) UPD.setReceiveWaveformDefined(0) UPD.setTransWaveformDefined(0) UPD.setDecomposedPtDefined(0) UPD.setDiscretePtDefined(1) UPD.setOriginDefined(0) UPD.setHeightDefined(0) UPD.setRgbDefined(1) UPD.setGeneratingSoftware('Python.') UPD.setUserMetaField('Processed by Osian!') # iterate through each line in the input file: for idx, line in enumerate(f): line = line.strip('\n').split(separator) try: # create point: Point = spdpy.createSPDPointPy() Point.returnID = 1 # this is set to 1 as Photogrammetry cannot receive multiple-returns. Point.x = float(line[x_col]) Point.y = float(line[y_col]) Point.z = float(line[z_col]) Point.height = 0.0 Point.amplitudeReturn = (int(line[r_col]) + int(line[g_col]) + int(line[b_col])) / 3 Point.red = int(line[r_col]) Point.green = int(line[g_col]) Point.blue = int(line[b_col]) Point.classification = 1 # 1 = unclassified Point = [Point] # assign point to pulse: Pulse = spdpy.createSPDPulsePy() Pulse.numberOfReturns = 1 # this is set to 1 as Photogrammetry cannot receive multiple-returns. Pulse.pts = Point spdWriter.writeData([Pulse]) del Pulse, Point except Exception: continue del line progress_bar(n_points, idx+1) # close the upd file: f.close() spdWriter.close(UPD) print('Done.')
def main(cmdargs): """ Read a CBL ascii file and write to a scan project SPD file Columns: Intensity, Azimuth, Zenith, Time of Flight and Return Number """ # Get file information zenith_resolution = 0.5 azimuth_resolution = 0.25 num_scanlines = 721 num_scanlinepulses = 541 numrecords = file_len(cmdargs.infile) # Open output SPD file outfile = cmdargs.infile.replace(".txt",".spd") spdoutfile = spdpy.createSPDFile(outfile) spdoutfile.setNumBinsX(num_scanlinepulses) spdoutfile.setNumBinsY(num_scanlines) spdoutfile.setBinSize(1) spdwriter = spdpy.SPDPySeqWriter() spdwriter.open(spdoutfile, outfile) # Define the data present spdoutfile.setReceiveWaveformDefined(0) spdoutfile.setTransWaveformDefined(0) spdoutfile.setDecomposedPtDefined(0) spdoutfile.setDiscretePtDefined(1) spdoutfile.setOriginDefined(1) spdoutfile.setHeightDefined(0) spdoutfile.setRgbDefined(0) # Set header attributes spdoutfile.setSensorHeight(1.2) spdoutfile.setBeamDivergence(15.0) spdoutfile.setPulseIdxMethod(5) spdoutfile.setZenithMin(0) spdoutfile.setZenithMax(135) spdoutfile.setAzimuthMin(0) spdoutfile.setAzimuthMax(360) # now read through the file pulsecount = 0 zenithcoltemp = -1.0 scanlineidxtemp = 1 scanlinecount = 1 scanline = list() f = open(cmdargs.infile, 'r') for i,line in enumerate(f): lparts = line.strip('\r\n').split() if len(lparts) > 0: # pulse - need to assume data is time sequential returnnum = int(float(lparts[4])) # Pulses with no returns if returnnum == 0: if i > 0: scanline.append([pulse]) pulsecount += 1 pulse = spdpy.createSPDPulsePy() pulse.pulseID = pulsecount zenithcoltemp += 1 pulse.numberOfReturns = returnnum # If it's a new scan line, write out previous one and set up new one if zenithcoltemp > 540: spdwriter.writeDataRow(scanline, scanlinecount-1) scanline = list() scanlinecount += 1 scanlineidxtemp = 1 pulse.zenith = 135 zenithcoltemp = 0 else: scanlineidxtemp += 1 pulse.zenith = abs(float(zenithcoltemp)*zenith_resolution - 135) # Calculate azimuth angle if zenithcoltemp > 270: pulse.azimuth = float(lparts[1]) * azimuth_resolution + 180 else: pulse.azimuth = float(lparts[1]) * azimuth_resolution pulse.xIdx = scanlineidxtemp pulse.yIdx = scanlinecount pulse.scanline = scanlinecount pulse.scanlineIdx = scanlineidxtemp # First return elif returnnum == 1: if i > 0: scanline.append([pulse]) # Initialise new pulse pulsecount += 1 pulse = spdpy.createSPDPulsePy() pulse.pulseID = pulsecount pulse.numberOfReturns = returnnum # If it's a new scan line, write out previous one and set up new one if float(lparts[2]) < zenithcoltemp: spdwriter.writeDataRow(scanline, scanlinecount-1) scanline = list() scanlinecount += 1 scanlineidxtemp = 1 else: scanlineidxtemp += 1 # Calculate zenith angle pulse.zenith = abs(float(lparts[2]) * zenith_resolution - 135) # Calculate azimuth angle if zenithcoltemp > 270: pulse.azimuth = float(lparts[1]) * azimuth_resolution + 180 else: pulse.azimuth = float(lparts[1]) * azimuth_resolution pulse.xIdx = scanlineidxtemp pulse.yIdx = scanlinecount pulse.scanline = scanlinecount pulse.scanlineIdx = scanlineidxtemp zenithcoltemp = float(lparts[2]) # Second return elif returnnum == 2: pulse.numberOfReturns = returnnum # Create a return if one exists if returnnum > 0: tof = float(lparts[0]) intensity = float(lparts[3]) point = create_point(tof,np.radians(pulse.zenith),np.radians(pulse.azimuth),intensity,returnnum) pulse.pts.append(point) # Let's monitor progress sys.stdout.write("Writing sequential SPD file %s (%i%%)\r" % (outfile, scanlinecount / float(num_scanlines) * 100)) # Write last scan line scanline.append([pulse]) spdwriter.writeDataRow(scanline, scanlinecount-1) spdoutfile.setNumPulses(pulsecount) # Close the output file f.close() spdwriter.close(spdoutfile)
def main(cmdargs): # Open UPD file spdOutFile = spdpy.createSPDFile(cmdargs.outputFile) updWriter = spdpy.UPDWriter() updWriter.open(spdOutFile, cmdargs.outputFile) outPulses = list() # Define contents this lidar dataset spdOutFile.setReceiveWaveformDefined(0) spdOutFile.setTransWaveformDefined(0) spdOutFile.setDecomposedPtDefined(1) spdOutFile.setDiscretePtDefined(0) spdOutFile.setOriginDefined(1) # For the RIEGL ASCII format, we do not know what pulse each return # is linked to so each return is assigned to a unique pulse and we # set this attribute to TRUE so users know the return number are synthetic spdOutFile.setReturnNumsSynGen(1) # Define scanner properties spdOutFile.setSensorHeight(cmdargs.agh) spdOutFile.setWavelength(1550.0) # Open ASCII file and read header asciiObj = open(cmdargs.inputFile, 'r') header = asciiObj.readline().strip('\r\n').split(',') nPoints = int(asciiObj.readline().strip('\r\n')) spdOutFile.setNumPulses(nPoints) spdOutFile.setNumPts(nPoints) if (header.count("Red") > 0): spdOutFile.setRgbDefined(1) # Loop through each line of data outPulses = list() pulsesInBuffer = 0 for i in range(nPoints): # Read and parse line line = asciiObj.readline().strip('\r\n') asciiData = parseLine(header, line) # Create pulse and add attributes pulse = spdpy.createSPDPulsePy() pulse.pulseID = asciiData["ID"] pulse.x0 = cmdargs.x0 pulse.y0 = cmdargs.y0 pulse.z0 = cmdargs.z0 pulse.azimuth = asciiData["Phi"] pulse.zenith = asciiData["Theta"] # Create point and add attributes point = spdpy.createSPDPointPy() point.returnID = 0 point.x = asciiData["X"] point.y = asciiData["Y"] point.z = asciiData["Z"] pulse.xIdx = asciiData["X"] pulse.yIdx = asciiData["Y"] point.range = asciiData["Range"] point.amplitudeReturn = asciiData["Amplitude"] #if asciiData.has_key("Reflectance"): # point.user = asciiData["Reflectance"] if asciiData.has_key("Deviation"): point.widthReturn = asciiData["Deviation"] if asciiData.has_key("Red"): point.red = asciiData["Red"] point.green = asciiData["Green"] point.blue = asciiData["Blue"] # Add point data to the pulse pulse.pts.append(point) pulse.numberOfReturns = 1 pulse.pts_start_idx = i # Update global statistics if i > 0: spdOutFile.setXMin(min(spdOutFile.xMin, asciiData["X"])) spdOutFile.setXMax(max(spdOutFile.xMax, asciiData["X"])) spdOutFile.setYMin(min(spdOutFile.yMin, asciiData["Y"])) spdOutFile.setYMax(max(spdOutFile.yMax, asciiData["Y"])) spdOutFile.setZMin(min(spdOutFile.zMin, asciiData["Z"])) spdOutFile.setZMax(max(spdOutFile.zMax, asciiData["Z"])) spdOutFile.setZenithMin( min(spdOutFile.zenithMin, asciiData["Theta"])) spdOutFile.setZenithMax( max(spdOutFile.zenithMax, asciiData["Theta"])) spdOutFile.setAzimuthMin( min(spdOutFile.azimuthMin, asciiData["Phi"])) spdOutFile.setAzimuthMax( max(spdOutFile.azimuthMax, asciiData["Phi"])) spdOutFile.setRangeMin(min(spdOutFile.rangeMin, asciiData["Range"])) spdOutFile.setRangeMax(max(spdOutFile.rangeMax, asciiData["Range"])) else: spdOutFile.setXMin(asciiData["X"]) spdOutFile.setXMax(asciiData["X"]) spdOutFile.setYMin(asciiData["Y"]) spdOutFile.setYMax(asciiData["Y"]) spdOutFile.setZMin(asciiData["Z"]) spdOutFile.setZMax(asciiData["Z"]) spdOutFile.setZenithMin(asciiData["Theta"]) spdOutFile.setZenithMax(asciiData["Theta"]) spdOutFile.setAzimuthMin(asciiData["Phi"]) spdOutFile.setAzimuthMax(asciiData["Phi"]) spdOutFile.setRangeMin(asciiData["Range"]) spdOutFile.setRangeMax(asciiData["Range"]) # If buffer size is reached, write out pulses outPulses.append(pulse) pulsesInBuffer += 1 if (pulsesInBuffer == spdOutFile.pulseBlockSize or i == (nPoints - 1)): try: updWriter.writeData(outPulses) except: raise IOError, "Error writing UPD File." pulsesInBuffer = 0 outPulses = list() # Let's monitor progress sys.stdout.write( "Writing UPD file %s (%i%%)\r" % (cmdargs.outputFile, int((i + 1) / float(nPoints) * 100.0))) # Close the input and output files asciiObj.close() updWriter.close(spdOutFile)
def main(cmdargs): # Open UPD file spdOutFile = spdpy.createSPDFile(cmdargs.outputFile); updWriter = spdpy.UPDWriter() updWriter.open(spdOutFile,cmdargs.outputFile) outPulses = list() # Define contents this lidar dataset spdOutFile.setReceiveWaveformDefined(1) spdOutFile.setTransWaveformDefined(1) spdOutFile.setDecomposedPtDefined(0) spdOutFile.setDiscretePtDefined(0) spdOutFile.setOriginDefined(1) # Define scanner properties spdOutFile.setWavelength(1550.0) spdOutFile.setTemporalBinSpacing(1) # Open ASCII file and read header asciiObj = open(cmdargs.inputFile, 'r') transmittedWaveform = [] receivedWaveform = [] i = 0 for eachLine in asciiObj: if i == 0: transmittedWaveform = parseLine(eachLine) elif i == 1: receivedWaveform = parseLine(eachLine) i = i + 1 linearVals = parseFileToList(cmdargs.linearFile) delogVals = parseFileToList(cmdargs.delogFile) transmittedWaveformScale = [] for val in transmittedWaveform: transmittedWaveformScale.append(delogVals[val]) receivedWaveformScale = [] for val in receivedWaveform: receivedWaveformScale.append(linearVals[val]) pulse = spdpy.createSPDPulsePy() pulse.pulseID = 0 pulse.x0 = 0 pulse.y0 = 0 pulse.z0 = 0 pulse.azimuth = 0 pulse.zenith = 0 pulse.numOfTransmittedBins = len(transmittedWaveformScale) pulse.transmitted = transmittedWaveformScale pulse.transWaveGain = 1 pulse.transWaveOffset = 0 pulse.numOfReceivedBins = len(receivedWaveformScale) pulse.received = receivedWaveformScale pulse.receiveWaveGain = 1 pulse.receiveWaveOffset = 0 pulse.waveNoiseThreshold = 9 outPulses.append(pulse) updWriter.writeData(outPulses) updWriter.close(spdOutFile)
def main(cmdargs): # debugging # import pdb; pdb.set_trace() driver=gdal.GetDriverByName('ENVI') """ Read a DWEL ENVI file and write to SPD """ # Open the data cube files and read header cds = gdal.Open(cmdargs.cubefile, gdal.GA_ReadOnly) ads = gdal.Open(cmdargs.ancillaryfile, gdal.GA_ReadOnly) # Get basic metadata from the ENVI .hdr file metaStr = ads.GetMetadata('') import pdb; pdb.set_trace() # Get the ENVI header file name tmpstr = cmdargs.ancillaryfile.rsplit('.') if os.path.isfile(tmpstr[0]+'.hdr'): hdrname = tmpstr[0]+'.hdr' else: hdrname = cmdargs.ancillaryfile + '.hdr' # Get all metadata including EVI/DWEL defined metadata from the ENVI .hdr file hdr = envi_header.ENVI_HDR(hdrname, 'r') metaDict = hdr.getmetadata() # Open output SPD file spdoutfile = spdpy.createSPDFile(cmdargs.outfile) spdoutfile.setNumBinsX(cds.RasterXSize) spdoutfile.setNumBinsY(cds.RasterYSize) spdoutfile.setBinSize(1) spdwriter = spdpy.SPDPySeqWriter() spdwriter.open(spdoutfile, cmdargs.outfile) # Define the data present spdoutfile.setReceiveWaveformDefined(1) spdoutfile.setTransWaveformDefined(0) spdoutfile.setDecomposedPtDefined(0) spdoutfile.setDiscretePtDefined(0) spdoutfile.setOriginDefined(1) spdoutfile.setHeightDefined(0) spdoutfile.setRgbDefined(0) # Set header attributes spdoutfile.setSensorHeight(metaDict['evi_scan_info']['EVI Height']) spdoutfile.setTemporalBinSpacing(1.0 / metaDict['evi_scan_info']['Digitiser Sampling Rate']) spdoutfile.setBeamDivergence(metaDict['evi_scan_info']['Beam Divergence'] * 1e-3 / np.pi * 180.0) # unit: degree spdoutfile.setPulseIdxMethod(5) spdoutfile.setNumPulses(cds.RasterXSize*cds.RasterYSize) # The time of captured should be read from the header file later. # Now because the DWEL raw data does not give any meta data, the time of capture # is manually populated according to the name of field campaign if cmdargs.cubefile.lower().find('brisbane') > -1: spdoutfile.setYearOfCapture(2013) spdoutfile.setMonthOfCapture(7) if cmdargs.cubefile.find('CA') > -1: spdoutfile.setYearOfCapture(2013) spdoutfile.setMonthOfCapture(6) spdoutfile.setWaveformBitRes(16) # spdoutfile.setNumOfWavelengths(int(metaDict['dwel_adaptation']['Wavelength'])) spdoutfile.setPulseRepetitionFreq(2000) spdoutfile.setMaxScanAngle(180.0) if metaDict['evi_scan_info']['Beam Divergence'] == 2.5: spdoutfile.setPulseAngularSpacingAzimuth(2.0 * 1e-3 / np.pi * 180.0) # unit: degree spdoutfile.setPulseAngularSpacingZenith(2.0 * 1e-3 / np.pi * 180.0) # unit: degree if metaDict['evi_scan_info']['Beam Divergence'] == 1.25: spdoutfile.setPulseAngularSpacingAzimuth(1.0 * 1e-3 / np.pi * 180.0) # unit: degree spdoutfile.setPulseAngularSpacingZenith(1.0 * 1e-3 / np.pi * 180.0) # unit: degree # Set user-defined header attribute string with JSON string format json_str = '{"evi_scan_info":{"Scan Duration":"' + metaDict['evi_scan_info']['Scan Duration'] + \ '","Bearing":"' + metaDict['evi_scan_info']['Bearing'] + \ '","Scan Description":"' + metaDict['evi_scan_info']['Scan Description'] + \ '","More Description":"' json_str = json_str + ','.join(s.replace('"', '\\"') for s in metaDict['evi_scan_info']['descript_str']) json_str = json_str + '"},"dwel_adaptation":{"More Description":"' json_str = json_str + ','.join(s.replace('"', '\\"') for s in metaDict['dwel_adaptation']['descript_str']) + '"}}' spdoutfile.setUserMetaField(json_str) minAz = 360.0 maxAz = 0.0 minZen = 180.0 maxZen = 0.0 # now read through the image blocks for y in range(cds.RasterYSize): # Read as scan line cdata = cds.ReadAsArray(xoff=0, yoff=y, xsize=cds.RasterXSize, ysize=1) adata = ads.ReadAsArray(xoff=0, yoff=y, xsize=ads.RasterXSize, ysize=1) scanline = list() for x in range(cds.RasterXSize): pulse = spdpy.createSPDPulsePy() pulse.x0, pulse.y0, pulse.z0 = 0.0, 0.0, 0.0 pulse.numberOfReturns = 0 # band 7 (index 6 here) in ancillary is mask, index to bands here # starts from 0. if adata[6,0,x] == 0: pulse.ignore = 1 # band 8 (index 7 here) in ancillary is zenith angle. pulse.zenith = adata[7,0,x]/10.0 # band 9 (index 8 here) in ancillary is azimuth angle. pulse.azimuth = adata[8,0,x]/10.0 if pulse.azimuth > maxAz: maxAz = pulse.azimuth if pulse.azimuth < minAz: minAz = pulse.azimuth if pulse.zenith > maxZen: maxZen = pulse.zenith if pulse.zenith < minZen: minZen = pulse.zenith pulse.numOfReceivedBins = cdata[:,0,x].size pulse.received = [int(w) for w in cdata[:,0,x]] pulse.wavelength = int(metaDict['dwel_adaptation']['Wavelength']) pulse.pulseID = y * x + x pulse.xIdx = x pulse.yIdx = y pulse.scanline = y pulse.scanlineIdx = x #scanline.append(pulse) scanline.append([pulse]) # Write scan line spdwriter.writeDataRow(scanline, y) # Let's monitor progress # sys.stdout.write("Writing sequential SPD file %s (%i%%)\r" % (cmdargs.outfile, y / float(cds.RasterYSize) * 100.0)) # set more header attributes spdoutfile.setZenithMin(minZen) spdoutfile.setZenithMax(maxZen) spdoutfile.setAzimuthMin(minAz) spdoutfile.setAzimuthMax(maxAz) # set more header attributes # the time of creation will be populated by the spdlib itself. # timenow = datetime.datetime.now() # spdoutfile.setYearOfCreation(timenow.year) # spdoutfile.setMonthOfCreation(timenow.month) # spdoutfile.setDayOfCreation(timenow.day) # spdoutfile.setHourOfCreation(timenow.hour) # spdoutfile.setMinuteOfCreation(timenow.minute) # spdoutfile.setSecondOfCreation(timenow.second) # Close the output file spdwriter.close(spdoutfile) # report it's finished sys.stdout.write("Writing sequential SPD file %s finished\n" % (cmdargs.outfile))