Module julius.utils

Non signal processing related utilities.

Expand source code Browse git
# File under the MIT license, see https://github.com/adefossez/julius/LICENSE for details.
# Author: adefossez, 2020
"""
Non signal processing related utilities.
"""

import inspect
import typing as tp
import sys
import time


def simple_repr(obj, attrs: tp.Optional[tp.Sequence[str]] = None,
                overrides: dict = {}):
    """
    Return a simple representation string for `obj`.
    If `attrs` is not None, it should be a list of attributes to include.
    """
    params = inspect.signature(obj.__class__).parameters
    attrs_repr = []
    if attrs is None:
        attrs = list(params.keys())
    for attr in attrs:
        display = False
        if attr in overrides:
            value = overrides[attr]
        elif hasattr(obj, attr):
            value = getattr(obj, attr)
        else:
            continue
        if attr in params:
            param = params[attr]
            if param.default is inspect._empty or value != param.default:  # type: ignore
                display = True
        else:
            display = True

        if display:
            attrs_repr.append(f"{attr}={value}")
    return f"{obj.__class__.__name__}({','.join(attrs_repr)})"


class MarkdownTable:
    """
    Simple MarkdownTable generator. The column titles should be large enough
    for the lines content. This will right align everything.

    >>> import io  # we use io purely for test purposes, default is sys.stdout.
    >>> file = io.StringIO()
    >>> table = MarkdownTable(["Item Name", "Price"], file=file)
    >>> table.header(); table.line(["Honey", "5"]); table.line(["Car", "5,000"])
    >>> print(file.getvalue().strip())  # Strip for test purposes
    | Item Name | Price |
    |-----------|-------|
    |     Honey |     5 |
    |       Car | 5,000 |
    """
    def __init__(self, columns, file=sys.stdout):
        self.columns = columns
        self.file = file

    def _writeln(self, line):
        self.file.write("|" + "|".join(line) + "|\n")

    def header(self):
        self._writeln(f" {col} " for col in self.columns)
        self._writeln("-" * (len(col) + 2) for col in self.columns)

    def line(self, line):
        out = []
        for val, col in zip(line, self.columns):
            val = format(val, '>' + str(len(col)))
            out.append(" " + val + " ")
        self._writeln(out)


class Chrono:
    """
    Measures ellapsed time, calling `torch.cuda.synchronize` if necessary.
    `Chrono` instances can be used as context managers (e.g. with `with`).
    Upon exit of the block, you can access the duration of the block in seconds
    with the `duration` attribute.

    >>> with Chrono() as chrono:
    ...     _ = sum(range(10_000))
    ...
    >>> print(chrono.duration < 10)  # Should be true unless on a really slow computer.
    True
    """
    def __init__(self):
        self.duration = None

    def __enter__(self):
        self._begin = time.time()
        return self

    def __exit__(self, exc_type, exc_value, exc_tracebck):
        import torch
        if torch.cuda.is_available():
            torch.cuda.synchronize()
        self.duration = time.time() - self._begin

Functions

def simple_repr(obj, attrs: Optional[Sequence[str]] = None, overrides: dict = {})

Return a simple representation string for obj. If attrs is not None, it should be a list of attributes to include.

Expand source code Browse git
def simple_repr(obj, attrs: tp.Optional[tp.Sequence[str]] = None,
                overrides: dict = {}):
    """
    Return a simple representation string for `obj`.
    If `attrs` is not None, it should be a list of attributes to include.
    """
    params = inspect.signature(obj.__class__).parameters
    attrs_repr = []
    if attrs is None:
        attrs = list(params.keys())
    for attr in attrs:
        display = False
        if attr in overrides:
            value = overrides[attr]
        elif hasattr(obj, attr):
            value = getattr(obj, attr)
        else:
            continue
        if attr in params:
            param = params[attr]
            if param.default is inspect._empty or value != param.default:  # type: ignore
                display = True
        else:
            display = True

        if display:
            attrs_repr.append(f"{attr}={value}")
    return f"{obj.__class__.__name__}({','.join(attrs_repr)})"

Classes

class Chrono

Measures ellapsed time, calling torch.cuda.synchronize if necessary. Chrono instances can be used as context managers (e.g. with with). Upon exit of the block, you can access the duration of the block in seconds with the duration attribute.

>>> with Chrono() as chrono:
...     _ = sum(range(10_000))
...
>>> print(chrono.duration < 10)  # Should be true unless on a really slow computer.
True
Expand source code Browse git
class Chrono:
    """
    Measures ellapsed time, calling `torch.cuda.synchronize` if necessary.
    `Chrono` instances can be used as context managers (e.g. with `with`).
    Upon exit of the block, you can access the duration of the block in seconds
    with the `duration` attribute.

    >>> with Chrono() as chrono:
    ...     _ = sum(range(10_000))
    ...
    >>> print(chrono.duration < 10)  # Should be true unless on a really slow computer.
    True
    """
    def __init__(self):
        self.duration = None

    def __enter__(self):
        self._begin = time.time()
        return self

    def __exit__(self, exc_type, exc_value, exc_tracebck):
        import torch
        if torch.cuda.is_available():
            torch.cuda.synchronize()
        self.duration = time.time() - self._begin
class MarkdownTable (columns, file=sys.stdout)

Simple MarkdownTable generator. The column titles should be large enough for the lines content. This will right align everything.

>>> import io  # we use io purely for test purposes, default is sys.stdout.
>>> file = io.StringIO()
>>> table = MarkdownTable(["Item Name", "Price"], file=file)
>>> table.header(); table.line(["Honey", "5"]); table.line(["Car", "5,000"])
>>> print(file.getvalue().strip())  # Strip for test purposes
| Item Name | Price |
|-----------|-------|
|     Honey |     5 |
|       Car | 5,000 |
Expand source code Browse git
class MarkdownTable:
    """
    Simple MarkdownTable generator. The column titles should be large enough
    for the lines content. This will right align everything.

    >>> import io  # we use io purely for test purposes, default is sys.stdout.
    >>> file = io.StringIO()
    >>> table = MarkdownTable(["Item Name", "Price"], file=file)
    >>> table.header(); table.line(["Honey", "5"]); table.line(["Car", "5,000"])
    >>> print(file.getvalue().strip())  # Strip for test purposes
    | Item Name | Price |
    |-----------|-------|
    |     Honey |     5 |
    |       Car | 5,000 |
    """
    def __init__(self, columns, file=sys.stdout):
        self.columns = columns
        self.file = file

    def _writeln(self, line):
        self.file.write("|" + "|".join(line) + "|\n")

    def header(self):
        self._writeln(f" {col} " for col in self.columns)
        self._writeln("-" * (len(col) + 2) for col in self.columns)

    def line(self, line):
        out = []
        for val, col in zip(line, self.columns):
            val = format(val, '>' + str(len(col)))
            out.append(" " + val + " ")
        self._writeln(out)

Methods

def header(self)
Expand source code Browse git
def header(self):
    self._writeln(f" {col} " for col in self.columns)
    self._writeln("-" * (len(col) + 2) for col in self.columns)
def line(self, line)
Expand source code Browse git
def line(self, line):
    out = []
    for val, col in zip(line, self.columns):
        val = format(val, '>' + str(len(col)))
        out.append(" " + val + " ")
    self._writeln(out)