Beispiel #1
0
def _grd_subset_georegion(infile, outfile, logfile, georegion):
    '''A wrapper around SNAP's subset routine

    This function takes an OST imported frame and subsets it according to
    the coordinates given in the region

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        georegion (str): a WKT style formatted POLYGON that bounds the
                   subset region
    '''
    # get Snap's gpt file
    gpt_file = h.gpt_path()

    # extract window from scene
    command = '{} Subset -x -q {} -Ssource=\'{}\' -t \'{}\' \
                 -PcopyMetadata=true -Pgeoregion=\'{}\''.format(
        gpt_file, 2 * os.cpu_count(), infile, outfile, georegion)

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        print(' INFO: Succesfully subsetted product')
    else:
        print(' ERROR: Subsetting exited with an error. \
                See {} for Snap Error output'.format(logfile))
        sys.exit(107)
Beispiel #2
0
def _grd_speckle_filter(infile, outfile, logfile, speckle_dict):
    '''A wrapper around SNAP's Lee-Sigma Speckle Filter

    This function takes OST imported Sentinel-1 product and applies
    a standardised version of the Lee-Sigma Speckle Filter with
    SNAP's defaut values.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
    '''

    # get path to SNAP's command line executable gpt
    gpt_file = h.gpt_path()

    print(' INFO: Applying speckle filtering.')
    # contrcut command string
    command = ('{} Speckle-Filter -x -q {}'
                  ' -PestimateENL={}'
                  ' -PanSize={}'
                  ' -PdampingFactor={}'
                  ' -Penl={}'
                  ' -Pfilter={}'
                  ' -PfilterSizeX={}'
                  ' -PfilterSizeY={}'
                  ' -PnumLooksStr={}'
                  ' -PsigmaStr={}'
                  ' -PtargetWindowSizeStr={}'
                  ' -PwindowSize={}'
                  '-t \'{}\' \'{}\''.format(
                      gpt_file, 2 * os.cpu_count(),
                      speckle_dict['estimate ENL'],
                      speckle_dict['pan size'],
                      speckle_dict['damping'],
                      speckle_dict['ENL'],
                      speckle_dict['filter'],
                      speckle_dict['filter x size'],
                      speckle_dict['filter y size'],
                      speckle_dict['num of looks'],
                      speckle_dict['sigma'],
                      speckle_dict['target window size'],
                      speckle_dict['window size'],
                      outfile, infile)
              )

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # hadle errors and logs
    if return_code == 0:
        print(' INFO: Succesfully applied speckle filtering.')
    else:
        print(' ERROR: Speckle Filtering exited with an error. \
                See {} for Snap Error output'.format(logfile))

    return return_code
Beispiel #3
0
def _slice_assembly(filelist, outfile, logfile, polar='VV,VH,HH,HV'):
    '''A wrapper of SNAP's slice assembly routine

    This function assembles consecutive frames acquired at the same date.
    Can be either GRD or SLC products

    Args:
        filelist (str): a string of a space separated list of OST imported
                        Sentinel-1 product slices to be assembled
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
    '''

    print(' INFO: Assembling consecutive frames:')

    # get path to SNAP's command line executable gpt
    gpt_file = h.gpt_path()

    # construct command
    command = '{} SliceAssembly -x -q {} -PselectedPolarisations={} \
               -t \'{}\' {}'.format(gpt_file, 2 * os.cpu_count(), polar,
                                    outfile, filelist)

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        print(' INFO: Succesfully assembled products')
    else:
        print(' ERROR: Slice Assembly exited with an error. \
                See {} for Snap Error output'.format(logfile))
        sys.exit(101)
Beispiel #4
0
def _grd_speckle_filter(infile, outfile, logfile):
    '''A wrapper around SNAP's Lee-Sigma Speckle Filter

    This function takes OST imported Sentinel-1 product and applies
    a standardised version of the Lee-Sigma Speckle Filter with
    SNAP's defaut values.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
    '''

    # get path to SNAP's command line executable gpt
    gpt_file = h.gpt_path()

    print(' INFO: Applying the Lee-Sigma Speckle Filter')
    # contrcut command string
    command = '{} Speckle-Filter -x -q {} -PestimateENL=true \
              -t \'{}\' \'{}\''.format(gpt_file, 2 * os.cpu_count(), outfile,
                                       infile)

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # hadle errors and logs
    if return_code == 0:
        print(' INFO: Succesfully imported product')
    else:
        print(' ERROR: Speckle Filtering exited with an error. \
                See {} for Snap Error output'.format(logfile))
        sys.exit(111)
Beispiel #5
0
def _grd_to_db(infile, outfile, logfile):
    '''A wrapper around SNAP's linear to db routine

    This function takes an OST calibrated Sentinel-1 product
    and converts it to dB.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
    '''

    # get path to SNAP's command line executable gpt
    gpt_file = h.gpt_path()

    print(' INFO: Converting the image to dB-scale.')
    # construct command string
    command = '{} LinearToFromdB -x -q {} -t \'{}\' {}'.format(
        gpt_file, 2 * os.cpu_count(), outfile, infile)

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        print(' INFO: Succesfully converted product to dB-scale.')
    else:
        print(' ERROR: Linear to dB conversion exited with an error. \
                See {} for Snap Error output'.format(logfile))
        sys.exit(113)
Beispiel #6
0
def _grd_ls_mask(infile, outfile, logfile, resolution, dem_dict):
    '''A wrapper around SNAP's Layover/Shadow mask routine

    This function takes OST imported Sentinel-1 product and calculates
    the Layover/Shadow mask.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        resolution (int): the resolution of the output product in meters
        dem (str): A Snap compliant string for the dem to use.
                   Possible choices are:
                       'SRTM 1sec HGT' (default)
                       'SRTM 3sec'
                       'ASTER 1sec GDEM'
                       'ACE30'

    '''

    # get path to SNAP's command line executable gpt
    gpt_file = h.gpt_path()

    # get path to ost package
    rootpath = importlib.util.find_spec('ost').submodule_search_locations[0]

    print(' INFO: Creating the Layover/Shadow mask')
    # get path to workflow xml
    graph = opj(rootpath, 'graphs', 'S1_GRD2ARD', '3_LSmap.xml')

    # construct command string
    #    command = '{} {} -x -q {} -Pinput=\'{}\' -Presol={} -Pdem=\'{}\' \
    #             -Poutput=\'{}\''.format(gpt_file, graph, 2 * os.cpu_count(),
    #                                     infile, resolution, dem, outfile)
    command = ('{} {} -x -q {} -Pinput=\'{}\' -Presol={} '
               ' -Pdem=\'{}\''
               ' -Pdem_file=\'{}\''
               ' -Pdem_nodata=\'{}\''
               ' -Pdem_resampling=\'{}\''
               ' -Pimage_resampling=\'{}\''
               ' -Poutput=\'{}\''.format(
                   gpt_file, graph, 2 * os.cpu_count(), infile, resolution,
                   dem_dict['dem name'], dem_dict['dem file'],
                   dem_dict['dem nodata'], dem_dict['dem resampling'],
                   dem_dict['image resampling'], outfile))
    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        print(' INFO: Succesfully create a Layover/Shadow mask')
    else:
        print(' ERROR: Layover/Shadow mask creation exited with an error. \
                See {} for Snap Error output'.format(logfile))

    return return_code
Beispiel #7
0
def _coreg2(master, slave, outfile, logfile, dem_dict, ncores=os.cpu_count()):
    '''A wrapper around SNAP's back-geocoding co-registration routine

    This function takes a list of 2 OST imported Sentinel-1 SLC products
    and co-registers them properly. This routine is sufficient for coherence
    estimation, but not for InSAR, since the ESD refinement is not applied.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        dem (str): A Snap compliant string for the dem to use.
                   Possible choices are:
                       'SRTM 1sec HGT' (default)
                       'SRTM 3sec'
                       'ASTER 1sec GDEM'
                       'ACE30'
        ncores(int): the number of cpu cores to allocate to the gpt job - defaults to cpu count


    '''

    # get gpt file
    gpt_file = h.gpt_path()

    # get path to graph
    rootpath = importlib.util.find_spec('ost').submodule_search_locations[0]
    graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_Coreg.xml')

    # make dem file snap readable in case of no external dem
    if not dem_dict['dem file']:
        dem_dict['dem file'] = " "

    print(' INFO: Co-registering {} and {}'.format(master, slave))
    command = ('{} {} -x -q {} '
               ' -Pmaster={}'
               ' -Pslave={}'
               ' -Pdem=\'{}\''
               ' -Pdem_file=\'{}\''
               ' -Pdem_nodata=\'{}\''
               ' -Pdem_resampling=\'{}\''
               ' -Poutput={} '.format(gpt_file, graph, ncores, master, slave,
                                      dem_dict['dem name'],
                                      dem_dict['dem file'],
                                      dem_dict['dem nodata'],
                                      dem_dict['dem resampling'], outfile))

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        print(' INFO: Succesfully coregistered product.')
    else:
        print(' ERROR: Co-registration exited with an error. \
                See {} for Snap Error output'.format(logfile))

    return return_code
def ls_mask(infile, outfile, logfile, config_dict):
    """Wrapper function of a Snap graph for Layover/Shadow mask creation

    :param infile:
    :param outfile:
    :param logfile:
    :param config_dict:
    :return:
    """

    # get relevant config parameters
    ard = config_dict['processing']['single_ARD']
    dem_dict = ard['dem']
    cpus = config_dict['snap_cpu_parallelism']

    # auto projections of snap
    if 42001 <= dem_dict['out_projection'] <= 97002:
        projection = f"AUTO:{dem_dict['out_projection']}"
    # epsg codes
    else:
        projection = f"EPSG:{dem_dict['out_projection']}"

    logger.debug('Creating the Layover/Shadow mask')

    # get path to workflow xml
    graph = OST_ROOT.joinpath('graphs/S1_GRD2ARD/3_LSmap.xml')

    command = (
        f'{GPT_FILE} {graph} -x -q {2 * cpus} '
        f'-Pinput=\'{str(infile)}\' '
        f'-Presol={ard["resolution"]} '
        f'-Pdem=\'{dem_dict["dem_name"]}\' '
        f'-Pdem_file=\'{dem_dict["dem_file"]}\' '
        f'-Pdem_nodata=\'{dem_dict["dem_nodata"]}\' '
        f'-Pdem_resampling=\'{dem_dict["dem_resampling"]}\' '
        f'-Pimage_resampling=\'{dem_dict["image_resampling"]}\' '
        f'-Pegm_correction=\'{str(dem_dict["egm_correction"]).lower()}\' '
        f'-Pprojection=\'{projection}\' '
        f'-Poutput=\'{str(outfile)}\'')

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        logger.debug('Succesfully created a Layover/Shadow mask')
    else:
        raise GPTRuntimeError(
            f'Layover/Shadow mask creation exited with error {return_code}. '
            f'See {logfile} for Snap\'s error message.')

    # do check routine
    return_code = h.check_out_dimap(outfile, test_stats=False)
    if return_code == 0:
        return str(outfile.with_suffix('.dim'))
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_code}')
Beispiel #9
0
def _grd_terrain_correction_deg(infile,
                                outfile,
                                logfile,
                                resolution,
                                dem='SRTM 1Sec HGT'):
    '''A wrapper around SNAP's Terrain Correction routine

    This function takes an OST calibrated Sentinel-1 product and
    does the geocodification.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        resolution (int): the resolution of the output product in meters
        dem (str): A Snap compliant string for the dem to use.
                   Possible choices are:
                       'SRTM 1sec HGT' (default)
                       'SRTM 3sec'
                       'ASTER 1sec GDEM'
                       'ACE30'

    '''

    # get path to SNAP's command line executable gpt
    gpt_file = h.gpt_path()

    # get path to ost package
    rootpath = importlib.util.find_spec('ost').submodule_search_locations[0]
    print(' INFO: Geocoding the calibrated product')

    # calculate the multi-look factor
    # multilook_factor = int(int(resolution) / 10)
    multilook_factor = 1

    graph = opj(rootpath, 'graphs', 'S1_GRD2ARD', '3_ML_TC_deg.xml')

    # construct command string
    command = '{} {} -x -q {} -Pinput=\'{}\' -Presol={} -Pml={} -Pdem=\'{}\' \
                 -Poutput=\'{}\''.format(gpt_file, graph, 2 * os.cpu_count(),
                                         infile, resolution, multilook_factor,
                                         dem, outfile)

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        print(' INFO: Succesfully imported product')
    else:
        print(' ERROR: Terain Correction exited with an error. \
                See {} for Snap Error output'.format(logfile))

    return return_code
def create_stack(
    file_list,
    out_stack,
    logfile,
    config_dict,
    polarisation=None,
    pattern=None,
):
    """

    :param file_list:
    :param out_stack:
    :param logfile:
    :param config_dict:
    :param polarisation:
    :param pattern:
    :return:
    """

    # get relevant config parameters
    cpus = config_dict['snap_cpu_parallelism']

    logger.debug('Creating multi-temporal stack.')

    if pattern:
        graph = OST_ROOT.joinpath('graphs/S1_TS/1_BS_Stacking_HAalpha.xml')

        command = (f'{GPT_FILE} {graph} -x -q {2*cpus} '
                   f'-Pfilelist={file_list} '
                   f'-PbandPattern=\'{pattern}.*\' '
                   f'-Poutput={out_stack}')

    else:
        graph = OST_ROOT.joinpath('graphs/S1_TS/1_BS_Stacking.xml')

        command = (f'{GPT_FILE} {graph} -x -q {2*cpus} '
                   f'-Pfilelist={file_list} '
                   f'-Ppol={polarisation} '
                   f'-Poutput={out_stack}')

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        logger.debug('Successfully created multi-temporal stack')
    else:
        raise GPTRuntimeError(
            f'Multi-temporal stack creation exited with error {return_code}. '
            f'See {logfile} for Snap\'s error message.')

    # do check routine
    return_msg = h.check_out_dimap(out_stack)
    if return_msg == 0:
        logger.debug('Product passed validity check.')
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_msg}')
Beispiel #11
0
def _grd_frame_import_subset(infile,
                             outfile,
                             georegion,
                             logfile,
                             polarisation='VV,VH,HH,HV'):
    '''A wrapper of SNAP import of a subset of single Sentinel-1 GRD product

    This function takes an original Sentinel-1 scene (either zip or
    SAFE format), updates the orbit information (does not fail if not
    available), removes the thermal noise, subsets it to the given georegion
    and stores it as a SNAP
    compatible EAM-Dimap format.


    Args:
        infile: string or os.path object for
                an original Sentinel-1 GRD product in zip or SAFE format
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        polarisation (str): a string consisiting of the polarisation (comma separated)
                     e.g. 'VV,VH',
                     default value: 'VV,VH,HH,HV'
        georegion (str): a WKT style formatted POLYGON that bounds the
                         subset region
    '''

    print(' INFO: Importing {} by applying precise orbit file and'
          ' removing thermal noise, as well as subsetting.'.format(
              os.path.basename(infile)))

    # get path to SNAP's command line executable gpt
    gpt_file = h.gpt_path()

    # get path to ost package
    rootpath = importlib.util.find_spec('ost').submodule_search_locations[0]
    graph = opj(rootpath, 'graphs', 'S1_GRD2ARD', '1_AO_TNR_SUB.xml')

    # construct command
    command = '{} {} -x -q {} -Pinput=\'{}\' -Pregion=\'{}\' -Ppolarisation={} \
                      -Poutput=\'{}\''.format(gpt_file, graph,
                                              2 * os.cpu_count(), infile,
                                              georegion, polarisation, outfile)

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        print(' INFO: Succesfully imported product')
    else:
        print(' ERROR: Frame import exited with an error. \
                See {} for Snap Error output'.format(logfile))

    return return_code
Beispiel #12
0
def slice_assembly(filelist, outfile, logfile, config_dict):
    """Wrapper function around SNAP's slice assembly routine

    :param filelist: a string of a space separated list of OST imported
                     Sentinel-1 GRD product frames to be assembled
    :type filelist: str
    :param outfile:
    :param logfile:
    :param config_dict:
    :return:
    """
    '''A wrapper of SNAP's slice assembly routine

    This function assembles consecutive frames acquired at the same date.
    Can be either GRD or SLC products

    Args:
        filelist (str): a string of a space separated list of OST imported
                        Sentinel-1 product slices to be assembled
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
    '''

    # get relevant config parameters
    ard = config_dict['processing']['single_ARD']
    polars = ard['polarisation'].replace(' ', '')
    cpus = config_dict['snap_cpu_parallelism']

    logger.debug('Assembling consecutive frames:')

    # construct command
    command = (f'{GPT_FILE} SliceAssembly -x -q {2*cpus} '
               f'-PselectedPolarisations={polars} '
               f'-t \'{str(outfile)}\' {filelist}')

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        logger.debug('Succesfully assembled products')
    else:
        raise GPTRuntimeError(
            f'ERROR: Slice Assembly exited with error {return_code}. '
            f'See {logfile} for Snap Error output')

    # do check routine
    return_code = h.check_out_dimap(outfile)
    if return_code == 0:
        return str(outfile.with_suffix('.dim'))
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_code}')
Beispiel #13
0
def coreg(master, slave, outfile, logfile, config_dict):
    """A wrapper around SNAP's back-geocoding co-registration routine

    This function takes 2 OST imported Sentinel-1 SLC products
    (master and slave) and co-registers them properly.
    This routine is sufficient for coherence estimation,
    but not for InSAR, since the ESD refinement is not applied.

    :param master:
    :param slave:
    :param outfile:
    :param logfile:
    :param config_dict:
    :return:
    """

    # get relevant config parameters
    cpus = config_dict['snap_cpu_parallelism']
    dem_dict = config_dict['processing']['single_ARD']['dem']

    logger.debug(f'Co-registering {master} and {slave}')

    # construct command
    command = (
        f'{GPT_FILE} Back-Geocoding -x -q {2*cpus} '
        f'-PdemName=\'{dem_dict["dem_name"]}\' '
        #f'-PdemName=\'SRTM 3Sec\' '
        f'-PdemResamplingMethod=\'{dem_dict["dem_resampling"]}\' '
        f'-PexternalDEMFile=\'{dem_dict["dem_file"]}\' '
        f'-PexternalDEMNoDataValue=\'{dem_dict["dem_nodata"]}\' '
        f'-PmaskOutAreaWithoutElevation=false '
        f'-PresamplingType=BILINEAR_INTERPOLATION '
        f'-t \'{str(outfile)}\''
        f' "{master}" "{slave}"'
    )

    logger.debug(f'Executing command: {command}')
    return_code = h.run_command(command, logfile)

    if return_code == 0:
        logger.debug('Succesfully coregistered product.')
    else:
        raise GPTRuntimeError(
            f'Co-registration exited with an error {return_code}. '
            f'See {logfile} for Snap error output.'
        )

    # do check routine
    return_code = h.check_out_dimap(outfile)
    if return_code == 0:
        return str(outfile.with_suffix('.dim'))
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_code}'
        )
Beispiel #14
0
def _import(infile,
            out_prefix,
            logfile,
            swath,
            burst,
            polar='VV,VH,HH,HV',
            ncores=os.cpu_count()):
    '''A wrapper of SNAP import of a single Sentinel-1 SLC burst

    This function takes an original Sentinel-1 scene (either zip or
    SAFE format), updates the orbit information (does not fail if not
    available), and extracts a single burst based on the
    given input parameters.

    Args:
        infile: string or os.path object for
                an original Sentinel-1 GRD product in zip or SAFE format
        out_prefix: string or os.path object for the output
                    file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        swath (str): the corresponding IW subswath of the burst
        burst (str): the burst number as in the Sentinel-1 annotation file
        polar (str): a string consisiting of the polarisation (comma separated)
                     e.g. 'VV,VH',
                     default value: 'VV,VH,HH,HV'
        ncores(int): the number of cpu cores to allocate to the gpt job - defaults to cpu count
    '''

    # get gpt file
    gpt_file = h.gpt_path()

    # get path to graph
    rootpath = importlib.util.find_spec('ost').submodule_search_locations[0]
    graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_BurstSplit_AO.xml')

    print(' INFO: Importing Burst {} from Swath {}'
          ' from scene {}'.format(burst, swath, os.path.basename(infile)))

    command = '{} {} -x -q {} -Pinput={} -Ppolar={} -Pswath={}\
                      -Pburst={} -Poutput={}' \
        .format(gpt_file, graph, ncores, infile, polar, swath,
                burst, out_prefix)

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        print(' INFO: Succesfully imported product')
    else:
        print(' ERROR: Frame import exited with an error. \
                See {} for Snap Error output'.format(logfile))
        # sys.exit(119)

    return return_code
Beispiel #15
0
def coreg2(master, slave, outfile, logfile, config_dict):
    """A wrapper around SNAP's back-geocoding co-registration routine

    This function takes 2 OST imported Sentinel-1 SLC products
    (master and slave) and co-registers them properly.
    This routine is sufficient for coherence estimation,
    but not for InSAR, since the ESD refinement is not applied.

    :param master:
    :param slave:
    :param outfile:
    :param logfile:
    :param config_dict:
    :return:
    """

    # get relevant config parameters
    cpus = config_dict['snap_cpu_parallelism']
    dem_dict = config_dict['processing']['single_ARD']['dem']

    # get path to graph
    graph = OST_ROOT.joinpath('graphs/S1_SLC2ARD/S1_SLC_Coreg.xml')

    logger.debug(f'Co-registering {master} and {slave}')
    command = (
        f"{GPT_FILE} {graph} -x -q {2*cpus} "
        f" -Pmaster={master} "
        f" -Pslave={slave} "
        f" -Pdem_name=\'{dem_dict['dem_name']}\' "
        f" -Pdem_file=\'{dem_dict['dem_file']}\' "
        f" -Pdem_nodata=\'{dem_dict['dem_nodata']}\' "
        f" -Pdem_resampling=\'{dem_dict['dem_resampling']}\' "
        f" -Poutput={str(outfile)}"
    )

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        logger.debug('Successfully co-registered product.')
    else:
        raise GPTRuntimeError(
            f'Co-registration exited with an error {return_code}. '
            f'See {logfile} for Snap\'s error message.'
        )

    # do check routine
    return_code = h.check_out_dimap(outfile)
    if return_code == 0:
        return str(outfile.with_suffix('.dim'))
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_code}'
        )
def speckle_filter(infile, outfile, logfile, config_dict):
    """Wrapper function around SNAP's Speckle Filter function

    This function takes OST imported Sentinel-1 product and applies
    the Speckle Filter as defind within the config dictionary.

    :param infile:
    :param outfile:
    :param logfile:
    :param config_dict:
    :return:
    """

    # get relevant config parameters
    cpus = config_dict['snap_cpu_parallelism']
    speckle_dict = config_dict['processing']['single_ARD']['speckle_filter']

    logger.debug('Applying speckle filtering.')

    # construct command string
    command = (
        f"{GPT_FILE} Speckle-Filter -x -q {2*cpus} "
        f"-PestimateENL=\'{speckle_dict['estimate_ENL']}\' "
        f"-PanSize=\'{speckle_dict['pan_size']}\' "
        f"-PdampingFactor=\'{speckle_dict['damping']}\' "
        f"-Penl=\'{speckle_dict['ENL']}\' "
        f"-Pfilter=\'{speckle_dict['filter']}\' "
        f"-PfilterSizeX=\'{speckle_dict['filter_x_size']}\' "
        f"-PfilterSizeY=\'{speckle_dict['filter_y_size']}\' "
        f"-PnumLooksStr=\'{speckle_dict['num_of_looks']}\' "
        f"-PsigmaStr=\'{speckle_dict['sigma']}\' "
        f"-PtargetWindowSizeStr=\"{speckle_dict['target_window_size']}\" "
        f"-PwindowSize=\"{speckle_dict['window_size']}\" "
        f"-t \'{str(outfile)}\' \'{str(infile)}\' ")

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        logger.debug('Successfully applied speckle filtering.')
    else:
        raise GPTRuntimeError(
            f'Speckle filtering exited with error {return_code}. '
            f'See {logfile} for Snap\'s error message.')

    # do check routine
    return_code = h.check_out_dimap(outfile)
    if return_code == 0:
        return str(outfile.with_suffix('.dim'))
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_code}')
Beispiel #17
0
def calibration(infile, outfile, logfile, config_dict):
    """

    :param infile:
    :param outfile:
    :param logfile:
    :param config_dict:
    :return:
    """

    # get relevant config parameters
    product_type = config_dict['processing']['single_ARD']['product_type']
    cpus = config_dict['snap_cpu_parallelism']

    # transform calibration parameter to snap readable
    sigma0, beta0, gamma0 = 'false', 'false', 'false'

    if product_type == 'GTC-sigma0':
        sigma0 = 'true'
    elif product_type == 'GTC-gamma0':
        gamma0 = 'true'
    elif product_type == 'RTC-gamma0':
        beta0 = 'true'
    else:
        raise TypeError('Wrong product type selected.')

    logger.debug(f'Calibrating the product to {product_type}.')

    # construct command string
    command = (f'{GPT_FILE} Calibration -x -q {2*cpus} '
               f' -PoutputBetaBand=\'{beta0}\' '
               f' -PoutputGammaBand=\'{gamma0}\' '
               f' -PoutputSigmaBand=\'{sigma0}\' '
               f' -t \'{str(outfile)}\' \'{str(infile)}\'')

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        logger.debug(f'Calibration to {product_type} successful.')
    else:
        raise GPTRuntimeError(f'Calibration exited with error {return_code}. '
                              f'See {logfile} for Snap\'s error message.')

    # do check routine
    return_code = h.check_out_dimap(outfile)
    if return_code == 0:
        return str(outfile.with_suffix('.dim'))
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_code}')
Beispiel #18
0
def _terrain_correction(infile, outfile, logfile, resolution, dem_dict):
    '''A wrapper around SNAP's Terrain Correction routine

    This function takes an OST calibrated Sentinel-1 product and
    does the geocodification.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        resolution (int): the resolution of the output product in meters
        dem (str): A Snap compliant string for the dem to use.
                   Possible choices are:
                       'SRTM 1sec HGT' (default)
                       'SRTM 3sec'
                       'ASTER 1sec GDEM'
                       'ACE30'

    '''

    # get gpt file
    gpt_file = h.gpt_path()

    print(" INFO: Geocoding input scene")

    command = ('{} Terrain-Correction -x -q {}'
               ' -PdemName=\'{}\''
               ' -PexternalDEMFile=\'{}\''
               ' -PexternalDEMNoDataValue=\'{}\''
               ' -PdemResamplingMethod=\'{}\''
               ' -PimgResamplingMethod=\'{}\''
               ' -PnodataValueAtSea=\'false\''
               ' -PpixelSpacingInMeter=\'{}\''
               ' -t {} {}'.format(gpt_file, 2 * os.cpu_count(),
                                  dem_dict['dem name'], dem_dict['dem file'],
                                  dem_dict['dem nodata'],
                                  dem_dict['dem resampling'],
                                  dem_dict['image resampling'], resolution,
                                  outfile, infile))

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        print(' INFO: Succesfully orthorectified product.')
    else:
        print(' ERROR: Geocoding exited with an error. \
                See {} for Snap Error output'.format(logfile))

    return return_code
Beispiel #19
0
def _terrain_correction_deg(infile,
                            outfile,
                            logfile,
                            resolution=0.001,
                            dem='SRTM 1sec HGT'):
    '''A wrapper around SNAP's Terrain Correction routine

    This function takes an OST calibrated Sentinel-1 product and
    does the geocodification.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        resolution (int): the resolution of the output product in degree
        dem (str): A Snap compliant string for the dem to use.
                   Possible choices are:
                       'SRTM 1sec HGT' (default)
                       'SRTM 3sec'
                       'ASTER 1sec GDEM'
                       'ACE30'

    '''

    # get gpt file
    gpt_file = h.gpt_path()

    print(" INFO: Geocoding input scene")
    command = '{} Terrain-Correction -x -q {} \
              -PdemResamplingMethod=\'BILINEAR_INTERPOLATION\' \
              -PimgResamplingMethod=\'BILINEAR_INTERPOLATION\' \
              -PnodataValueAtSea=\'false\' \
              -PpixelSpacingInDegree=\'{}\' \
              -PdemName=\'{}\' \
              -t {} {}' \
              .format(gpt_file, 2 * os.cpu_count(), resolution, dem,
                      outfile, infile)

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        print(' INFO: Succesfully imported product')
    else:
        print(' ERROR: Geocoding exited with an error. \
                See {} for Snap Error output'.format(logfile))
        # sys.exit(122)

    return return_code
Beispiel #20
0
def coherence(infile, outfile, logfile, config_dict):
    """A wrapper around SNAP's coherence routine

    This function takes a co-registered stack of 2 Sentinel-1 SLC products
    and calculates the coherence.

    :param infile:
    :param outfile:
    :param logfile:
    :param config_dict:
    :return:
    """

    # get relevant config parameters
    ard = config_dict['processing']['single_ARD']
    polars = ard['coherence_bands'].replace(' ', '')
    cpus = config_dict['snap_cpu_parallelism']

    # get path to graph
    graph = OST_ROOT.joinpath('graphs/S1_SLC2ARD/S1_SLC_Coh_Deb.xml')

    logger.debug('Coherence estimation')

    command = (
        f"{GPT_FILE} {graph} -x -q {2 * cpus} "
        f"-Pazimuth_window={ard['coherence_azimuth']} "
        f"-Prange_window={ard['coherence_range']} "
        f'-Ppolar=\'{polars}\' '
        f'-Pinput="{str(infile)}" '
        f'-Poutput="{str(outfile)}"'
    )

    logger.debug(f'Executing command: {command}')
    return_code = h.run_command(command, logfile)

    if return_code == 0:
        logger.debug('Succesfully created coherence product.')
    else:
        raise GPTRuntimeError(
            f'Coherence exited with an error {return_code}. '
            f'See {logfile} for Snap\'s error message.'
        )

    # do check routine
    return_code = h.check_out_dimap(outfile)
    if return_code == 0:
        return str(outfile.with_suffix('.dim'))
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_code}'
        )
Beispiel #21
0
def mt_speckle_filter(in_stack,
                      out_stack,
                      logfile,
                      speckle_dict,
                      ncores=os.cpu_count()):
    '''
    '''

    # get gpt file
    gpt_file = h.gpt_path()

    #    # get path to graph
    #    rootpath = importlib.util.find_spec('ost').submodule_search_locations[0]
    #    graph = opj(rootpath, 'graphs', 'S1_TS', '2_MT_Speckle.xml')
    #
    #    command = '{} {} -x -q {} -Pinput={} \
    #                   -Poutput={}'.format(gpt_file, graph, 2 * os.cpu_count(),
    #                                       in_stack, out_stack)

    print(' INFO: Applying multi-temporal speckle filtering.')
    # contrcut command string
    command = ('{} Multi-Temporal-Speckle-Filter -x -q {}'
               ' -PestimateENL={}'
               ' -PanSize={}'
               ' -PdampingFactor={}'
               ' -Penl={}'
               ' -Pfilter=\'{}\''
               ' -PfilterSizeX={}'
               ' -PfilterSizeY={}'
               ' -PnumLooksStr={}'
               ' -PsigmaStr={}'
               ' -PtargetWindowSizeStr={}'
               ' -PwindowSize={}'
               ' -t \'{}\' \'{}\''.format(
                   gpt_file, ncores, speckle_dict['estimate ENL'],
                   speckle_dict['pan size'], speckle_dict['damping'],
                   speckle_dict['ENL'], speckle_dict['filter'],
                   speckle_dict['filter x size'],
                   speckle_dict['filter y size'], speckle_dict['num of looks'],
                   speckle_dict['sigma'], speckle_dict['target window size'],
                   speckle_dict['window size'], out_stack, in_stack))

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        print(' INFO: Successfully applied multi-temporal speckle filtering')
    else:
        print(' ERROR: Multi-temporal speckle filtering exited with an error. \
                See {} for Snap Error output'.format(logfile))

    return return_code
def mt_speckle_filter(in_stack, out_stack, logfile, config_dict):
    """

    :param in_stack:
    :param out_stack:
    :param logfile:
    :param config_dict:
    :return:
    """

    # get relevant config parameters
    cpus = config_dict['snap_cpu_parallelism']
    speckle_dict = (
        config_dict['processing']['time-series_ARD']['mt_speckle_filter'])

    # debug message
    logger.debug('Applying multi-temporal speckle filtering.')

    # construct command string
    command = (
        f"{GPT_FILE} Multi-Temporal-Speckle-Filter -x -q {2*cpus} "
        f"-PestimateENL=\'{speckle_dict['estimate_ENL']}\' "
        f"-PanSize=\'{speckle_dict['pan_size']}\' "
        f"-PdampingFactor=\'{speckle_dict['damping']}\' "
        f"-Penl=\'{speckle_dict['ENL']}\' "
        f"-Pfilter=\'{speckle_dict['filter']}\' "
        f"-PfilterSizeX=\'{speckle_dict['filter_x_size']}\' "
        f"-PfilterSizeY=\'{speckle_dict['filter_y_size']}\' "
        f"-PnumLooksStr=\'{speckle_dict['num_of_looks']}\' "
        f"-PsigmaStr=\'{speckle_dict['sigma']}\' "
        f"-PtargetWindowSizeStr=\"{speckle_dict['target_window_size']}\" "
        f"-PwindowSize=\"{speckle_dict['window_size']}\" "
        f"-t \'{out_stack}\' \'{in_stack}\' ")

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        logger.debug('Successfully applied multi-temporal speckle filtering')
    else:
        raise GPTRuntimeError(
            f'Multi-temporal Spackle Filter exited with error {return_code}. '
            f'See {logfile} for Snap\'s error message.')

    # do check routine
    return_code = h.check_out_dimap(out_stack)
    if return_code == 0:
        return str(out_stack.with_suffix('.dim'))
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_code}')
Beispiel #23
0
def grd_subset_georegion(infile, outfile, logfile, config_dict):
    """Wrapper function around SNAP's subset routine

    This function takes an OST imported/slice assembled frame and
    subsets it according to the coordinates given in the region

    :param infile:
    :param outfile:
    :param logfile:
    :param config_dict:
    :return:
    """

    # get relevant config parameters
    cpus = config_dict['snap_cpu_parallelism']

    try:
        aoi = config_dict['aoi']
    except KeyError:
        aoi = ''

    logger.debug('Subsetting imported imagery.')

    # extract window from scene
    command = (f'{GPT_FILE} Subset -x -q {2*cpus} '
               f'-PcopyMetadata=true '
               f'-PgeoRegion=\'{aoi}\' '
               f'-Ssource=\'{str(infile)}\' '
               f'-t \'{str(outfile)}\'')

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        logger.debug('Succesfully subsetted product.')
    else:
        raise GPTRuntimeError(f'Subsetting exited with error {return_code}. '
                              f'See {logfile} for Snap\'s error message.')

    # do check routine
    return_code = h.check_out_dimap(outfile)
    if return_code == 0:
        return str(outfile.with_suffix('.dim'))
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_code}')
Beispiel #24
0
def _grd_frame_import(infile, outfile, logfile, polar='VV,VH,HH,HV'):
    '''A wrapper of SNAP import of a single Sentinel-1 GRD product

    This function takes an original Sentinel-1 scene (either zip or
    SAFE format), updates the orbit information (does not fail if not
    available), removes the thermal noise and stores it as a SNAP
    compatible BEAM-Dimap format.

    Args:
        infile: string or os.path object for
                an original Sentinel-1 GRD product in zip or SAFE format
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        polar (str): a string consisiting of the polarisation (comma separated)
                     e.g. 'VV,VH',
                     default value: 'VV,VH,HH,HV'
    '''

    print(' INFO: Importing {} by applying precise orbit file and'
          ' removing thermal noise'.format(os.path.basename(infile)))

    # get path to SNAP's command line executable gpt
    gpt_file = h.gpt_path()

    # get path to ost package
    root_path = imp.find_module('ost')[1]
    graph = opj(root_path, 'graphs', 'S1_GRD2ARD', '1_AO_TNR.xml')

    # construct command
    command = '{} {} -x -q {} -Pinput=\'{}\' -Ppolar={} \
               -Poutput=\'{}\''.format(gpt_file, graph, os.cpu_count(), infile,
                                       polar, outfile)

    # run command
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        print(' INFO: Succesfully imported product')
    else:
        print(' ERROR: Frame import exited with an error. \
                See {} for Snap Error output'.format(logfile))
        sys.exit(102)
Beispiel #25
0
def _ls_mask(infile, outfile, logfile, resolution, dem='SRTM 1sec HGT'):
    '''A wrapper around SNAP's Layover/Shadow mask routine

    This function takes OST imported Sentinel-1 product and calculates
    the Layover/Shadow mask.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        resolution (int): the resolution of the output product in meters
        dem (str): A Snap compliant string for the dem to use.
                   Possible choices are:
                       'SRTM 1sec HGT' (default)
                       'SRTM 3sec'
                       'ASTER 1sec GDEM'
                       'ACE30'

    '''

    # get gpt file
    gpt_file = h.gpt_path()

    # get path to graph
    rootpath = imp.find_module('ost')[1]
    graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_LS_TC.xml')

    print(" INFO: Compute Layover/Shadow mask")
    command = '{} {} -x -q {} -Pinput={} -Presol={} -Poutput={} -Pdem=\'{}\'' \
        .format(gpt_file, graph, 2 * os.cpu_count(), infile, resolution,
                outfile, dem)

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        print(' INFO: Succesfully created Layover/Shadow mask')
    else:
        print(' ERROR: Layover/Shadow mask creation exited with an error. \
                See {} for Snap Error output'.format(logfile))
        # sys.exit(121)

    return return_code
Beispiel #26
0
def _coreg2(master, slave, outfile, logfile, dem='SRTM 1sec HGT'):
    '''A wrapper around SNAP's back-geocoding co-registration routine

    This function takes a list of 2 OST imported Sentinel-1 SLC products
    and co-registers them properly. This routine is sufficient for coherence
    estimation, but not for InSAR, since the ESD refinement is not applied.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        dem (str): A Snap compliant string for the dem to use.
                   Possible choices are:
                       'SRTM 1sec HGT' (default)
                       'SRTM 3sec'
                       'ASTER 1sec GDEM'
                       'ACE30'

    '''

    # get gpt file
    gpt_file = h.gpt_path()

    # get path to graph
    rootpath = imp.find_module('ost')[1]
    graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_Coreg.xml')

    print(' INFO: Co-registering {} and {}'.format(master, slave))
    command = '{} {} -x -q {} -Pmaster={} -Pslave={} -Poutput={} -Pdem=\'{}\''\
        .format(gpt_file, graph, 2 * os.cpu_count(), master, slave,
                outfile, dem)

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        print(' INFO: Succesfully coregistered product')
    else:
        print(' ERROR: Co-registration exited with an error. \
                See {} for Snap Error output'.format(logfile))
        # sys.exit(112)

    return return_code
Beispiel #27
0
def _ha_alpha(infile, outfile, logfile, pol_speckle_filter=False):
    '''A wrapper of SNAP H-A-alpha polarimetric decomposition

    This function takes an OST imported Sentinel-1 scene/burst
    and calulates the polarimetric decomposition parameters for
    the H-A-alpha decomposition.

    Args:
        infile: string or os.path object for
                an original Sentinel-1 GRD product in zip or SAFE format
        out_prefix: string or os.path object for the output
                    file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        pol_speckle_filter (bool): wether or not to apply the
                                   polarimetric speckle filter

    '''

    # get gpt file
    gpt_file = h.gpt_path()

    # get path to graph
    rootpath = importlib.util.find_spec('ost').submodule_search_locations[0]

    if pol_speckle_filter:
        graph = opj(rootpath, 'graphs', 'S1_SLC2ARD',
                    'S1_SLC_Deb_Spk_Halpha.xml')
    else:
        graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_Deb_Halpha.xml')

    print(" INFO: Calculating the H-alpha dual polarisation")
    command = '{} {} -x -q {} -Pinput={} -Poutput={}' \
        .format(gpt_file, graph, 2 * os.cpu_count(), infile, outfile)

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        print(' INFO: Succesfully created H/Alpha product')
    else:
        print(' ERROR: H/Alpha exited with an error. \
                See {} for Snap Error output'.format(logfile))
        # sys.exit(121)

    return return_code
Beispiel #28
0
def _terrain_flattening(infile, outfile, logfile, dem_dict):
    '''A wrapper around SNAP's terrain flattening

    This function takes OST calibrated Sentinel-1 SLC product and applies
    the terrain flattening to correct for radiometric distortions along slopes

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to

    '''

    # get gpt file
    gpt_file = h.gpt_path()

    print(' INFO: Correcting for the illumination along slopes'
          ' (Terrain Flattening).')

    command = ('{} Terrain-Flattening -x -q {} '
               ' -PadditionalOverlap=0.15'
               ' -PoversamplingMultiple=1.5'
               ' -PdemName=\'{}\''
               ' -PexternalDEMFile=\'{}\''
               ' -PexternalDEMNoDataValue=\'{}\''
               ' -PdemResamplingMethod=\'{}\''
               ' -t {} {}'.format(gpt_file, 2 * os.cpu_count(),
                                  dem_dict['dem name'], dem_dict['dem file'],
                                  dem_dict['dem nodata'],
                                  dem_dict['dem resampling'], outfile, infile))

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        print(' INFO: Succesfully applied the terrain flattening.')
    else:
        print(' ERROR: Terrain Flattening exited with an error.'
              ' See {} for Snap Error output'.format(logfile))

    return return_code
Beispiel #29
0
def _coherence(infile,
               outfile,
               logfile,
               polar='VV,VH,HH,HV',
               ncores=os.cpu_count()):
    '''A wrapper around SNAP's coherence routine

    This function takes a co-registered stack of 2 Sentinel-1 SLC products
    and calculates the coherence.

    Args:
        infile: string or os.path object for
                an OST imported frame in BEAM-Dimap format (i.e. *.dim)
        outfile: string or os.path object for the output
                 file written in BEAM-Dimap format
        logfile: string or os.path object for the file
                 where SNAP'S STDOUT/STDERR is written to
        ncores(int): the number of cpu cores to allocate to the gpt job - defaults to cpu count


    '''

    # get gpt file
    gpt_file = h.gpt_path()

    # get path to graph
    rootpath = importlib.util.find_spec('ost').submodule_search_locations[0]
    graph = opj(rootpath, 'graphs', 'S1_SLC2ARD', 'S1_SLC_Coh_Deb.xml')

    print(' INFO: Coherence estimation')
    command = '{} {} -x -q {} -Pinput={} -Ppolar=\'{}\' -Poutput={}' \
        .format(gpt_file, graph, ncores, infile, polar, outfile)

    return_code = h.run_command(command, logfile)

    if return_code == 0:
        print(' INFO: Succesfully created coherence product.')
    else:
        print(' ERROR: Coherence exited with an error. \
                See {} for Snap Error output'.format(logfile))

    return return_code
def terrain_flattening(infile, outfile, logfile, config_dict):
    """Wrapper function to Snap's Terrain Flattening routine

    :param infile:
    :param outfile:
    :param logfile:
    :param config_dict:
    :return:
    """

    # get relevant config parameters
    cpus = config_dict['snap_cpu_parallelism']
    dem_dict = config_dict['processing']['single_ARD']['dem']

    logger.debug('Applying terrain flattening to calibrated product.')

    command = (f"{GPT_FILE} Terrain-Flattening -x -q {2*cpus} "
               f"-PdemName=\'{dem_dict['dem_name']}\' "
               f"-PdemResamplingMethod=\'{dem_dict['dem_resampling']}\' "
               f"-PexternalDEMFile=\'{dem_dict['dem_file']}\' "
               f"-PexternalDEMNoDataValue={dem_dict['dem_nodata']} "
               f"-t \'{str(outfile)}\' \'{str(infile)}\'")

    # run command and get return code
    return_code = h.run_command(command, logfile)

    # handle errors and logs
    if return_code == 0:
        logger.debug('Succesfully terrain flattened product')
    else:
        raise GPTRuntimeError(
            f'Terrain Flattening exited with error {return_code}. '
            f'See {logfile} for Snap\'s error message.')

    # do check routine
    return_code = h.check_out_dimap(outfile)
    if return_code == 0:
        return str(outfile.with_suffix('.dim'))
    else:
        raise NotValidFileError(
            f'Product did not pass file check: {return_code}')