Files
nerfstudio/mattport/utils/writer.py
T
2022-05-09 11:11:00 -07:00

153 lines
5.2 KiB
Python

"""
Generic Writer class
"""
import os
from abc import abstractmethod
from typing import Any, Dict
import imageio
import numpy as np
import torch
from omegaconf import DictConfig
from torch.utils.tensorboard import SummaryWriter
from torchtyping import TensorType
import mattport.utils.writer
from mattport.utils import comms
from mattport.utils.decorators import check_main_thread, decorate_all
to8b = lambda x: (255 * torch.clamp(x, min=0, max=1)).to(torch.uint8)
EVENT_WRITERS = []
def write_event(args: Dict[str, Any]):
"""write out values for all the event writers"""
assert comms.is_main_process(), "Writing out with process other than main"
for writer in EVENT_WRITERS:
if "x" in args:
writer.write_image(**args)
elif "scalar" in args:
writer.write_scalar(**args)
elif "scalar_dict" in args:
writer.write_scalar_dict(**args)
else:
raise NotImplementedError
def setup_event_writers(config: DictConfig) -> None:
"""Initialization of all event writers specified in config"""
if comms.is_main_process():
for writer_type in config:
curr_writer = getattr(mattport.utils.writer, writer_type)
EVENT_WRITERS.append(curr_writer(config[writer_type].save_dir))
def get_tensorboard_name(name: str, group: str = None, prefix: str = None):
"""Returns a string for tensorboard with an optional group and prefix.
Where tensorboard_name has the form `group/prefix-name`.
"""
group_string = f"{group}/" if group else ""
prefix_string = f"{prefix}" if prefix else ""
tensorboard_name = f"{group_string}{prefix_string}{name}"
return tensorboard_name
class Writer:
"""Writer class"""
def __init__(self, save_dir: str):
self.save_dir = save_dir
@abstractmethod
def write_image(
self, name: str, x: TensorType["H", "W", "C"], step: int, group: str = None, prefix: str = None
) -> None:
"""_summary_
Args:
name (str): data identifier
x (TensorType["H", "W", "C"]): rendered image to write
step (int): the time step to log
group (str): the group e.g., "Loss", "Accuracy", "Time"
prefix (str): the prefix e.g., "train-", "test-"
"""
raise NotImplementedError
@abstractmethod
def write_scalar(self, name: str, scalar: float, step: int, group: str = None, prefix: str = None) -> None:
"""Required method to write a single scalar value to the logger
Args:
name (str): data identifier
step (int): the time step to log
group (str): the group e.g., "Loss", "Accuracy", "Time"
prefix (str): the prefix e.g., "train-", "test-"
"""
raise NotImplementedError
@check_main_thread
def write_scalar_dict(
self, scalar_dict: Dict[str, float], step: int, group: str = None, prefix: str = None
) -> None:
"""Function that writes out all scalars from a given dictionary to the logger
Args:
scalar_dict (dict): dictionary containing all scalar values with key names and quantities
step (int): the time step to log
group (str): the group e.g., "Loss", "Accuracy", "Time"
prefix (str): the prefix e.g., "train-", "test-"
"""
for name, scalar in scalar_dict.items():
self.write_scalar(name, scalar, step, group=group, prefix=prefix)
@decorate_all([check_main_thread])
class TensorboardWriter(Writer):
"""Tensorboard Writer Class"""
def __init__(self, save_dir: str):
super().__init__(save_dir)
self.tb_writer = SummaryWriter(log_dir=self.save_dir)
def write_image(
self, name: str, x: TensorType["H", "W", "C"], step: int, group: str = None, prefix: str = None
) -> None:
"""_summary_
Args:
name (str): data identifier
x (TensorType["H", "W", "C"]): rendered image to write
"""
x = to8b(x)
tensorboard_name = get_tensorboard_name(name, group=group, prefix=prefix)
self.tb_writer.add_image(tensorboard_name, x, step, dataformats="HWC")
def write_scalar(self, name: str, scalar: float, step: int, group: str = None, prefix: str = None) -> None:
"""Tensorboard method to write a single scalar value to the logger
Args:
name (str): data identifier
x (float): x value to write
y (float): y value to write
group (str)): a prefix to group tensorboard scalars
"""
tensorboard_name = get_tensorboard_name(name, group=group, prefix=prefix)
self.tb_writer.add_scalar(tensorboard_name, scalar, step)
@decorate_all([check_main_thread])
class LocalWriter(Writer):
"""Local Writer Class"""
def write_image(
self, name: str, x: TensorType["H", "W", "C"], step: int, group: str = None, prefix: str = None
) -> None:
x = to8b(x)
image_path = os.path.join(self.save_dir, f"{name}.jpg")
imageio.imwrite(image_path, np.uint8(x.cpu().numpy() * 255.0))
def write_scalar(self, name: str, scalar: float, step: int, group: str = None, prefix: str = None) -> None:
raise NotImplementedError