Example #1
0
 def write_default_header(self):
     imf = self.image_file
     imf.extensionsAdd("", libe57.E57_V1_0_URI)
     self.root.set("formatName", libe57.StringNode(imf, "ASTM E57 3D Imaging Data File"))
     self.root.set("guid", libe57.StringNode(imf, "{%s}" % uuid.uuid4()))
     self.root.set("versionMajor", libe57.IntegerNode(imf, libe57.E57_FORMAT_MAJOR))
     self.root.set("versionMinor", libe57.IntegerNode(imf, libe57.E57_FORMAT_MINOR))
     self.root.set("e57LibraryVersion", libe57.StringNode(imf, libe57.E57_LIBRARY_ID))
     self.root.set("coordinateMetadata", libe57.StringNode(imf, ""))
     creation_date_time = libe57.StructureNode(imf)
     creation_date_time.set("dateTimeValue", libe57.FloatNode(imf, 0.0))
     creation_date_time.set("isAtomicClockReferenced", libe57.IntegerNode(imf, 0))
     self.root.set("creationDateTime", creation_date_time)
     self.root.set("data3D", libe57.VectorNode(imf, True))
     self.root.set("images2D", libe57.VectorNode(imf, True))
def test_get_data3d_nodes(e57_path):
    f = libe57.ImageFile(e57_path, "r")
    root = f.root()
    node = root.get("data3D")
    data3d = libe57.VectorNode(node)
    scan_count = data3d.childCount()
    assert scan_count == 4
    for scan_id in range(scan_count):
        assert isinstance(data3d.get(scan_id), libe57.Node)
def image_and_points(e57_path):
    f = libe57.ImageFile(e57_path, mode="r")
    scan_0 = libe57.StructureNode(
        libe57.VectorNode(f.root().get("/data3D")).get(0))
    points = libe57.CompressedVectorNode(scan_0.get("points"))
    return f, points
def test_get_read_data3d(e57_path):
    f = libe57.ImageFile(e57_path, "r")
    scan_0 = libe57.StructureNode(
        libe57.VectorNode(f.root().get("/data3D")).get(0))
    points = libe57.CompressedVectorNode(scan_0.get("points"))
    assert points.childCount() == 281300
Example #5
0
    def write_scan_raw(self,
                       data: Dict,
                       *,
                       name=None,
                       rotation=None,
                       translation=None,
                       scan_header=None):
        for field in data.keys():
            if field not in SUPPORTED_POINT_FIELDS:
                raise ValueError("Unsupported point field: %s" % field)

        if rotation is None:
            rotation = getattr(scan_header, "rotation", np.array([1, 0, 0, 0]))

        if translation is None:
            translation = getattr(scan_header, "translation",
                                  np.array([0, 0, 0]))

        if name is None:
            name = getattr(scan_header, "name", "Scan %s" % len(self.data3d))

        temperature = getattr(scan_header, "temperature", 0)
        relativeHumidity = getattr(scan_header, "relativeHumidity", 0)
        atmosphericPressure = getattr(scan_header, "atmosphericPressure", 0)

        scan_node = libe57.StructureNode(self.image_file)
        scan_node.set(
            "guid", libe57.StringNode(self.image_file, "{%s}" % uuid.uuid4()))
        scan_node.set("name", libe57.StringNode(self.image_file, name))
        scan_node.set("temperature",
                      libe57.FloatNode(self.image_file, temperature))
        scan_node.set("relativeHumidity",
                      libe57.FloatNode(self.image_file, relativeHumidity))
        scan_node.set("atmosphericPressure",
                      libe57.FloatNode(self.image_file, atmosphericPressure))
        scan_node.set(
            "description",
            libe57.StringNode(self.image_file, "pye57 v%s" % __version__))

        n_points = data["cartesianX"].shape[0]

        ibox = libe57.StructureNode(self.image_file)
        if "rowIndex" in data and "columnIndex" in data:
            min_row = np.min(data["rowIndex"])
            max_row = np.max(data["rowIndex"])
            min_col = np.min(data["columnIndex"])
            max_col = np.max(data["columnIndex"])
            ibox.set("rowMinimum", libe57.IntegerNode(self.image_file,
                                                      min_row))
            ibox.set("rowMaximum", libe57.IntegerNode(self.image_file,
                                                      max_row))
            ibox.set("columnMinimum",
                     libe57.IntegerNode(self.image_file, min_col))
            ibox.set("columnMaximum",
                     libe57.IntegerNode(self.image_file, max_col))
        else:
            ibox.set("rowMinimum", libe57.IntegerNode(self.image_file, 0))
            ibox.set("rowMaximum",
                     libe57.IntegerNode(self.image_file, n_points - 1))
            ibox.set("columnMinimum", libe57.IntegerNode(self.image_file, 0))
            ibox.set("columnMaximum", libe57.IntegerNode(self.image_file, 0))
        ibox.set("returnMinimum", libe57.IntegerNode(self.image_file, 0))
        ibox.set("returnMaximum", libe57.IntegerNode(self.image_file, 0))
        scan_node.set("indexBounds", ibox)

        if "intensity" in data:
            int_min = getattr(scan_header, "intensityMinimum",
                              np.min(data["intensity"]))
            int_max = getattr(scan_header, "intensityMaximum",
                              np.max(data["intensity"]))
            intbox = libe57.StructureNode(self.image_file)
            intbox.set("intensityMinimum",
                       libe57.FloatNode(self.image_file, int_min))
            intbox.set("intensityMaximum",
                       libe57.FloatNode(self.image_file, int_max))
            scan_node.set("intensityLimits", intbox)

        color = all(c in data for c in ["colorRed", "colorGreen", "colorBlue"])
        if color:
            colorbox = libe57.StructureNode(self.image_file)
            colorbox.set("colorRedMinimum",
                         libe57.IntegerNode(self.image_file, 0))
            colorbox.set("colorRedMaximum",
                         libe57.IntegerNode(self.image_file, 255))
            colorbox.set("colorGreenMinimum",
                         libe57.IntegerNode(self.image_file, 0))
            colorbox.set("colorGreenMaximum",
                         libe57.IntegerNode(self.image_file, 255))
            colorbox.set("colorBlueMinimum",
                         libe57.IntegerNode(self.image_file, 0))
            colorbox.set("colorBlueMaximum",
                         libe57.IntegerNode(self.image_file, 255))
            scan_node.set("colorLimits", colorbox)

        bbox_node = libe57.StructureNode(self.image_file)
        x, y, z = data["cartesianX"], data["cartesianY"], data["cartesianZ"]
        valid = None
        if "cartesianInvalidState" in data:
            valid = ~data["cartesianInvalidState"].astype("?")
            x, y, z = x[valid], y[valid], z[valid]
        bb_min = np.array([x.min(), y.min(), z.min()])
        bb_max = np.array([x.max(), y.max(), z.max()])
        del valid, x, y, z

        if scan_header is not None:
            bb_min_scaled = np.array([
                scan_header.xMinimum, scan_header.yMinimum,
                scan_header.zMinimum
            ])
            bb_max_scaled = np.array([
                scan_header.xMaximum, scan_header.yMaximum,
                scan_header.zMaximum
            ])
        else:
            bb_min_scaled = self.to_global(bb_min.reshape(-1, 3), rotation,
                                           translation)[0]
            bb_max_scaled = self.to_global(bb_max.reshape(-1, 3), rotation,
                                           translation)[0]

        bbox_node.set("xMinimum",
                      libe57.FloatNode(self.image_file, bb_min_scaled[0]))
        bbox_node.set("xMaximum",
                      libe57.FloatNode(self.image_file, bb_max_scaled[0]))
        bbox_node.set("yMinimum",
                      libe57.FloatNode(self.image_file, bb_min_scaled[1]))
        bbox_node.set("yMaximum",
                      libe57.FloatNode(self.image_file, bb_max_scaled[1]))
        bbox_node.set("zMinimum",
                      libe57.FloatNode(self.image_file, bb_min_scaled[2]))
        bbox_node.set("zMaximum",
                      libe57.FloatNode(self.image_file, bb_max_scaled[2]))
        scan_node.set("cartesianBounds", bbox_node)

        if rotation is not None and translation is not None:
            pose_node = libe57.StructureNode(self.image_file)
            scan_node.set("pose", pose_node)
            rotation_node = libe57.StructureNode(self.image_file)
            rotation_node.set("w",
                              libe57.FloatNode(self.image_file, rotation[0]))
            rotation_node.set("x",
                              libe57.FloatNode(self.image_file, rotation[1]))
            rotation_node.set("y",
                              libe57.FloatNode(self.image_file, rotation[2]))
            rotation_node.set("z",
                              libe57.FloatNode(self.image_file, rotation[3]))
            pose_node.set("rotation", rotation_node)
            translation_node = libe57.StructureNode(self.image_file)
            translation_node.set(
                "x", libe57.FloatNode(self.image_file, translation[0]))
            translation_node.set(
                "y", libe57.FloatNode(self.image_file, translation[1]))
            translation_node.set(
                "z", libe57.FloatNode(self.image_file, translation[2]))
            pose_node.set("translation", translation_node)

        start_datetime = getattr(scan_header, "acquisitionStart_dateTimeValue",
                                 0)
        start_atomic = getattr(scan_header,
                               "acquisitionStart_isAtomicClockReferenced",
                               False)
        end_datetime = getattr(scan_header, "acquisitionEnd_dateTimeValue", 0)
        end_atomic = getattr(scan_header,
                             "acquisitionEnd_isAtomicClockReferenced", False)
        acquisition_start = libe57.StructureNode(self.image_file)
        scan_node.set("acquisitionStart", acquisition_start)
        acquisition_start.set(
            "dateTimeValue", libe57.FloatNode(self.image_file, start_datetime))
        acquisition_start.set(
            "isAtomicClockReferenced",
            libe57.IntegerNode(self.image_file, start_atomic))
        acquisition_end = libe57.StructureNode(self.image_file)
        scan_node.set("acquisitionEnd", acquisition_end)
        acquisition_end.set("dateTimeValue",
                            libe57.FloatNode(self.image_file, end_datetime))
        acquisition_end.set("isAtomicClockReferenced",
                            libe57.IntegerNode(self.image_file, end_atomic))

        # todo: pointGroupingSchemes

        points_prototype = libe57.StructureNode(self.image_file)

        is_scaled = False
        precision = libe57.E57_DOUBLE if is_scaled else libe57.E57_SINGLE

        center = (bb_max + bb_min) / 2

        chunk_size = 5000000

        x_node = libe57.FloatNode(self.image_file, center[0], precision,
                                  bb_min[0], bb_max[0])
        y_node = libe57.FloatNode(self.image_file, center[1], precision,
                                  bb_min[1], bb_max[1])
        z_node = libe57.FloatNode(self.image_file, center[2], precision,
                                  bb_min[2], bb_max[2])
        points_prototype.set("cartesianX", x_node)
        points_prototype.set("cartesianY", y_node)
        points_prototype.set("cartesianZ", z_node)

        field_names = ["cartesianX", "cartesianY", "cartesianZ"]

        if "intensity" in data:
            intensity_min = np.min(data["intensity"])
            intensity_max = np.max(data["intensity"])
            intensity_node = libe57.FloatNode(self.image_file, intensity_min,
                                              precision, intensity_min,
                                              intensity_max)
            points_prototype.set("intensity", intensity_node)
            field_names.append("intensity")

        if all(color in data
               for color in ["colorRed", "colorGreen", "colorBlue"]):
            points_prototype.set(
                "colorRed", libe57.IntegerNode(self.image_file, 0, 0, 255))
            points_prototype.set(
                "colorGreen", libe57.IntegerNode(self.image_file, 0, 0, 255))
            points_prototype.set(
                "colorBlue", libe57.IntegerNode(self.image_file, 0, 0, 255))
            field_names.append("colorRed")
            field_names.append("colorGreen")
            field_names.append("colorBlue")

        if "rowIndex" in data and "columnIndex" in data:
            min_row = np.min(data["rowIndex"])
            max_row = np.max(data["rowIndex"])
            min_col = np.min(data["columnIndex"])
            max_col = np.max(data["columnIndex"])
            points_prototype.set(
                "rowIndex",
                libe57.IntegerNode(self.image_file, 0, min_row, max_row))
            field_names.append("rowIndex")
            points_prototype.set(
                "columnIndex",
                libe57.IntegerNode(self.image_file, 0, min_col, max_col))
            field_names.append("columnIndex")

        if "cartesianInvalidState" in data:
            min_state = np.min(data["cartesianInvalidState"])
            max_state = np.max(data["cartesianInvalidState"])
            points_prototype.set(
                "cartesianInvalidState",
                libe57.IntegerNode(self.image_file, 0, min_state, max_state))
            field_names.append("cartesianInvalidState")

        # other fields
        # // "sphericalRange"
        # // "sphericalAzimuth"
        # // "sphericalElevation"
        # // "timeStamp"
        # // "sphericalInvalidState"
        # // "isColorInvalid"
        # // "isIntensityInvalid"
        # // "isTimeStampInvalid"

        arrays, buffers = self.make_buffers(field_names, chunk_size)

        codecs = libe57.VectorNode(self.image_file, True)
        points = libe57.CompressedVectorNode(self.image_file, points_prototype,
                                             codecs)
        scan_node.set("points", points)

        self.data3d.append(scan_node)

        writer = points.writer(buffers)

        current_index = 0
        while current_index != n_points:
            current_chunk = min(n_points - current_index, chunk_size)

            for type_ in SUPPORTED_POINT_FIELDS:
                if type_ in arrays:
                    arrays[type_][:current_chunk] = data[type_][
                        current_index:current_index + current_chunk]

            writer.write(current_chunk)

            current_index += current_chunk

        writer.close()