Source code for laspy._compression.selection

import enum


def decompress_and_skip_methods(wrapped_enum):
    """This decorator is to be applied on an enum.IntFlag class

    It will add to this enum some methods:

    - set(self, flag_name) -> Self => to easily set a flag
    - unset(self, flag_name) -> Self => to easily unset a flag
    - is_set(self, flag_name) -> bool => to easily check if a flag is set


    If will also add for each flag member (as long as their name is uppercase)
    the following methods

    - decompress_$flag(self) -> Self
    - skip_$flag(self) -> Self


    # Example

    @load_and_skip_methods
    class Color(IntFlag):
        RED = 1
        GREEN = 2
        BLUE = 4


    will generate (ellipsis to keep it short)

    class Color(IntFlag):
        RED = 1
        GREEN = 2

    def _set(self, mask): ...

    def _unset(self, mask): ...

    def is_set(self, mask): ...


    def decompress_red(self) -> Color: ...
    def decompress_red(self) -> Color : ...
    def is_set_red(self) -> Color : ...
    def load_green(self) -> Color: ...
    def skip_green(self) -> Color: ...
    def is_set_green(self) -> Color : ...
    """

    def set_method(self, mask) -> wrapped_enum:
        return self | mask

    def unset_method(self, mask) -> wrapped_enum:
        return self & (~mask)

    def is_set_method(self, mask) -> bool:
        return (self & mask) != 0

    setattr(wrapped_enum, "_set", set_method)
    setattr(wrapped_enum, "_unset", unset_method)
    setattr(wrapped_enum, "is_set", is_set_method)

    def define_skip_method(mask_member_name: str):
        def skip_method(self):
            return self._unset(getattr(self, mask_member_name))

        return skip_method

    def define_decompress_method(mask_member_name: str):
        def decompress_method(self):
            return self._set(getattr(self, mask_member_name))

        return decompress_method

    def define_is_set_method(mask_member_name: str):
        def is_set_method(self):
            return self.is_set(getattr(self, mask_member_name))

        return is_set_method

    for member in dir(wrapped_enum):
        if not member.isupper():
            continue

        load_name = f"decompress_{member.lower()}"
        skip_name = f"skip_{member.lower()}"
        is_set_name = f"is_set_{member.lower()}"

        setattr(wrapped_enum, load_name, define_decompress_method(member))
        setattr(wrapped_enum, skip_name, define_skip_method(member))
        setattr(wrapped_enum, is_set_name, define_is_set_method(member))

    return wrapped_enum


[docs]@decompress_and_skip_methods class DecompressionSelection(enum.IntFlag): """ Holds which fields to decompress or not. Only used for files with version >= 1.4 && point format id >= 6. Ignored on other cases. Each flag in the enum has a corresponding ``decompress_$name`` and ``skip_$name`` methods to easily create a selection. >>> import laspy >>> # Creating a selection that decompresses the base + z field >>> selection = laspy.DecompressionSelection.base().decompress_z() >>> selection.is_set(laspy.DecompressionSelection.Z) True >>> selection.is_set(laspy.DecompressionSelection.INTENSITY) False >>> # Creating a selection that decompresses all fields but the intensity >>> selection = laspy.DecompressionSelection.all().skip_intensity() >>> selection.is_set(laspy.DecompressionSelection.INTENSITY) False >>> selection.is_set(laspy.DecompressionSelection.Z) True .. versionadded:: 2.4 """ #: Flag to decompress x, y, return number, number of returns and scanner channel XY_RETURNS_CHANNEL = enum.auto() #: Flag to decompress z Z = enum.auto() #: Flag to decompress the classification CLASSIFICATION = enum.auto() #: Flag to decompress the classification flags (withheld, key point, overlap, etc) FLAGS = enum.auto() #: Flag to decompress the intensity INTENSITY = enum.auto() #: Flag to decompress the scan angle SCAN_ANGLE = enum.auto() #: Flag to decompress the user data USER_DATA = enum.auto() #: Flag to decompress the point source id POINT_SOURCE_ID = enum.auto() #: Flag to decompress the gps time GPS_TIME = enum.auto() #: Flag to decompress the red, green, blue RGB = enum.auto() #: Flag to decompress the nir NIR = enum.auto() #: Flag to decompress the wavepacket WAVEPACKET = enum.auto() #: Flag to decompress all the extra bytes ALL_EXTRA_BYTES = enum.auto()
[docs] @classmethod def all(cls) -> "DecompressionSelection": """Returns a selection where all fields will be decompressed""" selection = cls.base() for flag in cls: selection = selection._set(flag) return selection
[docs] @classmethod def base(cls) -> "DecompressionSelection": """ Returns a decompression selection where only the base x, y, return number, number of returns and scanner channel will be decompressed """ return cls.xy_returns_channel()
[docs] @classmethod def xy_returns_channel(cls) -> "DecompressionSelection": """ Returns a decompression selection where only the base x, y, return number, number of returns and scanner channel will be decompressed """ return cls.XY_RETURNS_CHANNEL
[docs] def to_lazrs(self) -> "lazrs.DecompressionSelection": import lazrs variant_mapping = { DecompressionSelection.XY_RETURNS_CHANNEL: lazrs.SELECTIVE_DECOMPRESS_XY_RETURNS_CHANNEL, DecompressionSelection.Z: lazrs.SELECTIVE_DECOMPRESS_Z, DecompressionSelection.CLASSIFICATION: lazrs.SELECTIVE_DECOMPRESS_CLASSIFICATION, DecompressionSelection.FLAGS: lazrs.SELECTIVE_DECOMPRESS_FLAGS, DecompressionSelection.INTENSITY: lazrs.SELECTIVE_DECOMPRESS_INTENSITY, DecompressionSelection.SCAN_ANGLE: lazrs.SELECTIVE_DECOMPRESS_SCAN_ANGLE, DecompressionSelection.USER_DATA: lazrs.SELECTIVE_DECOMPRESS_USER_DATA, DecompressionSelection.POINT_SOURCE_ID: lazrs.SELECTIVE_DECOMPRESS_POINT_SOURCE_ID, DecompressionSelection.GPS_TIME: lazrs.SELECTIVE_DECOMPRESS_GPS_TIME, DecompressionSelection.RGB: lazrs.SELECTIVE_DECOMPRESS_RGB, DecompressionSelection.NIR: lazrs.SELECTIVE_DECOMPRESS_NIR, DecompressionSelection.WAVEPACKET: lazrs.SELECTIVE_DECOMPRESS_WAVEPACKET, DecompressionSelection.ALL_EXTRA_BYTES: lazrs.SELECTIVE_DECOMPRESS_ALL_EXTRA_BYTES, } lazrs_selection = lazrs.SELECTIVE_DECOMPRESS_XY_RETURNS_CHANNEL for variant in DecompressionSelection: lazrs_selection |= variant_mapping[variant] if self.is_set(variant) else 0 return lazrs.DecompressionSelection(lazrs_selection)
[docs] def to_laszip(self) -> int: import laszip variant_mapping = { DecompressionSelection.XY_RETURNS_CHANNEL: laszip.DECOMPRESS_SELECTIVE_CHANNEL_RETURNS_XY, DecompressionSelection.Z: laszip.DECOMPRESS_SELECTIVE_Z, DecompressionSelection.CLASSIFICATION: laszip.DECOMPRESS_SELECTIVE_CLASSIFICATION, DecompressionSelection.FLAGS: laszip.DECOMPRESS_SELECTIVE_FLAGS, DecompressionSelection.INTENSITY: laszip.DECOMPRESS_SELECTIVE_INTENSITY, DecompressionSelection.SCAN_ANGLE: laszip.DECOMPRESS_SELECTIVE_SCAN_ANGLE, DecompressionSelection.USER_DATA: laszip.DECOMPRESS_SELECTIVE_USER_DATA, DecompressionSelection.POINT_SOURCE_ID: laszip.DECOMPRESS_SELECTIVE_POINT_SOURCE, DecompressionSelection.GPS_TIME: laszip.DECOMPRESS_SELECTIVE_GPS_TIME, DecompressionSelection.RGB: laszip.DECOMPRESS_SELECTIVE_RGB, DecompressionSelection.NIR: laszip.DECOMPRESS_SELECTIVE_NIR, DecompressionSelection.WAVEPACKET: laszip.DECOMPRESS_SELECTIVE_WAVEPACKET, DecompressionSelection.ALL_EXTRA_BYTES: laszip.DECOMPRESS_SELECTIVE_EXTRA_BYTES, } laszip_selection = laszip.DECOMPRESS_SELECTIVE_CHANNEL_RETURNS_XY for variant in DecompressionSelection: laszip_selection |= variant_mapping[variant] if self.is_set(variant) else 0 return laszip_selection