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

Fix QgsRasterLayer and QgsRasterBlock as_numpy methods #60275

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
88 changes: 62 additions & 26 deletions python/PyQt6/core/__init__.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -569,11 +569,15 @@ try:
raise ValueError(f"The raster block data type '{str(self.dataType())}' is not compatible with NumPy arrays.")
src_array = _numpy.frombuffer(self.data(), dtype=raster_dtype)
src_array = src_array.reshape((self.height(), self.width()))
if not self.hasNoDataValue() or not use_masking:
return src_array
else:
no_data_value = self.noDataValue() if isinstance(self.noDataValue(), raster_dtype) else 0
if use_masking:
if not self.hasNoDataValue():
# Default to 0 as noDataValue if none is set
no_data_value = 0
else:
no_data_value = self.noDataValue()
return _numpy.ma.masked_equal(src_array, no_data_value)
else:
return src_array

QgsRasterBlock.as_numpy = _raster_block_as_numpy

Expand All @@ -586,34 +590,66 @@ try:
src_array = block.as_numpy(use_masking=use_masking)
arrays.append(src_array)

return _numpy.array(arrays) # This converts any maskedArrays to numpy.array
if use_masking:
return _numpy.ma.stack(arrays, axis=0)
else:
return _numpy.array(arrays)

QgsRasterLayer.as_numpy = _raster_layer_as_numpy

def _qgsgeometry_as_numpy(self) -> _typing.Union[_numpy.ndarray, _typing.List[_numpy.ndarray]]:
wkb_type = self.wkbType()
hasM = QgsWkbTypes.hasM(wkb_type)
hasZ = QgsWkbTypes.hasZ(wkb_type)
geometry_type = self.type()

def get_xyzm_coordinates(pt):
if hasZ and hasM:
return _numpy.array([pt.x(), pt.y(), pt.z(), pt.m()])
elif hasZ:
return _numpy.array([pt.x(), pt.y(), pt.z()])
elif hasM:
return _numpy.array([pt.x(), pt.y(), pt.m()])
else:
return _numpy.array([pt.x(), pt.y()])

def fill_structure_with_elements(lst: _typing.List, elements: _typing.List, idx: int=0):
for i in range(len(lst)):
if isinstance(lst[i], list):
idx = fill_structure_with_elements(lst[i], elements, idx)
else:
lst[i] = _numpy.array(elements[idx])
idx += 1
return idx

if self.isMultipart():
if self.type() == QgsWkbTypes.PointGeometry:
# MultiPoint
return [_numpy.array([pt.x(), pt.y()]) for pt in self.asMultiPoint()]
elif self.type() == QgsWkbTypes.LineGeometry:
# MultiLineString
return [_numpy.array([[pt.x(), pt.y()] for pt in line]) for line in self.asMultiPolyline()]
elif self.type() == QgsWkbTypes.PolygonGeometry:
# MultiPolygon
return [
[_numpy.array([[pt.x(), pt.y()] for pt in ring]) for ring in polygon]
for polygon in self.asMultiPolygon()
]
elements = [get_xyzm_coordinates(i) for i in self.vertices()]

if geometry_type == QgsWkbTypes.PointGeometry:
skeleton = self.asMultiPoint()
fill_structure_with_elements(skeleton, elements)
return skeleton

elif geometry_type == QgsWkbTypes.LineGeometry:
skeleton = self.asMultiPolyline()
fill_structure_with_elements(skeleton, elements)
return skeleton

elif geometry_type == QgsWkbTypes.PolygonGeometry:
skeleton = self.asMultiPolygon()
fill_structure_with_elements(skeleton, elements)
return skeleton
else:
if self.type() == QgsWkbTypes.PointGeometry:
point = self.asPoint()
return _numpy.array([point.x(), point.y()])
elif self.type() == QgsWkbTypes.LineGeometry:
line = self.asPolyline()
return _numpy.array([[pt.x(), pt.y()] for pt in line])
elif self.type() == QgsWkbTypes.PolygonGeometry:
polygon = self.asPolygon()
return _numpy.array([_numpy.array([[pt.x(), pt.y()] for pt in ring]) for ring in polygon])
if geometry_type == QgsWkbTypes.PointGeometry:
return _numpy.array([get_xyzm_coordinates(i) for i in self.vertices()][0])
elif geometry_type == QgsWkbTypes.LineGeometry:
line = self.vertices()
return _numpy.array([get_xyzm_coordinates(pt) for pt in line])
elif geometry_type == QgsWkbTypes.PolygonGeometry:
skeleton = self.asPolygon()
elements = [get_xyzm_coordinates(i) for i in self.vertices()]
fill_structure_with_elements(skeleton, elements)
return _numpy.array(skeleton)


QgsGeometry.as_numpy = _qgsgeometry_as_numpy
Expand Down
88 changes: 62 additions & 26 deletions python/core/__init__.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -579,11 +579,15 @@ try:
raise ValueError(f"The raster block data type '{str(self.dataType())}' is not compatible with NumPy arrays.")
src_array = _numpy.frombuffer(self.data(), dtype=raster_dtype)
src_array = src_array.reshape((self.height(), self.width()))
if not self.hasNoDataValue() or not use_masking:
return src_array
else:
no_data_value = self.noDataValue() if isinstance(self.noDataValue(), raster_dtype) else 0
if use_masking:
if not self.hasNoDataValue():
# Default to 0 as noDataValue if none is set
no_data_value = 0
else:
no_data_value = self.noDataValue()
return _numpy.ma.masked_equal(src_array, no_data_value)
else:
return src_array

QgsRasterBlock.as_numpy = _raster_block_as_numpy

Expand All @@ -596,34 +600,66 @@ try:
src_array = block.as_numpy(use_masking=use_masking)
arrays.append(src_array)

return _numpy.array(arrays) # This converts any maskedArrays to numpy.array
if use_masking:
return _numpy.ma.stack(arrays, axis=0)
else:
return _numpy.array(arrays)

QgsRasterLayer.as_numpy = _raster_layer_as_numpy

def _qgsgeometry_as_numpy(self) -> _typing.Union[_numpy.ndarray, _typing.List[_numpy.ndarray]]:
wkb_type = self.wkbType()
hasM = QgsWkbTypes.hasM(wkb_type)
hasZ = QgsWkbTypes.hasZ(wkb_type)
geometry_type = self.type()

def get_xyzm_coordinates(pt):
if hasZ and hasM:
return _numpy.array([pt.x(), pt.y(), pt.z(), pt.m()])
elif hasZ:
return _numpy.array([pt.x(), pt.y(), pt.z()])
elif hasM:
return _numpy.array([pt.x(), pt.y(), pt.m()])
else:
return _numpy.array([pt.x(), pt.y()])

def fill_structure_with_elements(lst: _typing.List, elements: _typing.List, idx: int=0):
for i in range(len(lst)):
if isinstance(lst[i], list):
idx = fill_structure_with_elements(lst[i], elements, idx)
else:
lst[i] = _numpy.array(elements[idx])
idx += 1
return idx

if self.isMultipart():
if self.type() == QgsWkbTypes.PointGeometry:
# MultiPoint
return [_numpy.array([pt.x(), pt.y()]) for pt in self.asMultiPoint()]
elif self.type() == QgsWkbTypes.LineGeometry:
# MultiLineString
return [_numpy.array([[pt.x(), pt.y()] for pt in line]) for line in self.asMultiPolyline()]
elif self.type() == QgsWkbTypes.PolygonGeometry:
# MultiPolygon
return [
[_numpy.array([[pt.x(), pt.y()] for pt in ring]) for ring in polygon]
for polygon in self.asMultiPolygon()
]
elements = [get_xyzm_coordinates(i) for i in self.vertices()]

if geometry_type == QgsWkbTypes.PointGeometry:
skeleton = self.asMultiPoint()
fill_structure_with_elements(skeleton, elements)
return skeleton

elif geometry_type == QgsWkbTypes.LineGeometry:
skeleton = self.asMultiPolyline()
fill_structure_with_elements(skeleton, elements)
return skeleton

elif geometry_type == QgsWkbTypes.PolygonGeometry:
skeleton = self.asMultiPolygon()
fill_structure_with_elements(skeleton, elements)
return skeleton
else:
if self.type() == QgsWkbTypes.PointGeometry:
point = self.asPoint()
return _numpy.array([point.x(), point.y()])
elif self.type() == QgsWkbTypes.LineGeometry:
line = self.asPolyline()
return _numpy.array([[pt.x(), pt.y()] for pt in line])
elif self.type() == QgsWkbTypes.PolygonGeometry:
polygon = self.asPolygon()
return _numpy.array([_numpy.array([[pt.x(), pt.y()] for pt in ring]) for ring in polygon])
if geometry_type == QgsWkbTypes.PointGeometry:
return _numpy.array([get_xyzm_coordinates(i) for i in self.vertices()][0])
elif geometry_type == QgsWkbTypes.LineGeometry:
line = self.vertices()
return _numpy.array([get_xyzm_coordinates(pt) for pt in line])
elif geometry_type == QgsWkbTypes.PolygonGeometry:
skeleton = self.asPolygon()
elements = [get_xyzm_coordinates(i) for i in self.vertices()]
fill_structure_with_elements(skeleton, elements)
return _numpy.array(skeleton)


QgsGeometry.as_numpy = _qgsgeometry_as_numpy
Expand Down
Loading
Loading