• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lunarlab-gatech / robotdataprocess / 20868268100

09 Jan 2026 11:10PM UTC coverage: 70.585% (-4.1%) from 74.672%
20868268100

Pull #10

github

DanielChaseButterfield
Remove tutrle import
Pull Request #10: (v0.2) Prototype code for ROS2 Publishing, and new ImageDataOnDisk class

508 of 747 new or added lines in 12 files covered. (68.01%)

3 existing lines in 2 files now uncovered.

1411 of 1999 relevant lines covered (70.59%)

1.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

51.92
/src/robotdataprocess/data_types/ImageData/ImageDataOnDisk.py
1
from __future__ import annotations
2✔
2

3
from ...conversion_utils import col_to_dec_arr
2✔
4
from .ImageData import ImageData
2✔
5
import numpy as np
2✔
6
from pathlib import Path
2✔
7
from PIL import Image
2✔
8
from typeguard import typechecked
2✔
9
from typing import Union, List
2✔
10

11
@typechecked
2✔
12
class ImageDataOnDisk(ImageData):
2✔
13

14
    class LazyImageArray:
2✔
15
        """A read-only array-like interface that loads PNG images from disk on demand."""
16
        
17
        height: int
2✔
18
        width: int
2✔
19
        encoding: ImageData.ImageEncoding
2✔
20
        image_paths: List[Path]
2✔
21

22
        def __init__(self, height: int, width: int, encoding: ImageData.ImageEncoding, image_paths: List[Path]):
2✔
NEW
23
            self.height = height
×
NEW
24
            self.width = width
×
NEW
25
            self.encoding = encoding
×
NEW
26
            self.image_paths = image_paths
×
27

28
        def __getitem__(self, idx) -> np.ndarray:
2✔
NEW
29
            path: Path = self.image_paths[idx]
×
NEW
30
            return np.array(Image.open(str(path)), dtype=self.dtype)
×
31

32
        def __setitem__(self, idx, value):
2✔
NEW
33
            raise RuntimeError("This LazyPNGArray is read-only; writes are forbidden.")
×
34
    
35
        def __len__(self):
2✔
NEW
36
            return len(self.image_paths)
×
37

38
        @property
2✔
39
        def shape(self):
2✔
NEW
40
            _, channels = ImageData.ImageEncoding.to_dtype_and_channels(self.encoding)
×
NEW
41
            if channels == 1:
×
NEW
42
                return (len(self), self.height, self.width)
×
43
            else:
NEW
44
                return (len(self), self.height, self.width, 3)
×
45

46
        @property
2✔
47
        def dtype(self):
2✔
NEW
48
            dtype_val, _ = ImageData.ImageEncoding.to_dtype_and_channels(self.encoding)
×
NEW
49
            return dtype_val
×
50
        
51
    images: ImageDataOnDisk.LazyImageArray # Not initalized here, but put here for visual code highlighting
2✔
52

53
    def __init__(self, frame_id: str, timestamps: Union[np.ndarray, list], images: ImageDataOnDisk.LazyImageArray):
2✔
NEW
54
        super().__init__(frame_id, timestamps, images.height, images.width, images.encoding, images)
×
55

56
    # =========================================================================
57
    # ============================ Class Methods ============================== 
58
    # =========================================================================  
59

60
    @classmethod
2✔
61
    def from_image_files(cls, image_folder_path: Union[Path, str], frame_id: str) -> ImageDataOnDisk:
2✔
62
        """
63
        Creates a class structure from a folder with .png files, using the file names
64
        as the timestamps.
65

66
        Args:
67
            image_folder_path (Path | str): Path to the folder with the images.
68
            frame_id (str): The frame where this image data was collected.
69
        Returns:
70
            ImageDataOnDisk: Instance of this class.
71
        """
72

73
        # Get all png files in the designated folder (sorted)
NEW
74
        all_image_files = [str(p) for p in Path(image_folder_path).glob("*.png")]
×
75

76
        # Extract the timestamps and sort them
NEW
77
        timestamps = col_to_dec_arr([s.split('/')[-1][:-4] for s in all_image_files])
×
NEW
78
        sorted_indices = np.argsort(timestamps)
×
NEW
79
        timestamps_sorted = timestamps[sorted_indices]
×
80

81
        # Use sorted_indices to sort all_image_files in the same way
NEW
82
        all_image_files_sorted: List[Path] = [Path(all_image_files[i]) for i in sorted_indices]
×
83

84
        # Make sure the mode is what we expect
NEW
85
        with Image.open(str(all_image_files_sorted[0])) as first_image:
×
NEW
86
            encoding = ImageData.ImageEncoding.from_pillow_str(first_image.mode)
×
NEW
87
            if encoding != ImageData.ImageEncoding.RGB8 and encoding != ImageData.ImageEncoding.Mono8:
×
NEW
88
                raise NotImplementedError(f"Unsupported encoding {encoding} for 'from_image_files' method!")
×
89
        
90
        # Return an ImageDataOnDisk class
NEW
91
        return cls(frame_id, timestamps_sorted, cls.LazyImageArray(first_image.height, first_image.width, encoding, all_image_files_sorted))
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc