Skip to content

sarlo.isce

Routines for interacting with the isce library

ALOS1_processing

Downloads and writes files necessary for ISCE Stripmap processing

Attributes:

Name Type Description
self.sensor

ALOS1 PALSAR

self.file1

raw file to be downloaded

self.file2

secondary raw file to be downloaded

self.date1

acquisition date of raw reference

self.date2

acquisition date of raw secondary

self.azimuth_lks

number of azimuth looks (default 2)

self.range_lks

number of range looks (default 10)

self.bounds

bounds for processing Stripmap

Source code in sarlo/isce.py
class ALOS1_processing(object):
    """Downloads and writes files necessary for ISCE Stripmap processing

    Attributes:
        self.sensor: ALOS1 PALSAR
        self.file1: raw file to be downloaded
        self.file2: secondary raw file to be downloaded
        self.date1: acquisition date of raw reference
        self.date2: acquisition date of raw secondary
        self.azimuth_lks: number of azimuth looks (default 2)
        self.range_lks: number of range looks (default 10)
        self.bounds: bounds for processing Stripmap
    """

    def __init__(
        self,
        file1: str,
        file2: str,
        azimuth_lks: int = 2,
        range_lks: int = 10,
        lonMin: int = None,
        lonMax: int = None,
        latMin: int = None,
        latMax: int = None,
    ):
        self.sensor = "ALOS1 PALSAR"
        self.file1 = file1
        self.date1 = None
        self.file2 = file2
        self.date2 = None
        self.azimuth_lks = azimuth_lks
        self.range_lks = range_lks
        self.bounds = [lonMin, lonMax, latMin, latMax]

    def configure_inputs(outDir: str, self):
        """Write Configuration files for ISCE2 stripmapApp to process NISAR sample products"""
        cmd_reference_config = """<component>
            <property name="IMAGEFILE">
            <value>[data/{0}/{1}/IMG-HH-{2}-H1.0__A]</value>
            </property>
            <property name="LEADERFILE">
                <value>[data/{0}/{1}/LED-{2}-H1.0__A]</value>
            </property>
            <property name="OUTPUT">
                <value>{0}</value>
            </property>
        </component>""".format(
            self.date1, self.file1, self.file1[:-5]
        )

        print("writing reference.xml")
        with open(os.path.join(outDir, "reference.xml"), "w") as fid:
            fid.write(cmd_reference_config)

        cmd_secondary_config = """<component>
            <property name="IMAGEFILE">
                <value>[data/{0}/{1}/IMG-HH-{2}-H1.0__A]</value>
            </property>
            <property name="LEADERFILE">
                <value>[data/{0}/{1}/LED-{2}-H1.0__A]</value>
            </property>
            <property name="OUTPUT">
                <value>{0}</value>
            </property>
        </component>""".format(
            self.date2, self.file2, self.file2[:-5]
        )

        print("writing secondary.xml")
        with open(os.path.join(outDir, "secondary.xml"), "w") as fid:
            fid.write(cmd_secondary_config)

        cmd_stripmap_config = """<?xml version="1.0" encoding="UTF-8"?>
            <stripmapApp>
            <component name="insar">
                <property name="sensor name">ALOS</property>
                <component name="reference">
                    <catalog>reference.xml</catalog>
                </component>
                <component name="secondary">
                    <catalog>secondary.xml</catalog>
                </component>
                <property name="do rubbersheetingAzimuth">True</property>
                <property name="do rubbersheetingRange">True</property>
                <property name="do denseoffsets">True</property>
            </component>
            </stripmapApp>"""

        print("writing stripmapApp.xml")
        with open(os.path.join(outDir, "stripmapApp.xml"), "w") as fid:
            fid.write(cmd_stripmap_config)

    def download_ALOS_raw(self, user: str = "", password: str = ""):
        """Download ALOS PALSAR Raw imagery from ASF

        Args:
            self.user: username for ASF download
            self.password: password for ASF download

        Return:
            None. Downloads and formats two ALOS PALSAR raw files for interferometric computing
        """
        self.user = user
        self.password = password

        home_dir = os.path.join(os.getenv("HOME"), "work")
        process_dir = os.path.join(home_dir, "Tahoe_{0}").format(self.sensor)
        data_dir = os.path.join(process_dir, "data")

        # If ASF USER/PWD is not provided read it from the .netrc file
        if (len(self.password) == 0 | len(self.user) == 0) & (
            os.path.exists(os.path.join(os.getenv("HOME"), ".netrc"))
        ):
            netrc_path = os.path.join(os.getenv("HOME"), ".netrc")
            count = len(open(netrc_path).readlines())
            if count == 1:
                file = open(os.path.join(os.getenv("HOME"), ".netrc"), "r")
                contents = file.read().split(" ")
                self.user = contents[3]
                self.password = contents[5]
                file.close()
            else:
                self.user = np.loadtxt(
                    os.path.join(os.getenv("HOME"), ".netrc"),
                    skiprows=1,
                    usecols=1,
                    dtype=str,
                )[0]
                self.password = np.loadtxt(
                    os.path.join(os.getenv("HOME"), ".netrc"),
                    skiprows=1,
                    usecols=1,
                    dtype=str,
                )[1]

        if (len(self.password) == 0 | len(self.user) == 0) & (
            not os.path.exists(os.path.join(os.getenv("HOME"), ".netrc"))
        ):
            print(
                "WARNING: The ASF User and Password needs to be included in ~/.netrc file."
            )
            print(" The ~/.netrc file does not exist or has not been setup properly")
            sys.exit("System Exiting until ~/.netrc file setup properly")

        # Now lets check if processing and data directories exist
        # If they do not we will make the directories

        if os.path.exists(process_dir) is False:
            print("create ", process_dir)
            os.makedirs(process_dir)
        else:
            print(process_dir, " exists")

        if os.path.exists(data_dir) is False:
            print("create ", data_dir)
            os.makedirs(data_dir)
        else:
            print(data_dir, " exists")

        os.chdir(data_dir)
        # Now lets download the data to the data directory
        if len(self.file1) == 0 | len(self.file2) == 0:
            sys.exit("Data links do not exist")
        else:
            cmd1 = ("wget  %s --user {0} --password {1}" % self.file1).format(
                self.user, self.password
            )
            zip1 = os.path.basename(os.path.normpath(self.file1))
            # isolating initial zip file
            if not os.path.exists(os.path.join(data_dir, zip1)):
                os.system(cmd1)
                os.system("unzip  %s" % zip1)
            else:
                print(zip1, " already exists")

            cmd2 = ("wget  %s --user {0} --password {1}" % self.file2).format(
                self.user, self.password
            )
            zip2 = os.path.basename(
                os.path.normpath(self.file2)
            )  # isolating initial zip file
            if not os.path.exists(os.path.join(data_dir, zip2)):
                os.system(cmd2)
                os.system("unzip  %s" % zip2)
            else:
                print(zip2, " already exists")

            SCDT1 = "{0}/{1}".format(zip1[:-4], "%s.l0.workreport" % zip1[:-9])
            with open(SCDT1, "r") as myfile:
                data = myfile.readlines()
                self.date1 = data[6]
                self.date1 = self.date1[38:46]
            print(self.date1)

            SCDT2 = "{0}/{1}".format(zip2[:-4], "%s.l0.workreport" % zip2[:-9])
            with open(SCDT2, "r") as myfile:
                data = myfile.readlines()
                self.date2 = data[6]
                self.date2 = self.date2[38:46]
            print(self.date2)
            if not os.path.exists(os.path.join(data_dir, self.date1)):
                os.mkdir(self.date1)
            if not os.path.exists(os.path.join(data_dir, self.date2)):
                os.mkdir(self.date2)

            os.system("mv {0} {1}".format(zip1[:-4], self.date1))
            os.system("mv {0} {1}".format(zip2[:-4], self.date2))

configure_inputs(outDir, self)

Write Configuration files for ISCE2 stripmapApp to process NISAR sample products

Source code in sarlo/isce.py
def configure_inputs(outDir: str, self):
    """Write Configuration files for ISCE2 stripmapApp to process NISAR sample products"""
    cmd_reference_config = """<component>
        <property name="IMAGEFILE">
        <value>[data/{0}/{1}/IMG-HH-{2}-H1.0__A]</value>
        </property>
        <property name="LEADERFILE">
            <value>[data/{0}/{1}/LED-{2}-H1.0__A]</value>
        </property>
        <property name="OUTPUT">
            <value>{0}</value>
        </property>
    </component>""".format(
        self.date1, self.file1, self.file1[:-5]
    )

    print("writing reference.xml")
    with open(os.path.join(outDir, "reference.xml"), "w") as fid:
        fid.write(cmd_reference_config)

    cmd_secondary_config = """<component>
        <property name="IMAGEFILE">
            <value>[data/{0}/{1}/IMG-HH-{2}-H1.0__A]</value>
        </property>
        <property name="LEADERFILE">
            <value>[data/{0}/{1}/LED-{2}-H1.0__A]</value>
        </property>
        <property name="OUTPUT">
            <value>{0}</value>
        </property>
    </component>""".format(
        self.date2, self.file2, self.file2[:-5]
    )

    print("writing secondary.xml")
    with open(os.path.join(outDir, "secondary.xml"), "w") as fid:
        fid.write(cmd_secondary_config)

    cmd_stripmap_config = """<?xml version="1.0" encoding="UTF-8"?>
        <stripmapApp>
        <component name="insar">
            <property name="sensor name">ALOS</property>
            <component name="reference">
                <catalog>reference.xml</catalog>
            </component>
            <component name="secondary">
                <catalog>secondary.xml</catalog>
            </component>
            <property name="do rubbersheetingAzimuth">True</property>
            <property name="do rubbersheetingRange">True</property>
            <property name="do denseoffsets">True</property>
        </component>
        </stripmapApp>"""

    print("writing stripmapApp.xml")
    with open(os.path.join(outDir, "stripmapApp.xml"), "w") as fid:
        fid.write(cmd_stripmap_config)

download_ALOS_raw(self, user='', password='')

Download ALOS PALSAR Raw imagery from ASF

Parameters:

Name Type Description Default
self.user

username for ASF download

required
self.password

password for ASF download

required

Returns:

Type Description

None. Downloads and formats two ALOS PALSAR raw files for interferometric computing

Source code in sarlo/isce.py
def download_ALOS_raw(self, user: str = "", password: str = ""):
    """Download ALOS PALSAR Raw imagery from ASF

    Args:
        self.user: username for ASF download
        self.password: password for ASF download

    Return:
        None. Downloads and formats two ALOS PALSAR raw files for interferometric computing
    """
    self.user = user
    self.password = password

    home_dir = os.path.join(os.getenv("HOME"), "work")
    process_dir = os.path.join(home_dir, "Tahoe_{0}").format(self.sensor)
    data_dir = os.path.join(process_dir, "data")

    # If ASF USER/PWD is not provided read it from the .netrc file
    if (len(self.password) == 0 | len(self.user) == 0) & (
        os.path.exists(os.path.join(os.getenv("HOME"), ".netrc"))
    ):
        netrc_path = os.path.join(os.getenv("HOME"), ".netrc")
        count = len(open(netrc_path).readlines())
        if count == 1:
            file = open(os.path.join(os.getenv("HOME"), ".netrc"), "r")
            contents = file.read().split(" ")
            self.user = contents[3]
            self.password = contents[5]
            file.close()
        else:
            self.user = np.loadtxt(
                os.path.join(os.getenv("HOME"), ".netrc"),
                skiprows=1,
                usecols=1,
                dtype=str,
            )[0]
            self.password = np.loadtxt(
                os.path.join(os.getenv("HOME"), ".netrc"),
                skiprows=1,
                usecols=1,
                dtype=str,
            )[1]

    if (len(self.password) == 0 | len(self.user) == 0) & (
        not os.path.exists(os.path.join(os.getenv("HOME"), ".netrc"))
    ):
        print(
            "WARNING: The ASF User and Password needs to be included in ~/.netrc file."
        )
        print(" The ~/.netrc file does not exist or has not been setup properly")
        sys.exit("System Exiting until ~/.netrc file setup properly")

    # Now lets check if processing and data directories exist
    # If they do not we will make the directories

    if os.path.exists(process_dir) is False:
        print("create ", process_dir)
        os.makedirs(process_dir)
    else:
        print(process_dir, " exists")

    if os.path.exists(data_dir) is False:
        print("create ", data_dir)
        os.makedirs(data_dir)
    else:
        print(data_dir, " exists")

    os.chdir(data_dir)
    # Now lets download the data to the data directory
    if len(self.file1) == 0 | len(self.file2) == 0:
        sys.exit("Data links do not exist")
    else:
        cmd1 = ("wget  %s --user {0} --password {1}" % self.file1).format(
            self.user, self.password
        )
        zip1 = os.path.basename(os.path.normpath(self.file1))
        # isolating initial zip file
        if not os.path.exists(os.path.join(data_dir, zip1)):
            os.system(cmd1)
            os.system("unzip  %s" % zip1)
        else:
            print(zip1, " already exists")

        cmd2 = ("wget  %s --user {0} --password {1}" % self.file2).format(
            self.user, self.password
        )
        zip2 = os.path.basename(
            os.path.normpath(self.file2)
        )  # isolating initial zip file
        if not os.path.exists(os.path.join(data_dir, zip2)):
            os.system(cmd2)
            os.system("unzip  %s" % zip2)
        else:
            print(zip2, " already exists")

        SCDT1 = "{0}/{1}".format(zip1[:-4], "%s.l0.workreport" % zip1[:-9])
        with open(SCDT1, "r") as myfile:
            data = myfile.readlines()
            self.date1 = data[6]
            self.date1 = self.date1[38:46]
        print(self.date1)

        SCDT2 = "{0}/{1}".format(zip2[:-4], "%s.l0.workreport" % zip2[:-9])
        with open(SCDT2, "r") as myfile:
            data = myfile.readlines()
            self.date2 = data[6]
            self.date2 = self.date2[38:46]
        print(self.date2)
        if not os.path.exists(os.path.join(data_dir, self.date1)):
            os.mkdir(self.date1)
        if not os.path.exists(os.path.join(data_dir, self.date2)):
            os.mkdir(self.date2)

        os.system("mv {0} {1}".format(zip1[:-4], self.date1))
        os.system("mv {0} {1}".format(zip2[:-4], self.date2))

Sentinel1_processing

Downloads and writes files necessary for ISCE TOPSAR processing

Attributes:

Name Type Description
self.sensor

S1A or S1B

self.file1

slc file to be downloaded

self.file2

secondary slc file to be downloaded

self.date1

acquisition date of slc reference

self.date2

acquisition date of slc secondary

self.azimuth_lks

number of azimuth looks (default 3)

self.range_lks

number of range looks (default 7)

self.bounds

bounds for processing TOPSAR

self.flag

set to False. Set to true after formation of amplitude to geocode

Source code in sarlo/isce.py
class Sentinel1_processing(object):
    """Downloads and writes files necessary for ISCE TOPSAR processing

    Attributes:
        self.sensor: S1A or S1B
        self.file1: slc file to be downloaded
        self.file2: secondary slc file to be downloaded
        self.date1: acquisition date of slc reference
        self.date2: acquisition date of slc secondary
        self.azimuth_lks: number of azimuth looks (default 3)
        self.range_lks: number of range looks (default 7)
        self.bounds: bounds for processing TOPSAR
        self.flag: set to False. Set to true after formation of amplitude to geocode
    """

    def __init__(
        self,
        query1: str,
        query2: str,
        lonMin: int,
        lonMax: int,
        latMin: int,
        latMax: int,
        azimuth_looks: int = 3,
        range_looks: int = 7,
        flag: bool = False,
    ):
        """Intitialze download of SLC files for ISCE processing.

        Args:
            query1: acquisition date of slc reference
            query2: acquisition date of slc secondary
            azimuth_lks: number of azimuth looks (default 3)
            range_lks: number of range looks (default 7)
            lonMin: longitude minimum extent
            lonMax: longitude maximum extent
            latMin: latitude minimum extent
            latMax: latitude maximum extent
            flag: set to False. Set to true after formation of amplitude to geocode

        Return:
            None.
        """

        self.query1 = query1
        self.query2 = query2
        self.date1 = None
        self.date2 = None
        self.azimuth_lks = azimuth_looks
        self.range_lks = range_looks
        self.bounds = [latMin, latMax, lonMin, lonMax]
        self.flag = flag

        # Variables that will not be controlled by user inputs
        self.user = None
        self.password = None
        self.title1 = None
        self.title2 = None
        self.id1 = None
        self.id2 = None
        self.mode1 = None
        self.mode2 = None
        self.frame1 = None
        self.frame2 = None
        self.relative_orbit1 = None
        self.relative_orbit2 = None
        self.Satellite_number1 = None
        self.Satellite_number2 = None
        self.polygon1 = None
        self.polygon2 = None
        self.center1 = None
        self.center2 = None

    def download_SLC(self, user: str = None, password: str = None):
        """Download S1 Single Look Complex imagery from ASF

        Args:
            self.user: string, optional
                username for Copernicus download
            self.password: string, optional
                password for Copernicus download

        Return:
            None. Downloads and formats two S1 SLC files for interferometric computing
        """

        self.user = user
        self.password = password

        if (len(self.password) is None | len(self.user) is None) & (
            not os.path.exists(os.path.join(os.getenv("HOME"), ".netrc"))
        ):
            print(
                "WARNING: The Username and Password needs to be included in ~/.netrc file."
            )
            print(" The ~/.netrc file does not exist or has not been setup properly")
            sys.exit("System Exiting until ~/.netrc file setup properly")

        # Now lets download the data to the data directory
        if len(self.query1) == 0 | len(self.query2) == 0:
            sys.exit("Data links do not exist")
        else:
            bounds = write_polygon_geojson(
                lonMin=self.lonMin,
                lonMax=self.lonMax,
                latMin=self.latMin,
                latMax=self.latMax,
            )
            download_SLC_pair(
                bounds,
                self.date1,
                self.date2,
                slcpath=os.path.join(os.getenv("HOME"), "downloads"),
                self=self,
                username=self.username,
                password=self.password,
            )

        home_dir = os.path.join(os.getenv("HOME"), "work")
        self.process_dir = os.path.join(
            home_dir,
            "S1_{0}_{1}".format(round(self.center1[1]), round(self.center1[0])),
        )
        data_dir = os.path.join(self.process_dir, "data")

        if os.path.exists(self.process_dir) is False:
            print("create ", self.process_dir)
            os.makedirs(self.process_dir)
        else:
            print(self.process_dir, " exists")

        if os.path.exists(data_dir) is False:
            print("create ", data_dir)
            os.makedirs(data_dir)
        else:
            print(data_dir, " exists")

        os.chdir(data_dir)

        if not os.path.exists(os.path.join(data_dir, "orbits")):
            os.mkdir("orbits")

        shutil.move(
            os.path.join(os.getenv("HOME"), "downloads", "{0}.zip".format(self.title1)),
            os.path.join(data_dir, "SLC"),
        )
        shutil.move(
            os.path.join(os.getenv("HOME"), "downloads", "{0}.zip".format(self.title2)),
            os.path.join(data_dir, "SLC"),
        )

        download_eofs(
            sentinel_file=os.path.join(data_dir),
            save_dir=os.path.join(data_dir, "orbits"),
        )

    def configure_inputs(self):
        """Writes XML files for TOPSAR processing

        Args:
            outdir: Directory in which XML files will be written

        Return:
            None. XML files x3 are written
        """
        cmd_reference_config = """<?xml version="1.0" encoding="UTF-8"?>
            <component name="reference">
            <property name="safe">data/SLC/{0}.zip</property>
            <property name="output directory">referencedir</property>
            <property name="orbit directory">data/orbits</property>
            </component>
            """.format(
            self.title1
        )

        print("writing Reference.xml")
        with open(os.path.join(self.process_dir, "Reference.xml"), "w") as fid:
            fid.write(cmd_reference_config)

        cmd_secondary_config = """<?xml version="1.0" encoding="UTF-8"?>
            <component name="reference">
            <property name="safe">data/SLC/{0}.zip</property>
            <property name="output directory">secondarydir</property>
            <property name="orbit directory">data/orbits</property>
            </component>
            """.format(
            self.title2
        )

        print("writing secondary.xml")
        with open(os.path.join(self.process_dir, "secondary.xml"), "w") as fid:
            fid.write(cmd_secondary_config)

        if None in self.bounds is False:
            if self.flag is False:
                cmd_topsApp_config = """<?xml version="1.0" encoding="UTF-8"?>
                    <topsApp>
                    <component name="topsinsar">
                        <property name="Sensor name">SENTINEL1</property>
                        <component name="reference">
                        <catalog>reference.xml</catalog>
                        </component>
                        <component name="secondary">
                        <catalog>secondary.xml</catalog>
                        </component>
                        <property name="do interferogram">True</property>
                        <property name="region of interest">{0}</property>
                        <property name="do denseoffsets">True</property>
                        <property name="range looks">{1}</property>
                        <property name="azimuth looks">{2}</property>
                        <property name="geocode bounding box">{0}</property>
                        <property name="do unwrap">True</property>
                        <property name="unwrapper name">
                            <value>snaphu_mcf</value>
                        </property>
                    </component>
                    </topsApp>""".format(
                    self.bounds, self.range_lks, self.azimuth_lks
                )
            elif self.flag is True:
                cmd_topsApp_config = """<?xml version="1.0" encoding="UTF-8"?>
                    <topsApp>
                    <component name="topsinsar">
                        <property name="Sensor name">SENTINEL1</property>
                        <component name="reference">
                        <catalog>reference.xml</catalog>
                        </component>
                        <component name="secondary">
                        <catalog>secondary.xml</catalog>
                        </component>
                        <property name="do interferogram">True</property>
                        <property name="region of interest">{0}</property>
                        <property name="do denseoffsets">True</property>
                        <property name="range looks">{1}</property>
                        <property name="azimuth looks">{2}</property>
                        <property name="geocode bounding box">{0}</property>
                        <property name="geocode">[./merged/resampOnlyImage.amp]</property>
                        <property name="do unwrap">True</property>
                        <property name="unwrapper name">
                            <value>snaphu_mcf</value>
                        </property>
                    </component>
                    </topsApp>""".format(
                    self.bounds, self.range_lks, self.azimuth_lks
                )
        elif None in self.bounds is True:
            if self.flag is False:
                cmd_topsApp_config = """<?xml version="1.0" encoding="UTF-8"?>
                    <topsApp>
                    <component name="topsinsar">
                        <property name="Sensor name">SENTINEL1</property>
                        <component name="reference">
                        <catalog>reference.xml</catalog>
                        </component>
                        <component name="secondary">
                        <catalog>secondary.xml</catalog>
                        </component>
                        <property name="do interferogram">True</property>
                        <property name="do denseoffsets">True</property>
                        <property name="range looks">{0}</property>
                        <property name="azimuth looks">{1}</property>
                        <property name="do unwrap">True</property>
                        <property name="unwrapper name">
                            <value>snaphu_mcf</value>
                        </property>
                    </component>
                    </topsApp>""".format(
                    self.range_lks, self.azimuth_lks
                )
            elif self.flag is True:
                cmd_topsApp_config = """<?xml version="1.0" encoding="UTF-8"?>
                    <topsApp>
                    <component name="topsinsar">
                        <property name="Sensor name">SENTINEL1</property>
                        <component name="reference">
                        <catalog>reference.xml</catalog>
                        </component>
                        <component name="secondary">
                        <catalog>secondary.xml</catalog>
                        </component>
                        <property name="do interferogram">True</property>
                        <property name="do denseoffsets">True</property>
                        <property name="range looks">{0}</property>
                        <property name="azimuth looks">{1}</property>
                        <property name="geocode">[./merged/resampOnlyImage.amp]</property>
                        <property name="do unwrap">True</property>
                        <property name="unwrapper name">
                            <value>snaphu_mcf</value>
                        </property>
                    </component>
                    </topsApp>""".format(
                    self.range_lks, self.azimuth_lks
                )

        print("writing topsApp.xml")
        with open(os.path.join(self.process_dir, "topsApp.xml"), "w") as fid:
            fid.write(cmd_topsApp_config)

        return

    def process_topsApp(self):

        os.system(
            "topsApp.py topsApp.xml --start=preprocess --end=geocodeoffsets | tee sentinel1.txt"
        )
        slc1 = os.path.join(self.process_dir, "merged", "reference.slc.full")
        slc2 = os.path.join(self.process_dir, "merged", "secondary.slc.full")

        # Single Look Complex imagery use real and imaginary numbers. Taking the absolute value of the reference and secondary SLC is how we create the amplitude file that is biweaved
        os.system(
            "imageMath.py -e 'abs(a);abs(b)' --a {0} --b {1} -o ./merged/topophase.amp.full -s BIP -t Float".format(
                slc1, slc2
            )
        )

        # Range and Azimuth looking are required to downsize the data to match topophase.cor.geo
        os.system(
            "looks.py -i ./merged/topophase.amp.full -o ./merged/topophase.amp -r {0} -a {1}".format(
                self.range, self.azimuth
            )
        )

        # Now we just rename topophase.amp to resampOnlyImage.amp
        os.system(
            "imageMath.py -e='a_0;a_1' --a ./merged/topophase.amp -o ./merged/resampOnlyImage.amp -s BIL -t FLOAT"
        )

        self.flag = True
        Sentinel1_processing.configure_inputs(self)

        os.system("topsApp.py topsApp.xml --dostep=geocode")

__init__(self, query1, query2, lonMin, lonMax, latMin, latMax, azimuth_looks=3, range_looks=7, flag=False) special

Intitialze download of SLC files for ISCE processing.

Parameters:

Name Type Description Default
query1 str

acquisition date of slc reference

required
query2 str

acquisition date of slc secondary

required
azimuth_lks

number of azimuth looks (default 3)

required
range_lks

number of range looks (default 7)

required
lonMin int

longitude minimum extent

required
lonMax int

longitude maximum extent

required
latMin int

latitude minimum extent

required
latMax int

latitude maximum extent

required
flag bool

set to False. Set to true after formation of amplitude to geocode

False

Returns:

Type Description

None.

Source code in sarlo/isce.py
def __init__(
    self,
    query1: str,
    query2: str,
    lonMin: int,
    lonMax: int,
    latMin: int,
    latMax: int,
    azimuth_looks: int = 3,
    range_looks: int = 7,
    flag: bool = False,
):
    """Intitialze download of SLC files for ISCE processing.

    Args:
        query1: acquisition date of slc reference
        query2: acquisition date of slc secondary
        azimuth_lks: number of azimuth looks (default 3)
        range_lks: number of range looks (default 7)
        lonMin: longitude minimum extent
        lonMax: longitude maximum extent
        latMin: latitude minimum extent
        latMax: latitude maximum extent
        flag: set to False. Set to true after formation of amplitude to geocode

    Return:
        None.
    """

    self.query1 = query1
    self.query2 = query2
    self.date1 = None
    self.date2 = None
    self.azimuth_lks = azimuth_looks
    self.range_lks = range_looks
    self.bounds = [latMin, latMax, lonMin, lonMax]
    self.flag = flag

    # Variables that will not be controlled by user inputs
    self.user = None
    self.password = None
    self.title1 = None
    self.title2 = None
    self.id1 = None
    self.id2 = None
    self.mode1 = None
    self.mode2 = None
    self.frame1 = None
    self.frame2 = None
    self.relative_orbit1 = None
    self.relative_orbit2 = None
    self.Satellite_number1 = None
    self.Satellite_number2 = None
    self.polygon1 = None
    self.polygon2 = None
    self.center1 = None
    self.center2 = None

configure_inputs(self)

Writes XML files for TOPSAR processing

Parameters:

Name Type Description Default
outdir

Directory in which XML files will be written

required

Returns:

Type Description

None. XML files x3 are written

Source code in sarlo/isce.py
def configure_inputs(self):
    """Writes XML files for TOPSAR processing

    Args:
        outdir: Directory in which XML files will be written

    Return:
        None. XML files x3 are written
    """
    cmd_reference_config = """<?xml version="1.0" encoding="UTF-8"?>
        <component name="reference">
        <property name="safe">data/SLC/{0}.zip</property>
        <property name="output directory">referencedir</property>
        <property name="orbit directory">data/orbits</property>
        </component>
        """.format(
        self.title1
    )

    print("writing Reference.xml")
    with open(os.path.join(self.process_dir, "Reference.xml"), "w") as fid:
        fid.write(cmd_reference_config)

    cmd_secondary_config = """<?xml version="1.0" encoding="UTF-8"?>
        <component name="reference">
        <property name="safe">data/SLC/{0}.zip</property>
        <property name="output directory">secondarydir</property>
        <property name="orbit directory">data/orbits</property>
        </component>
        """.format(
        self.title2
    )

    print("writing secondary.xml")
    with open(os.path.join(self.process_dir, "secondary.xml"), "w") as fid:
        fid.write(cmd_secondary_config)

    if None in self.bounds is False:
        if self.flag is False:
            cmd_topsApp_config = """<?xml version="1.0" encoding="UTF-8"?>
                <topsApp>
                <component name="topsinsar">
                    <property name="Sensor name">SENTINEL1</property>
                    <component name="reference">
                    <catalog>reference.xml</catalog>
                    </component>
                    <component name="secondary">
                    <catalog>secondary.xml</catalog>
                    </component>
                    <property name="do interferogram">True</property>
                    <property name="region of interest">{0}</property>
                    <property name="do denseoffsets">True</property>
                    <property name="range looks">{1}</property>
                    <property name="azimuth looks">{2}</property>
                    <property name="geocode bounding box">{0}</property>
                    <property name="do unwrap">True</property>
                    <property name="unwrapper name">
                        <value>snaphu_mcf</value>
                    </property>
                </component>
                </topsApp>""".format(
                self.bounds, self.range_lks, self.azimuth_lks
            )
        elif self.flag is True:
            cmd_topsApp_config = """<?xml version="1.0" encoding="UTF-8"?>
                <topsApp>
                <component name="topsinsar">
                    <property name="Sensor name">SENTINEL1</property>
                    <component name="reference">
                    <catalog>reference.xml</catalog>
                    </component>
                    <component name="secondary">
                    <catalog>secondary.xml</catalog>
                    </component>
                    <property name="do interferogram">True</property>
                    <property name="region of interest">{0}</property>
                    <property name="do denseoffsets">True</property>
                    <property name="range looks">{1}</property>
                    <property name="azimuth looks">{2}</property>
                    <property name="geocode bounding box">{0}</property>
                    <property name="geocode">[./merged/resampOnlyImage.amp]</property>
                    <property name="do unwrap">True</property>
                    <property name="unwrapper name">
                        <value>snaphu_mcf</value>
                    </property>
                </component>
                </topsApp>""".format(
                self.bounds, self.range_lks, self.azimuth_lks
            )
    elif None in self.bounds is True:
        if self.flag is False:
            cmd_topsApp_config = """<?xml version="1.0" encoding="UTF-8"?>
                <topsApp>
                <component name="topsinsar">
                    <property name="Sensor name">SENTINEL1</property>
                    <component name="reference">
                    <catalog>reference.xml</catalog>
                    </component>
                    <component name="secondary">
                    <catalog>secondary.xml</catalog>
                    </component>
                    <property name="do interferogram">True</property>
                    <property name="do denseoffsets">True</property>
                    <property name="range looks">{0}</property>
                    <property name="azimuth looks">{1}</property>
                    <property name="do unwrap">True</property>
                    <property name="unwrapper name">
                        <value>snaphu_mcf</value>
                    </property>
                </component>
                </topsApp>""".format(
                self.range_lks, self.azimuth_lks
            )
        elif self.flag is True:
            cmd_topsApp_config = """<?xml version="1.0" encoding="UTF-8"?>
                <topsApp>
                <component name="topsinsar">
                    <property name="Sensor name">SENTINEL1</property>
                    <component name="reference">
                    <catalog>reference.xml</catalog>
                    </component>
                    <component name="secondary">
                    <catalog>secondary.xml</catalog>
                    </component>
                    <property name="do interferogram">True</property>
                    <property name="do denseoffsets">True</property>
                    <property name="range looks">{0}</property>
                    <property name="azimuth looks">{1}</property>
                    <property name="geocode">[./merged/resampOnlyImage.amp]</property>
                    <property name="do unwrap">True</property>
                    <property name="unwrapper name">
                        <value>snaphu_mcf</value>
                    </property>
                </component>
                </topsApp>""".format(
                self.range_lks, self.azimuth_lks
            )

    print("writing topsApp.xml")
    with open(os.path.join(self.process_dir, "topsApp.xml"), "w") as fid:
        fid.write(cmd_topsApp_config)

    return

download_SLC(self, user=None, password=None)

Download S1 Single Look Complex imagery from ASF

Parameters:

Name Type Description Default
self.user

string, optional username for Copernicus download

required
self.password

string, optional password for Copernicus download

required

Returns:

Type Description

None. Downloads and formats two S1 SLC files for interferometric computing

Source code in sarlo/isce.py
def download_SLC(self, user: str = None, password: str = None):
    """Download S1 Single Look Complex imagery from ASF

    Args:
        self.user: string, optional
            username for Copernicus download
        self.password: string, optional
            password for Copernicus download

    Return:
        None. Downloads and formats two S1 SLC files for interferometric computing
    """

    self.user = user
    self.password = password

    if (len(self.password) is None | len(self.user) is None) & (
        not os.path.exists(os.path.join(os.getenv("HOME"), ".netrc"))
    ):
        print(
            "WARNING: The Username and Password needs to be included in ~/.netrc file."
        )
        print(" The ~/.netrc file does not exist or has not been setup properly")
        sys.exit("System Exiting until ~/.netrc file setup properly")

    # Now lets download the data to the data directory
    if len(self.query1) == 0 | len(self.query2) == 0:
        sys.exit("Data links do not exist")
    else:
        bounds = write_polygon_geojson(
            lonMin=self.lonMin,
            lonMax=self.lonMax,
            latMin=self.latMin,
            latMax=self.latMax,
        )
        download_SLC_pair(
            bounds,
            self.date1,
            self.date2,
            slcpath=os.path.join(os.getenv("HOME"), "downloads"),
            self=self,
            username=self.username,
            password=self.password,
        )

    home_dir = os.path.join(os.getenv("HOME"), "work")
    self.process_dir = os.path.join(
        home_dir,
        "S1_{0}_{1}".format(round(self.center1[1]), round(self.center1[0])),
    )
    data_dir = os.path.join(self.process_dir, "data")

    if os.path.exists(self.process_dir) is False:
        print("create ", self.process_dir)
        os.makedirs(self.process_dir)
    else:
        print(self.process_dir, " exists")

    if os.path.exists(data_dir) is False:
        print("create ", data_dir)
        os.makedirs(data_dir)
    else:
        print(data_dir, " exists")

    os.chdir(data_dir)

    if not os.path.exists(os.path.join(data_dir, "orbits")):
        os.mkdir("orbits")

    shutil.move(
        os.path.join(os.getenv("HOME"), "downloads", "{0}.zip".format(self.title1)),
        os.path.join(data_dir, "SLC"),
    )
    shutil.move(
        os.path.join(os.getenv("HOME"), "downloads", "{0}.zip".format(self.title2)),
        os.path.join(data_dir, "SLC"),
    )

    download_eofs(
        sentinel_file=os.path.join(data_dir),
        save_dir=os.path.join(data_dir, "orbits"),
    )

download_S1_orbits(date1, date2, Satellite_number1, Satellite_number2)

Download S1 orbit files for ISCE processing

Parameters:

Name Type Description Default
date1

string, date of first S1 SLC file

required
date2

string, date of second S1 SLC file

required
sensor1

string, S1 sensor A or B

required
sensor2

string, S1 sensor A or B

required

Returns:

Type Description

None. Downloads orbit files for both SLC files.

Source code in sarlo/isce.py
def download_S1_orbits(date1, date2, Satellite_number1, Satellite_number2):
    """Download S1 orbit files for ISCE processing

    Args:
        date1: string, date of first S1 SLC file
        date2: string, date of second S1 SLC file
        sensor1: string, S1 sensor A or B
        sensor2: string, S1 sensor A or B

    Return:
        None. Downloads orbit files for both SLC files.
    """
    if Satellite_number1 == "A":
        sensor1 = "S1A"
    else:
        sensor1 = "S1B"
    if Satellite_number2 == "A":
        sensor2 = "S1A"
    else:
        sensor2 = "S1B"
    download_eofs([str(date1), str(date2)], [sensor1, sensor2], save_dir="./orbits")

download_SLC_pair(geojson, date1, date2, slcpath='.', self=None, username=None, password=None)

Download S1 SLC files

Parameters:

Name Type Description Default
username str

username for scihub.copernicus.eu

None
password str

password for scihub.copernicus.eu

None
geojson

geojson with boundary for search area

required
date1 str

slc window for reference slc

required
date2 str

slc window for secondary slc

required
slcpath str

path to download SLC files

'.'

Returns:

Type Description

None. Downloads SLC files.

Source code in sarlo/isce.py
def download_SLC_pair(
    geojson,
    date1: str,
    date2: str,
    slcpath: str = ".",
    self=None,
    username: str = None,
    password: str = None,
):
    """Download S1 SLC files

    Args:
        username: username for scihub.copernicus.eu
        password: password for scihub.copernicus.eu
        geojson: geojson with boundary for search area
        date1: slc window for reference slc
        date2: slc window for secondary slc
        slcpath: path to download SLC files

    Return:
        None. Downloads SLC files.
    """
    api = SentinelAPI(username, password, "https://scihub.copernicus.eu/dhus")
    footprint = geojson_to_wkt(read_geojson(geojson))
    date1 = datetime.datetime.strptime(str(date1, "%Y%m%d"))
    enddate1 = datetime.timedelta(days=10) + date1
    products = api.query(
        area=footprint,
        date=(date1, enddate1),
        platformname="Sentinel-1",
        producttype="SLC",
    )
    products_df = api.to_geodataframe(products)
    products_df_sorted = products_df.sort_values(["ingestiondate"], ascending=[True])
    products_df_sorted = products_df_sorted.head(1)
    if self is not None:
        (
            self.title1,
            self.date1,
            self.id1,
            self.mode1,
            self.frame1,
            self.relative_orbit1,
            self.Satellite_number1,
            self.polygon1,
            self.center1,
        ) = read_sentinelsat_meta(api, products_df_sorted["uuid"][0])
    api.download_all(products=products_df_sorted["uuid"], directory_path=slcpath)

    date2 = datetime.datetime.strptime(str(date2, "%Y%m%d"))
    enddate2 = datetime.timedelta(days=10) + date2
    products = api.query(
        area=footprint,
        date=(date2, enddate2),
        platformname="Sentinel-1",
        producttype="SLC",
    )
    products_df = api.to_geodataframe(products)
    products_df_sorted = products_df.sort_values(["ingestiondate"], ascending=[True])
    products_df_sorted = products_df_sorted.head(1)
    if self is not None:
        (
            self.title2,
            self.date2,
            self.id2,
            self.mode2,
            self.frame2,
            self.relative_orbit2,
            self.Satellite_number2,
            self.polygon2,
            self.center2,
        ) = read_sentinelsat_meta(api, products_df_sorted["uuid"][0])
    api.download_all(products=products_df_sorted["uuid"], directory_path=slcpath)

read_sentinelsat_meta(api, id)

Reads the meta

Parameters:

Name Type Description Default
api object

class, sentinelsatAPI object

required
id str

string, product to be downloaded id

required

Returns:

Type Description
title

S1 file name date: acquisition date id: full product id mode: frame: relative_orbit: Satellite_number: polygon: center:

Source code in sarlo/isce.py
def read_sentinelsat_meta(api: object, id: str):
    """Reads the meta

    Args:
        api: class, sentinelsatAPI object
        id: string, product to be downloaded id

    Returns:
        title: S1 file name
        date: acquisition date
        id: full product id
        mode:
        frame:
        relative_orbit:
        Satellite_number:
        polygon:
        center:
    """

    meta = api.get_product_odata(id=id, full=True)
    title = meta["title"]
    date = meta["date"]
    id = meta["id"]
    mode = meta["mode"]
    frame = meta["Cycle number"]
    relative_orbit = meta["Relative orbit (start)"]
    Satellite_number = meta["Satellite number"]
    polygon = meta["JTS footprint"]
    center = center_polygon(polygon_text=polygon)
    return (
        title,
        date,
        id,
        mode,
        frame,
        relative_orbit,
        Satellite_number,
        polygon,
        center,
    )
Back to top