From 0f92b1ae8396487a4f4f9bf7d0aab8abcc50da9e Mon Sep 17 00:00:00 2001 From: CunrenLiang <56097947+CunrenLiang@users.noreply.github.com> Date: Tue, 10 Aug 2021 04:31:40 +0800 Subject: [PATCH] add an option for masking out islands in ionosphere computation (#306) * add an option for masking out islands in ionosphere computation * Update topsApp.py add some comments for new parameter "areas masked out in ionospheric phase estimation" --- applications/topsApp.py | 17 +++++++++++++++++ components/isceobj/TopsProc/runIon.py | 25 +++++++++++++++++++++++++ examples/input_files/topsApp.xml | 10 ++++++++++ 3 files changed, 52 insertions(+) diff --git a/applications/topsApp.py b/applications/topsApp.py index 6dd2b65..66baa8b 100755 --- a/applications/topsApp.py +++ b/applications/topsApp.py @@ -519,6 +519,22 @@ ION_AZSHIFT_FLAG = Application.Parameter('ION_azshiftFlag', mandatory=False, doc='') +#seperated islands or areas usually affect ionosphere estimation and it's better to mask them +#out. check ion/ion_cal/raw_no_projection.ion for areas to be masked out. +#The parameter is a 2-D list. Each element in the 2-D list is a four-element list: [firstLine, +#lastLine, firstColumn, lastColumn], with line/column numbers starting with 1. If one of the +#four elements is specified as -1, the program will use firstLine/lastLine/firstColumn/ +#lastColumn instead. For exmple, if you want to mask the following two areas out, you can +#specify a 2-D list like: +#[[100, 200, 100, 200],[1000, 1200, 500, 600]] +ION_MASKED_AREAS = Application.Parameter('ION_maskedAreas', + public_name = 'areas masked out in ionospheric phase estimation', + default = None, + type = int, + mandatory = False, + container = list, + doc = 'areas masked out in ionospheric phase estimation') + ION_NUMBER_AZIMUTH_LOOKS = Application.Parameter('ION_numberAzimuthLooks', public_name='total number of azimuth looks in the ionosphere processing', default=50, @@ -674,6 +690,7 @@ class TopsInSAR(Application): ION_IONSHIFT_FILTERING_WINSIZE_MAX, ION_IONSHIFT_FILTERING_WINSIZE_MIN, ION_AZSHIFT_FLAG, + ION_MASKED_AREAS, ION_NUMBER_AZIMUTH_LOOKS, ION_NUMBER_RANGE_LOOKS, ION_NUMBER_AZIMUTH_LOOKS0, diff --git a/components/isceobj/TopsProc/runIon.py b/components/isceobj/TopsProc/runIon.py index 06b48a1..c81655f 100644 --- a/components/isceobj/TopsProc/runIon.py +++ b/components/isceobj/TopsProc/runIon.py @@ -14,6 +14,7 @@ import isceobj import logging from isceobj.Constants import SPEED_OF_LIGHT from isceobj.TopsProc.runBurstIfg import loadVirtualArray +from isceobj.Alos2Proc.runIonFilt import reformatMaskedAreas logger = logging.getLogger('isce.topsinsar.ion') @@ -89,6 +90,7 @@ def setup(self): ionParam.ionshiftFilteringWinsizeMax = self.ION_ionshiftFilteringWinsizeMax ionParam.ionshiftFilteringWinsizeMin = self.ION_ionshiftFilteringWinsizeMin ionParam.azshiftFlag = self.ION_azshiftFlag + ionParam.maskedAreas = self.ION_maskedAreas ionParam.numberAzimuthLooks = self.ION_numberAzimuthLooks ionParam.numberRangeLooks = self.ION_numberRangeLooks @@ -1283,6 +1285,14 @@ def ionosphere(self, ionParam): cor = (np.fromfile(corfile, dtype=np.float32).reshape(length*2, width))[1:length*2:2, :] amp = np.sqrt(lowerAmp**2+upperAmp**2) + #masked out user-specified areas + if ionParam.maskedAreas != None: + maskedAreas = reformatMaskedAreas(ionParam.maskedAreas, length, width) + for area in maskedAreas: + lowerUnw[area[0]:area[1], area[2]:area[3]] = 0 + upperUnw[area[0]:area[1], area[2]:area[3]] = 0 + cor[area[0]:area[1], area[2]:area[3]] = 0 + #compute ionosphere fl = SPEED_OF_LIGHT / ionParam.radarWavelengthLower fu = SPEED_OF_LIGHT / ionParam.radarWavelengthUpper @@ -1549,6 +1559,14 @@ def ionSwathBySwath(self, ionParam): cor = (np.fromfile(corfile, dtype=np.float32).reshape(length*2, width))[1:length*2:2, :] amp = np.sqrt(lowerAmp**2+upperAmp**2) + #masked out user-specified areas + if ionParam.maskedAreas != None: + maskedAreas = reformatMaskedAreas(ionParam.maskedAreas, length, width) + for area in maskedAreas: + lowerUnw[area[0]:area[1], area[2]:area[3]] = 0 + upperUnw[area[0]:area[1], area[2]:area[3]] = 0 + cor[area[0]:area[1], area[2]:area[3]] = 0 + #compute ionosphere fl = SPEED_OF_LIGHT / ionParam.radarWavelengthLower fu = SPEED_OF_LIGHT / ionParam.radarWavelengthUpper @@ -1923,6 +1941,13 @@ def filt_gaussian(self, ionParam): cor = (np.fromfile(corfile, dtype=np.float32).reshape(length*2, width))[1:length*2:2, :] amp = (np.fromfile(ionfile, dtype=np.float32).reshape(length*2, width))[0:length*2:2, :] + #masked out user-specified areas + if ionParam.maskedAreas != None: + maskedAreas = reformatMaskedAreas(ionParam.maskedAreas, length, width) + for area in maskedAreas: + ion[area[0]:area[1], area[2]:area[3]] = 0 + cor[area[0]:area[1], area[2]:area[3]] = 0 + ######################################################################################## #AFTER COHERENCE IS RESAMPLED AT grd2ion, THERE ARE SOME WIRED VALUES cor[np.nonzero(cor<0)] = 0.0 diff --git a/examples/input_files/topsApp.xml b/examples/input_files/topsApp.xml index ae3241d..cc96c81 100644 --- a/examples/input_files/topsApp.xml +++ b/examples/input_files/topsApp.xml @@ -200,6 +200,16 @@ By default, ESD is always performed. #2: use full burst 1 +#seperated islands or areas usually affect ionosphere estimation and it's better to mask them +#out. check ion/ion_cal/raw_no_projection.ion for areas to be masked out. +#The parameter is a 2-D list. Each element in the 2-D list is a four-element list: [firstLine, +#lastLine, firstColumn, lastColumn], with line/column numbers starting with 1. If one of the +#four elements is specified as -1, the program will use firstLine/lastLine/firstColumn/ +#lastColumn instead. For exmple, if you want to mask the following two areas out, you can +#specify a 2-D list like: +#[[100, 200, 100, 200],[1000, 1200, 500, 600]] +None + #better NOT try changing the following two parameters, since they are related #to the filtering parameters above 50