Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 0.4.2 #274

Merged
merged 96 commits into from
Jun 26, 2020
Merged
Show file tree
Hide file tree
Changes from 95 commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
b158b28
readonly prepifg implemented. Tests updated
basaks May 22, 2020
39def0f
conv2tif output is readonly, prepifg readonly tests
basaks May 22, 2020
c30c1fb
send correct headers during network method
basaks May 22, 2020
13ce4b4
orbitmethod=2 needs headers during multilooking
basaks May 22, 2020
92289b0
Merge branch 'develop' into sb/ro-prepifg
basaks May 22, 2020
61b9b7f
resolved merge conflict with develop
basaks May 22, 2020
8356b89
read ref phase inside for loop to save memory
basaks May 25, 2020
bf2f7eb
fixed process workflow
basaks May 27, 2020
96338e8
fixed tests, disabled legacy maxvar and vcm test
basaks May 27, 2020
41a5425
minor edit to screen messages
May 27, 2020
d340c41
Merge pull request #267 from GeoscienceAustralia/sb/ro-prepifg
May 27, 2020
3d2e921
read ref phase inside for loop to save memory
basaks May 25, 2020
3cbb193
fixed process workflow
basaks May 27, 2020
024366e
fixed tests, disabled legacy maxvar and vcm test
basaks May 27, 2020
35e5080
change log level of ref_phs_est messages
May 27, 2020
7e5c1a3
updated local gdal calc and use nans as nodataval
basaks May 15, 2020
3e39320
split maxsig masking into separate function
May 18, 2020
d54690c
fix stacking tests
May 18, 2020
a2c318a
refactor merge.py; apply mask_rate during Merge step
May 18, 2020
8e240fd
minor edits to configuration/config modules
May 18, 2020
6275853
implement skipping of masking if maxsig=0
May 18, 2020
1a59443
refactor stack module: expose two functions to docs - i) single pixel…
May 19, 2020
6665c99
refactor merge.py; remove duplicated code to reusable generic functions
May 19, 2020
9d4b05c
update doc string and expose function to docs. fix tests.common import
May 27, 2020
3c16d27
fix stack tests; add new tests for mask_rate algorithm
May 20, 2020
1d2cb43
update dev and test requirements, and dev hints
May 20, 2020
dddfcc1
expose assemble_tiles function, write docstring, and re-use in APS mo…
May 21, 2020
e98a0a3
add pytest slow mark and increase travis_wait time for pytest command
May 21, 2020
a253548
remove tests for outdir/stack*.npy existence. these files are not cre…
May 28, 2020
b7aee40
revise the log message verbosity
May 28, 2020
666a902
update changelog
May 28, 2020
a78f74e
improve stack params doco
May 28, 2020
a669455
Merge pull request #268 from GeoscienceAustralia/sb/ref_phs_investiga…
May 29, 2020
23168d6
file type names changed
basaks May 28, 2020
9634c48
output file extensions changed, many functions in common.py removed
basaks May 29, 2020
57034bd
all tests pass
basaks May 29, 2020
b9fbce5
update mpi tests
basaks May 29, 2020
38e4f2d
input filetypes are enumerated
basaks May 30, 2020
b9da9b4
Merge remote-tracking branch 'origin/develop' into sb/file-types-hand…
basaks May 30, 2020
aa60e74
some house keeping
basaks May 30, 2020
e6a998f
big fix: handle both types
basaks May 30, 2020
37793d5
big fix: pass multiple paths instead to orbfit calc
basaks May 30, 2020
33c8d56
fixed mpi and test_pyrate/orbital tests
basaks May 30, 2020
2638adb
Merge remote-tracking branch 'origin/mg/maxsig' into sb/file-types-ha…
basaks May 30, 2020
5a63512
optionally output stack*.npy files
basaks May 30, 2020
c3cc03d
minor fix
basaks May 30, 2020
132e52b
return ints from ref pixel method
basaks May 31, 2020
d91610d
include mpi tests for different refx/refy setups
basaks May 31, 2020
01cdeba
Merge pull request #269 from GeoscienceAustralia/mg/maxsig
Jun 14, 2020
a6645e9
add pixel latlon converter and refpixel metadata update functionality
sheecegardezi May 5, 2020
aeffcbc
lat/lon ref pixel setup complete
basaks Jun 11, 2020
195a15a
lat/lon reference pixel supported
basaks Jun 11, 2020
a79c3c8
fixed refpixel tests
basaks Jun 11, 2020
6e817b9
stop overwriting test files during ref pixel tests
basaks Jun 12, 2020
4f654c8
add refpixel metadata tests
basaks Jun 12, 2020
a28dcbe
new Ifg function add metadata to update metadata of interferograms
basaks Jun 12, 2020
8cf8f1c
pass through lat/lon provided by user to the refpixel output
basaks Jun 12, 2020
ae04591
Merge branch 'develop' into sb/file-types-handling
Jun 15, 2020
116d808
fix npy file save for time series epoch files; add savenpy option to …
Jun 15, 2020
a3af624
bugfix and more tests for refpixel
basaks Jun 12, 2020
f3e8d72
more refpixel test
basaks Jun 12, 2020
c8ea6c7
need more resolution for correct refpixel and pytest slow marker for …
basaks Jun 15, 2020
3b1fb55
minor improvement in file types checks
basaks Jun 15, 2020
da326b6
Merge branch 'sb/file-types-handling' into sb/refpixel-lat-lon
basaks Jun 15, 2020
bd52a76
fix prepifg output of multi_looked coherence files
basaks Jun 16, 2020
b3fc30e
prepifg write mlooked coh files and fixed tests
basaks Jun 16, 2020
6c40014
Merge branch 'sb/file-types-handling' of github.com:GeoscienceAustral…
basaks Jun 16, 2020
7aca232
Merge pull request #270 from GeoscienceAustralia/sb/file-types-handling
Jun 16, 2020
20507ba
update changelog
Jun 16, 2020
3e53979
change metadata tag entries for refpixel
Jun 16, 2020
2341d54
improve console messages for x/y and lon/lat refpixel coords
Jun 16, 2020
8f10ca1
Merge branch 'develop' into sb/refpixel-lat-lon
basaks Jun 16, 2020
d495572
minor changes
basaks Jun 16, 2020
e994110
rounding may work better for refpixel
basaks Jun 18, 2020
2c8f20f
simpler prepfig functions and type hints
basaks Jun 19, 2020
5d0edbb
refpixel validation
basaks Jun 19, 2020
2757b68
refactor supplied lat/lon value validation; improve error messages
Jun 22, 2020
52d226f
minor edit - fix up tests
Jun 23, 2020
9c743c8
minor fix
basaks Jun 23, 2020
fbab134
update refpixel tests and validation
basaks Jun 23, 2020
3f25d50
update refpixel tests
basaks Jun 23, 2020
226cd59
update tests
basaks Jun 23, 2020
79b5d29
Merge pull request #272 from GeoscienceAustralia/sb/refpixel-lat-lon
Jun 24, 2020
05b88a7
enabled the calculation of colourmaps for stack_rate and stack_error …
tfuhrmann Jun 17, 2020
b7e6ce0
fixed and enhanced merge test
basaks Jun 17, 2020
ab43978
refactor and reuse png/kml generation
basaks Jun 17, 2020
abc688a
update integration tests
basaks Jun 17, 2020
af535f8
kml and png files skip equality check
basaks Jun 17, 2020
57829fb
slow marker and remove unused `merge` test files
basaks Jun 17, 2020
aba9530
added in white-red colourmap for quickview image of stack_error.tif
Jun 18, 2020
48deea0
minor simplifactions (no_of_steps), added more comments
Jun 18, 2020
4033e78
replaced np.arange by np.linspace to avoid potential numerical issues
Jun 18, 2020
e5a9f28
minor refactor
Jun 23, 2020
82b0720
Merge pull request #273 from GeoscienceAustralia/tf/colourmap-new
Jun 24, 2020
1241ec7
update history
Jun 24, 2020
8b4fee0
fix log messages for ref_phs and aps
Jun 25, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,11 @@ install:
- pip install GDAL==$(gdal-config --version)
- python setup.py install
- rm -rf Py_Rate.egg-info # remove the local egg
- export PYRATEPATH=$(pwd)
- export PYTHONPATH=$PYRATEPATH:$PYTHONPATH
- chmod 444 tests/test_data/small_test/tif/geo_070709-070813_unw.tif # makes the file readonly, used in a test

# command to run tests, e.g. python setup.py test
script:
# - python scripts/update_placeholder_paths.py
- mpirun -n 3 pytest tests/test_mpi.py
- pytest --cov-config=.coveragerc --cov-report term-missing:skip-covered --cov=pyrate tests/


Expand All @@ -79,7 +76,7 @@ deploy:
verbose: true
on:
branch: master
condition: $GDALVERSION="3.0.2" && $TRAVIS_PYTHON_VERSION=3.8.*
python: 3.8
github_token: $GITHUB_TOKEN2
local_dir: docs/_build/html
project_name: PyRate
Expand Down
48 changes: 45 additions & 3 deletions docs/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,50 @@

Release History
===============

0.4.2 (2020-06-26)
------------------
Added
+++++
- Save full-res coherence files to disk in ``conv2tif`` step if ``cohmask = 1``.
- Save multi-looked coherence files to disk in ``prepifg`` step if ``cohmask = 1``.
- Additional ``DATA_TYPE`` geotiff header metadata for above coherence files.
- ``conv2tif`` and ``prepifg`` output files have a tag applied to filename dependent
on data type, i.e. ``_ifg.tif``, ``_coh.tif``, ``_dem.tif``.
- Metadata about used reference pixel is added to interferogram geotiff headers:
lat/lon and x/y values; mean and standard deviation of reference window samples.
- Quicklook PNG and KML files are generated for the ``Stack Rate`` error map by default.

Changed
+++++++
- Bugfix: ensure ``prepifg`` treats input data files as `read only`.
- Bugfix: fix the way that the reference phase is subtracted from interferograms
during ``process`` step.
- Bugfix: manual entry of ``refx/y`` converted to type ``int``.
- User supplies latitude and longitude values when specifying a reference pixel in
the config file. Pixel x/y values are calculated and used internally.
- Move ``Stack Rate`` masking to a standalone function ``pyrate.core.stack.mask_rate``,
applied during the ``merge`` step and add unit tests.
- Skip ``Stack Rate`` masking if threshold parameter ``maxsig = 0``.
- Provide log message indicating the percentage of pixels masked by
``pyrate.core.stack.mask_rate``.
- Refactor ``pyrate.core.stack`` module; expose two functions in documentation:
i) single pixel stacking algorithm, and
ii) loop function for processing full ifg array.
- Refactor ``pyrate.merge`` script; remove duplicated code and create reusable
generic functions.
- Colourmap used to render quicklook PNG images is calculated from min/max values of
the geotiff band.
- Updated ``test`` and ``dev`` requirements.

Removed
+++++++
- Deprecate unused functions in ``pyrate.core.config`` and corresponding tests.
- Static colourmap ``utils/colourmap.txt`` that was previously used to render
quicklook PNG images is removed.

0.4.1 (2020-05-19)
-----------------------
------------------
Added
+++++
- Python 3.8 support.
Expand Down Expand Up @@ -31,7 +73,7 @@ Removed
- Deprecate ``parallel = 2`` option; splitting image via rows for parallelisation.

0.4.0 (2019-10-31)
-----------------------
------------------
Added
+++++
- Python 3.7 support.
Expand Down Expand Up @@ -64,7 +106,7 @@ Removed
- Unused tests for legacy api.

0.3.0 (2019-07-26)
-----------------------
------------------
Added
+++++
- ``utils/apt_install.sh`` script that lists Ubuntu/apt package requirements.
Expand Down
25 changes: 14 additions & 11 deletions input_parameters.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,27 @@
# Optional ON/OFF switches - ON = 1; OFF = 0

# Coherence masking (PREPIFG)
cohmask: 1
cohmask: 0

# Orbital error correction (PROCESS)
orbfit: 1
orbfit: 1

# APS correction using spatio-temporal filter (PROCESS)
apsest: 0
apsest: 0

# Time series calculation (PROCESS)
tscal: 1
tscal: 1

# Optional save of numpy array files for output products (MERGE)
savenpy: 0

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Multi-threading parameters used by stacking/timeseries/prepifg
# gamma prepifg runs in parallel on a single machine if parallel = 1
# parallel: 1 = parallel, 0 = serial
parallel: 0
parallel: 0
# number of processes
processes: 8
processes: 8

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Input/Output file locations
Expand Down Expand Up @@ -85,8 +88,8 @@ nan_conversion: 1
# refnx/y: number of search grid points in x/y image dimensions
# refchipsize: size of the data window at each search grid point
# refminfrac: minimum fraction of valid (non-NaN) pixels in the data window
refx:
refy:
refx: 150.941666654
refy: -34.218333314
refnx: 5
refny: 5
refchipsize: 5
Expand Down Expand Up @@ -149,9 +152,9 @@ ts_pthr: 10
#------------------------------------
# Stacking calculation parameters

# pthr: minimum number of coherent ifg connections for each pixel
# nsig: n-sigma used as residuals threshold for iterative least squares stacking
# maxsig: maximum residual used as a threshold for values in the rate map
# pthr: threshold for minimum number of ifg observations for each pixel
# nsig: threshold for iterative removal of observations
# maxsig: maximum sigma (std dev) used as an output masking threshold applied in Merge step. 0 = OFF.
pthr: 5
nsig: 3
maxsig: 1000
31 changes: 19 additions & 12 deletions pyrate/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
This Python module contains utilities to validate user input parameters
parsed in a PyRate configuration file.
"""
from configparser import ConfigParser
from pathlib import Path, PurePath
import re
from pyrate.constants import NO_OF_PARALLEL_PROCESSES
from pyrate.default_parameters import PYRATE_DEFAULT_CONFIGURATION
from pyrate.core.algorithm import factorise_integer
from pyrate.core.shared import extract_epochs_from_filename
from pyrate.core.shared import extract_epochs_from_filename, InputTypes
from pyrate.core.config import parse_namelist, ConfigException


Expand All @@ -44,17 +47,17 @@ def validate_parameter_value(input_name, input_value, min_value=None, max_value=
if min_value is not None:
if input_value < min_value: # pragma: no cover
raise ValueError(
"Invalid value for " + str(input_name) + " supplied: " + str(input_value) + ". Please provided a valid value greater than " + str(min_value) + ".")
"Invalid value for " + str(input_name) + " supplied: " + str(input_value) + ". Provide a value greater than or equal to " + str(min_value) + ".")
if input_value is not None:
if max_value is not None:
if input_value > max_value: # pragma: no cover
raise ValueError(
"Invalid value for " + str(input_name) + " supplied: " + str(input_value) + ". Please provided a valid value less than " + str(max_value) + ".")
"Invalid value for " + str(input_name) + " supplied: " + str(input_value) + ". Provide a value less than or equal to " + str(max_value) + ".")

if possible_values is not None:
if input_value not in possible_values: # pragma: no cover
raise ValueError(
"Invalid value for " + str(input_name) + " supplied: " + str(input_value) + ". Please provided a valid value from with in: " + str(possible_values) + ".")
"Invalid value for " + str(input_name) + " supplied: " + str(input_value) + ". Provide a value from: " + str(possible_values) + ".")
return True


Expand All @@ -74,7 +77,9 @@ def validate_file_list_values(file_list, no_of_epochs):


class MultiplePaths:
def __init__(self, out_dir, file_name, ifglksx=1, ifgcropopt=1):
def __init__(self, out_dir: str, file_name: str, ifglksx: int = 1, ifgcropopt: int = 1,
input_type: InputTypes = InputTypes.IFG):
self.input_type = input_type
b = Path(file_name)
if b.suffix == ".tif":
self.unwrapped_path = None
Expand All @@ -83,7 +88,8 @@ def __init__(self, out_dir, file_name, ifglksx=1, ifgcropopt=1):
b.stem + '_' + str(ifglksx) + "rlks_" + str(ifgcropopt) + "cr.tif").as_posix()
else:
self.unwrapped_path = b.as_posix()
converted_path = Path(out_dir).joinpath(b.stem + '_' + b.suffix[1:]).with_suffix('.tif')
converted_path = Path(out_dir).joinpath(
b.stem.split('.')[0] + '_' + b.suffix[1:] + input_type.value).with_suffix('.tif')
self.sampled_path = converted_path.with_name(
converted_path.stem + '_' + str(ifglksx) + "rlks_" + str(ifgcropopt) + "cr.tif").as_posix()
self.converted_path = converted_path.as_posix()
Expand Down Expand Up @@ -171,20 +177,21 @@ def __init__(self, config_file_path):
if self.cohfilelist is not None:
# if self.processor != 0: # not roipac
validate_file_list_values(self.cohfilelist, 1)
self.coherence_file_paths = self.__get_files_from_attr('cohfilelist')
self.coherence_file_paths = self.__get_files_from_attr('cohfilelist', input_type=InputTypes.COH)

self.header_file_paths = self.__get_files_from_attr('hdrfilelist')
self.header_file_paths = self.__get_files_from_attr('hdrfilelist', input_type=InputTypes.HEADER)

self.interferogram_files = self.__get_files_from_attr('ifgfilelist')

self.dem_file = MultiplePaths(self.outdir, self.demfile, self.ifglksx, self.ifgcropopt)
self.dem_file = MultiplePaths(self.outdir, self.demfile, self.ifglksx, self.ifgcropopt,
input_type=InputTypes.DEM)

# backward compatibility for string paths
for key in self.__dict__:
if isinstance(self.__dict__[key], PurePath):
self.__dict__[key] = str(self.__dict__[key])

def __get_files_from_attr(self, attr):
def __get_files_from_attr(self, attr, input_type=InputTypes.IFG):
val = self.__getattribute__(attr)
files = parse_namelist(val)
return [MultiplePaths(self.outdir, p, self.ifglksx, self.ifgcropopt) for p in files]
return [MultiplePaths(self.outdir, p, self.ifglksx, self.ifgcropopt, input_type=input_type) for p in files]
1 change: 0 additions & 1 deletion pyrate/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
PROCESS = 'process'
MERGE = 'merge'

REF_COLOR_MAP_PATH = os.path.join(PYRATEPATH, "utils", "colourmap.txt")
# distance division factor of 1000 converts to km and is needed to match legacy output
DISTFACT = 1000
# mappings for metadata in header for interferogram
Expand Down
4 changes: 4 additions & 0 deletions pyrate/conv2tif.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
from typing import Tuple, List
from joblib import Parallel, delayed
import numpy as np
from pathlib import Path

from pyrate.core.prepifg_helper import PreprocessError
from pyrate.core import shared, mpiops, config as cf, gamma, roipac
from pyrate.core import ifgconstants as ifc
from pyrate.core.logger import pyratelogger as log
from pyrate.configuration import MultiplePaths
from pyrate.core.shared import mpi_vs_multiprocess_logging
Expand Down Expand Up @@ -103,7 +105,9 @@ def _geotiff_multiprocessing(unw_path: MultiplePaths, params: dict) -> Tuple[str
header = roipac.roipac_header(unw_path.unwrapped_path, params)
else:
raise PreprocessError('Processor must be ROI_PAC (0) or GAMMA (1)')
header[ifc.INPUT_TYPE] = unw_path.input_type
shared.write_fullres_geotiff(header, unw_path.unwrapped_path, dest, nodata=params[cf.NO_DATA_VALUE])
Path(dest).chmod(0o444) # readonly output
return dest, True
else:
log.warning(f"Full-res geotiff already exists in {dest}! Returning existing geotiff!")
Expand Down
14 changes: 8 additions & 6 deletions pyrate/core/aps.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from pyrate.core.algorithm import get_epochs
from pyrate.core.shared import Ifg
from pyrate.core.timeseries import time_series
from pyrate.merge import _assemble_tiles
from pyrate.merge import assemble_tiles

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -101,16 +101,15 @@ def _calc_svd_time_series(ifg_paths, params, preread_ifgs, tiles):
new_params[cf.TIME_SERIES_METHOD] = 2 # use SVD method

process_tiles = mpiops.array_split(tiles)
output_dir = params[cf.TMPDIR]

nvels = None
for t in process_tiles:
log.debug('Calculating time series for tile {} during APS '
'correction'.format(t.index))
ifg_parts = [shared.IfgPart(p, t, preread_ifgs, params) for p in ifg_paths]
mst_tile = np.load(os.path.join(output_dir, 'mst_mat_{}.npy'.format(t.index)))
mst_tile = np.load(os.path.join(params[cf.TMPDIR], 'mst_mat_{}.npy'.format(t.index)))
tsincr = time_series(ifg_parts, new_params, vcmt=None, mst=mst_tile)[0]
np.save(file=os.path.join(output_dir, 'tsincr_aps_{}.npy'.format(t.index)), arr=tsincr)
np.save(file=os.path.join(params[cf.TMPDIR], 'tsincr_aps_{}.npy'.format(t.index)), arr=tsincr)
nvels = tsincr.shape[2]

nvels = mpiops.comm.bcast(nvels, root=0)
Expand All @@ -125,11 +124,14 @@ def _assemble_tsincr(ifg_paths, params, preread_ifgs, tiles, nvels):
"""
Helper function to reconstruct time series images from tiles
"""
# pre-allocate dest 3D array
shape = preread_ifgs[ifg_paths[0]].shape + (nvels,)
tsincr_g = np.empty(shape=shape, dtype=np.float32)
# shape of one 2D time-slice array
s = preread_ifgs[ifg_paths[0]].shape
# loop over the time slices and assemble dest 3D array
for i in range(nvels):
for n, t in enumerate(tiles):
_assemble_tiles(i, n, t, tsincr_g[:, :, i], params[cf.TMPDIR], 'tsincr_aps')
tsincr_g[:, :, i] = assemble_tiles(s, params[cf.TMPDIR], tiles, out_type='tsincr_aps', index=i)

return tsincr_g

Expand Down
Loading