Ejemplo n.º 1
0
def estimateFrameOffset(swath1, swath2, image1, image2, matchingMode=0):
    '''
    estimate offset of two adjacent frames using matching
    matchingMode:  0: ScanSAR full-aperture image
                   1: regular image
    '''
    import isceobj
    from isceobj.Alos2Proc.Alos2ProcPublic import cullOffsets
    from isceobj.Alos2Proc.Alos2ProcPublic import cullOffsetsRoipac
    from isceobj.Alos2Proc.Alos2ProcPublic import meanOffset
    from mroipac.ampcor.Ampcor import Ampcor

    ##########################################
    #2. match using ampcor
    ##########################################
    ampcor = Ampcor(name='insarapp_slcs_ampcor')
    ampcor.configure()

    #mSLC = isceobj.createSlcImage()
    mSLC = isceobj.createImage()
    mSLC.load(image1 + '.xml')
    mSLC.setFilename(image1)
    #mSLC.extraFilename = image1 + '.vrt'
    mSLC.setAccessMode('read')
    mSLC.createImage()

    #sSLC = isceobj.createSlcImage()
    sSLC = isceobj.createImage()
    sSLC.load(image2 + '.xml')
    sSLC.setFilename(image2)
    #sSLC.extraFilename = image2 + '.vrt'
    sSLC.setAccessMode('read')
    sSLC.createImage()

    if mSLC.dataType.upper() == 'CFLOAT':
        ampcor.setImageDataType1('complex')
        ampcor.setImageDataType2('complex')
    elif mSLC.dataType.upper() == 'FLOAT':
        ampcor.setImageDataType1('real')
        ampcor.setImageDataType2('real')
    else:
        raise Exception('file type not supported yet.')

    ampcor.setMasterSlcImage(mSLC)
    ampcor.setSlaveSlcImage(sSLC)

    #MATCH REGION
    #compute an offset at image center to use
    rgoff = -(swath2.startingRange -
              swath1.startingRange) / swath1.rangePixelSize
    azoff = -(
        (swath2.sensingStart -
         swath1.sensingStart).total_seconds()) / swath1.azimuthLineInterval
    rgoff = int(rgoff)
    azoff = int(azoff)
    #it seems that we cannot use 0, haven't look into the problem
    if rgoff == 0:
        rgoff = 1
    if azoff == 0:
        azoff = 1
    firstSample = 1
    if rgoff < 0:
        firstSample = int(35 - rgoff)
    firstLine = 1
    if azoff < 0:
        firstLine = int(35 - azoff)
    ampcor.setAcrossGrossOffset(rgoff)
    ampcor.setDownGrossOffset(azoff)
    ampcor.setFirstSampleAcross(firstSample)
    ampcor.setLastSampleAcross(mSLC.width)
    ampcor.setNumberLocationAcross(30)
    ampcor.setFirstSampleDown(firstLine)
    ampcor.setLastSampleDown(mSLC.length)
    ampcor.setNumberLocationDown(10)

    #MATCH PARAMETERS
    #full-aperture mode
    if matchingMode == 0:
        ampcor.setWindowSizeWidth(64)
        ampcor.setWindowSizeHeight(512)
        #note this is the half width/length of search area, number of resulting correlation samples: 32*2+1
        ampcor.setSearchWindowSizeWidth(32)
        ampcor.setSearchWindowSizeHeight(32)
        #triggering full-aperture mode matching
        ampcor.setWinsizeFilt(8)
        ampcor.setOversamplingFactorFilt(64)
    #regular mode
    else:
        ampcor.setWindowSizeWidth(64)
        ampcor.setWindowSizeHeight(64)
        ampcor.setSearchWindowSizeWidth(32)
        ampcor.setSearchWindowSizeHeight(32)

    #REST OF THE STUFF
    ampcor.setAcrossLooks(1)
    ampcor.setDownLooks(1)
    ampcor.setOversamplingFactor(64)
    ampcor.setZoomWindowSize(16)
    #1. The following not set
    #Matching Scale for Sample/Line Directions                       (-)    = 1. 1.
    #should add the following in Ampcor.py?
    #if not set, in this case, Ampcor.py'value is also 1. 1.
    #ampcor.setScaleFactorX(1.)
    #ampcor.setScaleFactorY(1.)

    #MATCH THRESHOLDS AND DEBUG DATA
    #2. The following not set
    #in roi_pac the value is set to 0 1
    #in isce the value is set to 0.001 1000.0
    #SNR and Covariance Thresholds                                   (-)    =  {s1} {s2}
    #should add the following in Ampcor?
    #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC
    #ampcor.setThresholdSNR(0)
    #ampcor.setThresholdCov(1)
    ampcor.setDebugFlag(False)
    ampcor.setDisplayFlag(False)

    #in summary, only two things not set which are indicated by 'The following not set' above.

    #run ampcor
    ampcor.ampcor()
    offsets = ampcor.getOffsetField()
    #ampcorOffsetFile = 'ampcor.off'
    #writeOffset(offsets, ampcorOffsetFile)

    #finalize image, and re-create it
    #otherwise the file pointer is still at the end of the image
    mSLC.finalizeImage()
    sSLC.finalizeImage()

    #############################################
    #3. cull offsets
    #############################################
    #refinedOffsets = cullOffsets(offsets)
    refinedOffsets = cullOffsetsRoipac(offsets, numThreshold=50)

    if refinedOffsets != None:
        rangeOffset, azimuthOffset = meanOffset(refinedOffsets)
        return (rangeOffset, azimuthOffset)
    else:
        return None
def estimateOffsetField(reference, secondary, azoffset=0, rgoffset=0):
    '''
    Estimate offset field between burst and simamp.
    '''

    sim = isceobj.createSlcImage()
    sim.load(secondary + '.xml')
    sim.setAccessMode('READ')
    sim.createImage()

    sar = isceobj.createSlcImage()
    sar.load(reference + '.xml')
    sar.setAccessMode('READ')
    sar.createImage()

    width = sar.getWidth()
    length = sar.getLength()

    objOffset = Ampcor(name='reference_offset1')
    objOffset.configure()
    objOffset.setAcrossGrossOffset(rgoffset)
    objOffset.setDownGrossOffset(azoffset)
    objOffset.setWindowSizeWidth(128)
    objOffset.setWindowSizeHeight(128)
    objOffset.setSearchWindowSizeWidth(40)
    objOffset.setSearchWindowSizeHeight(40)
    margin = 2 * objOffset.searchWindowSizeWidth + objOffset.windowSizeWidth

    nAcross = 60
    nDown = 60

    offAc = max(101, -rgoffset) + margin
    offDn = max(101, -azoffset) + margin

    lastAc = int(min(width, sim.getWidth() - offAc) - margin)
    lastDn = int(min(length, sim.getLength() - offDn) - margin)

    if not objOffset.firstSampleAcross:
        objOffset.setFirstSampleAcross(offAc)

    if not objOffset.lastSampleAcross:
        objOffset.setLastSampleAcross(lastAc)

    if not objOffset.firstSampleDown:
        objOffset.setFirstSampleDown(offDn)

    if not objOffset.lastSampleDown:
        objOffset.setLastSampleDown(lastDn)

    if not objOffset.numberLocationAcross:
        objOffset.setNumberLocationAcross(nAcross)

    if not objOffset.numberLocationDown:
        objOffset.setNumberLocationDown(nDown)

    objOffset.setFirstPRF(1.0)
    objOffset.setSecondPRF(1.0)
    objOffset.setImageDataType1('complex')
    objOffset.setImageDataType2('complex')

    objOffset.ampcor(sar, sim)

    sar.finalizeImage()
    sim.finalizeImage()

    result = objOffset.getOffsetField()
    return result
Ejemplo n.º 3
0
                    ampcor.setLastSampleAcross(mSLC.width)
                    ampcor.setNumberLocationAcross(
                        numberOfOffsetsRangeUsed[i][j])
                    ampcor.setFirstSampleDown(firstLine)
                    ampcor.setLastSampleDown(mSLC.length)
                    ampcor.setNumberLocationDown(
                        numberOfOffsetsAzimuthUsed[i][j])

                    #MATCH PARAMETERS
                    #full-aperture mode
                    if referenceTrack.operationMode in scansarModes:
                        ampcor.setWindowSizeWidth(64)
                        ampcor.setWindowSizeHeight(512)
                        #note this is the half width/length of search area, number of resulting correlation samples: 32*2+1
                        ampcor.setSearchWindowSizeWidth(32)
                        ampcor.setSearchWindowSizeHeight(32)
                        #triggering full-aperture mode matching
                        ampcor.setWinsizeFilt(8)
                        ampcor.setOversamplingFactorFilt(64)
                    #regular mode
                    else:
                        ampcor.setWindowSizeWidth(64)
                        ampcor.setWindowSizeHeight(64)
                        ampcor.setSearchWindowSizeWidth(32)
                        ampcor.setSearchWindowSizeHeight(32)

                    #REST OF THE STUFF
                    ampcor.setAcrossLooks(1)
                    ampcor.setDownLooks(1)
                    ampcor.setOversamplingFactor(64)
                    ampcor.setZoomWindowSize(16)
Ejemplo n.º 4
0
def runSlcOffset(self):
    '''estimate SLC offsets
    '''
    if hasattr(self, 'doInSAR'):
        if not self.doInSAR:
            print('\nInSAR processing not requested, skip this and the remaining InSAR steps...')
            return

    catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name)
    self.updateParamemetersFromUser()

    referenceTrack = self._insar.loadTrack(reference=True)
    secondaryTrack = self._insar.loadTrack(reference=False)

    demFile = os.path.abspath(self._insar.dem)
    wbdFile = os.path.abspath(self._insar.wbd)

    for i, frameNumber in enumerate(self._insar.referenceFrames):
        frameDir = 'f{}_{}'.format(i+1, frameNumber)
        os.chdir(frameDir)
        for j, swathNumber in enumerate(range(self._insar.startingSwath, self._insar.endingSwath + 1)):
            swathDir = 's{}'.format(swathNumber)
            os.chdir(swathDir)

            print('estimating offset frame {}, swath {}'.format(frameNumber, swathNumber))

            referenceSwath = referenceTrack.frames[i].swaths[j]
            secondarySwath = secondaryTrack.frames[i].swaths[j]

            ##########################################
            #1. set number of matching points
            ##########################################
            #set initinial numbers
            if (self._insar.modeCombination == 21) or (self._insar.modeCombination == 22):
                numberOfOffsetsRange = 10
                numberOfOffsetsAzimuth = 40
            else:
                numberOfOffsetsRange = 20
                numberOfOffsetsAzimuth = 20

            #change the initial numbers using water body
            if self.useWbdForNumberOffsets and (self._insar.wbd != None):
                numberRangeLooks=100
                numberAzimuthLooks=100
                #compute land ratio using topo module
                topo(referenceSwath, referenceTrack, demFile, 'lat.rdr', 'lon.rdr', 'hgt.rdr', losFile='los.rdr', 
                    incFile=None, mskFile=None, 
                    numberRangeLooks=numberRangeLooks, numberAzimuthLooks=numberAzimuthLooks, multilookTimeOffset=False)
                waterBodyRadar('lat.rdr', 'lon.rdr', wbdFile, 'wbd.rdr')

                wbdImg = isceobj.createImage()
                wbdImg.load('wbd.rdr.xml')
                width = wbdImg.width
                length = wbdImg.length

                wbd = np.fromfile('wbd.rdr', dtype=np.byte).reshape(length, width)
                landRatio = np.sum(wbd==0) / (length*width)

                if (landRatio <= 0.00125):
                    print('\n\nWARNING: land too small for estimating slc offsets at frame {}, swath {}'.format(frameNumber, swathNumber))
                    print('proceed to use geometric offsets for forming interferogram')
                    print('but please consider not using this swath\n\n')
                    catalog.addItem('warning message', 'land too small for estimating slc offsets at frame {}, swath {}, use geometric offsets'.format(frameNumber, swathNumber), 'runSlcOffset')
                    
                    #compute geomtricla offsets
                    geo2rdr(secondarySwath, secondaryTrack, 'lat.rdr', 'lon.rdr', 'hgt.rdr', 'rg.rdr', 'az.rdr', numberRangeLooks=numberRangeLooks, numberAzimuthLooks=numberAzimuthLooks, multilookTimeOffset=False)
                    reformatGeometricalOffset('rg.rdr', 'az.rdr', 'cull.off', rangeStep=numberRangeLooks, azimuthStep=numberAzimuthLooks, maximumNumberOfOffsets=2000)

                    os.remove('lat.rdr')
                    os.remove('lat.rdr.vrt')
                    os.remove('lat.rdr.xml')
                    os.remove('lon.rdr')
                    os.remove('lon.rdr.vrt')
                    os.remove('lon.rdr.xml')
                    os.remove('hgt.rdr')
                    os.remove('hgt.rdr.vrt')
                    os.remove('hgt.rdr.xml')
                    os.remove('los.rdr')
                    os.remove('los.rdr.vrt')
                    os.remove('los.rdr.xml')
                    os.remove('wbd.rdr')
                    os.remove('wbd.rdr.vrt')
                    os.remove('wbd.rdr.xml')

                    os.remove('rg.rdr')
                    os.remove('rg.rdr.vrt')
                    os.remove('rg.rdr.xml')
                    os.remove('az.rdr')
                    os.remove('az.rdr.vrt')
                    os.remove('az.rdr.xml')

                    os.chdir('../')
                    continue


                os.remove('lat.rdr')
                os.remove('lat.rdr.vrt')
                os.remove('lat.rdr.xml')
                os.remove('lon.rdr')
                os.remove('lon.rdr.vrt')
                os.remove('lon.rdr.xml')
                os.remove('hgt.rdr')
                os.remove('hgt.rdr.vrt')
                os.remove('hgt.rdr.xml')
                os.remove('los.rdr')
                os.remove('los.rdr.vrt')
                os.remove('los.rdr.xml')
                os.remove('wbd.rdr')
                os.remove('wbd.rdr.vrt')
                os.remove('wbd.rdr.xml')

                #put the results on a grid with a specified interval
                interval = 0.2
                axisRatio = int(np.sqrt(landRatio)/interval)*interval + interval
                if axisRatio > 1:
                    axisRatio = 1

                numberOfOffsetsRange = int(numberOfOffsetsRange/axisRatio)
                numberOfOffsetsAzimuth = int(numberOfOffsetsAzimuth/axisRatio)
            else:
                catalog.addItem('warning message', 'no water mask used to determine number of matching points. frame {} swath {}'.format(frameNumber, swathNumber), 'runSlcOffset')

            #user's settings
            if self.numberRangeOffsets != None:
                numberOfOffsetsRange = self.numberRangeOffsets[i][j]
            if self.numberAzimuthOffsets != None:
                numberOfOffsetsAzimuth = self.numberAzimuthOffsets[i][j]

            catalog.addItem('number of offsets range frame {} swath {}'.format(frameNumber, swathNumber), numberOfOffsetsRange, 'runSlcOffset')
            catalog.addItem('number of offsets azimuth frame {} swath {}'.format(frameNumber, swathNumber), numberOfOffsetsAzimuth, 'runSlcOffset')

            ##########################################
            #2. match using ampcor
            ##########################################
            ampcor = Ampcor(name='insarapp_slcs_ampcor')
            ampcor.configure()

            mSLC = isceobj.createSlcImage()
            mSLC.load(self._insar.referenceSlc+'.xml')
            mSLC.setAccessMode('read')
            mSLC.createImage()

            sSLC = isceobj.createSlcImage()
            sSLC.load(self._insar.secondarySlc+'.xml')
            sSLC.setAccessMode('read')
            sSLC.createImage()

            ampcor.setImageDataType1('complex')
            ampcor.setImageDataType2('complex')

            ampcor.setReferenceSlcImage(mSLC)
            ampcor.setSecondarySlcImage(sSLC)

            #MATCH REGION
            #compute an offset at image center to use
            rgoff, azoff = computeOffsetFromOrbit(referenceSwath, referenceTrack, secondarySwath, secondaryTrack, 
                referenceSwath.numberOfSamples * 0.5, 
                referenceSwath.numberOfLines * 0.5)
            #it seems that we cannot use 0, haven't look into the problem
            if rgoff == 0:
                rgoff = 1
            if azoff == 0:
                azoff = 1
            firstSample = 1
            if rgoff < 0:
                firstSample = int(35 - rgoff)
            firstLine = 1
            if azoff < 0:
                firstLine = int(35 - azoff)
            ampcor.setAcrossGrossOffset(rgoff)
            ampcor.setDownGrossOffset(azoff)
            ampcor.setFirstSampleAcross(firstSample)
            ampcor.setLastSampleAcross(mSLC.width)
            ampcor.setNumberLocationAcross(numberOfOffsetsRange)
            ampcor.setFirstSampleDown(firstLine)
            ampcor.setLastSampleDown(mSLC.length)
            ampcor.setNumberLocationDown(numberOfOffsetsAzimuth)

            #MATCH PARAMETERS
            #full-aperture mode
            if (self._insar.modeCombination == 21) or \
               (self._insar.modeCombination == 22) or \
               (self._insar.modeCombination == 31) or \
               (self._insar.modeCombination == 32):
                ampcor.setWindowSizeWidth(64)
                ampcor.setWindowSizeHeight(512)
                #note this is the half width/length of search area, number of resulting correlation samples: 32*2+1
                ampcor.setSearchWindowSizeWidth(32)
                ampcor.setSearchWindowSizeHeight(32)
                #triggering full-aperture mode matching
                ampcor.setWinsizeFilt(8)
                ampcor.setOversamplingFactorFilt(64)
            #regular mode
            else:
                ampcor.setWindowSizeWidth(64)
                ampcor.setWindowSizeHeight(64)
                ampcor.setSearchWindowSizeWidth(32)
                ampcor.setSearchWindowSizeHeight(32)

            #REST OF THE STUFF
            ampcor.setAcrossLooks(1)
            ampcor.setDownLooks(1)
            ampcor.setOversamplingFactor(64)
            ampcor.setZoomWindowSize(16)
            #1. The following not set
            #Matching Scale for Sample/Line Directions                       (-)    = 1. 1.
            #should add the following in Ampcor.py?
            #if not set, in this case, Ampcor.py'value is also 1. 1.
            #ampcor.setScaleFactorX(1.)
            #ampcor.setScaleFactorY(1.)

            #MATCH THRESHOLDS AND DEBUG DATA
            #2. The following not set
            #in roi_pac the value is set to 0 1
            #in isce the value is set to 0.001 1000.0
            #SNR and Covariance Thresholds                                   (-)    =  {s1} {s2}
            #should add the following in Ampcor?
            #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC
            #ampcor.setThresholdSNR(0)
            #ampcor.setThresholdCov(1)
            ampcor.setDebugFlag(False)
            ampcor.setDisplayFlag(False)

            #in summary, only two things not set which are indicated by 'The following not set' above.

            #run ampcor
            ampcor.ampcor()
            offsets = ampcor.getOffsetField()
            ampcorOffsetFile = 'ampcor.off'
            writeOffset(offsets, ampcorOffsetFile)

            #finalize image, and re-create it
            #otherwise the file pointer is still at the end of the image
            mSLC.finalizeImage()
            sSLC.finalizeImage()

            ##########################################
            #3. cull offsets
            ##########################################
            refinedOffsets = cullOffsets(offsets)
            if refinedOffsets == None:
                print('******************************************************************')
                print('WARNING: There are not enough offsets left, so we are forced to')
                print('         use offset without culling. frame {}, swath {}'.format(frameNumber, swathNumber))
                print('******************************************************************')
                catalog.addItem('warning message', 'not enough offsets left, use offset without culling. frame {} swath {}'.format(frameNumber, swathNumber), 'runSlcOffset')
                refinedOffsets = offsets

            cullOffsetFile = 'cull.off'
            writeOffset(refinedOffsets, cullOffsetFile)

            os.chdir('../')
        os.chdir('../')

    catalog.printToLog(logger, "runSlcOffset")
    self._insar.procDoc.addAllFromCatalog(catalog)
Ejemplo n.º 5
0
        ampcor.setFirstSampleDown(firstLine)
        ampcor.setLastSampleDown(masterLength)
        ampcor.setNumberLocationDown(numAzimuth)

        #MATCH PARAMETERS
        ########################################
        fftWidth = inps.rgfftw
        fftLength = inps.azfftw
        searchMaxWidth = inps.rgsmax
        searchMaxLength = inps.azsmax

        ########################################
        ampcor.setWindowSizeWidth(fftWidth)
        ampcor.setWindowSizeHeight(fftLength)
        ampcor.setSearchWindowSizeWidth(searchMaxWidth)
        ampcor.setSearchWindowSizeHeight(searchMaxLength)
        ampcor.setAcrossLooks(1)
        ampcor.setDownLooks(1)
        ampcor.setOversamplingFactor(64)
        ampcor.setZoomWindowSize(16)
        ampcor.setAcrossGrossOffset(meanOffsetSamples)
        ampcor.setDownGrossOffset(meanOffsetLines)
        #1. The following not set
        #Matching Scale for Sample/Line Directions                       (-)    = 1. 1.
        #should add the following in Ampcor.py?
        #if not set, in this case, Ampcor.py'value is also 1. 1.
        #ampcor.setScaleFactorX(1.)
        #ampcor.setScaleFactorY(1.)


        #MATCH THRESHOLDS AND DEBUG DATA
Ejemplo n.º 6
0
def runCoregCc(self):
    '''coregister bursts by cross correlation
    '''
    catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name)
    self.updateParamemetersFromUser()

    masterTrack = self._insar.loadTrack(master=True)
    slaveTrack = self._insar.loadTrack(master=False)

    #demFile = os.path.abspath(self._insar.dem)
    #wbdFile = os.path.abspath(self._insar.wbd)
    ###############################################################################
    self._insar.rangeResidualOffsetCc = [
        [] for i in range(len(masterTrack.frames))
    ]
    self._insar.azimuthResidualOffsetCc = [
        [] for i in range(len(masterTrack.frames))
    ]
    for i, frameNumber in enumerate(self._insar.masterFrames):
        frameDir = 'f{}_{}'.format(i + 1, frameNumber)
        os.chdir(frameDir)
        for j, swathNumber in enumerate(
                range(self._insar.startingSwath, self._insar.endingSwath + 1)):
            swathDir = 's{}'.format(swathNumber)
            os.chdir(swathDir)

            print('processing frame {}, swath {}'.format(
                frameNumber, swathNumber))

            masterSwath = masterTrack.frames[i].swaths[j]
            slaveSwath = slaveTrack.frames[i].swaths[j]

            ##################################################
            # estimate cross-correlation offsets
            ##################################################
            #compute number of offsets to use
            wbdImg = isceobj.createImage()
            wbdImg.load(self._insar.wbdOut + '.xml')
            width = wbdImg.width
            length = wbdImg.length

            #initial number of offsets to use
            numberOfOffsets = 800

            #compute land ratio to further determine the number of offsets to use
            if self.useWbdForNumberOffsets:
                wbd = np.memmap(self._insar.wbdOut,
                                dtype='byte',
                                mode='r',
                                shape=(length, width))
                landRatio = np.sum(wbd == 0) / length / width
                del wbd
                if (landRatio <= 0.00125):
                    print(
                        '\n\nWARNING: land area too small for estimating offsets between master and slave magnitudes at frame {}, swath {}'
                        .format(frameNumber, swathNumber))
                    print('set offsets to zero\n\n')
                    self._insar.rangeResidualOffsetCc[i].append(0.0)
                    self._insar.azimuthResidualOffsetCc[i].append(0.0)
                    catalog.addItem(
                        'warning message',
                        'land area too small for estimating offsets between master and slave magnitudes at frame {}, swath {}'
                        .format(frameNumber, swathNumber), 'runCoregCc')
                    continue
                #total number of offsets to use
                numberOfOffsets /= landRatio

            #allocate number of offsets in range/azimuth according to image width/length
            #number of offsets to use in range/azimuth
            numberOfOffsetsRange = int(
                np.sqrt(numberOfOffsets * width / length))
            numberOfOffsetsAzimuth = int(
                length / width * np.sqrt(numberOfOffsets * width / length))

            #this should be better?
            numberOfOffsetsRange = int(np.sqrt(numberOfOffsets))
            numberOfOffsetsAzimuth = int(np.sqrt(numberOfOffsets))

            if numberOfOffsetsRange > int(width / 2):
                numberOfOffsetsRange = int(width / 2)
            if numberOfOffsetsAzimuth > int(length / 2):
                numberOfOffsetsAzimuth = int(length / 2)

            if numberOfOffsetsRange < 10:
                numberOfOffsetsRange = 10
            if numberOfOffsetsAzimuth < 10:
                numberOfOffsetsAzimuth = 10

            #user's settings
            if self.numberRangeOffsets != None:
                numberOfOffsetsRange = self.numberRangeOffsets[i][j]
            if self.numberAzimuthOffsets != None:
                numberOfOffsetsAzimuth = self.numberAzimuthOffsets[i][j]

            catalog.addItem(
                'number of range offsets at frame {}, swath {}'.format(
                    frameNumber, swathNumber),
                '{}'.format(numberOfOffsetsRange), 'runCoregCc')
            catalog.addItem(
                'number of azimuth offsets at frame {}, swath {}'.format(
                    frameNumber, swathNumber),
                '{}'.format(numberOfOffsetsAzimuth), 'runCoregCc')

            #need to cp to current directory to make it (gdal) work
            if not os.path.isfile(self._insar.masterMagnitude):
                os.symlink(
                    os.path.join(self._insar.masterBurstPrefix,
                                 self._insar.masterMagnitude),
                    self._insar.masterMagnitude)
            #shutil.copy2() can overwrite
            shutil.copy2(
                os.path.join(self._insar.masterBurstPrefix,
                             self._insar.masterMagnitude + '.vrt'),
                self._insar.masterMagnitude + '.vrt')
            shutil.copy2(
                os.path.join(self._insar.masterBurstPrefix,
                             self._insar.masterMagnitude + '.xml'),
                self._insar.masterMagnitude + '.xml')

            if not os.path.isfile(self._insar.slaveMagnitude):
                os.symlink(
                    os.path.join(
                        self._insar.slaveBurstPrefix + '_1_coreg_geom',
                        self._insar.slaveMagnitude),
                    self._insar.slaveMagnitude)
            #shutil.copy2() can overwrite
            shutil.copy2(
                os.path.join(self._insar.slaveBurstPrefix + '_1_coreg_geom',
                             self._insar.slaveMagnitude + '.vrt'),
                self._insar.slaveMagnitude + '.vrt')
            shutil.copy2(
                os.path.join(self._insar.slaveBurstPrefix + '_1_coreg_geom',
                             self._insar.slaveMagnitude + '.xml'),
                self._insar.slaveMagnitude + '.xml')

            #matching
            ampcor = Ampcor(name='insarapp_slcs_ampcor')
            ampcor.configure()

            mMag = isceobj.createImage()
            mMag.load(self._insar.masterMagnitude + '.xml')
            mMag.setAccessMode('read')
            mMag.createImage()

            sMag = isceobj.createImage()
            sMag.load(self._insar.slaveMagnitude + '.xml')
            sMag.setAccessMode('read')
            sMag.createImage()

            ampcor.setImageDataType1('real')
            ampcor.setImageDataType2('real')

            ampcor.setMasterSlcImage(mMag)
            ampcor.setSlaveSlcImage(sMag)

            #MATCH REGION
            rgoff = 0
            azoff = 0
            #it seems that we cannot use 0, haven't look into the problem
            if rgoff == 0:
                rgoff = 1
            if azoff == 0:
                azoff = 1
            firstSample = 1
            if rgoff < 0:
                firstSample = int(35 - rgoff)
            firstLine = 1
            if azoff < 0:
                firstLine = int(35 - azoff)
            ampcor.setAcrossGrossOffset(rgoff)
            ampcor.setDownGrossOffset(azoff)
            ampcor.setFirstSampleAcross(firstSample)
            ampcor.setLastSampleAcross(mMag.width)
            ampcor.setNumberLocationAcross(numberOfOffsetsRange)
            ampcor.setFirstSampleDown(firstLine)
            ampcor.setLastSampleDown(mMag.length)
            ampcor.setNumberLocationDown(numberOfOffsetsAzimuth)

            #MATCH PARAMETERS
            ampcor.setWindowSizeWidth(64)
            ampcor.setWindowSizeHeight(64)
            #note this is the half width/length of search area, so number of resulting correlation samples: 8*2+1
            ampcor.setSearchWindowSizeWidth(8)
            ampcor.setSearchWindowSizeHeight(8)

            #REST OF THE STUFF
            ampcor.setAcrossLooks(1)
            ampcor.setDownLooks(1)
            ampcor.setOversamplingFactor(64)
            ampcor.setZoomWindowSize(16)
            #1. The following not set
            #Matching Scale for Sample/Line Directions                       (-)    = 1. 1.
            #should add the following in Ampcor.py?
            #if not set, in this case, Ampcor.py'value is also 1. 1.
            #ampcor.setScaleFactorX(1.)
            #ampcor.setScaleFactorY(1.)

            #MATCH THRESHOLDS AND DEBUG DATA
            #2. The following not set
            #in roi_pac the value is set to 0 1
            #in isce the value is set to 0.001 1000.0
            #SNR and Covariance Thresholds                                   (-)    =  {s1} {s2}
            #should add the following in Ampcor?
            #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC
            #ampcor.setThresholdSNR(0)
            #ampcor.setThresholdCov(1)
            ampcor.setDebugFlag(False)
            ampcor.setDisplayFlag(False)

            #in summary, only two things not set which are indicated by 'The following not set' above.

            #run ampcor
            ampcor.ampcor()
            offsets = ampcor.getOffsetField()
            refinedOffsets = cullOffsetsRoipac(offsets, numThreshold=50)

            #finalize image, and re-create it
            #otherwise the file pointer is still at the end of the image
            mMag.finalizeImage()
            sMag.finalizeImage()

            #clear up
            os.remove(self._insar.masterMagnitude)
            os.remove(self._insar.masterMagnitude + '.vrt')
            os.remove(self._insar.masterMagnitude + '.xml')
            os.remove(self._insar.slaveMagnitude)
            os.remove(self._insar.slaveMagnitude + '.vrt')
            os.remove(self._insar.slaveMagnitude + '.xml')

            #compute average offsets to use in resampling
            if refinedOffsets == None:
                rangeOffset = 0
                azimuthOffset = 0
                self._insar.rangeResidualOffsetCc[i].append(rangeOffset)
                self._insar.azimuthResidualOffsetCc[i].append(azimuthOffset)
                print(
                    '\n\nWARNING: too few offsets left in matching master and slave magnitudes at frame {}, swath {}'
                    .format(frameNumber, swathNumber))
                print('set offsets to zero\n\n')
                catalog.addItem(
                    'warning message',
                    'too few offsets left in matching master and slave magnitudes at frame {}, swath {}'
                    .format(frameNumber, swathNumber), 'runCoregCc')
            else:
                rangeOffset, azimuthOffset = meanOffset(refinedOffsets)
                #for range offset, need to compute from a polynomial
                #see components/isceobj/Location/Offset.py and components/isceobj/Util/Library/python/Poly2D.py for definations
                (azimuthPoly,
                 rangePoly) = refinedOffsets.getFitPolynomials(rangeOrder=2,
                                                               azimuthOrder=2)
                #make a deep copy, otherwise it also changes original coefficient list of rangePoly, which affects following rangePoly(*, *) computation
                polyCoeff = copy.deepcopy(rangePoly.getCoeffs())
                rgIndex = (np.arange(width) - rangePoly.getMeanRange()
                           ) / rangePoly.getNormRange()
                azIndex = (np.arange(length) - rangePoly.getMeanAzimuth()
                           ) / rangePoly.getNormAzimuth()
                rangeOffset =  polyCoeff[0][0] + polyCoeff[0][1]*rgIndex[None,:] + polyCoeff[0][2]*rgIndex[None,:]**2 + \
                              (polyCoeff[1][0] + polyCoeff[1][1]*rgIndex[None,:]) * azIndex[:, None] + \
                               polyCoeff[2][0] * azIndex[:, None]**2
                polyCoeff.append([
                    rangePoly.getMeanRange(),
                    rangePoly.getNormRange(),
                    rangePoly.getMeanAzimuth(),
                    rangePoly.getNormAzimuth()
                ])
                self._insar.rangeResidualOffsetCc[i].append(polyCoeff)
                self._insar.azimuthResidualOffsetCc[i].append(azimuthOffset)

                catalog.addItem(
                    'range residual offset at {} {} at frame {}, swath {}'.
                    format(0, 0, frameNumber, swathNumber),
                    '{}'.format(rangePoly(0, 0)), 'runCoregCc')
                catalog.addItem(
                    'range residual offset at {} {} at frame {}, swath {}'.
                    format(0, width - 1, frameNumber, swathNumber),
                    '{}'.format(rangePoly(0, width - 1)), 'runCoregCc')
                catalog.addItem(
                    'range residual offset at {} {} at frame {}, swath {}'.
                    format(length - 1, 0, frameNumber, swathNumber),
                    '{}'.format(rangePoly(length - 1, 0)), 'runCoregCc')
                catalog.addItem(
                    'range residual offset at {} {} at frame {}, swath {}'.
                    format(length - 1, width - 1, frameNumber, swathNumber),
                    '{}'.format(rangePoly(length - 1,
                                          width - 1)), 'runCoregCc')
                catalog.addItem(
                    'azimuth residual offset at frame {}, swath {}'.format(
                        frameNumber, swathNumber), '{}'.format(azimuthOffset),
                    'runCoregCc')

                DEBUG = False
                if DEBUG:
                    print('+++++++++++++++++++++++++++++')
                    print(rangeOffset[0, 0], rangePoly(0, 0))
                    print(rangeOffset[0, width - 1], rangePoly(0, width - 1))
                    print(rangeOffset[length - 1, 0], rangePoly(length - 1, 0))
                    print(rangeOffset[length - 1, width - 1],
                          rangePoly(length - 1, width - 1))
                    print(
                        rangeOffset[int((length - 1) / 2),
                                    int((width - 1) / 2)],
                        rangePoly(int((length - 1) / 2), int((width - 1) / 2)))
                    print('+++++++++++++++++++++++++++++')

            ##################################################
            # resample bursts
            ##################################################
            slaveBurstResampledDir = self._insar.slaveBurstPrefix + '_2_coreg_cc'
            #interferogramDir = self._insar.masterBurstPrefix + '-' + self._insar.slaveBurstPrefix + '_coreg_geom'
            interferogramDir = 'burst_interf_2_coreg_cc'
            interferogramPrefix = self._insar.masterBurstPrefix + '-' + self._insar.slaveBurstPrefix
            resampleBursts(masterSwath,
                           slaveSwath,
                           self._insar.masterBurstPrefix,
                           self._insar.slaveBurstPrefix,
                           slaveBurstResampledDir,
                           interferogramDir,
                           self._insar.masterBurstPrefix,
                           self._insar.slaveBurstPrefix,
                           self._insar.slaveBurstPrefix,
                           interferogramPrefix,
                           self._insar.rangeOffset,
                           self._insar.azimuthOffset,
                           rangeOffsetResidual=rangeOffset,
                           azimuthOffsetResidual=azimuthOffset)

            ##################################################
            # mosaic burst amplitudes and interferograms
            ##################################################
            os.chdir(slaveBurstResampledDir)
            mosaicBurstAmplitude(masterSwath,
                                 self._insar.slaveBurstPrefix,
                                 self._insar.slaveMagnitude,
                                 numberOfLooksThreshold=4)
            os.chdir('../')

            os.chdir(interferogramDir)
            mosaicBurstInterferogram(masterSwath,
                                     interferogramPrefix,
                                     self._insar.interferogram,
                                     numberOfLooksThreshold=4)
            os.chdir('../')

            ##################################################
            # final amplitude and interferogram
            ##################################################
            amp = np.zeros(
                (masterSwath.numberOfLines, 2 * masterSwath.numberOfSamples),
                dtype=np.float32)
            amp[0:, 1:masterSwath.numberOfSamples*2:2] = np.fromfile(os.path.join(slaveBurstResampledDir, self._insar.slaveMagnitude), \
                dtype=np.float32).reshape(masterSwath.numberOfLines, masterSwath.numberOfSamples)
            amp[0:, 0:masterSwath.numberOfSamples*2:2] = np.fromfile(os.path.join(self._insar.masterBurstPrefix, self._insar.masterMagnitude), \
                dtype=np.float32).reshape(masterSwath.numberOfLines, masterSwath.numberOfSamples)
            amp.astype(np.float32).tofile(self._insar.amplitude)
            create_xml(self._insar.amplitude, masterSwath.numberOfSamples,
                       masterSwath.numberOfLines, 'amp')

            os.rename(
                os.path.join(interferogramDir, self._insar.interferogram),
                self._insar.interferogram)
            os.rename(
                os.path.join(interferogramDir,
                             self._insar.interferogram + '.vrt'),
                self._insar.interferogram + '.vrt')
            os.rename(
                os.path.join(interferogramDir,
                             self._insar.interferogram + '.xml'),
                self._insar.interferogram + '.xml')

            os.chdir('../')
        os.chdir('../')

###############################################################################
    catalog.printToLog(logger, "runCoregCc")
    self._insar.procDoc.addAllFromCatalog(catalog)
Ejemplo n.º 7
0
def runRdrDemOffset(self):
    '''estimate between radar image and dem
    '''
    catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name)
    self.updateParamemetersFromUser()

    referenceTrack = self._insar.loadTrack(reference=True)
    demFile = os.path.abspath(self._insar.dem)

    insarDir = 'insar'
    os.makedirs(insarDir, exist_ok=True)
    os.chdir(insarDir)

    rdrDemDir = 'rdr_dem_offset'
    os.makedirs(rdrDemDir, exist_ok=True)
    os.chdir(rdrDemDir)

    ##################################################################################################
    #compute dem pixel size
    demImage = isceobj.createDemImage()
    demImage.load(demFile + '.xml')
    #DEM pixel size in meters (appoximate value)
    demDeltaLon = abs(demImage.getDeltaLongitude()) / 0.0002777777777777778 * 30.0
    demDeltaLat = abs(demImage.getDeltaLatitude())  / 0.0002777777777777778 * 30.0

    #number of looks to take in range
    if self._insar.numberRangeLooksSim == None:
        if self._insar.numberRangeLooks1 * referenceTrack.rangePixelSize > demDeltaLon:
            self._insar.numberRangeLooksSim = 1
        else:
            self._insar.numberRangeLooksSim = int(demDeltaLon / (self._insar.numberRangeLooks1 * referenceTrack.rangePixelSize) + 0.5)
    #number of looks to take in azimuth
    if self._insar.numberAzimuthLooksSim == None:
        if self._insar.numberAzimuthLooks1 * referenceTrack.azimuthPixelSize > demDeltaLat:
            self._insar.numberAzimuthLooksSim = 1
        else:
            self._insar.numberAzimuthLooksSim = int(demDeltaLat / (self._insar.numberAzimuthLooks1 * referenceTrack.azimuthPixelSize) + 0.5)

    #simulate a radar image using dem
    simulateRadar(os.path.join('../', self._insar.height), self._insar.sim, scale=3.0, offset=100.0)
    sim = isceobj.createImage()
    sim.load(self._insar.sim+'.xml')

    #take looks
    if (self._insar.numberRangeLooksSim == 1) and (self._insar.numberAzimuthLooksSim == 1):
        simLookFile = self._insar.sim
        ampLookFile = 'amp_{}rlks_{}alks.float'.format(self._insar.numberRangeLooksSim*self._insar.numberRangeLooks1, 
                                                       self._insar.numberAzimuthLooksSim*self._insar.numberAzimuthLooks1)
        cmd = "imageMath.py -e='sqrt(a_0*a_0+a_1*a_1)' --a={} -o {} -t float".format(os.path.join('../', self._insar.amplitude), ampLookFile)
        runCmd(cmd)
    else:
        simLookFile = 'sim_{}rlks_{}alks.float'.format(self._insar.numberRangeLooksSim*self._insar.numberRangeLooks1, 
                                                       self._insar.numberAzimuthLooksSim*self._insar.numberAzimuthLooks1)
        ampLookFile = 'amp_{}rlks_{}alks.float'.format(self._insar.numberRangeLooksSim*self._insar.numberRangeLooks1, 
                                                       self._insar.numberAzimuthLooksSim*self._insar.numberAzimuthLooks1)
        ampTmpFile = 'amp_tmp.float'
        look(self._insar.sim, simLookFile, sim.width, self._insar.numberRangeLooksSim, self._insar.numberAzimuthLooksSim, 2, 0, 1)
        look(os.path.join('../', self._insar.amplitude), ampTmpFile, sim.width, self._insar.numberRangeLooksSim, self._insar.numberAzimuthLooksSim, 4, 1, 1)
 
        width = int(sim.width/self._insar.numberRangeLooksSim)
        length = int(sim.length/self._insar.numberAzimuthLooksSim)
        create_xml(simLookFile, width, length, 'float')
        create_xml(ampTmpFile, width, length, 'amp')

        cmd = "imageMath.py -e='sqrt(a_0*a_0+a_1*a_1)' --a={} -o {} -t float".format(ampTmpFile, ampLookFile)
        runCmd(cmd)
        os.remove(ampTmpFile)
        os.remove(ampTmpFile+'.vrt')
        os.remove(ampTmpFile+'.xml')

    #initial number of offsets to use
    numberOfOffsets = 800
    #compute land ratio to further determine the number of offsets to use
    wbd=np.memmap(os.path.join('../', self._insar.wbdOut), dtype='byte', mode='r', shape=(sim.length, sim.width))
    landRatio = np.sum(wbd[0:sim.length:10, 0:sim.width:10]!=-1) / int(sim.length/10) / int(sim.width/10)
    del wbd
    if (landRatio <= 0.00125):
        print('\n\nWARNING: land area too small for estimating offsets between radar and dem')
        print('do not estimate offsets between radar and dem\n\n')
        self._insar.radarDemAffineTransform = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0]
        catalog.addItem('warning message', 'land area too small for estimating offsets between radar and dem', 'runRdrDemOffset')

        os.chdir('../../')

        catalog.printToLog(logger, "runRdrDemOffset")
        self._insar.procDoc.addAllFromCatalog(catalog)

        return

    #total number of offsets to use
    numberOfOffsets /= landRatio
    #allocate number of offsets in range/azimuth according to image width/length
    width = int(sim.width/self._insar.numberRangeLooksSim)
    length = int(sim.length/self._insar.numberAzimuthLooksSim)
    #number of offsets to use in range/azimuth
    numberOfOffsetsRange = int(np.sqrt(numberOfOffsets * width / length))
    numberOfOffsetsAzimuth = int(length / width * np.sqrt(numberOfOffsets * width / length))

    #this should be better?
    numberOfOffsetsRange = int(np.sqrt(numberOfOffsets))
    numberOfOffsetsAzimuth = int(np.sqrt(numberOfOffsets))


    if numberOfOffsetsRange > int(width/2):
        numberOfOffsetsRange = int(width/2)
    if numberOfOffsetsAzimuth > int(length/2):
        numberOfOffsetsAzimuth = int(length/2)

    if numberOfOffsetsRange < 10:
        numberOfOffsetsRange = 10
    if numberOfOffsetsAzimuth < 10:
        numberOfOffsetsAzimuth = 10

    catalog.addItem('number of range offsets', '{}'.format(numberOfOffsetsRange), 'runRdrDemOffset')
    catalog.addItem('number of azimuth offsets', '{}'.format(numberOfOffsetsAzimuth), 'runRdrDemOffset')

    #matching
    ampcor = Ampcor(name='insarapp_slcs_ampcor')
    ampcor.configure()

    mMag = isceobj.createImage()
    mMag.load(ampLookFile+'.xml')
    mMag.setAccessMode('read')
    mMag.createImage()

    sMag = isceobj.createImage()
    sMag.load(simLookFile+'.xml')
    sMag.setAccessMode('read')
    sMag.createImage()

    ampcor.setImageDataType1('real')
    ampcor.setImageDataType2('real')

    ampcor.setReferenceSlcImage(mMag)
    ampcor.setSecondarySlcImage(sMag)

    #MATCH REGION
    rgoff = 0
    azoff = 0
    #it seems that we cannot use 0, haven't look into the problem
    if rgoff == 0:
        rgoff = 1
    if azoff == 0:
        azoff = 1
    firstSample = 1
    if rgoff < 0:
        firstSample = int(35 - rgoff)
    firstLine = 1
    if azoff < 0:
        firstLine = int(35 - azoff)
    ampcor.setAcrossGrossOffset(rgoff)
    ampcor.setDownGrossOffset(azoff)
    ampcor.setFirstSampleAcross(firstSample)
    ampcor.setLastSampleAcross(width)
    ampcor.setNumberLocationAcross(numberOfOffsetsRange)
    ampcor.setFirstSampleDown(firstLine)
    ampcor.setLastSampleDown(length)
    ampcor.setNumberLocationDown(numberOfOffsetsAzimuth)

    #MATCH PARAMETERS
    ampcor.setWindowSizeWidth(64)
    ampcor.setWindowSizeHeight(64)
    #note this is the half width/length of search area, so number of resulting correlation samples: 8*2+1
    ampcor.setSearchWindowSizeWidth(16)
    ampcor.setSearchWindowSizeHeight(16)

    #REST OF THE STUFF
    ampcor.setAcrossLooks(1)
    ampcor.setDownLooks(1)
    ampcor.setOversamplingFactor(64)
    ampcor.setZoomWindowSize(16)
    #1. The following not set
    #Matching Scale for Sample/Line Directions                       (-)    = 1. 1.
    #should add the following in Ampcor.py?
    #if not set, in this case, Ampcor.py'value is also 1. 1.
    #ampcor.setScaleFactorX(1.)
    #ampcor.setScaleFactorY(1.)

    #MATCH THRESHOLDS AND DEBUG DATA
    #2. The following not set
    #in roi_pac the value is set to 0 1
    #in isce the value is set to 0.001 1000.0
    #SNR and Covariance Thresholds                                   (-)    =  {s1} {s2}
    #should add the following in Ampcor?
    #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC
    #ampcor.setThresholdSNR(0)
    #ampcor.setThresholdCov(1)
    ampcor.setDebugFlag(False)
    ampcor.setDisplayFlag(False)

    #in summary, only two things not set which are indicated by 'The following not set' above.

    #run ampcor
    ampcor.ampcor()
    offsets = ampcor.getOffsetField()
    ampcorOffsetFile = 'ampcor.off'
    cullOffsetFile = 'cull.off'
    affineTransformFile = 'affine_transform.txt'
    writeOffset(offsets, ampcorOffsetFile)

    #finalize image, and re-create it
    #otherwise the file pointer is still at the end of the image
    mMag.finalizeImage()
    sMag.finalizeImage()

    # #cull offsets
    # import io
    # from contextlib import redirect_stdout
    # f = io.StringIO()
    # with redirect_stdout(f):
    #     fitoff(ampcorOffsetFile, cullOffsetFile, 1.5, .5, 50)
    # s = f.getvalue()
    # #print(s)
    # with open(affineTransformFile, 'w') as f:
    #     f.write(s)

    #cull offsets
    import subprocess
    proc = subprocess.Popen(["python3", "-c", "import isce; from contrib.alos2proc_f.alos2proc_f import fitoff; fitoff('ampcor.off', 'cull.off', 1.5, .5, 50)"], stdout=subprocess.PIPE)
    out = proc.communicate()[0]
    with open(affineTransformFile, 'w') as f:
        f.write(out.decode('utf-8'))

    #check number of offsets left
    with open(cullOffsetFile, 'r') as f:
        numCullOffsets = sum(1 for linex in f)
    if numCullOffsets < 50:
        print('\n\nWARNING: too few points left after culling, {} left'.format(numCullOffsets))
        print('do not estimate offsets between radar and dem\n\n')
        self._insar.radarDemAffineTransform = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0]
        catalog.addItem('warning message', 'too few points left after culling, {} left'.format(numCullOffsets), 'runRdrDemOffset')

        os.chdir('../../')

        catalog.printToLog(logger, "runRdrDemOffset")
        self._insar.procDoc.addAllFromCatalog(catalog)

        return

    #read affine transform parameters
    with open(affineTransformFile) as f:
        lines = f.readlines()
    i = 0
    for linex in lines:
        if 'Affine Matrix ' in linex:
            m11 = float(lines[i + 2].split()[0])
            m12 = float(lines[i + 2].split()[1])
            m21 = float(lines[i + 3].split()[0])
            m22 = float(lines[i + 3].split()[1])
            t1  = float(lines[i + 7].split()[0])
            t2  = float(lines[i + 7].split()[1])
            break
        i += 1    

    self._insar.radarDemAffineTransform = [m11, m12, m21, m22, t1, t2]
    ##################################################################################################

    os.chdir('../../')


    catalog.printToLog(logger, "runRdrDemOffset")
    self._insar.procDoc.addAllFromCatalog(catalog)
Ejemplo n.º 8
0
def estimateSwathOffset(swath1,
                        swath2,
                        image1,
                        image2,
                        rangeScale1=1,
                        azimuthScale1=1,
                        rangeScale2=1,
                        azimuthScale2=1,
                        numberOfAzimuthLooks=10):
    '''
    estimate offset of two adjacent swaths using matching
    '''
    from osgeo import gdal
    import isceobj
    from contrib.alos2proc_f.alos2proc_f import rect_with_looks
    from isceobj.Alos2Proc.Alos2ProcPublic import create_xml
    from isceobj.Alos2Proc.Alos2ProcPublic import cullOffsets
    from isceobj.Alos2Proc.Alos2ProcPublic import meanOffset
    from mroipac.ampcor.Ampcor import Ampcor

    #processing image 1
    rangeOff1 = int(
        (swath2.startingRange - swath1.startingRange) / swath1.rangePixelSize)
    if rangeOff1 < 0:
        rangeOff1 = 0
    numberOfSamples1 = swath1.numberOfSamples - rangeOff1

    numberOfSamplesRect1 = int(numberOfSamples1 / rangeScale1)
    numberOfLinesRect1 = int(swath1.numberOfLines / azimuthScale1)

    numberOfSamplesLook1 = int(numberOfSamplesRect1 / 1)
    numberOfLinesLook1 = int(numberOfLinesRect1 / numberOfAzimuthLooks)

    #get magnitude image whether complex or not
    #ReadAsArray: https://pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html
    ds = gdal.Open(image1 + '.vrt', gdal.GA_ReadOnly)
    data = ds.ReadAsArray(rangeOff1, 0, numberOfSamples1, swath1.numberOfLines)
    ds = None
    (np.absolute(data)).astype(np.float32).tofile('image1.float')

    #rectify
    if rangeScale1 == 1 and azimuthScale1 == 1:
        os.rename('image1.float', 'image1_rect.float')
    else:
        rect_with_looks('image1.float', 'image1_rect.float', numberOfSamples1,
                        swath1.numberOfLines, numberOfSamplesRect1,
                        numberOfLinesRect1, rangeScale1, 0.0, 0.0,
                        azimuthScale1, 0.0, 0.0, 1, 1, 1, 1, 'REAL',
                        'Bilinear')
        os.remove('image1.float')

    #take looks
    if numberOfAzimuthLooks == 1:
        os.rename('image1_rect.float', 'image1_look.float')
    else:
        data1 = np.fromfile('image1_rect.float',
                            dtype=np.float32).reshape(numberOfLinesRect1,
                                                      numberOfSamplesRect1)
        data1 = np.sqrt(multilook(data1**2, numberOfAzimuthLooks, 1))
        data1.astype(np.float32).tofile('image1_look.float')
        os.remove('image1_rect.float')
    create_xml('image1_look.float', numberOfSamplesLook1, numberOfLinesLook1,
               'float')

    #processing image 2
    rangeOff2 = 0
    numberOfSamples2 = int(
        (swath1.startingRange + swath1.rangePixelSize *
         (swath1.numberOfSamples - 1) - swath2.startingRange) /
        swath2.rangePixelSize) + 1
    if numberOfSamples2 > swath2.numberOfSamples:
        numberOfSamples2 = swath2.numberOfSamples

    numberOfSamplesRect2 = int(numberOfSamples2 / rangeScale2)
    numberOfLinesRect2 = int(swath2.numberOfLines / azimuthScale2)

    numberOfSamplesLook2 = int(numberOfSamplesRect2 / 1)
    numberOfLinesLook2 = int(numberOfLinesRect2 / numberOfAzimuthLooks)

    #get magnitude image whether complex or not
    ds = gdal.Open(image2 + '.vrt', gdal.GA_ReadOnly)
    data = ds.ReadAsArray(rangeOff2, 0, numberOfSamples2, swath2.numberOfLines)
    ds = None
    (np.absolute(data)).astype(np.float32).tofile('image2.float')

    #rectify
    if rangeScale2 == 1 and azimuthScale2 == 1:
        os.rename('image2.float', 'image2_rect.float')
    else:
        rect_with_looks('image2.float', 'image2_rect.float', numberOfSamples2,
                        swath2.numberOfLines, numberOfSamplesRect2,
                        numberOfLinesRect2, rangeScale2, 0.0, 0.0,
                        azimuthScale2, 0.0, 0.0, 1, 1, 1, 1, 'REAL',
                        'Bilinear')
        os.remove('image2.float')

    #take looks
    if numberOfAzimuthLooks == 1:
        os.rename('image2_rect.float', 'image2_look.float')
    else:
        data2 = np.fromfile('image2_rect.float',
                            dtype=np.float32).reshape(numberOfLinesRect2,
                                                      numberOfSamplesRect2)
        data2 = np.sqrt(multilook(data2**2, numberOfAzimuthLooks, 1))
        data2.astype(np.float32).tofile('image2_look.float')
        os.remove('image2_rect.float')
    create_xml('image2_look.float', numberOfSamplesLook2, numberOfLinesLook2,
               'float')

    #matching
    ampcor = Ampcor(name='insarapp_slcs_ampcor')
    ampcor.configure()

    mMag = isceobj.createImage()
    mMag.load('image1_look.float.xml')
    mMag.setAccessMode('read')
    mMag.createImage()

    sMag = isceobj.createImage()
    sMag.load('image2_look.float.xml')
    sMag.setAccessMode('read')
    sMag.createImage()

    ampcor.setImageDataType1('real')
    ampcor.setImageDataType2('real')

    ampcor.setReferenceSlcImage(mMag)
    ampcor.setSecondarySlcImage(sMag)

    #MATCH REGION
    rgoff = 0
    azoff = int(
        (swath1.sensingStart - swath2.sensingStart).total_seconds() /
        swath1.azimuthLineInterval / azimuthScale1 / numberOfAzimuthLooks)
    #it seems that we cannot use 0, haven't look into the problem
    if rgoff == 0:
        rgoff = 1
    if azoff == 0:
        azoff = 1
    firstSample = 1
    if rgoff < 0:
        firstSample = int(35 - rgoff)
    firstLine = 1
    if azoff < 0:
        firstLine = int(35 - azoff)
    ampcor.setAcrossGrossOffset(rgoff)
    ampcor.setDownGrossOffset(azoff)
    ampcor.setFirstSampleAcross(firstSample)
    ampcor.setLastSampleAcross(numberOfSamplesLook1)
    ampcor.setNumberLocationAcross(20)
    ampcor.setFirstSampleDown(firstLine)
    ampcor.setLastSampleDown(numberOfLinesLook1)
    ampcor.setNumberLocationDown(100)

    #MATCH PARAMETERS
    ampcor.setWindowSizeWidth(32)
    ampcor.setWindowSizeHeight(32)
    #note this is the half width/length of search area, so number of resulting correlation samples: 8*2+1
    ampcor.setSearchWindowSizeWidth(8)
    ampcor.setSearchWindowSizeHeight(8)

    #REST OF THE STUFF
    ampcor.setAcrossLooks(1)
    ampcor.setDownLooks(1)
    ampcor.setOversamplingFactor(64)
    ampcor.setZoomWindowSize(16)
    #1. The following not set
    #Matching Scale for Sample/Line Directions                       (-)    = 1. 1.
    #should add the following in Ampcor.py?
    #if not set, in this case, Ampcor.py'value is also 1. 1.
    #ampcor.setScaleFactorX(1.)
    #ampcor.setScaleFactorY(1.)

    #MATCH THRESHOLDS AND DEBUG DATA
    #2. The following not set
    #in roi_pac the value is set to 0 1
    #in isce the value is set to 0.001 1000.0
    #SNR and Covariance Thresholds                                   (-)    =  {s1} {s2}
    #should add the following in Ampcor?
    #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC
    #ampcor.setThresholdSNR(0)
    #ampcor.setThresholdCov(1)
    ampcor.setDebugFlag(False)
    ampcor.setDisplayFlag(False)

    #in summary, only two things not set which are indicated by 'The following not set' above.

    #run ampcor
    ampcor.ampcor()
    offsets = ampcor.getOffsetField()
    refinedOffsets = cullOffsets(offsets)

    #finalize image, and re-create it
    #otherwise the file pointer is still at the end of the image
    mMag.finalizeImage()
    sMag.finalizeImage()

    os.remove('image1_look.float')
    os.remove('image1_look.float.vrt')
    os.remove('image1_look.float.xml')
    os.remove('image2_look.float')
    os.remove('image2_look.float.vrt')
    os.remove('image2_look.float.xml')

    if refinedOffsets != None:
        rangeOffset, azimuthOffset = meanOffset(refinedOffsets)
        rangeOffset -= rangeOff1 / rangeScale1
        azimuthOffset *= numberOfAzimuthLooks
        return (rangeOffset, azimuthOffset)
    else:
        return None
Ejemplo n.º 9
0
def runSlcMatch(self):
    '''match a pair of SLCs
    '''
    if not self.doDenseOffset:
        return
    if not ((self._insar.modeCombination == 0) or (self._insar.modeCombination == 1)):
        return

    catalog = isceobj.Catalog.createCatalog(self._insar.procDoc.name)
    self.updateParamemetersFromUser()

    demFile = os.path.abspath(self._insar.dem)
    wbdFile = os.path.abspath(self._insar.wbd)

    denseOffsetDir = 'dense_offset'
    os.makedirs(denseOffsetDir, exist_ok=True)
    os.chdir(denseOffsetDir)

    masterTrack = self._insar.loadProduct(self._insar.masterTrackParameter)
    slaveTrack = self._insar.loadProduct(self._insar.slaveTrackParameter)

#########################################################################################


    ##################################################
    # compute geometric offsets
    ##################################################
    if self.useGPU and self._insar.hasGPU():
        topoGPU(masterTrack, 1, 1, demFile, 
                       'lat.rdr', 'lon.rdr', 'hgt.rdr', 'los.rdr')
        geo2RdrGPU(slaveTrack, 1, 1, 
            'lat.rdr', 'lon.rdr', 'hgt.rdr', 'rg.off', 'az.off')
    else:
        topoCPU(masterTrack, 1, 1, demFile, 
                       'lat.rdr', 'lon.rdr', 'hgt.rdr', 'los.rdr')
        geo2RdrCPU(slaveTrack, 1, 1, 
            'lat.rdr', 'lon.rdr', 'hgt.rdr', 'rg.off', 'az.off')


    ##################################################
    # resample SLC
    ##################################################
    #SlaveSlcResampled = os.path.splitext(self._insar.slaveSlc)[0]+'_resamp'+os.path.splitext(self._insar.slaveSlc)[1]
    SlaveSlcResampled = self._insar.slaveSlcCoregistered
    rangeOffsets2Frac = 0.0
    azimuthOffsets2Frac = 0.0
    resamp(self._insar.slaveSlc,
           SlaveSlcResampled,
           'rg.off',
           'az.off',
           masterTrack.numberOfSamples, masterTrack.numberOfLines,
           slaveTrack.prf,
           slaveTrack.dopplerVsPixel,
           [rangeOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
           [azimuthOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
    create_xml(SlaveSlcResampled, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'slc')


    if self.estimateResidualOffset:

        numberOfOffsets = 800
        rangeStep = 50

        length = masterTrack.numberOfLines
        width = masterTrack.numberOfSamples
        waterBodyRadar('lat.rdr', 'lon.rdr', wbdFile, 'wbd.rdr')
        wbd=np.memmap('wbd.rdr', dtype=np.int8, mode='r', shape=(length, width))
        azimuthStep = int(length/width*rangeStep+0.5)
        landRatio = np.sum(wbd[0:length:azimuthStep,0:width:rangeStep]!=-1)/(int(length/azimuthStep)*int(width/rangeStep))
        del wbd

        if (landRatio <= 0.00125):
            print('\n\nWARNING: land area too small for estimating residual slc offsets')
            print('do not estimate residual offsets\n\n')
            catalog.addItem('warning message', 'land area too small for estimating residual slc offsets', 'runSlcMatch')
        else:
            numberOfOffsets /= landRatio
            #we use equal number of offsets in range and azimuth here
            numberOfOffsetsRange = int(np.sqrt(numberOfOffsets)+0.5)
            numberOfOffsetsAzimuth = int(np.sqrt(numberOfOffsets)+0.5)
            if numberOfOffsetsRange > int(width/2):
                numberOfOffsetsRange = int(width/2)
            if numberOfOffsetsAzimuth > int(length/2):
                numberOfOffsetsAzimuth = int(length/2)
            if numberOfOffsetsRange < 10:
                numberOfOffsetsRange = 10
            if numberOfOffsetsAzimuth < 10:
                numberOfOffsetsAzimuth = 10


            ##########################################
            #2. match using ampcor
            ##########################################
            ampcor = Ampcor(name='insarapp_slcs_ampcor')
            ampcor.configure()

            mSLC = isceobj.createSlcImage()
            mSLC.load(self._insar.masterSlc+'.xml')
            mSLC.setAccessMode('read')
            mSLC.createImage()

            sSLC = isceobj.createSlcImage()
            sSLC.load(SlaveSlcResampled+'.xml')
            sSLC.setAccessMode('read')
            sSLC.createImage()

            ampcor.setImageDataType1('complex')
            ampcor.setImageDataType2('complex')

            ampcor.setMasterSlcImage(mSLC)
            ampcor.setSlaveSlcImage(sSLC)

            #MATCH REGION
            #compute an offset at image center to use
            rgoff = 0.0
            azoff = 0.0
            #it seems that we cannot use 0, haven't look into the problem
            if rgoff == 0:
                rgoff = 1
            if azoff == 0:
                azoff = 1
            firstSample = 1
            if rgoff < 0:
                firstSample = int(35 - rgoff)
            firstLine = 1
            if azoff < 0:
                firstLine = int(35 - azoff)
            ampcor.setAcrossGrossOffset(rgoff)
            ampcor.setDownGrossOffset(azoff)
            ampcor.setFirstSampleAcross(firstSample)
            ampcor.setLastSampleAcross(mSLC.width)
            ampcor.setNumberLocationAcross(numberOfOffsetsRange)
            ampcor.setFirstSampleDown(firstLine)
            ampcor.setLastSampleDown(mSLC.length)
            ampcor.setNumberLocationDown(numberOfOffsetsAzimuth)

            #MATCH PARAMETERS
            #full-aperture mode
            if (self._insar.modeCombination == 21) or \
               (self._insar.modeCombination == 22) or \
               (self._insar.modeCombination == 31) or \
               (self._insar.modeCombination == 32):
                ampcor.setWindowSizeWidth(64)
                ampcor.setWindowSizeHeight(512)
                #note this is the half width/length of search area, number of resulting correlation samples: 32*2+1
                ampcor.setSearchWindowSizeWidth(32)
                ampcor.setSearchWindowSizeHeight(32)
                #triggering full-aperture mode matching
                ampcor.setWinsizeFilt(8)
                ampcor.setOversamplingFactorFilt(64)
            #regular mode
            else:
                ampcor.setWindowSizeWidth(64)
                ampcor.setWindowSizeHeight(64)
                ampcor.setSearchWindowSizeWidth(16)
                ampcor.setSearchWindowSizeHeight(16)

            #REST OF THE STUFF
            ampcor.setAcrossLooks(1)
            ampcor.setDownLooks(1)
            ampcor.setOversamplingFactor(64)
            ampcor.setZoomWindowSize(16)
            #1. The following not set
            #Matching Scale for Sample/Line Directions                       (-)    = 1. 1.
            #should add the following in Ampcor.py?
            #if not set, in this case, Ampcor.py'value is also 1. 1.
            #ampcor.setScaleFactorX(1.)
            #ampcor.setScaleFactorY(1.)

            #MATCH THRESHOLDS AND DEBUG DATA
            #2. The following not set
            #in roi_pac the value is set to 0 1
            #in isce the value is set to 0.001 1000.0
            #SNR and Covariance Thresholds                                   (-)    =  {s1} {s2}
            #should add the following in Ampcor?
            #THIS SHOULD BE THE ONLY THING THAT IS DIFFERENT FROM THAT OF ROI_PAC
            #ampcor.setThresholdSNR(0)
            #ampcor.setThresholdCov(1)
            ampcor.setDebugFlag(False)
            ampcor.setDisplayFlag(False)

            #in summary, only two things not set which are indicated by 'The following not set' above.

            #run ampcor
            ampcor.ampcor()
            offsets = ampcor.getOffsetField()
            mSLC.finalizeImage()
            sSLC.finalizeImage()


            #3. cull offsets
            refinedOffsets = cullOffsetsRoipac(offsets, numThreshold=50)
            if refinedOffsets == None:
                print('\n\nWARNING: too few offsets left for slc residual offset estimation')
                print('do not estimate residual offsets\n\n')
                catalog.addItem('warning message', 'too few offsets left for slc residual offset estimation', 'runSlcMatch')
            else:
                rangeOffset, azimuthOffset = meanOffset(refinedOffsets)
                os.remove(SlaveSlcResampled)
                os.remove(SlaveSlcResampled+'.vrt')
                os.remove(SlaveSlcResampled+'.xml')
                
                rangeOffsets2Frac = rangeOffset
                azimuthOffsets2Frac = azimuthOffset
                resamp(self._insar.slaveSlc,
                       SlaveSlcResampled,
                       'rg.off',
                       'az.off',
                       masterTrack.numberOfSamples, masterTrack.numberOfLines,
                       slaveTrack.prf,
                       slaveTrack.dopplerVsPixel,
                       [rangeOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                       [azimuthOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
                create_xml(SlaveSlcResampled, masterTrack.numberOfSamples, masterTrack.numberOfLines, 'slc')

                catalog.addItem('number of offsets range', numberOfOffsetsRange, 'runSlcMatch')
                catalog.addItem('number of offsets azimuth', numberOfOffsetsAzimuth, 'runSlcMatch')
                catalog.addItem('range residual offset after geometric coregistration', rangeOffset, 'runSlcMatch')
                catalog.addItem('azimuth residual offset after geometric coregistration', azimuthOffset, 'runSlcMatch')




    if self.deleteGeometryFiles:
        os.remove('lat.rdr')
        os.remove('lat.rdr.vrt')
        os.remove('lat.rdr.xml')
        os.remove('lon.rdr')
        os.remove('lon.rdr.vrt')
        os.remove('lon.rdr.xml')
        os.remove('hgt.rdr')
        os.remove('hgt.rdr.vrt')
        os.remove('hgt.rdr.xml')
        os.remove('los.rdr')
        os.remove('los.rdr.vrt')
        os.remove('los.rdr.xml')
        # if os.path.isfile('wbd.rdr'):
        #     os.remove('wbd.rdr')
        #     os.remove('wbd.rdr.vrt')
        #     os.remove('wbd.rdr.xml')

#########################################################################################

    os.chdir('../')
    catalog.printToLog(logger, "runSlcMatch")
    self._insar.procDoc.addAllFromCatalog(catalog)
Ejemplo n.º 10
0
def estimateOffsetField(burst, simfile,offset=0.0):
    '''
    Estimate offset field between burst and simamp.
    '''


    sim = isceobj.createImage()
    sim.load(simfile+'.xml')
    sim.setAccessMode('READ')
    sim.createImage()

    sar = isceobj.createSlcImage()
    sar.load(burst.getImage().filename + '.xml')
    sar.setAccessMode('READ')
    sar.createImage()

    width = sar.getWidth()
    length = sar.getLength()

    objOffset = Ampcor(name='reference_offset')
    objOffset.configure()
    objOffset.setWindowSizeWidth(128)
    objOffset.setWindowSizeHeight(128)
    objOffset.setSearchWindowSizeWidth(16)
    objOffset.setSearchWindowSizeHeight(16)
    margin = 2*objOffset.searchWindowSizeWidth + objOffset.windowSizeWidth

    nAcross = 40
    nDown = 40

    if not objOffset.firstSampleAcross:
        objOffset.setFirstSampleAcross(margin+101)

    if not objOffset.lastSampleAcross:
        objOffset.setLastSampleAcross(width-margin-101)

    if not objOffset.firstSampleDown:
        objOffset.setFirstSampleDown(margin+offset+101)

    if not objOffset.lastSampleDown:
        objOffset.setLastSampleDown(length - margin-101)

    if not objOffset.acrossGrossOffset:
        objOffset.setAcrossGrossOffset(0.0)

    if not objOffset.downGrossOffset:
        objOffset.setDownGrossOffset(offset)

    if not objOffset.numberLocationAcross:
        objOffset.setNumberLocationAcross(nAcross)

    if not objOffset.numberLocationDown:
        objOffset.setNumberLocationDown(nDown)        

    objOffset.setFirstPRF(1.0)
    objOffset.setSecondPRF(1.0)
    objOffset.setImageDataType1('complex')
    objOffset.setImageDataType2('real') 

    objOffset.ampcor(sar, sim)

    sar.finalizeImage()
    sim.finalizeImage()

    result = objOffset.getOffsetField()
    return result