Utilities¶
Module specs, logging and serialization¶
utils
¶
Module construction, experiment logging, serialization and image operators.
JSONLogger
¶
Logger that appends timestamped records to a JSON file.
Records are pretty-printed JSON objects separated by newlines. Read them with
read_json_records or iter_json_records.
Parameters:
-
path(str | PathLike[str] | None, default:None) –File to append to;
Noneor an empty path disables writing.
Source code in inro/utils.py
log
¶
Append a JSON-serializable record with a UTC ISO 8601 timestamp.
Parameters:
-
entry(Mapping[str, Any]) –Record to append; its own
timestamp, if any, takes precedence.
Source code in inro/utils.py
build_module
¶
build_module(spec: ModuleSpec, registry: Mapping[str, type[Module]], *args: Any, **kwargs: Any) -> Module
Build a module from an instance, registry key, class, or (key/class, params).
An instance is returned unchanged. Otherwise the class receives *args,
**params and **kwargs.
Parameters:
-
spec(ModuleSpec) –Module instance, key, class, or a key or class paired with parameters, in a tuple or a list, so that specs can come from JSON.
-
registry(Mapping[str, type[Module]]) –Mapping from string keys to module classes.
-
*args(Any, default:()) –Positional arguments of the constructor.
-
**kwargs(Any, default:{}) –Keyword arguments of the constructor, which must not repeat
params.
Raises:
-
ValueError–If
spechas another form. -
KeyError–If the key is not in
registry.
Examples:
>>> build_module(("linear", {"bias": False}), {"linear": nn.Linear}, 4, 2)
Linear(in_features=4, out_features=2, bias=False)
Source code in inro/utils.py
count_parameters
¶
Count parameters as real numbers, counting complex elements twice.
Counting real components makes real and complex models comparable.
Parameters:
-
model(Module) –Module whose parameters are counted.
-
trainable_only(bool, default:True) –Whether to count only parameters with
requires_grad=True.
Examples:
Source code in inro/utils.py
setup_experiment_loggers
¶
setup_experiment_loggers(log_dir: str | PathLike[str] | None, logger_name: str, log_filename: str = 'log.txt', json_filename: str = 'log.json', mode: Literal['w', 'a'] = 'w') -> tuple[Logger, JSONLogger]
Configure console, text and JSON logging for an experiment.
Replaces the named logger's handlers and disables propagation. The console shows
INFO messages, written around a progress bar rather than through it, and the
text file DEBUG ones as well. JSON records always append.
Parameters:
-
log_dir(str | PathLike[str] | None) –Directory of the logs, created if needed;
Nonewrites no files. -
logger_name(str) –Name passed to
logging.getLogger. -
log_filename(str, default:'log.txt') –Name of the text log within
log_dir. -
json_filename(str, default:'log.json') –Name of the JSON log within
log_dir. -
mode(Literal['w', 'a'], default:'w') –"w"truncates the text log first;"a"appends, so that training and evaluation can share the file.
Returns:
-
tuple[Logger, JSONLogger]–The text logger and the JSON logger, which writes nothing without
log_dir.
Source code in inro/utils.py
iter_json_records
¶
Yield records from a stream of JSON objects, including pretty-printed logs.
Parsing stops at the first malformed or incomplete record, so an interrupted final write is ignored.
Parameters:
-
path(str | PathLike[str]) –JSON log file.
Yields:
-
dict[str, Any]–Each record as a dictionary.
Source code in inro/utils.py
read_json_records
¶
Read all records that iter_json_records yields.
Parameters:
-
path(str | PathLike[str]) –JSON log file.
sobel_gradients
¶
sobel_gradients(image: Tensor, normalize: bool = True, padding_mode: Literal['constant', 'reflect', 'replicate', 'circular'] = 'replicate') -> tuple[Tensor, Tensor]
Return per-channel Sobel gradients (gx, gy) of a channels-last batch.
gx points along increasing columns and gy along increasing rows. Computation
uses float32.
Parameters:
-
image(Tensor) –Image batch.
-
normalize(bool, default:True) –Whether to divide the kernels by 8, so that a unit ramp has unit gradient.
-
padding_mode(Literal['constant', 'reflect', 'replicate', 'circular'], default:'replicate') –Mode of the one-pixel padding;
"constant"pads with zeros.
Shape
- Input:
(B, H, W, channels). - Output: Two tensors
(B, H, W, channels).
Examples:
>>> ramp = torch.arange(4.0).expand(4, 4)[None, :, :, None]
>>> gx, gy = sobel_gradients(ramp)
>>> gx[0, 1, 1, 0].item(), gy[0, 1, 1, 0].item()
(1.0, 0.0)
Source code in inro/utils.py
encode_dict
¶
Serialize a tensor dictionary to bytes with torch.save.
To round-trip through decode_dict, values must be tensors, primitive types
or standard containers accepted by torch.load(weights_only=True).
Parameters:
-
data(dict[str, Any]) –Dictionary to serialize.
-
compress(bool, default:True) –Whether to compress with gzip.
Examples:
>>> encoded = encode_dict({"weight": torch.ones(2)})
>>> decode_dict(encoded)["weight"].tolist()
[1.0, 1.0]
Source code in inro/utils.py
decode_dict
¶
Deserialize encode_dict output, loading tensors onto the CPU.
Loading uses PyTorch's default weights_only=True.
Parameters:
-
encoded(bytes) –Serialized dictionary.
-
compressed(bool, default:True) –Whether
encodedis gzipped, matching the encoder'scompress.
Source code in inro/utils.py
read_config
¶
Read a UTF-8 JSON configuration file.
Parameters:
-
path(str | PathLike[str]) –File to read.
save_results
¶
save_results(results: Sequence[dict[str, Any]], save_dir: str | PathLike[str], prefix: str = '') -> None
Write records to save_dir/{prefix}_results.json, replacing any existing file.
Parameters:
-
results(Sequence[dict[str, Any]]) –JSON-serializable records.
-
save_dir(str | PathLike[str]) –Output directory, created if needed.
-
prefix(str, default:'') –Prefix of the file name.
Source code in inro/utils.py
add_sensor_noise
¶
add_sensor_noise(image: Tensor, readout_noise_std: float = 1.0, integration_time: float = 1.0, seed: int = 0) -> Tensor
Simulate photon shot noise and Gaussian readout noise.
The image is scaled to photon counts, Poisson-sampled and perturbed by Gaussian
noise, then divided by the integration time and clamped to [0, 1].
Parameters:
-
image(Tensor) –Image in
[0, 1]. -
readout_noise_std(float, default:1.0) –Gaussian standard deviation in count units.
-
integration_time(float, default:1.0) –Photon-count scale; longer exposures reduce relative noise.
-
seed(int, default:0) –Seed of the global PyTorch RNG.
Returns:
-
Tensor–Noisy float32 image, with the shape and device of
image.
Source code in inro/utils.py
render_mesh
¶
render_mesh(mesh_path: str | PathLike[str], image_path: str | PathLike[str], width: int = 1920, height: int = 1080) -> None
Render a mesh to an image with a hidden Open3D window (3d extra).
Parameters:
-
mesh_path(str | PathLike[str]) –Mesh file loaded with trimesh; a scene is joined into one mesh.
-
image_path(str | PathLike[str]) –Output image, whose suffix sets the format.
-
width(int, default:1920) –Image width in pixels.
-
height(int, default:1080) –Image height in pixels.
Source code in inro/utils.py
radon
¶
Compute a sinogram by rotating the image and summing along its height.
Rotations use Kornia's bilinear interpolation and zero padding.
Parameters:
-
image(Tensor) –Image
(1, channels, H, W). -
angles(Tensor) –Angles
(A,)in degrees, on the image's device.
Returns:
-
Tensor–Sinogram
(A, channels, W), with singleton dimensions removed.
Source code in inro/utils.py
Plotting¶
visualization
¶
Plotting helpers for experiment results.
LinePlot
¶
LinePlot(data: DataFrame | Mapping[str, Sequence[Any]] | Sequence[dict[str, Any]], columns: Sequence[str] | None = None)
Seaborn line plot of tabular results, such as rate-distortion curves.
Parameters:
-
data(DataFrame | Mapping[str, Sequence[Any]] | Sequence[dict[str, Any]]) –Results in any form
pandas.DataFrameaccepts: a DataFrame, a mapping from column names to sequences, or a sequence of record dictionaries. -
columns(Sequence[str] | None, default:None) –Columns passed to
pandas.DataFrame;Nonekeeps all columns.
Attributes:
-
data–The results as a
pandas.DataFrame. -
fig(Figure | None) –Figure created by the last
plotcall, orNone. -
ax(Axes | None) –Axes created by the last
plotcall, orNone.
Examples:
>>> records = [
... {"bpp": 0.1, "psnr": 30.0, "method": "FUTON"},
... {"bpp": 0.2, "psnr": 33.0, "method": "FUTON"},
... ]
>>> plot = LinePlot(records)
>>> fig, ax = plot.plot(x="bpp", y="psnr", hue="method")
>>> plot.save("figures", "rate_distortion")
Source code in inro/visualization.py
plot
¶
plot(x: str, y: str, hue: str, xlim: tuple[float | None, float | None] = (None, None), ylim: tuple[float | None, float | None] = (None, None), legend_labels: Sequence[str] | None = None, legend_loc: str = 'lower right', **kwargs: Any) -> tuple[Figure, Axes]
Draw lines grouped by hue and store the resulting fig and ax.
Parameters:
-
x(str) –Column of the x-axis.
-
y(str) –Column of the y-axis.
-
hue(str) –Column defining both line color and style.
-
xlim(tuple[float | None, float | None], default:(None, None)) –Left and right limits;
Nonekeeps a limit automatic. -
ylim(tuple[float | None, float | None], default:(None, None)) –Bottom and top limits;
Nonekeeps a limit automatic. -
legend_labels(Sequence[str] | None, default:None) –Existing labels to keep in the legend, in order, matching exactly;
Noneuses thehuevalues in order of appearance, which must be strings. -
legend_loc(str, default:'lower right') –Legend location accepted by
matplotlib.axes.Axes.legend. -
**kwargs(Any, default:{}) –Passed to
seaborn.lineplot, such as aggregation options.
Returns:
-
tuple[Figure, Axes]–The new figure and axes.
Source code in inro/visualization.py
save
¶
Save the last plot to save_dir/{file_name}.{format} with tight bounds.
Call plot first.
Parameters:
-
save_dir(str | PathLike[str], default:'.') –Output directory, created if needed.
-
file_name(str, default:'') –File name without extension; must not be empty, for matplotlib to recognize the extension.
-
format(str, default:'pdf') –Extension of the file, which sets its format.