Skip to content
This repository has been archived by the owner on Aug 18, 2022. It is now read-only.

Commit

Permalink
Merge branch 'feature/array-view'
Browse files Browse the repository at this point in the history
  • Loading branch information
tmontaigu committed Sep 24, 2020
2 parents 6c16ead + 8664d12 commit 2fe8118
Show file tree
Hide file tree
Showing 12 changed files with 394 additions and 202 deletions.
6 changes: 0 additions & 6 deletions docs/basic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,6 @@ To access point records using the dimension name, you have 2 options:
>>> np.all(las.user_data == las['user_data'])
True

However if you wish to retrieve the x, y, z coordinates with scale and offset applied
your only option is the first method.

>>> las.x.max().dtype
dtype('float64')

The dimensions available in a file are dictated by the point format id.
The tables in the introduction section contains the list of dimensions for each of the
point format.
Expand Down
7 changes: 0 additions & 7 deletions docs/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,6 @@ your code.
The dimensions 'X', 'Y', 'Z' are signed integers without the scale and
offset applied. To access the coordinates as doubles simply use 'x', 'y' , 'z'

>>> import pylas
>>> las = pylas.read('pylastests/simple.las')
>>> las.X.dtype
dtype('int32')
>>> las.x.dtype
dtype('float64')


Point Format 0
++++++++++++++
Expand Down
74 changes: 22 additions & 52 deletions pylas/lasdatas/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,15 @@

from pylas.vlrs.known import ExtraBytesStruct, ExtraBytesVlr
from .. import errors, extradims
from ..compression import LazBackend
from ..laswriter import LasWriter
from ..point import record, dims, PointFormat
from ..point.record import scale_dimension, unscale_dimension
from ..point.dims import ScaledArrayView
from ..vlrs import vlrlist
from ..compression import LazBackend

logger = logging.getLogger(__name__)


def is_in_bounds_of_type(array, type_info):
return array.max() < type_info.max and array.min() > type_info.min


OVERFLOW_ERR_MSG = (
"Values given for '{}' won't fit in an {} array, with the current scale ({})"
)


class LasBase(object):
"""LasBase is the base of all the different LasData classes.
These classes are objects that the user will interact with to manipulate las data.
Expand Down Expand Up @@ -54,56 +45,35 @@ def __init__(self, *, header, vlrs=None, points=None):
@property
def x(self):
"""Returns the scaled x positions of the points as doubles"""
return scale_dimension(self.X, self.header.x_scale, self.header.x_offset)
return ScaledArrayView(self.X, self.header.x_scale, self.header.x_offset)

@property
def y(self):
"""Returns the scaled y positions of the points as doubles"""
return scale_dimension(self.Y, self.header.y_scale, self.header.y_offset)
return ScaledArrayView(self.Y, self.header.y_scale, self.header.y_offset)

@property
def z(self):
"""Returns the scaled z positions of the points as doubles"""
return scale_dimension(self.Z, self.header.z_scale, self.header.z_offset)
return ScaledArrayView(self.Z, self.header.z_scale, self.header.z_offset)

@x.setter
def x(self, value):
if self.header.x_offset == 0.0:
self.header.x_offset = np.min(value)

X = unscale_dimension(value, self.header.x_scale, self.header.x_offset)
dim_info = self.point_format.dimension_type_info("X")
if not is_in_bounds_of_type(X, dim_info):
raise OverflowError(
OVERFLOW_ERR_MSG.format("x", dim_info.dtype, self.header.x_scale)
)
self.X = X
if len(value) > len(self.points_data):
self.points_data.resize(len(value))
self.x[:] = value

@y.setter
def y(self, value):
if self.header.y_offset == 0.0:
self.header.y_offset = np.min(value)

Y = unscale_dimension(value, self.header.y_scale, self.header.y_offset)
dim_info = self.point_format.dimension_type_info("Y")
if not is_in_bounds_of_type(Y, dim_info):
raise OverflowError(
OVERFLOW_ERR_MSG.format("y", dim_info.dtype, self.header.y_scale)
)
self.Y = Y
if len(value) > len(self.points_data):
self.points_data.resize(len(value))
self.y[:] = value

@z.setter
def z(self, value):
if self.header.z_offset == 0.0:
self.header.z_offset = np.min(value)

Z = unscale_dimension(value, self.header.z_scale, self.header.z_offset)
dim_info = self.point_format.dimension_type_info("Z")
if not is_in_bounds_of_type(Z, dim_info):
raise OverflowError(
OVERFLOW_ERR_MSG.format("z", dim_info.dtype, self.header.z_scale)
)
self.Z = Z
if len(value) > len(self.points_data):
self.points_data.resize(len(value))
self.z[:] = value

@property
def point_format(self):
Expand Down Expand Up @@ -235,7 +205,7 @@ def update_header(self):
self.header.number_of_points_by_return = counts

def write_to(
self, out_stream, do_compress=False, laz_backends=LazBackend.detect_available()
self, out_stream, do_compress=False, laz_backends=LazBackend.detect_available()
):
"""writes the data to a stream
Expand All @@ -247,12 +217,12 @@ def write_to(
Flag to indicate if you want the date to be compressed
"""
with LasWriter(
out_stream,
self.header,
self.vlrs,
do_compress=do_compress,
closefd=False,
laz_backends=laz_backends,
out_stream,
self.header,
self.vlrs,
do_compress=do_compress,
closefd=False,
laz_backends=laz_backends,
) as writer:
writer.write(self.points_data)

Expand Down Expand Up @@ -285,7 +255,7 @@ def write_to_file(self, filename, do_compress=None):
self.write_to(out, do_compress=do_compress)

def write(
self, destination, do_compress=None, laz_backend=LazBackend.detect_available()
self, destination, do_compress=None, laz_backend=LazBackend.detect_available()
):
"""Writes to a stream or file
Expand Down
3 changes: 1 addition & 2 deletions pylas/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from .lasappender import LasAppender
from .point import dims, record, PointFormat

USE_UNPACKED = False
logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -147,7 +146,7 @@ def read_las(source, closefd=True, laz_backend=LazBackend.detect_available()):
>>> las = read_las("pylastests/simple.las")
>>> las.classification
array([1, 1, 1, ..., 1, 1, 1], dtype=uint8)
<SubFieldView([1 1 1 ... 1 1 1])>
Parameters
----------
Expand Down

0 comments on commit 2fe8118

Please sign in to comment.