Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reworking wright-tools entry points #1152

Merged
merged 34 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3404b34
click, add convert
ddkohler Jan 29, 2024
81d3f3e
wt-tree crawl
ddkohler Jan 30, 2024
73cd489
Data.print_tree tweak
ddkohler Jan 30, 2024
ca16c77
wt-tree crawl -p
ddkohler Jan 30, 2024
fd9d75c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 30, 2024
200c557
removing pause from crawl
ddkohler Feb 1, 2024
cce05ef
Update __main__.py
ddkohler Feb 1, 2024
3af74fa
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 1, 2024
bae841e
entry point crawl revision
ddkohler Feb 2, 2024
59984c6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 2, 2024
ce1a822
Update _glob.py
ddkohler Feb 2, 2024
b47e82a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 2, 2024
e6953fa
wt-tree -> wtools
ddkohler Feb 2, 2024
82fe3c1
crawl -> scan
ddkohler Feb 2, 2024
0de18ce
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 2, 2024
b797ef7
change entry points
ddkohler Feb 17, 2024
a4a0a45
Merge branch 'master' into wt-tree
ddkohler Feb 17, 2024
6c59e2a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 17, 2024
28ebbb2
refactor cli
ddkohler Feb 19, 2024
a097b42
Update _glob.py
ddkohler Feb 19, 2024
b8e93a9
refactor kit path/glob utils
ddkohler Feb 19, 2024
8e4fbc2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 19, 2024
7757bbb
Update _wt5.py
ddkohler Feb 19, 2024
acc6b36
Update _glob.py
ddkohler Feb 19, 2024
2c4de2c
tree and convert work
ddkohler Feb 19, 2024
fd0ddc5
cleanup
ddkohler Feb 19, 2024
b380fcd
docs
ddkohler Feb 19, 2024
f7d44a6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 19, 2024
ba91121
Update wt_tree.py
ddkohler Feb 20, 2024
f6c2b00
Update _units.py
ddkohler Feb 20, 2024
28a6bef
Update _glob.py
ddkohler Feb 20, 2024
fae48ae
wt5 glob and explore
ddkohler Feb 20, 2024
a1f118d
Update CHANGELOG.md
ddkohler Feb 20, 2024
a05f6b3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).

## [Unreleased]

### Added
- `wt5` entry point: methods `load`, `explore`, `glob`, `tree`
- `wt-convert` entry point: convert a number to different units
- new glob utilities in `kit`

### Changed
- `wt-tree` entry point removed. Use `wt5 tree` instead.

## [3.5.1]

### Added
Expand Down
29 changes: 0 additions & 29 deletions WrightTools/__main__.py

This file was deleted.

2 changes: 2 additions & 0 deletions WrightTools/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import _units
from . import _wt5
50 changes: 50 additions & 0 deletions WrightTools/cli/_units.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# --- import --------------------------------------------------------------------------------------


import click
from WrightTools import __version__ as __wt_version__
from WrightTools.units import is_valid_conversion, get_valid_conversions, convert
from WrightTools.exceptions import UnitsError


# --- define --------------------------------------------------------------------------------------


@click.command(name="convert", help="convert numbers to different units.")
@click.version_option(__wt_version__, prog_name="WrightTools")
@click.argument("number", type=float, nargs=1)
@click.argument("unit", nargs=1)
@click.argument("destination_unit", default=None, nargs=-1)
def cli(number, unit, destination_unit=None):
"""Convert numbers to different units."""

if int(number) == number:
number = int(number)
sig_figs = len(str(number))
sig_figs -= 1 if "." in str(number) else 0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guess we are presuming no Europeans who use commas instead of decimal points...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Europeans have to use . when working with python anyways (unless they change default formatting). In any case, I don't see our notation as a meaningful hindrance. I am fine with the syntax as is until someone raises an issue.

def fmt(new):
exponent = int(f"{new:e}".split("e")[1])
if exponent > 6 or exponent < -3:
return f"{new:{sig_figs}e}"
else: # if a "normal" size number
if sig_figs - exponent <= 0:
return f"{int(round(new, sig_figs-exponent))}"
else:
return f"{round(new, sig_figs-exponent)}"

if len(destination_unit): # units provided
destination_unit = destination_unit[0]
if not is_valid_conversion(unit, destination_unit):
raise UnitsError(get_valid_conversions(unit), destination_unit)
new = convert(number, unit, destination_unit)
print(f"{number} {unit} = {fmt(new)} {destination_unit}")
else:
valid_units = get_valid_conversions(unit)
for d_unit in valid_units:
new = convert(number, unit, d_unit)
print(f"{fmt(new)} {d_unit}")


if __name__ == "__main__":
cli()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a CLI?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a feature request (issue #653). A quick entry point to check how units convert (according to wright tools)

150 changes: 150 additions & 0 deletions WrightTools/cli/_wt5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# --- import --------------------------------------------------------------------------------------


import click
import WrightTools as wt


# --- define --------------------------------------------------------------------------------------


@click.group()
@click.version_option(wt.__version__, prog_name="WrightTools")
def cli():
pass


@cli.command(name="tree", help="Print a given data tree.")
@click.argument("path", nargs=1)
@click.option(
"--internal_path", default="/", help="specify a path internal to the file. Defaults to root"
)
@click.option("--depth", "-d", "-L", type=int, default=9, help="Depth to print.")
@click.option("--verbose", "-v", is_flag=True, default=False, help="Print a more detailed tree.")
def tree(path, internal_path, depth=9, verbose=False):
# open the object
obj = wt.open(path)[internal_path]

if isinstance(obj, wt.Data):
obj.print_tree(verbose=verbose)
else:
obj.print_tree(verbose=verbose, depth=depth)


@cli.command(name="load", help="Open a python cli with the object pre-loaded.")
@click.argument("path")
def load(path):
import code

shell = code.InteractiveConsole()
_interact(shell, path)


@cli.command(name="glob", help="Find paths to all wt5 files within a directory.")
@click.option(
"--directory", "-d", default=None, help="Directory to scan. Defaults to current directory."
)
@click.option("--no-recursion", is_flag=True, help="Turns recursive scan off.")
def glob(directory=None, no_recursion=False):
for path in wt.kit.glob_wt5s(directory, not no_recursion):
print(str(path))


@cli.command(name="explore", help="Scan a directory and survey the wt5 objects found.")
@click.option(
"--directory", "-d", default=None, help="Directory to scan. Defaults to current directory."
)
@click.option("--no-recursion", is_flag=True, help="Turns recursive scan off.")
# TODO: formatting options (e.g. json)?
def scan(directory=None, no_recursion=False):
import os, code
from rich.live import Live
from rich.table import Table

if directory is None:
directory = os.getcwd()

table = Table(title=directory)
table.add_column("", justify="right") # index
table.add_column("path", max_width=60, no_wrap=True, style="blue")
table.add_column("size (MB)", justify="center", style="blue")
table.add_column("created", max_width=30, style="blue")
table.add_column("name", style="blue")
table.add_column("shape", style="blue")
table.add_column("axes", max_width=50, style="blue")
table.add_column("variables", style="blue")
table.add_column("channels", style="blue")

update_title = lambda n: directory + f" ({n} wt5 file{'s' if n != 1 else None} found)"
paths = []

with Live(table) as live:
for i, path in enumerate(wt.kit.glob_wt5s(directory, not no_recursion)):
desc = wt.kit.describe_wt5(path)
desc["filesize"] = f"{os.path.getsize(path) / 1e6:.1f}"
path = path.relative_to(directory)
paths.append(path)
desc["path"] = (
f"[link={path.parent}]{path.parent}[/link]" + r"\\"
if str(path.parent) != "."
else ""
)
desc["path"] += f"[bold]{path.name}[/bold]"
# desc["path"] = f"[link={str(path)}]{path}[/link]"
row = [f"{i}"] + [
str(desc[k])
for k in ["path", "filesize", "created", "name", "shape", "axes", "nvars", "nchan"]
]
table.title = update_title(i + 1)
table.add_row(*row)
live.update(table)

# give option to interact
def raise_sys_exit():
raise SystemExit

shell = code.InteractiveConsole(locals={"exit": raise_sys_exit, "quit": raise_sys_exit})

while True:
msg = shell.raw_input(
" ".join(
[
"Specify an index to load that entry.",
"Use `t` to rerender table.",
"Use no argument to exit.",
]
)
)
if msg == "t":
with Live(table) as live:
pass
continue
try:
valid = 0 <= int(msg) < len(paths)
except ValueError:
break
if valid:
print("interacting...")
_interact(shell, str(paths[int(msg)]))
continue


def _interact(shell, path):
lines = [
"import WrightTools as wt",
"import matplotlib.pyplot as plt",
f"d = wt.open(r'{path}')",
]

[shell.push(line) for line in lines]
banner = "--- INTERACTING --- (to continue, call exit() or quit())\n"
banner += "\n".join([">>> " + line for line in lines])

try:
shell.interact(banner=banner)
except SystemExit:
pass


if __name__ == "__main__":
cli()
16 changes: 8 additions & 8 deletions WrightTools/data/_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,30 +272,30 @@ def print_leaves(prefix, lis, vline=True):

if verbose:
# axes
print(prefix + "├── axes")
print(prefix + f"├── axes ({len(self.axes)})")
print_leaves(prefix, self.axes)
# constants
print(prefix + "├── constants")
print(prefix + f"├── constants ({len(self.constants)})")
print_leaves(prefix, self.constants)
# variables
print(prefix + "├── variables")
print(prefix + f"├── variables ({len(self.variables)})")
print_leaves(prefix, self.variables)
# channels
print(prefix + "└── channels")
print(prefix + f"└── channels ({len(self.channels)})")
print_leaves(prefix, self.channels, vline=False)
else:
# axes
s = "axes: "
s = f"axes ({len(self.axes)}): "
s += ", ".join(["{0} ({1})".format(a.expression, a.units) for a in self.axes])
print(prefix + "├── " + s)
# constants
s = "constants: "
s = f"constants ({len(self.constants)}): "
s += ", ".join(
["{0} ({1} {2})".format(a.expression, a.value, a.units) for a in self.constants]
)
print(prefix + "├── " + s)
# channels
s = "channels: "
s = f"channels ({len(self.channels)}): "
s += ", ".join(self.channel_names)
print(prefix + "└── " + s)

Expand Down Expand Up @@ -1506,7 +1506,7 @@ def offset(

def print_tree(self, *, verbose=True):
"""Print a ascii-formatted tree representation of the data contents."""
print("{0} ({1})".format(self.natural_name, self.filepath))
print("{0} ({1}) {2}".format(self.natural_name, self.filepath, self.shape))
self._print_branch("", depth=0, verbose=verbose)

def prune(self, keep_channels=True, *, verbose=True):
Expand Down
1 change: 1 addition & 0 deletions WrightTools/kit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
from ._timestamp import *
from ._unicode import *
from ._utilities import *
from ._glob import *
Loading
Loading