Skip to content

Commit b63fd87

Browse files
committed
bug fix related to large nodata values
1 parent cf43137 commit b63fd87

File tree

6 files changed

+138
-27
lines changed

6 files changed

+138
-27
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ VectorFieldCalc is a QGIS plugin for calculating physical parameters (e.g., dive
66

77
Contacts:
88

9-
Mauro Alberti - [email protected]
9+
Mauro Alberti - [email protected]

help/help.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55
<link href="style.css" rel="stylesheet" type="text/css" />
66
</head>
77
<body>
8-
<h2>VectorFieldCalc v. 1.6</h2>
8+
<h2>VectorFieldCalc v. 1.5.3</h2>
99
<p>
1010
This plugin for Quantum GIS allows to calculate physical parameters (e.g., divergence, curl module, pathlines), given a 2D, steady vector field,
1111
such as the velocity field of glacial flows.
1212
</p>
13+
<p>
14+
IT IS STRONGLY ADVISED TO WORK WITH PROJECTED DATASETS (e.g., Polar, Lambert, UTM), NOT POLAR ONES (i.e., Lat-Long),
15+
SINCE THE CALCULATIONS ARE PERFORMED IN A CARTESIAN COORDINATE FRAME.
16+
</p>
1317

1418
<div>
1519
In details, the calculated parameters are summarized below:
@@ -166,7 +170,7 @@ <h4>Pathlines</h4>
166170
<div style="font-size: 85%; font-style: italic;">
167171
-----
168172
<br /><br />
169-
Doc version 2018-08-16, by Mauro Alberti - <a href="mailto:[email protected]">[email protected]</a>
173+
Doc version 2019-06-30, by Mauro Alberti - <a href="mailto:[email protected]">[email protected]</a>
170174
</div>
171175

172176
<br /><br />

main_dialog.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
from __future__ import absolute_import
44

5-
6-
from builtins import str
75
from builtins import zip
8-
import os, webbrowser
6+
97
from osgeo import ogr
108

119
from qgis.PyQt.QtCore import *
@@ -16,7 +14,6 @@
1614

1715
from .vfc_utils import *
1816

19-
from .pygsf.libs_utils.gdal.gdal import *
2017
from .qgis_utils.qgs import *
2118
from .pygsf.spatial.rasters.geoarray import *
2219
from .pygsf.spatial.rasters.io import *
@@ -39,7 +36,6 @@ def __init__(self):
3936

4037
self.adjustSize()
4138

42-
4339
def setup_help_widget(self):
4440

4541
help_widget = QTextBrowser()
@@ -495,7 +491,7 @@ def calculate_vectorfieldops(self):
495491
"No output layer defined")
496492
return
497493

498-
### PROCESSINGS
494+
# PROCESSINGS
499495

500496
# create velocity geoarray
501497

@@ -1056,11 +1052,11 @@ def about(self):
10561052

10571053
QMessageBox.about(self, "About VectorFieldCalc",
10581054
"""
1059-
<p>VectorFieldCalc version 1.5.1<br />License: GPL v. 3</p>
1055+
<p>VectorFieldCalc version 1.5.3<br />License: GPL v. 3</p>
10601056
<p>Mauro Alberti</p>
10611057
<p>This application calculates vector field parameters (e.g., divergence, curl module, gradients)
10621058
and pathlines.
10631059
</p>
1064-
<p>Please report any bug to <a href="mailto:[email protected]">[email protected]</a></p>
1060+
<p>Please report any bug to <a href="mailto:[email protected]">[email protected]</a></p>
10651061
""")
10661062

metadata.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
[general]
22
name=VectorFieldCalc
3-
3+
44
author=Mauro Alberti
55
qgisMinimumVersion=3.0
66
description=Calculation of vector field parameters
77
about=This plugin calculates vector field parameters (e.g., magnitude, divergence, curl) and pathlines, given two rasters representing x- and y- velocities
8-
version=1.5.2
8+
version=1.5.3
99
tracker=https://github.com/mauroalberti/VectorFieldCalc/issues
1010
repository=https://github.com/mauroalberti/VectorFieldCalc/releases
1111
; end of mandatory metadata
1212

1313
; start of optional metadata
1414
category=Plugins
1515
changelog=
16+
1.5.3 - {2019-06-30} fixed bug ....
1617
1.5.2 - fixed bug with missing asc extension in file names
1718
1.5.1: - fixed problem with help in Windows
1819
1.5: - based on pygsf

pygsf/libs_utils/gdal/gdal.py

Lines changed: 122 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
from typing import Any, Tuple, Dict, Optional, Union
55

6+
import os
7+
68
from math import isfinite
79

810
import numpy as np
@@ -11,7 +13,11 @@
1113

1214
from .exceptions import *
1315

16+
from ...defaults.constants import GRID_NULL_VALUE
17+
from ...defaults.typing import Number
18+
from ...mathematics.scalars import areClose
1419
from ...spatial.rasters.geotransform import GeoTransform
20+
from ...spatial.rasters.geoarray import GeoArray
1521

1622

1723
def read_raster(file_ref: Any) -> Tuple[gdal.Dataset, Optional[GeoTransform], int, str]:
@@ -48,7 +54,7 @@ def read_raster(file_ref: Any) -> Tuple[gdal.Dataset, Optional[GeoTransform], in
4854
return dataset, geotransform, num_bands, projection
4955

5056

51-
def read_band(dataset: gdal.Dataset, bnd_ndx: int=1) -> Tuple[dict, 'np.array']:
57+
def read_band(dataset: gdal.Dataset, bnd_ndx: int = 1) -> Tuple[dict, 'np.array']:
5258
"""
5359
Read data and metadata of a rasters band based on GDAL.
5460
@@ -103,7 +109,7 @@ def read_band(dataset: gdal.Dataset, bnd_ndx: int=1) -> Tuple[dict, 'np.array']:
103109
# if nodatavalue exists, set null values to NaN in numpy array
104110

105111
if noDataVal is not None and isfinite(noDataVal):
106-
grid_values = np.where(abs(grid_values - noDataVal) > 1e-10, grid_values, np.NaN)
112+
grid_values = np.where(np.isclose(grid_values, noDataVal), np.NaN, grid_values)
107113

108114
band_params = dict(
109115
dataType=data_type,
@@ -116,6 +122,13 @@ def read_band(dataset: gdal.Dataset, bnd_ndx: int=1) -> Tuple[dict, 'np.array']:
116122

117123

118124
def try_read_raster_band(raster_source: str, bnd_ndx: int=1) -> Tuple[bool, Union[str, Tuple[GeoTransform, str, Dict, 'np.array']]]:
125+
"""
126+
Deprecated. Use "read_raster_band" instead.
127+
128+
:param raster_source:
129+
:param bnd_ndx:
130+
:return:
131+
"""
119132

120133
# get raster parameters and data
121134
try:
@@ -128,6 +141,113 @@ def try_read_raster_band(raster_source: str, bnd_ndx: int=1) -> Tuple[bool, Unio
128141
return True, (geotransform, projection, band_params, data)
129142

130143

144+
def read_raster_band(raster_source: str, bnd_ndx: int = 1, epsg_cd: int = -1) -> Optional[GeoArray]:
145+
"""
146+
Read parameters and values of a raster band.
147+
Since it is not immediate to get the EPSG code of the input raster,
148+
the user is advised to provide it directly in the function call.
149+
150+
151+
:param raster_source: the raster path.
152+
:param bnd_ndx: the optional band index.
153+
:param epsg_cd: the EPSG code of the raster.
154+
:return: the band as a geoarray.
155+
:rtype: Optional GeoArray.
156+
"""
157+
158+
try:
159+
160+
dataset, geotransform, num_bands, projection = read_raster(raster_source)
161+
band_params, data = read_band(dataset, bnd_ndx)
162+
ga = GeoArray(
163+
inGeotransform=geotransform,
164+
epsg_cd=epsg_cd,
165+
inLevels=[data]
166+
)
167+
168+
return ga
169+
170+
except:
171+
172+
return None
173+
174+
175+
def try_write_esrigrid(geoarray: GeoArray, outgrid_flpth: str, esri_nullvalue: Number=GRID_NULL_VALUE, level_ndx: int=0) -> Tuple[bool, str]:
176+
"""
177+
Writes ESRI ascii grid.
178+
179+
:param geoarray:
180+
:param outgrid_flpth:
181+
:param esri_nullvalue:
182+
:param level_ndx: index of the level array to write.
183+
:type level_ndx: int.
184+
:return: success and descriptive message
185+
:rtype: tuple made up by a boolean and a string
186+
"""
187+
188+
outgrid_flpth = str(outgrid_flpth)
189+
190+
out_fldr, out_flnm = os.path.split(outgrid_flpth)
191+
if not out_flnm.lower().endswith('.asc'):
192+
out_flnm += '.asc'
193+
194+
outgrid_flpth = os.path.join(
195+
out_fldr,
196+
out_flnm
197+
)
198+
199+
# checking existence of output slope grid
200+
201+
if os.path.exists(outgrid_flpth):
202+
return False, "Output grid '{}' already exists".format(outgrid_flpth)
203+
204+
try:
205+
outputgrid = open(outgrid_flpth, 'w') # create the output ascii file
206+
except Exception:
207+
return False, "Unable to create output grid '{}'".format(outgrid_flpth)
208+
209+
if outputgrid is None:
210+
return False, "Unable to create output grid '{}'".format(outgrid_flpth)
211+
212+
if geoarray.has_rotation:
213+
return False, "Grid has axes rotations defined"
214+
215+
cell_size_x = geoarray.src_cellsize_j
216+
cell_size_y = geoarray.src_cellsize_i
217+
218+
if not areClose(cell_size_x, cell_size_y):
219+
return False, "Cell sizes in the x- and y- directions are not similar"
220+
221+
arr = geoarray.level(level_ndx)
222+
if arr is None:
223+
return False, "Array with index {} does not exist".format(level_ndx)
224+
225+
num_rows, num_cols = arr.shape
226+
llc_x, llc_y = geoarray.level_llc(level_ndx)
227+
228+
# writes header of grid ascii file
229+
230+
outputgrid.write("NCOLS %d\n" % num_cols)
231+
outputgrid.write("NROWS %d\n" % num_rows)
232+
outputgrid.write("XLLCORNER %.8f\n" % llc_x)
233+
outputgrid.write("YLLCORNER %.8f\n" % llc_y)
234+
outputgrid.write("CELLSIZE %.8f\n" % cell_size_x)
235+
outputgrid.write("NODATA_VALUE %.8f\n" % esri_nullvalue)
236+
237+
esrigrid_outvalues = np.where(np.isnan(arr), esri_nullvalue, arr)
238+
239+
# output of results
240+
241+
for i in range(0, num_rows):
242+
for j in range(0, num_cols):
243+
outputgrid.write("%.8f " % (esrigrid_outvalues[i, j]))
244+
outputgrid.write("\n")
245+
246+
outputgrid.close()
247+
248+
return True, "Data saved in {}".format(outgrid_flpth)
249+
250+
131251
if __name__ == "__main__":
132252

133253
import doctest

vfc_main.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,17 @@
22

33
from builtins import object
44

5-
import os
6-
7-
from builtins import object
8-
import numpy as np
9-
10-
11-
import webbrowser
12-
135
from qgis.PyQt.QtCore import *
146

157

168
from qgis.PyQt.QtGui import *
179
from qgis.PyQt.QtWidgets import *
1810

1911
from qgis.core import *
20-
21-
22-
from . import resources
23-
2412
from .qgis_utils.gui import *
2513

14+
from . import resources # maintain however
15+
2616

2717
from .main_dialog import MainDialog, HelpDialog
2818

0 commit comments

Comments
 (0)