Skip to content

modosaic.services.experiment

modosaic.services.experiment

ExperimentService

ExperimentService(root='experiments', experiment_name=None)

Persist generated artifacts below one experiment directory.

Attributes:

Name Type Description
experiment_path Path

Directory where this run writes artifacts.

Initialize an experiment folder.

Parameters:

Name Type Description Default
root str | Path

Parent directory for experiments.

'experiments'
experiment_name str | None

Optional run directory name. A timestamp is used when omitted.

None
Source code in modosaic/services/experiment.py
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def __init__(
        self,
        root: str | Path = "experiments",
        experiment_name: str | None = None,
):
    """Initialize an experiment folder.

    Args:
        root: Parent directory for experiments.
        experiment_name: Optional run directory name. A timestamp is used
            when omitted.
    """
    current_date = experiment_name or datetime.now().strftime("%Y%m%d-%H%M%S")
    self.experiment_path = Path(root) / current_date
    self.experiment_path.mkdir(parents=True, exist_ok=True)
    logger.debug(f"Experiment artifacts will be saved under {self.experiment_path}")

save_array_artifact

save_array_artifact(relative_path, array)

Save a NumPy array with numpy.save.

Source code in modosaic/services/experiment.py
 94
 95
 96
 97
 98
 99
100
101
def save_array_artifact(self, relative_path: str | Path, array: np.ndarray) -> Path:
    """Save a NumPy array with `numpy.save`."""
    artifact_path = self._artifact_path(relative_path)
    artifact_path.parent.mkdir(parents=True, exist_ok=True)
    with artifact_path.open("wb") as file:
        np.save(file, array)
    logger.debug(f"Saved array artifact to {artifact_path}")
    return artifact_path

save_array_collection_artifact

save_array_collection_artifact(relative_path, arrays)

Save an array collection with numpy.savez.

Source code in modosaic/services/experiment.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def save_array_collection_artifact(
        self,
        relative_path: str | Path,
        arrays: Sequence[np.ndarray] | Mapping[str, np.ndarray],
) -> Path:
    """Save an array collection with `numpy.savez`."""
    artifact_path = self._artifact_path(relative_path)
    artifact_path.parent.mkdir(parents=True, exist_ok=True)
    with artifact_path.open("wb") as file:
        if isinstance(arrays, Mapping):
            np.savez(file, **arrays)
        else:
            np.savez(file, *arrays)
    logger.debug(f"Saved array collection artifact to {artifact_path}")
    return artifact_path

save_artifact

save_artifact(artifact)

Save one artifact using its declared kind.

Parameters:

Name Type Description Default
artifact ExperimentArtifact[Any]

Artifact to persist.

required

Returns:

Type Description
Path

Path written to disk.

Raises:

Type Description
ValueError

If the artifact kind is unsupported.

Source code in modosaic/services/experiment.py
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
def save_artifact(self, artifact: ExperimentArtifact[Any]) -> Path:
    """Save one artifact using its declared kind.

    Args:
        artifact: Artifact to persist.

    Returns:
        Path written to disk.

    Raises:
        ValueError: If the artifact kind is unsupported.
    """
    logger.debug(f"Saving {artifact.kind} artifact to {artifact.relative_path}")
    match artifact.kind:
        case ExperimentArtifactKind.TEXT:
            return self.save_text_artifact(artifact.relative_path, artifact.payload)
        case ExperimentArtifactKind.ARRAY:
            return self.save_array_artifact(artifact.relative_path, artifact.payload)
        case ExperimentArtifactKind.ARRAY_COLLECTION:
            return self.save_array_collection_artifact(artifact.relative_path, artifact.payload)
        case ExperimentArtifactKind.IMAGE:
            return self.save_image_artifact(artifact.relative_path, artifact.payload)
        case ExperimentArtifactKind.JSON:
            return self.save_json_artifact(artifact.relative_path, artifact.payload)
        case ExperimentArtifactKind.BYTES:
            return self.save_bytes_artifact(artifact.relative_path, artifact.payload)
        case _:
            raise ValueError(f"Unsupported experiment artifact kind: {artifact.kind}")

save_artifacts

save_artifacts(artifacts)

Save many artifacts.

Parameters:

Name Type Description Default
artifacts Iterable[ExperimentArtifact[Any]]

Artifact objects to persist.

required

Returns:

Type Description
list[Path]

Paths written to disk.

Source code in modosaic/services/experiment.py
43
44
45
46
47
48
49
50
51
52
53
54
55
def save_artifacts(self, artifacts: Iterable[ExperimentArtifact[Any]]) -> list[Path]:
    """Save many artifacts.

    Args:
        artifacts: Artifact objects to persist.

    Returns:
        Paths written to disk.
    """
    return [
        self.save_artifact(artifact)
        for artifact in artifacts
    ]

save_bytes_artifact

save_bytes_artifact(relative_path, payload)

Save raw bytes below the experiment directory.

Source code in modosaic/services/experiment.py
138
139
140
141
142
143
144
def save_bytes_artifact(self, relative_path: str | Path, payload: bytes) -> Path:
    """Save raw bytes below the experiment directory."""
    artifact_path = self._artifact_path(relative_path)
    artifact_path.parent.mkdir(parents=True, exist_ok=True)
    artifact_path.write_bytes(payload)
    logger.debug(f"Saved bytes artifact to {artifact_path}")
    return artifact_path

save_depth

save_depth(depth, depth_img)

Save legacy depth array and preview image artifacts.

Source code in modosaic/services/experiment.py
150
151
152
153
154
155
156
157
def save_depth(self, depth: np.ndarray, depth_img: Image) -> list[Path]:
    """Save legacy depth array and preview image artifacts."""
    depth_path = Path("depth")

    return [
        self.save_array_artifact(depth_path / "depth.npy", depth),
        self.save_image_artifact(depth_path / "depth.png", depth_img),
    ]

save_image_artifact

save_image_artifact(relative_path, image)

Save a PIL image below the experiment directory.

Source code in modosaic/services/experiment.py
119
120
121
122
123
124
125
def save_image_artifact(self, relative_path: str | Path, image: Image) -> Path:
    """Save a PIL image below the experiment directory."""
    artifact_path = self._artifact_path(relative_path)
    artifact_path.parent.mkdir(parents=True, exist_ok=True)
    image.save(artifact_path)
    logger.debug(f"Saved image artifact to {artifact_path}")
    return artifact_path

save_json_artifact

save_json_artifact(relative_path, payload)

Save a JSON-serializable payload below the experiment directory.

Source code in modosaic/services/experiment.py
127
128
129
130
131
132
133
134
135
136
def save_json_artifact(self, relative_path: str | Path, payload: Any) -> Path:
    """Save a JSON-serializable payload below the experiment directory."""
    artifact_path = self._artifact_path(relative_path)
    artifact_path.parent.mkdir(parents=True, exist_ok=True)
    artifact_path.write_text(
        json.dumps(payload, default=self._json_default, indent=2, sort_keys=True),
        encoding="utf-8",
    )
    logger.debug(f"Saved JSON artifact to {artifact_path}")
    return artifact_path

save_normals

save_normals(normals, normal_img)

Save legacy normals array and preview image artifacts.

Source code in modosaic/services/experiment.py
159
160
161
162
163
164
165
166
def save_normals(self, normals: np.ndarray, normal_img: Image) -> list[Path]:
    """Save legacy normals array and preview image artifacts."""
    normals_path = Path("normals")

    return [
        self.save_array_artifact(normals_path / "normals.npy", normals),
        self.save_image_artifact(normals_path / "normals.png", normal_img),
    ]

save_segmentation_masks

save_segmentation_masks(segmentation_masks, segmentation_masks_img)

Save legacy segmentation mask arrays and preview image artifacts.

Source code in modosaic/services/experiment.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
def save_segmentation_masks(
        self,
        segmentation_masks: list[np.ndarray],
        segmentation_masks_img: Image,
) -> list[Path]:
    """Save legacy segmentation mask arrays and preview image artifacts."""
    segmentation_masks_path = Path("segmentation_masks")

    return [
        self.save_array_collection_artifact(
            segmentation_masks_path / "segmentation_masks.npz",
            segmentation_masks,
        ),
        self.save_image_artifact(
            segmentation_masks_path / "segmentation_masks.png",
            segmentation_masks_img,
        ),
    ]

save_text

save_text(text_caption)

Save a legacy caption artifact under text/result.txt.

Source code in modosaic/services/experiment.py
146
147
148
def save_text(self, text_caption: str) -> Path:
    """Save a legacy caption artifact under `text/result.txt`."""
    return self.save_text_artifact("text/result.txt", text_caption)

save_text_artifact

save_text_artifact(relative_path, text)

Save UTF-8 text below the experiment directory.

Source code in modosaic/services/experiment.py
86
87
88
89
90
91
92
def save_text_artifact(self, relative_path: str | Path, text: str) -> Path:
    """Save UTF-8 text below the experiment directory."""
    artifact_path = self._artifact_path(relative_path)
    artifact_path.parent.mkdir(parents=True, exist_ok=True)
    artifact_path.write_text(text, encoding="utf-8")
    logger.debug(f"Saved text artifact to {artifact_path}")
    return artifact_path