diff --git a/.circleci/config.yml b/.circleci/config.yml index 435523dd5..b9935b6a6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,7 +38,7 @@ jobs: export PATH=${CONDA_PREFIX}/bin:${PATH} # install dependencies and source code source activate root - mamba install --verbose --yes gdal">=3" --file ${MINTPY_HOME}/docs/requirements.txt + mamba install --verbose --yes gdal">=3" --file ${MINTPY_HOME}/requirements.txt python -m pip install ${MINTPY_HOME} # test installation smallbaselineApp.py -v diff --git a/docs/installation.md b/docs/installation.md index 387c39f8a..4e9336ebe 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -22,7 +22,7 @@ Then complete the [post-installation setup](#3-post-installation-setup). Note: The installation note below is tested on Linux and macOS, and is still experimental on Windows (may has bugs). -MintPy is written in Python 3 and relies on several Python modules, check the [requirements.txt](https://github.com/insarlab/MintPy/blob/main/docs/requirements.txt) file for details. We recommend using [conda](https://docs.conda.io/en/latest/miniconda.html) or [macports](https://www.macports.org/install.php) to install the python environment and the prerequisite packages, because of the convenient management and default [performance setting with numpy/scipy](http://markus-beuckelmann.de/blog/boosting-numpy-blas.html) and [pyresample](https://pyresample.readthedocs.io/en/latest/installation.html#using-pykdtree). +MintPy is written in Python 3 and relies on several Python modules, check the [requirements.txt](https://github.com/insarlab/MintPy/blob/main/requirements.txt) file for details. We recommend using [conda](https://docs.conda.io/en/latest/miniconda.html) or [macports](https://www.macports.org/install.php) to install the python environment and the prerequisite packages, because of the convenient management and default [performance setting with numpy/scipy](http://markus-beuckelmann.de/blog/boosting-numpy-blas.html) and [pyresample](https://pyresample.readthedocs.io/en/latest/installation.html#using-pykdtree). Quick links: @@ -62,7 +62,7 @@ Install the dependencies into an custom existing environment [recommended] by ru # Add "gdal'>=3'" below to install extra dependencies if you use ARIA, FRInGE, HyP3 or GMTSAR # Add "isce2" below to install extra dependencies if you use ISCE-2 -conda install -c conda-forge --file ~/tools/MintPy/docs/requirements.txt +conda install -c conda-forge --file ~/tools/MintPy/requirements.txt ``` Or install the dependencies to a new environment named "mintpy" by running: diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index f5a365ef5..000000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,28 +0,0 @@ -# requirements4rtd.txt for readthedocs, which uses pip with limited memory usage -# requirements.txt for dependency installation via conda -# environment.yml for dependency installation via conda and create a new environment -# ports.txt for dependency installation via mac-ports -# setup.py for mintpy installation via pip after the dependency installation above -python>=3.6 -pip -cartopy -cvxopt -dask>=1.0 -dask-jobqueue>=0.3 -defusedxml -h5py -joblib -lxml -matplotlib -numpy -pyaps3 -pykml>=0.2 -pyproj -pysolid -scikit-image -scipy -# for ARIA, FRInGE, HyP3, GMTSAR -# gdal>=3 -# for pyresample -pyresample -openmp diff --git a/mintpy/asc_desc2horz_vert.py b/mintpy/asc_desc2horz_vert.py index 7b831699f..9cced9c54 100755 --- a/mintpy/asc_desc2horz_vert.py +++ b/mintpy/asc_desc2horz_vert.py @@ -111,10 +111,10 @@ def cmd_line_parse(iargs=None): ref_y_diff = abs((ref_lat1 - ref_lat2) / float(atr1['Y_STEP'])) ref_x_diff = abs((ref_lon1 - ref_lon2) / float(atr1['X_STEP'])) if any(ref_diff > inps.max_ref_yx_diff for ref_diff in [ref_y_diff, ref_x_diff]): - msg = 'REF_Y/X difference between input files > {}!\n'.format(inps.max_ref_yx_diff) - for fname, ref_lalo, ref_yx in zip(inps.file, [ref_lalo1, ref_lalo2], [ref_yx1, ref_yx2]): + msg = 'REF_LAT/LON difference between input files > {} pixels!\n'.format(inps.max_ref_yx_diff) + for fname, ref_lat, ref_lon in zip(inps.file, [ref_lat1, ref_lat2], [ref_lon1, ref_lon2]): msg += 'file1: {}\n'.format(fname) - msg += '\tREF_LAT/LON: {}\n'.format(ref_lalo) + msg += '\tREF_LAT/LON: [{:.8f}, {:.8f}]\n'.format(ref_lat, ref_lon) raise ValueError(msg) return inps @@ -341,18 +341,18 @@ def run_asc_desc2horz_vert(inps): if inps.one_outfile: print('write asc/desc/horz/vert datasets into {}'.format(inps.one_outfile)) dsDict = {} - for i, atr in enumerate(atr_list): + for i, atr_i in enumerate(atr_list): # dataset name for LOS data - track_num = atr.get('trackNumber', None) - proj_name = atr.get('PROJECT_NAME', None) + track_num = atr_i.get('trackNumber', None) + proj_name = atr_i.get('PROJECT_NAME', None) if proj_name in ['none', 'None', None]: - proj_name = atr.get('FILE_PATH', None) + proj_name = atr_i.get('FILE_PATH', None) proj_name = sensor.project_name2sensor_name(proj_name)[0] ds_name = proj_name if proj_name else '' - ds_name += 'A' if atr['ORBIT_DIRECTION'].lower().startswith('asc') else 'D' + ds_name += 'A' if atr_i['ORBIT_DIRECTION'].lower().startswith('asc') else 'D' ds_name += f'T{track_num}' if track_num else '' - ds_name += '_{}'.format(atr['DATE12']) + ds_name += '_{}'.format(atr_i['DATE12']) # assign dataset value dsDict[ds_name] = dlos[i] diff --git a/mintpy/utils/arg_group.py b/mintpy/utils/arg_group.py index e0e6b1504..e1102a02c 100644 --- a/mintpy/utils/arg_group.py +++ b/mintpy/utils/arg_group.py @@ -215,6 +215,9 @@ def add_map_argument(parser): "This will enable --lalo-label option.\n" "Link: https://scitools.org.uk/cartopy/docs/latest/matplotlib/geoaxes.html" "#cartopy.mpl.geoaxes.GeoAxes.coastlines") + mapg.add_argument('--coastline-lw', '--coastline-linewidth', dest='coastline_linewidth', + metavar='NUM', type=float, default=1, + help='Coastline linewidth (default: %(default)s).') # lalo label mapg.add_argument('--lalo-label', dest='lalo_label', action='store_true', @@ -227,6 +230,11 @@ def add_map_argument(parser): mapg.add_argument('--lalo-loc', dest='lalo_loc', type=int, nargs=4, default=[1, 0, 0, 1], metavar=('left', 'right', 'top', 'bottom'), help='Draw lalo label in [left, right, top, bottom] (default: %(default)s).') + mapg.add_argument('--lalo-off','--lalo-offset', dest='lalo_offset', type=float, nargs=2, + help='Distance between tick and label in points (default: %(default)s).\n' + 'Set to negative value, e.g. -36 -18, to move the ticklabel inside the plot.') + mapg.add_argument('--lalo-fs','--lalo-fontsize', dest='lalo_font_size', type=float, + help='Lalo label font size in points (default: %(default)s).') #mapg.add_argument('--proj', '--projection', '--map-proj', dest='map_projection', metavar='NAME', # help='map projection when plotting in geo-coordinate.\n' diff --git a/mintpy/utils/plot.py b/mintpy/utils/plot.py index ccc571124..837ac0681 100644 --- a/mintpy/utils/plot.py +++ b/mintpy/utils/plot.py @@ -1675,7 +1675,7 @@ def auto_lalo_sequence(geo_box, lalo_step=None, lalo_max_num=4, step_candidate=[ def draw_lalo_label(geo_box, ax=None, lalo_step=None, lalo_loc=[1, 0, 0, 1], lalo_max_num=4, - font_size=12, xoffset=None, yoffset=None, projection=ccrs.PlateCarree(), print_msg=True): + lalo_offset=None, font_size=None, projection=ccrs.PlateCarree(), print_msg=True): """Auto draw lat/lon label/tick based on coverage from geo_box Parameters: geo_box : 4-tuple of float, (W, N, E, S) in degree ax : CartoPy axes. @@ -1683,6 +1683,8 @@ def draw_lalo_label(geo_box, ax=None, lalo_step=None, lalo_loc=[1, 0, 0, 1], lal lalo_loc : list of 4 bool, positions where the labels are drawn as in [left, right, top, bottom] default: [1,0,0,1] lalo_max_num : int + x/yoffset : float, distance in points between tick and label. + Set to negative value to move the ticklabel inside the plot. ... Example: geo_box = (128.0, 37.0, 138.0, 30.0) m.draw_lalo_label(geo_box) @@ -1701,10 +1703,9 @@ def draw_lalo_label(geo_box, ax=None, lalo_step=None, lalo_loc=[1, 0, 0, 1], lal left=True, right=True, top=True, bottom=True, labelleft=lalo_loc[0], labelright=lalo_loc[1], labeltop=lalo_loc[2], labelbottom=lalo_loc[3]) - if xoffset is not None: - ax.tick_params(axis='x', which='major', pad=xoffset) - if yoffset is not None: - ax.tick_params(axis='y', which='major', pad=yoffset) + if lalo_offset: + ax.tick_params(axis='x', which='major', pad=lalo_offset[1]) + ax.tick_params(axis='y', which='major', pad=lalo_offset[0]) # ticklabel symbol style decimal_digit = max(0, 0-digit) diff --git a/mintpy/utils/readfile.py b/mintpy/utils/readfile.py index 229247918..0aa56319f 100644 --- a/mintpy/utils/readfile.py +++ b/mintpy/utils/readfile.py @@ -128,6 +128,8 @@ 5 : 'int32', 6 : 'float32', 7 : 'float64', + 8 : 'cint16', # for translation purpose only, as numpy does not support complex int + 9 : 'cint32', # for translation purpose only, as numpy does not support complex int 10: 'complex64', 11: 'complex128', } @@ -141,6 +143,8 @@ "int32" : 5, "float32" : 6, "float64" : 7, + "cint16" : 8, # for translation purpose only, as numpy does not support complex int + "cint32" : 9, # for translation purpose only, as numpy does not support complex int "complex64" : 10, "complex128": 11, } @@ -166,7 +170,7 @@ # single file (data + attributes) supported by GDAL -GDAL_FILE_EXTS = ['.tif', '.grd'] +GDAL_FILE_EXTS = ['.tiff', '.tif', '.grd'] ENVI_BAND_INTERLEAVE = { 'BAND' : 'BSQ', diff --git a/mintpy/utils/utils1.py b/mintpy/utils/utils1.py index ab5c62fdb..1c57a92af 100644 --- a/mintpy/utils/utils1.py +++ b/mintpy/utils/utils1.py @@ -520,22 +520,23 @@ def update_template_file(template_file, extra_dict, delimiter='='): key = c[0] value = str.replace(c[1], '\n', '').split("#")[0].strip() - # prepare value to search following "re" expression syntax - # link: https://docs.python.org/3/library/re.html - # 1. interpret special symbols as characters - value2search = value - for symbol in ['*', '[', ']', '(', ')']: - value2search = value2search.replace(symbol, "\{}".format(symbol)) - # 2. use "= {OLD_VALUE}" for search/replace to be more robust - # against the scenario when key name contains {OLD_VALUE} - # i.e. mintpy.load.autoPath - value2search = delimiter+'[\s]*'+value2search - if key in extra_dict.keys() and extra_dict[key] != value: + # prepare value string to search & replace following "re" expression syntax + # link: https://docs.python.org/3/library/re.html + value2search = value + # 1. interpret special symbols as characters + for symbol in ['*', '[', ']', '(', ')']: + value2search = value2search.replace(symbol, "\{}".format(symbol)) + # 2. use "= {OLD_VALUE}" for search/replace to be more robust + # against the scenario when key name contains {OLD_VALUE} + # i.e. mintpy.load.autoPath + value2search = delimiter+'[\s]*'+value2search + old_value_str = re.findall(value2search, line)[0] new_value_str = old_value_str.replace(value, extra_dict[key]) line = line.replace(old_value_str, new_value_str, 1) print(' {}: {} --> {}'.format(key, value, extra_dict[key])) + f_tmp.write(line) f_tmp.close() diff --git a/mintpy/view.py b/mintpy/view.py index 2b509634f..da8a2b646 100755 --- a/mintpy/view.py +++ b/mintpy/view.py @@ -548,7 +548,7 @@ def plot_slice(ax, data, metadata, inps=None): # Draw coastline using cartopy resolution parameters if inps.coastline: vprint('draw coast line with resolution: {}'.format(inps.coastline)) - ax.coastlines(resolution=inps.coastline) + ax.coastlines(resolution=inps.coastline, linewidth=inps.coastline_linewidth) # Plot DEM if inps.dem_file: @@ -598,7 +598,8 @@ def plot_slice(ax, data, metadata, inps=None): lalo_step=inps.lalo_step, lalo_loc=inps.lalo_loc, lalo_max_num=inps.lalo_max_num, - font_size=inps.font_size, + lalo_offset=inps.lalo_offset, + font_size=inps.lalo_font_size if inps.lalo_font_size else inps.font_size, projection=inps.map_proj_obj, print_msg=inps.print_msg) else: @@ -1485,7 +1486,7 @@ def prep_slice(cmd, auto_fig=False): cmd += f'--sub-lon {W} {E} --sub-lat {S} {N} -c jet -v -3 10 ' cmd += '--cbar-loc bottom --cbar-nbins 3 --cbar-ext both --cbar-size 5% ' cmd += '--lalo-step 0.2 --lalo-loc 1 0 1 0 --scalebar 0.3 0.80 0.05 --notitle' - data, atr ,inps = view.prep_slice(cmd) + data, atr, inps = view.prep_slice(cmd) ax, inps, im, cbar = view.plot_slice(ax, data, atr, inps) plt.show() """ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..0b98a6546 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,28 @@ +# requirements.txt for dependency installation via conda +# docs/environment.yml for dependency installation via conda and create a new environment +# docs/ports.txt for dependency installation via mac-ports +# setup.py for mintpy installation via pip after the dependency installation above +# docs/requirements4rtd.txt for readthedocs, which uses pip with limited memory usage +python>=3.6 +pip +cartopy +cvxopt +dask>=1.0 +dask-jobqueue>=0.3 +defusedxml +h5py +joblib +lxml +matplotlib +numpy +pyaps3 +pykml>=0.2 +pyproj +pysolid +scikit-image +scipy +# for ARIA, FRInGE, HyP3, GMTSAR +# gdal>=3 +# for pyresample +pyresample +openmp