Example #1
0
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
Example #2
0
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
Example #3
0
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.')
Example #4
0
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)
Example #5
0
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)
Example #6
0
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)
Example #7
0
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))