Ejemplo n.º 1
0
    def unwrap_tile(self):

        cmd = 'snaphu -f {config_file} -d {wrapped_file} {line_length} -o ' \
              '{unwrapped_file} --tile {ytile} {xtile} 500 500 ' \
              '--nproc {num_proc}'.format(config_file=self.config_file, wrapped_file=self.inp_wrapped,
                                          line_length=self.width, unwrapped_file=self.out_unwrapped, ytile=self.y_tile,
                                          xtile=self.x_tile, num_proc=self.num_tiles)
        print(cmd)
        
        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        output, error = p.communicate()
        print(error)

        if 'ERROR' in error.decode('UTF-8') or 'Error' in error.decode('UTF-8'):  # or len(error.decode('UTF-8'))>0:
           raise RuntimeError(error)  
        
        if os.path.exists(self.out_unwrapped):
  
            IML.renderISCEXML(self.out_unwrapped, bands=2, nyy=self.length, nxx=self.width,
                              datatype='float32', scheme='BIL')

            IML.renderISCEXML(self.conncomp, bands=1, nyy=self.length, nxx=self.width,
                              datatype='BYTE', scheme='BIL')

        return
Ejemplo n.º 2
0
def create_demZero(dem, outdir):
    """ create DEM with zero elevation """

    demImage = isceobj.createDemImage()
    demImage.load(dem + '.xml')

    zerodem_name = outdir + '/demzero.wgs84'

    immap = IML.memmap(zerodem_name,
                       mode='write',
                       nchannels=demImage.bands,
                       nxx=demImage.coord1.coordSize,
                       nyy=demImage.coord2.coordSize,
                       scheme=demImage.scheme,
                       dataType=demImage.toNumpyDataType())

    IML.renderISCEXML(zerodem_name,
                      demImage.bands,
                      demImage.coord2.coordSize,
                      demImage.coord1.coordSize,
                      demImage.toNumpyDataType(),
                      demImage.scheme,
                      bbox=demImage.getsnwe())

    demZero = isceobj.createDemImage()
    demZero.load(zerodem_name + '.xml')

    return demZero
Ejemplo n.º 3
0
def flattenWithOffsets(fname, offname, flatname, frame, rglooks):
    from isceobj.Util.ImageUtil import ImageLib as IML
    import logging

    ifg = IML.mmapFromISCE(fname, logging).bands[0]
    off = IML.mmapFromISCE(offname, logging).bands[0]

    lgt = min(ifg.shape[0], off.shape[0])

    delr = 0.5 * SPEED_OF_LIGHT / frame.rangeSamplingRate
    wvl = frame.getInstrument().getRadarWavelength()
    factor = 4 * np.pi * delr * rglooks / wvl
    cJ = np.complex64(1.0j)

    fid = open(flatname, 'wb')
    for ii in range(lgt):
        data = ifg[ii] * np.exp(-cJ * factor * off[ii])
        data.astype(np.complex64).tofile(fid)

    fid.close()

    img = isceobj.createIntImage()
    img.setFilename(flatname)
    img.setWidth(ifg.shape[1])
    img.setAccessMode('READ')
    img.renderHdr()

    pass
Ejemplo n.º 4
0
def subset(inname, outname, sliceline, slicepix, 
        virtual=False):
    '''Subset the input image to output image.
    '''

    gdalmap = {'FLOAT': 'Float32',
                'CFLOAT': 'CFloat32',
                'DOUBLE' : 'Float64'}

    inimg = isceobj.createImage()
    inimg.load(inname + '.xml')
    inimg.filename = outname

    inwidth = inimg.width
    inlength = inimg.length
    outwidth = slicepix.stop - slicepix.start
    outlength = sliceline.stop - sliceline.start
    inimg.setWidth(outwidth)
    inimg.setLength(outlength)
    inimg.setAccessMode('READ')
    inimg.renderHdr()

    if not virtual:
        indata = IML.mmapFromISCE(inname, logging).bands[0]
        outdata = indata[sliceline, slicepix]
        outdata.tofile(outname)
        indata = None

    else:

        relpath = os.path.relpath(inname, os.path.dirname(outname))

        rdict = {'outwidth'   : outwidth,
                 'outlength'  : outlength,
                 'inwidth'    : inwidth,
                 'inlength'   : inlength,
                 'xoffset'    : slicepix.start,
                 'yoffset'    : sliceline.start,
                 'dtype'      : gdalmap[inimg.dataType.upper()],
                 'filename'   : relpath + '.vrt'}

       

        tmpl = '''<VRTDataset rasterXSize="{outwidth}" rasterYSize="{outlength}">
    <VRTRasterBand dataType="{dtype}" band="1">
        <NoDataValue>0.0</NoDataValue>
        <SimpleSource>
            <SourceFilename relativeToVRT="1">{filename}</SourceFilename>
            <SourceBand>1</SourceBand>
            <SourceProperties RasterXSize="{inwidth}" RasterYSize="{inlength}" DataType="{dtype}"/>
            <SrcRect xOff="{xoffset}" yOff="{yoffset}" xSize="{outwidth}" ySize="{outlength}"/>
            <DstRect xOff="0" yOff="0" xSize="{outwidth}" ySize="{outlength}"/>
        </SimpleSource>
    </VRTRasterBand>
</VRTDataset>'''

        with open(outname + '.vrt', 'w') as fid:
            fid.write(tmpl.format(**rdict))

    return
Ejemplo n.º 5
0
def parseInputFile(varname, args):
    '''
    Get the input string corresponding to given variable name.
    '''

    inarg = varname.strip()
    ####Keyname corresponds to specific
    key = '--' + inarg

    if len(varname.strip()) > 1:
        raise IOError('Input variable names should be single characters.\n' +
                'Invalid variable name: %s'%varname)

    if (inarg != inarg.lower()):
        raise IOError('Input variable names should be lower case. \n' +
                'Invalud variable name: %s'%varname)

    #####Create a simple parser
    parser = IML.customArgumentParser(description='Parser for band math.',
            add_help=False)
    parser.add_argument(key, type=str, required=True, action='store',
            help='Input string for a particular variable.', dest='instr')

    try:
        infile, rest = parser.parse_known_args(args)
    except:
        raise SyntaxError('Input file : "%s" not defined on command line'%varname)
    return infile.instr, rest
Ejemplo n.º 6
0
def createCoherence(intfile, win=5):
    '''
    Compute coherence using scipy convolve 2D.
    '''

    corfile = os.path.splitext(intfile)[0] + '.cor'
    filt = np.ones((win, win)) / (1.0 * win * win)

    inimg = IML.mmapFromISCE(intfile + '.xml', logging)
    cJ = np.complex64(1.0j)
    angle = np.exp(cJ * np.angle(inimg.bands[0]))

    res = SS.convolve2d(angle, filt, mode='same')
    res[0:win - 1, :] = 0.0
    res[-win + 1:, :] = 0.0
    res[:, 0:win - 1] = 0.0
    res[:, -win + 1:] = 0.0

    res = np.abs(res)

    with open(corfile, 'wb') as f:
        res.astype(np.float32).tofile(f)

    img = isceobj.createImage()
    img.setFilename(corfile)
    img.setWidth(res.shape[1])
    img.dataType = 'FLOAT'
    img.setAccessMode('READ')
    img.renderHdr()
    img.renderVRT()
    #  img.createImage()
    #  img.finalizeImage()

    return corfile
Ejemplo n.º 7
0
    def createImage(self):
        '''
        Create an image object to pass to C extension.
        '''
        from isceobj.Util.ImageUtil import ImageLib as IML
        img = IML.loadImage(self.fileName)[0]

        if img.dataType.upper().startswith('C'):
            img.setCaster('read','CDOUBLE')
        else:
            img.setCaster('read', 'DOUBLE')

        self.image = img
        self.image.createImage()
Ejemplo n.º 8
0
def read(file, processor='ISCE', bands=None, dataType=None):
    ''' raeder based on GDAL.
       
    Args:

        * file      -> File name to be read

    Kwargs:

        * processor -> the processor used for the InSAR processing. default: ISCE
        * bands     -> a list of bands to be extracted. If not specified all bands will be extracted. 
        * dataType  -> if not specified, it will be extracted from the data itself
    Returns:
        * data : A numpy array with dimensions : number_of_bands * length * width
    '''
    # generate ENVI hdr file and fix the file path in xml
    file = os.path.abspath(file)
    if processor == 'ISCE':
        img, dataname, metaname = IML.loadImage(file)
        img.filename = file
        img.setAccessMode('READ')
        img.renderHdr()

    dataset = gdal.Open(file, GA_ReadOnly)

    ######################################
    # if the bands have not been specified, all bands will be extracted
    if bands is None:
        bands = range(1, dataset.RasterCount + 1)
    ######################################
    # if dataType is not known let's get it from the data:
    if dataType is None:
        band = dataset.GetRasterBand(1)
        dataType = GDAL2NUMPY_DATATYPE[band.DataType]

    ######################################
    # Form a numpy array of zeros with the the shape of (number of bands * length * width) and a given data type
    data = np.zeros((len(bands), dataset.RasterYSize, dataset.RasterXSize),
                    dtype=dataType)
    ######################################
    # Fill the array with the Raster bands
    idx = 0
    for i in bands:
        band = dataset.GetRasterBand(i)
        data[idx, :, :] = band.ReadAsArray()
        idx += 1

    dataset = None
    return data
Ejemplo n.º 9
0
def detailedHelp():
    '''
    Return the detailed help message.
    '''
    msg = helpStr + '\n\n'+ \
              'Available Functions \n' + \
              '********************\n' + \
              str(IML.fnDict.keys()) + '\n\n' + \
              'Available Constants \n' + \
              '********************\n' + \
              str(IML.constDict.keys()) + '\n\n' + \
              'Available DataTypes -> numpy code mapping  \n' + \
              '*****************************************  \n'+ \
              IML.printNUMPYMap() + '\n'

    return msg
Ejemplo n.º 10
0
def imagePathXml(imageFile, fullPath=True):
    import os
    import isceobj
    from isceobj.Util.ImageUtil import ImageLib as IML

    img = IML.loadImage(imageFile)[0]

    dirname = os.path.dirname(imageFile)
    if fullPath:
        fname = os.path.abspath(
            os.path.join(dirname, os.path.basename(imageFile)))
    else:
        fname = os.path.basename(imageFile)

    img.filename = fname
    img.setAccessMode('READ')
    img.renderHdr()
Ejemplo n.º 11
0
def firstPassCommandLine():
    '''
    Take a first parse at command line parsing.
    Read only the basic required fields
    '''

    #####Create the generic parser to get equation and output format first
    parser = argparse.ArgumentParser(description='ISCE Band math calculator.',
            formatter_class=IML.customArgparseFormatter)

#    help_parser = subparser.add_
    parser.add_argument('-H','--hh', nargs=0, action=customArgparseAction,
            help='Display detailed help information.')
    parser.add_argument('-e','--eval', type=str, required=True, action='store',
            help='Expression to evaluate.', dest='equation')
    parser.add_argument('-o','--out', type=str, default=None, action='store',
            help='Name of the output file', dest='out')
    parser.add_argument('-s','--scheme',type=str, default='BSQ', action='store',
            help='Output file format.', dest='scheme')
    parser.add_argument('-t','--type', type=str, default='float', action='store',
            help='Output data type.', dest='dtype')
    parser.add_argument('-d','--debug', action='store_true', default=False,
            help='Print debugging statements', dest='debug')
    parser.add_argument('-n','--noxml', action='store_true', default=False,
            help='Do not create an ISCE XML file for the output.', dest='noxml')

    #######Parse equation and output format first
    args, files = parser.parse_known_args()

    #####Check the output scheme for errors
    if args.scheme.upper() not in ['BSQ', 'BIL', 'BIP']:
        raise IOError('Unknown output scheme: %s'%(args.scheme))
    iMath['outScheme'] = args.scheme.upper()

    npType = IML.NUMPY_type(args.dtype)
    iMath['outType'] = npType

    return args, files
Ejemplo n.º 12
0
def subset_file(fname, subset_dict_input, out_file=None):
    """Subset file with
    Inputs:
        fname        : str, path/name of file
        out_file     : str, path/name of output file
        subset_dict : dict, subsut parameter, including the following items:
                      subset_x   : list of 2 int,   subset in x direction,   default=None
                      subset_y   : list of 2 int,   subset in y direction,   default=None
                      subset_lat : list of 2 float, subset in lat direction, default=None
                      subset_lon : list of 2 float, subset in lon direction, default=None
                      fill_value : float, optional. filled value for area outside of data coverage. default=None
                                   None/not-existed to subset within data coverage only.
                      tight  : bool, tight subset or not, for lookup table file, i.e. geomap*.trans
    Outputs:
        out_file :  str, path/name of output file; 
                   out_file = 'subset_'+fname, if fname is in current directory;
                   out_file = fname, if fname is not in the current directory.
    """

    # Input File Info
    atr = readfile.read_attribute(fname)
    width = int(atr['WIDTH'])
    length = int(atr['LENGTH'])
    k = atr['FILE_TYPE']
    print('subset ' + k + ' file: ' + fname + ' ...')

    subset_dict = subset_dict_input.copy()
    # Read Subset Inputs into 4-tuple box in pixel and geo coord
    pix_box, geo_box = subset_input_dict2box(subset_dict, atr)

    coord = ut.coordinate(atr)
    # if fill_value exists and not None, subset data and fill assigned value for area out of its coverage.
    # otherwise, re-check subset to make sure it's within data coverage and initialize the matrix with np.nan
    outfill = False
    if 'fill_value' in subset_dict.keys() and subset_dict['fill_value']:
        outfill = True
    else:
        outfill = False
    if not outfill:
        pix_box = coord.check_box_within_data_coverage(pix_box)
        subset_dict['fill_value'] = np.nan

    geo_box = coord.box_pixel2geo(pix_box)
    data_box = (0, 0, width, length)
    print('data   range in (x0,y0,x1,y1): {}'.format(data_box))
    print('subset range in (x0,y0,x1,y1): {}'.format(pix_box))
    print('data   range in (W, N, E, S): {}'.format(
        coord.box_pixel2geo(data_box)))
    print('subset range in (W, N, E, S): {}'.format(geo_box))

    if pix_box == data_box:
        print('Subset range == data coverage, no need to subset. Skip.')
        return fname

    # Calculate Subset/Overlap Index
    pix_box4data, pix_box4subset = get_box_overlap_index(data_box, pix_box)

    ###########################  Data Read and Write  ######################
    # Output File Name
    if not out_file:
        if os.getcwd() == os.path.dirname(os.path.abspath(fname)):
            if 'tight' in subset_dict.keys() and subset_dict['tight']:
                out_file = '{}_tight{}'.format(
                    os.path.splitext(fname)[0],
                    os.path.splitext(fname)[1])
            else:
                out_file = 'sub_' + os.path.basename(fname)
        else:
            out_file = os.path.basename(fname)
    print('writing >>> ' + out_file)

    # update metadata
    atr = attr.update_attribute4subset(atr, pix_box)

    # subset datasets one by one
    dsNames = readfile.get_dataset_list(fname)
    maxDigit = max([len(i) for i in dsNames])

    ext = os.path.splitext(out_file)[1]
    if ext in ['.h5', '.he5']:
        # initiate the output file
        writefile.layout_hdf5(out_file, metadata=atr, ref_file=fname)

        # subset dataset one-by-one
        for dsName in dsNames:
            with h5py.File(fname, 'r') as fi:
                ds = fi[dsName]
                ds_shape = ds.shape
                ds_ndim = ds.ndim
                print('cropping {d} in {b} from {f} ...'.format(
                    d=dsName, b=pix_box4data, f=os.path.basename(fname)))

                if ds_ndim == 2:
                    # read
                    data = ds[pix_box4data[1]:pix_box4data[3],
                              pix_box4data[0]:pix_box4data[2]]

                    # crop
                    data_out = np.ones(
                        (pix_box[3] - pix_box[1], pix_box[2] - pix_box[0]),
                        data.dtype) * subset_dict['fill_value']
                    data_out[pix_box4subset[1]:pix_box4subset[3],
                             pix_box4subset[0]:pix_box4subset[2]] = data
                    data_out = np.array(data_out, dtype=data.dtype)

                    # write
                    block = [0, int(atr['LENGTH']), 0, int(atr['WIDTH'])]
                    writefile.write_hdf5_block(out_file,
                                               data=data_out,
                                               datasetName=dsName,
                                               block=block,
                                               print_msg=True)

                if ds_ndim == 3:
                    prog_bar = ptime.progressBar(maxValue=ds_shape[0])
                    for i in range(ds_shape[0]):
                        # read
                        data = ds[i, pix_box4data[1]:pix_box4data[3],
                                  pix_box4data[0]:pix_box4data[2]]

                        # crop
                        data_out = np.ones(
                            (1, pix_box[3] - pix_box[1],
                             pix_box[2] - pix_box[0]),
                            data.dtype) * subset_dict['fill_value']
                        data_out[:, pix_box4subset[1]:pix_box4subset[3],
                                 pix_box4subset[0]:pix_box4subset[2]] = data

                        # write
                        block = [
                            i, i + 1, 0,
                            int(atr['LENGTH']), 0,
                            int(atr['WIDTH'])
                        ]
                        writefile.write_hdf5_block(out_file,
                                                   data=data_out,
                                                   datasetName=dsName,
                                                   block=block,
                                                   print_msg=False)

                        prog_bar.update(i + 1,
                                        suffix='{}/{}'.format(
                                            i + 1, ds_shape[0]))
                    prog_bar.close()
                    print('finished writing to file: {}'.format(out_file))

    else:
        # IO for binary files
        dsDict = dict()
        for dsName in dsNames:
            dsDict[dsName] = subset_dataset(
                fname,
                dsName,
                pix_box,
                pix_box4data,
                pix_box4subset,
                fill_value=subset_dict['fill_value'])
        writefile.write(dsDict,
                        out_file=out_file,
                        metadata=atr,
                        ref_file=fname)

        # write extra metadata files for ISCE data files
        if os.path.isfile(fname + '.xml') or os.path.isfile(fname +
                                                            '.aux.xml'):
            # write ISCE XML file
            dtype_gdal = readfile.NUMPY2GDAL_DATATYPE[atr['DATA_TYPE']]
            dtype_isce = readfile.GDAL2ISCE_DATATYPE[dtype_gdal]
            writefile.write_isce_xml(out_file,
                                     width=int(atr['WIDTH']),
                                     length=int(atr['LENGTH']),
                                     bands=len(dsDict.keys()),
                                     data_type=dtype_isce,
                                     scheme=atr['scheme'],
                                     image_type=atr['FILE_TYPE'])
            print(f'write file: {out_file}.xml')

            # write GDAL VRT file
            if os.path.isfile(fname + '.vrt'):
                from isceobj.Util.ImageUtil import ImageLib as IML
                img = IML.loadImage(out_file)[0]
                img.renderVRT()
                print(f'write file: {out_file}.vrt')

    return out_file
Ejemplo n.º 13
0
def estimateOffsetField(reference, secondary, inps=None):
    """Estimte offset field using PyCuAmpcor.
    Parameters: reference - str, path of the reference SLC file
                secondary - str, path of the secondary SLC file
                inps      - Namespace, input configuration
    Returns:    objOffset - PyCuAmpcor object
                geomDict  - dict, geometry location info of the offset field
    """

    # update file path in xml file
    if inps.fixImageXml:
        for fname in [reference, secondary]:
            fname = os.path.abspath(fname)
            img = IML.loadImage(fname)[0]
            img.filename = fname
            img.setAccessMode('READ')
            img.renderHdr()

    ###Loading the secondary image object
    sim = isceobj.createSlcImage()
    sim.load(secondary + '.xml')
    sim.setAccessMode('READ')
    sim.createImage()

    ###Loading the reference image object
    sar = isceobj.createSlcImage()
    sar.load(reference + '.xml')

    sar.setAccessMode('READ')
    sar.createImage()

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

    # create a PyCuAmpcor instance
    objOffset = PyCuAmpcor()

    objOffset.algorithm = inps.algorithm
    objOffset.deviceID = inps.gpuid
    objOffset.nStreams = inps.nstreams  #cudaStreams
    objOffset.derampMethod = inps.deramp
    print('deramp method (0 for magnitude, 1 for complex): ',
          objOffset.derampMethod)

    objOffset.referenceImageName = reference + '.vrt'
    objOffset.referenceImageHeight = length
    objOffset.referenceImageWidth = width
    objOffset.secondaryImageName = secondary + '.vrt'
    objOffset.secondaryImageHeight = length
    objOffset.secondaryImageWidth = width

    print("image length:", length)
    print("image width:", width)

    # if using gross offset, adjust the margin
    margin = max(inps.margin, abs(inps.azshift), abs(inps.rgshift))

    # determine the number of windows down and across
    # that's also the size of the output offset field
    objOffset.numberWindowDown = inps.numWinDown if inps.numWinDown > 0 \
        else (length-2*margin-2*inps.srchgt-inps.winhgt)//inps.skiphgt
    objOffset.numberWindowAcross = inps.numWinAcross if inps.numWinAcross > 0 \
        else (width-2*margin-2*inps.srcwidth-inps.winwidth)//inps.skipwidth
    print('the number of windows: {} by {}'.format(
        objOffset.numberWindowDown, objOffset.numberWindowAcross))

    # window size
    objOffset.windowSizeHeight = inps.winhgt
    objOffset.windowSizeWidth = inps.winwidth
    print('window size for cross-correlation: {} by {}'.format(
        objOffset.windowSizeHeight, objOffset.windowSizeWidth))

    # search range
    objOffset.halfSearchRangeDown = inps.srchgt
    objOffset.halfSearchRangeAcross = inps.srcwidth
    print('initial search range: {} by {}'.format(inps.srchgt, inps.srcwidth))

    # starting pixel
    objOffset.referenceStartPixelDownStatic = inps.startpixeldw if inps.startpixeldw != -1 \
        else margin + objOffset.halfSearchRangeDown    # use margin + halfSearchRange instead
    objOffset.referenceStartPixelAcrossStatic = inps.startpixelac if inps.startpixelac != -1 \
        else margin + objOffset.halfSearchRangeAcross

    print('the first pixel in reference image is: ({}, {})'.format(
        objOffset.referenceStartPixelDownStatic,
        objOffset.referenceStartPixelAcrossStatic))

    # skip size
    objOffset.skipSampleDown = inps.skiphgt
    objOffset.skipSampleAcross = inps.skipwidth
    print('search step: {} by {}'.format(inps.skiphgt, inps.skipwidth))

    # oversample raw data (SLC)
    objOffset.rawDataOversamplingFactor = inps.raw_oversample

    # correlation surface
    objOffset.corrStatWindowSize = inps.corr_stat_win_size

    corr_win_size = 2 * inps.corr_srch_size * inps.raw_oversample
    objOffset.corrSurfaceZoomInWindow = corr_win_size
    print('correlation surface zoom-in window size:', corr_win_size)

    objOffset.corrSurfaceOverSamplingMethod = inps.corr_oversamplemethod
    objOffset.corrSurfaceOverSamplingFactor = inps.corr_oversample
    print('correlation surface oversampling factor:', inps.corr_oversample)

    # output filenames
    fbase = '{}{}'.format(inps.outprefix, inps.outsuffix)
    objOffset.offsetImageName = fbase + '.bip'
    objOffset.grossOffsetImageName = fbase + '_gross.bip'
    objOffset.snrImageName = fbase + '_snr.bip'
    objOffset.covImageName = fbase + '_cov.bip'
    print("offsetfield: ", objOffset.offsetImageName)
    print("gross offsetfield: ", objOffset.grossOffsetImageName)
    print("snr: ", objOffset.snrImageName)
    print("cov: ", objOffset.covImageName)

    # whether to include the gross offset in offsetImage
    objOffset.mergeGrossOffset = inps.merge_gross_offset

    try:
        offsetImageName = objOffset.offsetImageName.decode('utf8')
        grossOffsetImageName = objOffset.grossOffsetImageName.decode('utf8')
        snrImageName = objOffset.snrImageName.decode('utf8')
        covImageName = objOffset.covImageName.decode('utf8')
    except:
        offsetImageName = objOffset.offsetImageName
        grossOffsetImageName = objOffset.grossOffsetImageName
        snrImageName = objOffset.snrImageName
        covImageName = objOffset.covImageName

    # generic control
    objOffset.numberWindowDownInChunk = inps.numWinDownInChunk
    objOffset.numberWindowAcrossInChunk = inps.numWinAcrossInChunk
    objOffset.useMmap = inps.usemmap
    objOffset.mmapSize = inps.mmapsize

    # setup and check parameters
    objOffset.setupParams()

    ## Set Gross Offset ###
    if inps.gross == 0:  # use static grossOffset
        print('Set constant grossOffset ({}, {})'.format(
            inps.azshift, inps.rgshift))
        objOffset.setConstantGrossOffset(inps.azshift, inps.rgshift)

    else:  # use varying offset
        print("Set varying grossOffset from file {}".format(
            inps.gross_offset_file))
        grossOffset = np.fromfile(inps.gross_offset_file, dtype=np.int32)
        numberWindows = objOffset.numberWindowDown * objOffset.numberWindowAcross
        if grossOffset.size != 2 * numberWindows:
            print((
                'WARNING: The input gross offsets do not match the number of windows:'
                ' {} by {} in int32 type').format(
                    objOffset.numberWindowDown, objOffset.numberWindowAcross))
            return 0

        grossOffset = grossOffset.reshape(numberWindows, 2)
        grossAzimuthOffset = grossOffset[:, 0]
        grossRangeOffset = grossOffset[:, 1]
        # enforce C-contiguous flag
        grossAzimuthOffset = grossAzimuthOffset.copy(order='C')
        grossRangeOffset = grossRangeOffset.copy(order='C')
        # set varying gross offset
        objOffset.setVaryingGrossOffset(grossAzimuthOffset, grossRangeOffset)

    # check
    objOffset.checkPixelInImageRange()

    # save output geometry location info
    geomDict = {
        'x_start':
        objOffset.referenceStartPixelAcrossStatic +
        int(objOffset.windowSizeWidth / 2.),
        'y_start':
        objOffset.referenceStartPixelDownStatic +
        int(objOffset.windowSizeHeight / 2.),
        'x_step':
        objOffset.skipSampleAcross,
        'y_step':
        objOffset.skipSampleDown,
        'x_win_num':
        objOffset.numberWindowAcross,
        'y_win_num':
        objOffset.numberWindowDown,
    }

    # check redo
    print('redo: ', inps.redo)
    if not inps.redo:
        offsetImageName = '{}{}.bip'.format(inps.outprefix, inps.outsuffix)
        if os.path.exists(offsetImageName):
            print(
                'offset field file: {} exists and w/o redo, skip re-estimation.'
                .format(offsetImageName))
            return objOffset, geomDict

    # Run the code
    print('Running PyCuAmpcor')

    objOffset.runAmpcor()
    print('Finished')

    sar.finalizeImage()
    sim.finalizeImage()

    # Finalize the results
    # offsetfield
    outImg = isceobj.createImage()
    outImg.setDataType('FLOAT')
    outImg.setFilename(offsetImageName)
    outImg.setBands(2)
    outImg.scheme = 'BIP'
    outImg.setWidth(objOffset.numberWindowAcross)
    outImg.setLength(objOffset.numberWindowDown)
    outImg.setAccessMode('read')
    outImg.renderHdr()

    # gross offsetfield
    outImg = isceobj.createImage()
    outImg.setDataType('FLOAT')
    outImg.setFilename(grossOffsetImageName)
    outImg.setBands(2)
    outImg.scheme = 'BIP'
    outImg.setWidth(objOffset.numberWindowAcross)
    outImg.setLength(objOffset.numberWindowDown)
    outImg.setAccessMode('read')
    outImg.renderHdr()

    # snr
    snrImg = isceobj.createImage()
    snrImg.setFilename(snrImageName)
    snrImg.setDataType('FLOAT')
    snrImg.setBands(1)
    snrImg.setWidth(objOffset.numberWindowAcross)
    snrImg.setLength(objOffset.numberWindowDown)
    snrImg.setAccessMode('read')
    snrImg.renderHdr()

    # cov
    covImg = isceobj.createImage()
    covImg.setFilename(covImageName)
    covImg.setDataType('FLOAT')
    covImg.setBands(3)
    covImg.scheme = 'BIP'
    covImg.setWidth(objOffset.numberWindowAcross)
    covImg.setLength(objOffset.numberWindowDown)
    covImg.setAccessMode('read')
    covImg.renderHdr()

    return objOffset, geomDict
Ejemplo n.º 14
0
    def readIsce(self, dates, filesDir, igramName):
        '''
        Read files from ISCE software.

        Args:
            * dates             : Dates of the interferogram (list)
            * filesDir          : Files directory (str)
            * igramName         : Interferogram filename (str)
        '''

        # Import ISCE stuff
        import isce
        import isceobj
        from isceobj.Util.ImageUtil import ImageLib as IML

        #-------------------------------------------------
        # READ IGRAM

        # Igram filenames (wrapped, unwrapped and corrected)
        ifgInt = '{}/{}_{}/{}.int'.format(
            filesDir, dates[0], dates[1],
            os.path.splitext(os.path.basename(igramName))[0])
        ifgFile = '{}/{}_{}/{}'.format(filesDir, dates[0], dates[1], igramName)
        ifgFile_corrected = '{}_corrected{}'.format(
            os.path.splitext(ifgFile)[0],
            os.path.splitext(ifgFile)[1])

        # Igram.unw xml infos
        imgIfgFile = isceobj.createImage()
        imgIfgFile.load(ifgFile + '.xml')
        bands = imgIfgFile.bands
        length = imgIfgFile.getLength()
        width = imgIfgFile.getWidth()
        scheme = imgIfgFile.scheme

        # Igram.int xml infos
        imgInt = isceobj.createImage()
        imgInt.load(ifgInt + '.xml')
        bandsInt = imgInt.bands
        schemeInt = imgInt.scheme
        datatypeInt = IML.NUMPY_type(imgInt.dataType)

        # Igram not yet corrected
        if not os.path.exists(ifgFile_corrected):

            # Read igram.unw
            data = IML.memmap(ifgFile,
                              mode='readonly',
                              nchannels=bands,
                              nyy=length,
                              nxx=width,
                              scheme=scheme)

            # Create the corrected igram
            data_corrected = IML.memmap(ifgFile_corrected,
                                        mode='write',
                                        nchannels=bands,
                                        nyy=length,
                                        nxx=width,
                                        scheme=scheme)

            # Copy igram.unw in the new file
            data_corrected.bands[0][:, :] = data.bands[0][:, :]
            data_corrected.bands[1][:, :] = data.bands[1][:, :]

            # New xml infos
            data_correctedXml = isceobj.Image.createUnwImage()
            data_correctedXml.bands = 2
            data_correctedXml.setWidth(width)
            data_correctedXml.setLength(length)
            data_correctedXml.setFilename(ifgFile_corrected)
            data_correctedXml.renderHdr()
            data_correctedXml.renderVRT()

            # Flag
            flag_corr = True

        # Igram already corrected, start from it
        else:

            # Read igram.unw already corrected
            data = IML.memmap(ifgFile_corrected,
                              mode='readwrite',
                              nchannels=bands,
                              nyy=length,
                              nxx=width,
                              scheme=scheme)

            # Flag
            flag_corr = False

        # Read wrap igram where to compute misclosure
        data_int = IML.memmap(ifgInt,
                              mode='readonly',
                              nchannels=bandsInt,
                              dataType=datatypeInt,
                              nyy=length,
                              nxx=width,
                              scheme=schemeInt)

        #-------------------------------------------------
        # READ MASK

        # Initialize the mask
        mask = np.zeros((length, width))

        #-------------------------------------------------
        # SAVE

        # Save things
        if flag_corr:
            self.phase = data_corrected.bands[1]
        else:
            self.phase = data.bands[1]
        self.phase_int = data_int.bands[0]
        self.dates = dates
        self.igramsDir = filesDir
        self.igramName = igramName
        self.width = width
        self.length = length
        self.ifgFile_corrected = ifgFile_corrected

        # Close files
        del data
        del data_int

        # All done
        return
Ejemplo n.º 15
0
        '--base',
        action='store_true',
        help='Replace filename with basename to use in current directory')

    inps = parser.parse_args()
    return inps


if __name__ == '__main__':
    '''
    Main driver.
    '''
    inps = cmdLineParse()

    if inps.infile.endswith('.xml'):
        inps.infile = os.path.splitext(inps.infile)[0]

    dirname = os.path.dirname(inps.infile)

    img = IML.loadImage(inps.infile)[0]

    if inps.full:
        fname = os.path.abspath(
            os.path.join(dirname, os.path.basename(inps.infile)))
    else:
        fname = os.path.basename(os.path.basename(inps.infile))

    img.filename = fname
    img.setAccessMode('READ')
    img.renderHdr()
Ejemplo n.º 16
0
def mergeBursts(frame, fileList, outfile,
        method='top'):
    '''
    Merge burst products into single file.
    Simple numpy based stitching
    '''

    ###Check against metadata
    if frame.numberOfBursts != len(fileList):
        print('Warning : Number of burst products does not appear to match number of bursts in metadata')


    t0 = frame.bursts[0].sensingStart
    dt = frame.bursts[0].azimuthTimeInterval
    width = frame.bursts[0].numberOfSamples

    #######
    tstart = frame.bursts[0].sensingStart 
    tend = frame.bursts[-1].sensingStop
    nLines = int( np.round((tend - tstart).total_seconds() / dt)) + 1
    print('Expected total nLines: ', nLines)


    img = isceobj.createImage()
    img.load( fileList[0] + '.xml')
    bands = img.bands
    scheme = img.scheme
    npType = IML.NUMPY_type(img.dataType)

    azMasterOff = []
    for index in range(frame.numberOfBursts):
        burst = frame.bursts[index]
        soff = burst.sensingStart + datetime.timedelta(seconds = (burst.firstValidLine*dt)) 
        start = int(np.round((soff - tstart).total_seconds() / dt))
        end = start + burst.numValidLines

        azMasterOff.append([start,end])

        print('Burst: ', index, [start,end])

        if index == 0:
            linecount = start

    outMap = IML.memmap(outfile, mode='write', nchannels=bands,
            nxx=width, nyy=nLines, scheme=scheme, dataType=npType)

    for index in range(frame.numberOfBursts):
        curBurst = frame.bursts[index]
        curLimit = azMasterOff[index]

        curMap = IML.mmapFromISCE(fileList[index], logging)

        #####If middle burst
        if index > 0:
            topBurst = frame.bursts[index-1]
            topLimit = azMasterOff[index-1]
            topMap = IML.mmapFromISCE(fileList[index-1], logging)

            olap = topLimit[1] - curLimit[0]

            print("olap: ", olap)

            if olap <= 0:
                raise Exception('No Burst Overlap')


            for bb in range(bands):
                topData =  topMap.bands[bb][topBurst.firstValidLine: topBurst.firstValidLine + topBurst.numValidLines,:]

                curData =  curMap.bands[bb][curBurst.firstValidLine: curBurst.firstValidLine + curBurst.numValidLines,:]

                im1 = topData[-olap:,:]
                im2 = curData[:olap,:]

                if method=='avg':
                    data = 0.5*(im1 + im2)
                elif method == 'top':
                    data = im1
                elif method == 'bot':
                    data = im2
                else:
                    raise Exception('Method should be top/bot/avg')

                outMap.bands[bb][linecount:linecount+olap,:] = data

            tlim = olap
        else:
            tlim = 0

        linecount += tlim
            
        if index != (frame.numberOfBursts-1):
            botBurst = frame.bursts[index+1]
            botLimit = azMasterOff[index+1]
            
            olap = curLimit[1] - botLimit[0]

            if olap < 0:
                raise Exception('No Burst Overlap')

            blim = botLimit[0] - curLimit[0]
        else:
            blim = curBurst.numValidLines
       
        lineout = blim - tlim
        
        for bb in range(bands):
            curData =  curMap.bands[bb][curBurst.firstValidLine: curBurst.firstValidLine + curBurst.numValidLines,:]
            outMap.bands[bb][linecount:linecount+lineout,:] = curData[tlim:blim,:] 

        linecount += lineout
        curMap = None
        topMap = None

    IML.renderISCEXML(outfile, bands,
            nLines, width,
            img.dataType, scheme)

    oimg = isceobj.createImage()
    oimg.load(outfile + '.xml')
    oimg.imageType = img.imageType
    oimg.renderHdr()
    try:
        outMap.bands[0].base.base.flush()
    except:
        pass
Ejemplo n.º 17
0
            help = 'Replace filename with full path including dir in which file is located')
    fname.add_argument('-b', '--base', action='store_true',
            help = 'Replace filename with basename to use in current directory')

    inps = parser.parse_args()
    return inps


if __name__ == '__main__':
    '''
    Main driver.
    '''
    inps = cmdLineParse()

    for fname in inps.infile:
        if fname.endswith('.xml'):
            fname = os.path.splitext(fname)[0]
        print('fixing xml file for file: {}'.format(fname))

        if inps.full:
            fdir = os.path.dirname(fname)
            fname = os.path.abspath(os.path.join(fdir, os.path.basename(fname)))
        else:
            fname = os.path.basename(os.path.basename(fname))

        img = IML.loadImage(fname)[0]
        img.filename = fname
        img.setAccessMode('READ')
        img.renderHdr()

Ejemplo n.º 18
0
def main(args, files):
    #######Set up logger appropriately
    logger = IML.createLogger(args.debug, name='imageMath')
    logger.debug('Known: '+ str(args))
    logger.debug('Optional: '+ str(files))


    #######Determine number of input and output bands
    bandList = []
    for ii,expr in enumerate(args.equation.split(';')):

        #####Now parse the equation to get the file names used
        nsp = NumericStringParser(expr.strip())
        logger.debug('Input Expression: %d : %s'%(ii, expr))
        bands, known = nsp.parse()
        logger.debug('Unknown variables: ' + str(bands))
        logger.debug('Known variables: ' + str(known))

        iMath['equations'].append(expr)
        bandList = bandList + bands

    bandList = IML.uniqueList(bandList)

    numOutBands = len(iMath['equations'])
    logger.debug('Number of output bands = %d'%(numOutBands))
    logger.debug('Number of input bands used = %d'%(len(bandList)))
    logger.debug('Input bands used = ' + str(bandList))


    #####Determine unique images from the bandList
    fileList = IML.bandsToFiles(bandList, logger)


    ######Create input memmaps
    for ii,infile in enumerate(fileList):
        fstr, files = parseInputFile(infile, files)
        logger.debug('Input string for File %d: %s: %s'%(ii, infile, fstr))

        if len(fstr.split(';')) > 1:
            fmap = IML.mmapFromStr(fstr, logger)
            bbox = None
        else:
            fmap = IML.mmapFromISCE(fstr, logger)
            bbox = IML.getGeoInfo(fstr)


        iMath['inFiles'][infile] = fmap

        if len(fmap.bands) == 1:
            iMath['inBands'][infile] = fmap.bands[0]

        for ii in range(len(fmap.bands)):
            iMath['inBands']['%s_%d'%(infile, ii)] = fmap.bands[ii]

        if bbox is not None:
            iMath['bboxes'].append(bbox)

    if len(files):
        raise IOError('Unused input variables set:\n'+ ' '.join(files))

    #######Some debugging
    logger.debug('List of available bands: ' + str(iMath['inBands'].keys()))

    ####If used in calculator mode.
    if len(bandList) == 0:
        dataDict=dict(IML.fnDict.items() + IML.constDict.items())
        logger.info('Calculator mode. No output files created')
        for ii, equation in enumerate(iMath['equations']):
            res=eval(expr, dataDict)
            logger.info('Output Band %d : %f '%(ii, res))

        sys.exit(0)
    else:
        if args.out is None:
            raise IOError('Output file has not been defined.')

    #####Check if all bands in bandList have been accounted for
    for band in bandList:
        if band not in iMath['inBands'].keys():
            raise ValueError('Undefined band : %s '%(band))

    ######Check if all the widths match
    widths = [img.width for var,img in iMath['inFiles'].items() ]
    if len(widths) != widths.count(widths[0]):
        logger.debug('Widths of images: ' +
                str([(var, img.name, img.width) for var,img in iMath['inFiles'].items()]))
        raise IOError('Input images are not of same width')

    iMath['width'] = widths[0]
    logger.debug('Output Width =  %d'%(iMath['width']))

    #######Check if all the lengths match
    lengths=[img.length for var,img in iMath['inFiles'].items()]
    if len(lengths) != lengths.count(lengths[0]):
        logger.debug('Lengths of images: ' +
             str([(var, img.name, img.length) for var,img in iMath['inFiles'].items()]))

        raise IOError('Input images are not of the same length')

    iMath['length'] = lengths[0]
    logger.debug('Output Length = %d'%(iMath['length']))

    #####Now create the output file
    outmap = IML.memmap(args.out, mode='write', nchannels=numOutBands,
            nxx=iMath['width'], nyy=iMath['length'], scheme=iMath['outScheme'],
            dataType=iMath['outType'])

    logger.debug('Creating output ISCE mmap with \n' +
            'file = %s \n'%(args.out) +
            'bands = %d \n'%(numOutBands) +
            'width = %d \n'%(iMath['width']) +
            'length = %d \n'%(iMath['length'])+
            'scheme = %s \n'%(iMath['outScheme']) +
            'dtype = %s \n'%(iMath['outType']))

    iMath['outBands'] = outmap.bands

    #####Start evaluating the expressions

    ####Set up the name space to use
    dataDict=dict(IML.fnDict.items() | IML.constDict.items())
    bands = iMath['inBands']
    outBands = iMath['outBands']

    ####Array representing columns
    dataDict['COL'] = np.arange(iMath['width'], dtype=np.float)

    #####Replace ^ by **
    for lineno in range(int(iMath['length'])):

        ####Setting row number
        dataDict['ROW'] = lineno*1.0

        ####Load one line from each of the the bands
        for band in bandList:  #iMath['inBands'].iteritems():
            dataDict[band] = bands[band][lineno,:]

        ####For each output band
        for kk,expr in enumerate(iMath['equations']):
            res = eval(expr, dataDict)
            outBands[kk][lineno,:] = res

    ######Determine common bbox if any
    outputBbox = mergeBbox(iMath['bboxes'])

    ######Render ISCE XML if needed
    if not args.noxml:
        IML.renderISCEXML(args.out, numOutBands,
                iMath['length'], iMath['width'],
                iMath['outType'], iMath['outScheme'],
                bbox = outputBbox,
                descr = ' '.join(sys.argv))
Ejemplo n.º 19
0
def initiate_stacks(slc_stack, patch_dir, box, mini_stack_default_size, phase_linking_method, shp_size, range_window,
                    azimuth_window):

    shp_file = patch_dir + '/shp'
    rslc_file = patch_dir + '/rslc'
    datum_file = patch_dir + '/datum_shift'
    squeezed_file = patch_dir + '/squeezed_images'
    rslc_ref_file = patch_dir + '/rslc_ref'
    quality_file = patch_dir + '/quality'

    # create PATCH_* folder if not exist
    os.makedirs(patch_dir, exist_ok=True)

    length = box[3] - box[1]
    width = box[2] - box[0]

    # read current slc_stack to be inverted
    RSLC = h5py.File(slc_stack, 'a')
    rslc_stack = RSLC['slc']
    numSlc, rslc_length, rslc_width = rslc_stack.shape

    # big box is box + shp window
    big_box = get_big_box(box, range_window, azimuth_window, rslc_width, rslc_length)
    big_length = big_box[3] - big_box[1]
    big_width = big_box[2] - big_box[0]

    if 'sequential' in phase_linking_method:
        total_num_mini_stacks = numSlc // mini_stack_default_size

        # subset squeezed images stack for the patch with the big box size
        if not os.path.exists(squeezed_file):
            squeezed_image = np.memmap(squeezed_file, dtype='complex64', mode='w+', shape=(total_num_mini_stacks,
                                                                                           length, width))
            IML.renderISCEXML(squeezed_file, bands=total_num_mini_stacks, nyy=length, nxx=width,
                              datatype='complex64', scheme='BSQ')

        # subset datum shift stack for the patch with the big box size
        if not os.path.exists(datum_file):
            datum_shift = np.memmap(datum_file, dtype='float32', mode='w+',
                                    shape=(total_num_mini_stacks, length, width))
            IML.renderISCEXML(datum_file, bands=total_num_mini_stacks, nyy=length, nxx=width,
                              datatype='float32', scheme='BSQ')
    else:
        total_num_mini_stacks = 1

    # subset slc stack for the patch with the big box size
    if not os.path.exists(rslc_file):
        rslc = np.memmap(rslc_file, dtype='complex64', mode='w+', shape=(numSlc, big_length, big_width))
        rslc[:, :, :] = rslc_stack[:, big_box[1]: big_box[3], big_box[0]:big_box[2]]
        RSLC.close()
        IML.renderISCEXML(rslc_file, bands=numSlc, nyy=length, nxx=width, datatype='complex64', scheme='BSQ')

    # initiate refined slc file for the patch
    if not os.path.exists(rslc_ref_file):
        rslc_ref = np.memmap(rslc_ref_file, dtype='complex64', mode='w+', shape=(numSlc, length, width))
        IML.renderISCEXML(rslc_ref_file, bands=numSlc, nyy=length, nxx=width, datatype='complex64', scheme='BSQ')

    # initiate shp file for the patch
    if not os.path.isfile(shp_file):
        shp = np.memmap(shp_file, dtype='byte', mode='w+', shape=(shp_size, length, width))
        IML.renderISCEXML(shp_file, bands=shp_size, nyy=length, nxx=width, datatype='byte', scheme='BSQ')

    # initiate quality file for the patch
    if not os.path.exists(quality_file):
        quality = np.memmap(quality_file, dtype='float32', mode='w+', shape=(length, width))
        quality[:, :] = -1
        IML.renderISCEXML(quality_file, bands=1, nyy=length, nxx=width, datatype='float32', scheme='BIL')

    return big_box, total_num_mini_stacks
Ejemplo n.º 20
0
def multilook_file(infile,
                   lks_y,
                   lks_x,
                   outfile=None,
                   method='average',
                   margin=[0, 0, 0, 0],
                   max_memory=4):
    """ Multilook input file
    Parameters: infile - str, path of input file to be multilooked.
                lks_y  - int, number of looks in y / row direction.
                lks_x  - int, number of looks in x / column direction.
                margin - list of 4 int, number of pixels to be skipped during multilooking.
                         useful for offset product, where the marginal pixels are ignored during
                         cross correlation matching.
                outfile - str, path of output file
    Returns:    outfile - str, path of output file
    """
    lks_y = int(lks_y)
    lks_x = int(lks_x)

    # input file info
    atr = readfile.read_attribute(infile)
    length, width = int(atr['LENGTH']), int(atr['WIDTH'])
    k = atr['FILE_TYPE']
    print('multilooking {} {} file: {}'.format(atr['PROCESSOR'], k, infile))
    print('number of looks in y / azimuth direction: %d' % lks_y)
    print('number of looks in x / range   direction: %d' % lks_x)
    print('multilook method: {}'.format(method))

    # margin --> box
    if margin is not [0, 0, 0, 0]:  # top, bottom, left, right
        box = (margin[2], margin[0], width - margin[3], length - margin[1])
        print(
            'number of pixels to skip in top/bottom/left/right boundaries: {}'.
            format(margin))
    else:
        box = (0, 0, width, length)

    # output file name
    ext = os.path.splitext(infile)[1]
    if not outfile:
        if os.getcwd() == os.path.dirname(os.path.abspath(infile)):
            outfile = os.path.splitext(infile)[0] + '_' + str(
                lks_y) + 'alks_' + str(lks_x) + 'rlks' + ext
        else:
            outfile = os.path.basename(infile)

    # update metadata
    atr = attr.update_attribute4multilook(atr, lks_y, lks_x, box=box)

    if ext in ['.h5', '.he5']:
        writefile.layout_hdf5(outfile, metadata=atr, ref_file=infile)

    # read source data and multilooking
    dsNames = readfile.get_dataset_list(infile)
    maxDigit = max([len(i) for i in dsNames])
    dsDict = dict()
    for dsName in dsNames:
        print('multilooking {d:<{w}} from {f} ...'.format(
            d=dsName, w=maxDigit, f=os.path.basename(infile)))

        # split in Y/row direction for IO for HDF5 only
        if ext in ['.h5', '.he5']:
            # calc step size with memory usage up to 4 GB
            with h5py.File(infile, 'r') as f:
                ds = f[dsName]
                ds_size = np.prod(ds.shape) * 4
            num_step = int(np.ceil(ds_size * 4 / (max_memory * 1024**3)))
            row_step = int(np.rint(length / num_step / 10) * 10)
            row_step = max(row_step, 10)

        else:
            row_step = box[3] - box[1]

        num_step = int(np.ceil((box[3] - box[1]) / (row_step * lks_y)))
        for i in range(num_step):
            r0 = box[1] + row_step * lks_y * i
            r1 = box[1] + row_step * lks_y * (i + 1)
            r1 = min(r1, box[3])
            # IO box
            box_i = (box[0], r0, box[2], r1)
            box_o = (int((box[0] - box[0]) / lks_x), int(
                (r0 - box[1]) / lks_y), int(
                    (box[2] - box[0]) / lks_x), int((r1 - box[1]) / lks_y))
            print('box: {}'.format(box_o))

            # read / multilook
            if method == 'nearest':
                data = readfile.read(infile,
                                     datasetName=dsName,
                                     box=box_i,
                                     xstep=lks_x,
                                     ystep=lks_y,
                                     print_msg=False)[0]

            else:
                data = readfile.read(infile,
                                     datasetName=dsName,
                                     box=box_i,
                                     print_msg=False)[0]

                data = multilook_data(data, lks_y, lks_x)

            # output block
            if data.ndim == 3:
                block = [
                    0, data.shape[0], box_o[1], box_o[3], box_o[0], box_o[2]
                ]
            else:
                block = [box_o[1], box_o[3], box_o[0], box_o[2]]

            # write
            if ext in ['.h5', '.he5']:
                writefile.write_hdf5_block(outfile,
                                           data=data,
                                           datasetName=dsName,
                                           block=block,
                                           print_msg=False)
            else:
                dsDict[dsName] = data

    # for binary file with 2 bands, always use BIL scheme
    if (len(dsDict.keys()) == 2
            and os.path.splitext(infile)[1] not in ['.h5', '.he5']
            and atr.get('scheme', 'BIL').upper() != 'BIL'):
        print('the input binary file has 2 bands with band interleave as: {}'.
              format(atr['scheme']))
        print(
            'for the output binary file, change the band interleave to BIL as default.'
        )
        atr['scheme'] = 'BIL'

    if ext not in ['.h5', '.he5']:
        writefile.write(dsDict,
                        out_file=outfile,
                        metadata=atr,
                        ref_file=infile)

        # write extra metadata files for ISCE data files
        if os.path.isfile(infile + '.xml') or os.path.isfile(infile +
                                                             '.aux.xml'):
            # write ISCE XML file
            dtype_gdal = readfile.NUMPY2GDAL_DATATYPE[atr['DATA_TYPE']]
            dtype_isce = readfile.GDAL2ISCE_DATATYPE[dtype_gdal]
            writefile.write_isce_xml(outfile,
                                     width=int(atr['WIDTH']),
                                     length=int(atr['LENGTH']),
                                     bands=len(dsDict.keys()),
                                     data_type=dtype_isce,
                                     scheme=atr['scheme'],
                                     image_type=atr['FILE_TYPE'])
            print(f'write file: {outfile}.xml')

            # write GDAL VRT file
            if os.path.isfile(infile + '.vrt'):
                from isceobj.Util.ImageUtil import ImageLib as IML
                img = IML.loadImage(outfile)[0]
                img.renderVRT()
                print(f'write file: {outfile}.vrt')

    return outfile