def parse_point_data_file(ifp, op=None):
        """Parse a point data file.

        Supported file formats are: :code:`.ply`, :code:`.pcd`, :code:`.las`,
        :code:`.laz`, :code:`.asc`, :code:`.pts` and :code:`.csv`.

        Relies on the :code:`pyntcloud`, the :code:`laspy` and/or the
        :code:`lazrs` library to parse the different file formats.
        """

        log_report("INFO", "Parse Point Data File: ...", op)
        # https://pyntcloud.readthedocs.io/en/latest/io.html
        # https://www.cloudcompare.org/doc/wiki/index.php?title=FILE_I/O
        module_spec = importlib.util.find_spec("pyntcloud")
        if module_spec is None:
            log_report(
                "ERROR",
                "Importing this file type requires the pyntcloud library.",
                op,
            )
            assert False
        from pyntcloud import PyntCloud

        assert os.path.isfile(ifp)
        ext = os.path.splitext(ifp)[1].lower()
        if ext in [".asc", ".pts"]:
            sep = " "
            data_semantics = (
                PointDataFileHandler._get_data_semantics_from_ascii(
                    ifp, sep, has_header=True, op=op
                )
            )
            names = PointDataFileHandler._convert_data_semantics_to_list(
                data_semantics
            )
            point_cloud = PyntCloud.from_file(
                ifp, sep=sep, header=0, names=names
            )
            pseudo_color = data_semantics.pseudo_color
        elif ext == ".csv":
            sep = ","
            data_semantics = (
                PointDataFileHandler._get_data_semantics_from_ascii(
                    ifp, sep, has_header=False, op=op
                )
            )
            names = PointDataFileHandler._convert_data_semantics_to_list(
                data_semantics
            )
            point_cloud = PyntCloud.from_file(
                ifp, sep=sep, header=0, names=names
            )
            pseudo_color = data_semantics.pseudo_color
        else:
            pseudo_color = False
            point_cloud = PyntCloud.from_file(ifp)
        xyz_arr = point_cloud.points.loc[:, ["x", "y", "z"]].to_numpy()
        if {"red", "green", "blue"}.issubset(point_cloud.points.columns):
            color_arr = point_cloud.points.loc[
                :, ["red", "green", "blue"]
            ].to_numpy()
            if 0 <= np.min(color_arr) <= 1 and 0 <= np.max(color_arr) <= 1:
                # if all color values are set in between zero and one
                # scale to be in range from 0.0 to 255.0
                pseudo_color = True
            if pseudo_color:
                color_arr *= 255
        else:
            color_arr = np.ones_like(xyz_arr) * 255
        num_points = xyz_arr.shape[0]
        points = []
        for idx in range(num_points):
            point = Point(
                coord=xyz_arr[idx].astype("float64"),
                color=color_arr[idx].astype("int"),
                id=idx,
                scalars=dict(),
            )
            points.append(point)
        log_report("INFO", f"Number Points {len(points)}", op)
        log_report("INFO", "Parse Point Data File: Done", op)
        return points
Parse a point data file.

        Supported file formats are: :code:`.ply`, :code:`.pcd`, :code:`.las`,
        :code:`.laz`, :code:`.asc`, :code:`.pts` and :code:`.csv`.

        Relies on the :code:`pyntcloud`, the :code:`laspy` and/or the
        :code:`lazrs` library to parse the different file formats.
        
photogrammetry_importer/file_handlers/point_data_file_handler.py