From 3404b347b0977810812d00cc8f02f69ef2c3f7a2 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:03:23 -0600 Subject: [PATCH 01/33] click, add convert --- WrightTools/__main__.py | 74 +++++++++++++++++++++++++++++++++-------- setup.py | 3 +- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index aedc5dff3..7187b9f95 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -1,29 +1,77 @@ # --- import -------------------------------------------------------------------------------------- +import click import WrightTools as wt -import argparse # --- define -------------------------------------------------------------------------------------- -def wt_tree(): - parser = argparse.ArgumentParser(description="Print a given data tree.") +@click.group() +@click.version_option(wt.__version__) +def cli(): + pass - # Add arguments - parser.add_argument("path", type=str) - parser.add_argument("--verbose", "-v", action="store_true", help="Verbose? False by default") - parser.add_argument("--depth", "-d", "-L", type=int, default=9, help="depth to print (int)") - parser.add_argument("internal_path", nargs="?", default="/") - args = parser.parse_args() +@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): # Create the data/collection object - obj = wt.open(args.path)[args.internal_path] + obj = wt.open(path)[internal_path] - # Print the tree # If the object is a data object, it doesn't take depth as a parameter if isinstance(obj, wt.Data): - obj.print_tree(verbose=args.verbose) + obj.print_tree(verbose=verbose) else: - obj.print_tree(verbose=args.verbose, depth=args.depth) + obj.print_tree(verbose=verbose, depth=depth) + + +@cli.command(name="crawl", help="Crawl a directory and report the wt5 objects found.") +@click.argument("directory", default=".") +def crawl(directory=None): + ... + +@cli.command(name="convert", help="Convert numbers to different units.") +@click.argument("number", type=float, nargs=1) +@click.argument("unit", nargs=1) +@click.argument("destination_unit", default=None, nargs=-1) +def convert(number, unit, destination_unit=None): + + def gen_fmt(ref): + sig_figs = len(str(ref)) + print(str(ref)) + print(sig_figs) + + def fmt(new): + exponent = int(f"{new:e}".split("e")[1]) + if exponent > 6 or exponent < -3: + return f"{new:{sig_figs}e}" + else: # a "normal" size number + return f"{round(new, sig_figs-exponent)}" + + return fmt + + fmt = gen_fmt(number) + + if len(destination_unit): # units provided + if not wt.units.is_valid_conversion(unit, destination_unit): + raise wt.exceptions.UnitsError( + wt.units.get_valid_conversions(unit), destination_unit + ) + new = wt.units.convert(number, unit, destination_unit) + print(f"{fmt(new)} {destination_unit}") + else: + valid_units = wt.units.get_valid_conversions(unit) + print(valid_units) + for d_unit in valid_units: + new = wt.units.convert(number, unit, d_unit) + print(f"{fmt(new)} {d_unit}") + + +if __name__ == "__main__": + cli() + diff --git a/setup.py b/setup.py index 53d512fd9..6c08e3258 100755 --- a/setup.py +++ b/setup.py @@ -44,6 +44,7 @@ def read(fname): "pint", "python-dateutil", "scipy", + "click", "tidy_headers>=1.0.0", ], extras_require={ @@ -66,7 +67,7 @@ def read(fname): license="MIT", url="http://wright.tools", keywords="spectroscopy science multidimensional visualization", - entry_points={"console_scripts": ["wt-tree=WrightTools.__main__:wt_tree"]}, + entry_points={"console_scripts": ["wt-tree=WrightTools.__main__:cli"]}, classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Science/Research", From 81d3f3e05de9d6a663414e0448817f7c8268e79d Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 29 Jan 2024 21:20:06 -0600 Subject: [PATCH 02/33] wt-tree crawl working example --- WrightTools/__main__.py | 94 +++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 22 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index 7187b9f95..9995c8611 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -4,7 +4,6 @@ import click import WrightTools as wt - # --- define -------------------------------------------------------------------------------------- @@ -20,7 +19,7 @@ def cli(): @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): - # Create the data/collection object + # open the object obj = wt.open(path)[internal_path] # If the object is a data object, it doesn't take depth as a parameter @@ -30,43 +29,94 @@ def tree(path, internal_path, depth=9, verbose=False): obj.print_tree(verbose=verbose, depth=depth) -@cli.command(name="crawl", help="Crawl a directory and report the wt5 objects found.") -@click.argument("directory", default=".") -def crawl(directory=None): +@cli.command(name="load", help="Open a python cli with the object pre-loaded.") +@click.argument("path") +def load(path): + import code + d = wt.open(d) ... -@cli.command(name="convert", help="Convert numbers to different units.") + +@cli.command(name="crawl", help="Crawl a directory and survey the wt5 objects found.") +@click.argument("directory", nargs=-1, default=None) +@click.option("--recursive", "-r", is_flag=True, help="explore all levels of the directory") +@click.option("--pausing", "-p", is_flag=True, help="pause at each file and give option to interact.") +def crawl(directory=(), recursive=False, pausing=False): + import glob, os + + if not directory: + directory = os.getcwd() + else: + directory = directory[0] + + if pausing: + import code + shell = code.InteractiveConsole() + + for pathname in glob.iglob("**/*.wt5", root_dir=directory, recursive=recursive): + print(pathname) + d = wt.open(os.path.join(directory, pathname)) + if isinstance(d, wt.Data): + d.print_tree(verbose=False) + elif isinstance(d, wt.Collection): + d.print_tree(depth=1, verbose=False) + + if pausing: + msg = shell.raw_input("Continue [y]/n/interact? ") + if msg == "n": + break + elif msg == "interact": + lines = ["import WrightTools as wt"] + if isinstance(d, wt.Data): + lines += [ + "import matplotlib.pyplot as plt", + f"path = r'{os.path.join(directory, pathname)}'", + "d = wt.open(path)", + ] + elif isinstance(d, wt.Collection): + lines.append(f"c = wt.open(r'{os.path.join(directory, pathname)}')") + + [shell.push(line) for line in lines] + shell.interact(banner="\n".join([">>> "+line for line in lines])) + else: + continue + print("-"*100) + d.close() + + +@cli.command(name="convert") @click.argument("number", type=float, nargs=1) @click.argument("unit", nargs=1) @click.argument("destination_unit", default=None, nargs=-1) def convert(number, unit, destination_unit=None): - - def gen_fmt(ref): - sig_figs = len(str(ref)) - print(str(ref)) - print(sig_figs) - - def fmt(new): - exponent = int(f"{new:e}".split("e")[1]) - if exponent > 6 or exponent < -3: - return f"{new:{sig_figs}e}" - else: # a "normal" size number + """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 + + 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)}" - return fmt - - fmt = gen_fmt(number) if len(destination_unit): # units provided + destination_unit = destination_unit[0] if not wt.units.is_valid_conversion(unit, destination_unit): raise wt.exceptions.UnitsError( wt.units.get_valid_conversions(unit), destination_unit ) new = wt.units.convert(number, unit, destination_unit) - print(f"{fmt(new)} {destination_unit}") + print(f"{number} {unit} = {fmt(new)} {destination_unit}") else: valid_units = wt.units.get_valid_conversions(unit) - print(valid_units) for d_unit in valid_units: new = wt.units.convert(number, unit, d_unit) print(f"{fmt(new)} {d_unit}") From 73cd489fadb27595f01f952041c13a5249d6bd52 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 29 Jan 2024 21:20:30 -0600 Subject: [PATCH 03/33] Data.print_tree tweak --- WrightTools/data/_data.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/WrightTools/data/_data.py b/WrightTools/data/_data.py index 86d496d31..5ded034d8 100644 --- a/WrightTools/data/_data.py +++ b/WrightTools/data/_data.py @@ -273,30 +273,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) @@ -1444,7 +1444,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): From ca16c778c9d92207bb58dbc62aae2261265a7cbd Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 29 Jan 2024 21:46:15 -0600 Subject: [PATCH 04/33] wt-tree crawl -p clean exit --- WrightTools/__main__.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index 9995c8611..90afdc24d 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -40,7 +40,7 @@ def load(path): @cli.command(name="crawl", help="Crawl a directory and survey the wt5 objects found.") @click.argument("directory", nargs=-1, default=None) @click.option("--recursive", "-r", is_flag=True, help="explore all levels of the directory") -@click.option("--pausing", "-p", is_flag=True, help="pause at each file and give option to interact.") +@click.option("--pausing", "-p", is_flag=True, help="pause at each file readout. Interaction with data is possible.") def crawl(directory=(), recursive=False, pausing=False): import glob, os @@ -51,8 +51,16 @@ def crawl(directory=(), recursive=False, pausing=False): if pausing: import code - shell = code.InteractiveConsole() + def raise_sys_exit(): + raise SystemExit + + shell = code.InteractiveConsole(locals={ + "exit": raise_sys_exit, + "quit": raise_sys_exit + }) + + print("-"*100) for pathname in glob.iglob("**/*.wt5", root_dir=directory, recursive=recursive): print(pathname) d = wt.open(os.path.join(directory, pathname)) @@ -76,8 +84,14 @@ def crawl(directory=(), recursive=False, pausing=False): elif isinstance(d, wt.Collection): lines.append(f"c = wt.open(r'{os.path.join(directory, pathname)}')") - [shell.push(line) for line in lines] - shell.interact(banner="\n".join([">>> "+line for line in lines])) + [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 else: continue print("-"*100) From fd9d75c335d723ca7dddb6804b6cbcfa4956bd4b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 03:55:31 +0000 Subject: [PATCH 05/33] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- WrightTools/__main__.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index 90afdc24d..8cef6f900 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -15,7 +15,9 @@ def cli(): @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( + "--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): @@ -33,6 +35,7 @@ def tree(path, internal_path, depth=9, verbose=False): @click.argument("path") def load(path): import code + d = wt.open(d) ... @@ -40,7 +43,12 @@ def load(path): @cli.command(name="crawl", help="Crawl a directory and survey the wt5 objects found.") @click.argument("directory", nargs=-1, default=None) @click.option("--recursive", "-r", is_flag=True, help="explore all levels of the directory") -@click.option("--pausing", "-p", is_flag=True, help="pause at each file readout. Interaction with data is possible.") +@click.option( + "--pausing", + "-p", + is_flag=True, + help="pause at each file readout. Interaction with data is possible.", +) def crawl(directory=(), recursive=False, pausing=False): import glob, os @@ -55,12 +63,9 @@ def crawl(directory=(), recursive=False, pausing=False): def raise_sys_exit(): raise SystemExit - shell = code.InteractiveConsole(locals={ - "exit": raise_sys_exit, - "quit": raise_sys_exit - }) + shell = code.InteractiveConsole(locals={"exit": raise_sys_exit, "quit": raise_sys_exit}) - print("-"*100) + print("-" * 100) for pathname in glob.iglob("**/*.wt5", root_dir=directory, recursive=recursive): print(pathname) d = wt.open(os.path.join(directory, pathname)) @@ -86,15 +91,15 @@ def raise_sys_exit(): [shell.push(line) for line in lines] banner = "--- INTERACTING --- (to continue, call exit() or quit())\n" - banner += "\n".join([">>> "+line for line in lines]) - + banner += "\n".join([">>> " + line for line in lines]) + try: shell.interact(banner=banner) except SystemExit: pass else: continue - print("-"*100) + print("-" * 100) d.close() @@ -114,19 +119,16 @@ 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: + 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 wt.units.is_valid_conversion(unit, destination_unit): - raise wt.exceptions.UnitsError( - wt.units.get_valid_conversions(unit), destination_unit - ) + raise wt.exceptions.UnitsError(wt.units.get_valid_conversions(unit), destination_unit) new = wt.units.convert(number, unit, destination_unit) print(f"{number} {unit} = {fmt(new)} {destination_unit}") else: @@ -138,4 +140,3 @@ def fmt(new): if __name__ == "__main__": cli() - From 200c557c28bf37ed8858bffcf6388006925da604 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:57:46 -0600 Subject: [PATCH 06/33] removing pause from crawl --- WrightTools/__main__.py | 123 ++++++++++++++++++++++++++++------------ 1 file changed, 86 insertions(+), 37 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index 8cef6f900..3105c39bb 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -4,6 +4,7 @@ import click import WrightTools as wt + # --- define -------------------------------------------------------------------------------------- @@ -24,7 +25,6 @@ def tree(path, internal_path, depth=9, verbose=False): # open the object obj = wt.open(path)[internal_path] - # If the object is a data object, it doesn't take depth as a parameter if isinstance(obj, wt.Data): obj.print_tree(verbose=verbose) else: @@ -41,21 +41,21 @@ def load(path): @cli.command(name="crawl", help="Crawl a directory and survey the wt5 objects found.") -@click.argument("directory", nargs=-1, default=None) -@click.option("--recursive", "-r", is_flag=True, help="explore all levels of the directory") +@click.option("--directory", "-d", default=None, help="Directory to crawl. Defaults to current directory.") +@click.option("--recursive", "-r", is_flag=True, help="Explore all levels of the directory") @click.option( "--pausing", "-p", is_flag=True, help="pause at each file readout. Interaction with data is possible.", ) -def crawl(directory=(), recursive=False, pausing=False): +@click.option("--format", "-f", default=None, help="Formatting keys (default only atm)") +# TODO: write output as an option +def crawl(directory=None, recursive=False, pausing=False, format=None): import glob, os - if not directory: + if directory is None: directory = os.getcwd() - else: - directory = directory[0] if pausing: import code @@ -65,44 +65,93 @@ def raise_sys_exit(): shell = code.InteractiveConsole(locals={"exit": raise_sys_exit, "quit": raise_sys_exit}) - print("-" * 100) - for pathname in glob.iglob("**/*.wt5", root_dir=directory, recursive=recursive): - print(pathname) - d = wt.open(os.path.join(directory, pathname)) - if isinstance(d, wt.Data): - d.print_tree(verbose=False) - elif isinstance(d, wt.Collection): - d.print_tree(depth=1, verbose=False) + paths = glob.glob("**/*.wt5", root_dir=directory, recursive=recursive) + print(f"{len(paths)} wt5 file{'s' if len(paths) != 1 else None} found in {directory}") + + from rich.console import Console + from rich.table import Table + + console = Console() + + table = Table(title=directory) + table.add_column("", justify="right") # index + table.add_column("path", max_width=60) + table.add_column("size (MB)", justify="center") + table.add_column("created", max_width=30) + table.add_column("name") + table.add_column("shape") + table.add_column("axes") + table.add_column("variables") + table.add_column("channels") + + + for i, pathname in enumerate(paths): + path = os.path.join(directory, pathname) + d = wt.open(path) + infos = [str(i), pathname, str(int(os.path.getsize(path)/1e6)), *_format_entry(d)] + table.add_row(*infos) if pausing: - msg = shell.raw_input("Continue [y]/n/interact? ") - if msg == "n": + msg = shell.raw_input("Interact ([n=no]/y=yes/q=quit)? ") + if msg.lower() in ["q", "quit"]: break - elif msg == "interact": - lines = ["import WrightTools as wt"] - if isinstance(d, wt.Data): - lines += [ - "import matplotlib.pyplot as plt", - f"path = r'{os.path.join(directory, pathname)}'", - "d = wt.open(path)", - ] - elif isinstance(d, wt.Collection): - lines.append(f"c = wt.open(r'{os.path.join(directory, pathname)}')") - - [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 + elif msg.lower() in ["y", "yes"]: + _interact(shell, os.path.join(directory, pathname), isinstance(d, wt.Collection)) + print("-" * 100) else: continue - print("-" * 100) d.close() +from typing import Tuple, Optional +class TableEntry: + created: str = "" + name: str = "" + shape: Optional(Tuple(int)) + axes: Optional(Tuple(str)) + nvars: Optional(int) + nchan: Optional(int) + def __init__(self, wt5): + self.name = wt5.natural_name + self.created = wt5.attrs["created"].date + if isinstance(wt5, wt.Data): + self.shape = wt5.shape + self.axes = wt5.axis_expressions + self.nvars = len(wt5.variables) + self.nchan = len(wt5.channels) + + + + + + +def _format_entry(wt5, format=None): + if isinstance(wt5, wt.Data): + values = [f"{wt5.attrs['created']}", wt5.natural_name, f"{wt5.shape}", f"{wt5.axis_expressions}", str(len(wt5.variables)), str(len(wt5.channels))] + elif isinstance(wt5, wt.Collection): + values = ["---"] + [wt5.natural_name] + ["---"] * 4 + else: + values = ["---"] + [""] + ["---"] * 4 + return values + + +def _interact(shell, path, is_collection): + lines = [ + "import WrightTools as wt", + "import matplotlib.pyplot as plt", + f"{'c' if is_collection else '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 + + @cli.command(name="convert") @click.argument("number", type=float, nargs=1) @click.argument("unit", nargs=1) From cce05ef4b84f21d4707b065b585d30e6355cd966 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Thu, 1 Feb 2024 13:04:42 -0600 Subject: [PATCH 07/33] Update __main__.py interact with crawl after table is made --- WrightTools/__main__.py | 126 +++++++++++++++------------------------- 1 file changed, 48 insertions(+), 78 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index 3105c39bb..aa8b56437 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -35,111 +35,81 @@ def tree(path, internal_path, depth=9, verbose=False): @click.argument("path") def load(path): import code - - d = wt.open(d) - ... + # def raise_sys_exit(): + # raise SystemExit + shell = code.InteractiveConsole() # locals={"exit": raise_sys_exit, "quit": raise_sys_exit}) + _interact(shell, path) @cli.command(name="crawl", help="Crawl a directory and survey the wt5 objects found.") @click.option("--directory", "-d", default=None, help="Directory to crawl. Defaults to current directory.") @click.option("--recursive", "-r", is_flag=True, help="Explore all levels of the directory") -@click.option( - "--pausing", - "-p", - is_flag=True, - help="pause at each file readout. Interaction with data is possible.", -) @click.option("--format", "-f", default=None, help="Formatting keys (default only atm)") -# TODO: write output as an option -def crawl(directory=None, recursive=False, pausing=False, format=None): - import glob, os +# TODO: write output as an option; format kwarg? +def crawl(directory=None, recursive=False, format=None): + import glob, os, code + # from rich.console import Console + from rich.live import Live + from rich.table import Table if directory is None: directory = os.getcwd() - if pausing: - import code - - def raise_sys_exit(): - raise SystemExit - - shell = code.InteractiveConsole(locals={"exit": raise_sys_exit, "quit": raise_sys_exit}) - paths = glob.glob("**/*.wt5", root_dir=directory, recursive=recursive) - print(f"{len(paths)} wt5 file{'s' if len(paths) != 1 else None} found in {directory}") - - from rich.console import Console - from rich.table import Table - console = Console() + def _parse_entry(i, relpath): + size = os.path.getsize(os.path.join(directory, relpath)) / 1e6 + wt5 = wt.open(os.path.join(directory, relpath)) + name = wt5.natural_name + try: + created = wt5.created.human + except: # likely an old timestamp that cannot be parsed + created = wt5.attrs["created"] - table = Table(title=directory) + if isinstance(wt5, wt.Data): + shape = wt5.shape + axes = wt5.axis_expressions + nvars = len(wt5.variables) + nchan = len(wt5.channels) + elif isinstance(wt5, wt.Collection): + shape = axes = nvars = nchan = "---" + return [ + str(i), relpath, f"{size:0.1f}", created, name, str(shape), str(axes), str(nvars), str(nchan) + ] + + table = Table(title=directory + f" ({len(paths)} wt5 file{'s' if len(paths) != 1 else None} found)") table.add_column("", justify="right") # index - table.add_column("path", max_width=60) + table.add_column("path", max_width=60, no_wrap=True) table.add_column("size (MB)", justify="center") table.add_column("created", max_width=30) table.add_column("name") table.add_column("shape") - table.add_column("axes") + table.add_column("axes", max_width=50) table.add_column("variables") table.add_column("channels") - - for i, pathname in enumerate(paths): - path = os.path.join(directory, pathname) - d = wt.open(path) - infos = [str(i), pathname, str(int(os.path.getsize(path)/1e6)), *_format_entry(d)] - table.add_row(*infos) - - if pausing: - msg = shell.raw_input("Interact ([n=no]/y=yes/q=quit)? ") - if msg.lower() in ["q", "quit"]: - break - elif msg.lower() in ["y", "yes"]: - _interact(shell, os.path.join(directory, pathname), isinstance(d, wt.Collection)) - print("-" * 100) - else: - continue - d.close() - - -from typing import Tuple, Optional -class TableEntry: - created: str = "" - name: str = "" - shape: Optional(Tuple(int)) - axes: Optional(Tuple(str)) - nvars: Optional(int) - nchan: Optional(int) - def __init__(self, wt5): - self.name = wt5.natural_name - self.created = wt5.attrs["created"].date - if isinstance(wt5, wt.Data): - self.shape = wt5.shape - self.axes = wt5.axis_expressions - self.nvars = len(wt5.variables) - self.nchan = len(wt5.channels) - + with Live(table) as live: + for i, path in enumerate(paths): + table.add_row(*_parse_entry(i, path)) + live.update(table) + # give option to interact + shell = code.InteractiveConsole() + msg = shell.raw_input("Do you wish to load an entry? (specify an index to load, or don't and exit) ") + try: + valid = 0 < int(msg) + 1 < len(paths) + except ValueError: + print("invalid index") + return + if valid: + _interact(shell, os.path.join(directory, paths[int(msg)])) - - -def _format_entry(wt5, format=None): - if isinstance(wt5, wt.Data): - values = [f"{wt5.attrs['created']}", wt5.natural_name, f"{wt5.shape}", f"{wt5.axis_expressions}", str(len(wt5.variables)), str(len(wt5.channels))] - elif isinstance(wt5, wt.Collection): - values = ["---"] + [wt5.natural_name] + ["---"] * 4 - else: - values = ["---"] + [""] + ["---"] * 4 - return values - - -def _interact(shell, path, is_collection): +def _interact(shell, path): lines = [ "import WrightTools as wt", "import matplotlib.pyplot as plt", - f"{'c' if is_collection else 'd'} = wt.open(r'{path}')", + f"d = wt.open(r'{path}')", ] [shell.push(line) for line in lines] From 3af74fa879ad5d85f0a1ee854b5653750cfe0865 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 19:04:58 +0000 Subject: [PATCH 08/33] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- WrightTools/__main__.py | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index aa8b56437..c507c3013 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -35,19 +35,23 @@ def tree(path, internal_path, depth=9, verbose=False): @click.argument("path") def load(path): import code + # def raise_sys_exit(): # raise SystemExit - shell = code.InteractiveConsole() # locals={"exit": raise_sys_exit, "quit": raise_sys_exit}) + shell = code.InteractiveConsole() # locals={"exit": raise_sys_exit, "quit": raise_sys_exit}) _interact(shell, path) @cli.command(name="crawl", help="Crawl a directory and survey the wt5 objects found.") -@click.option("--directory", "-d", default=None, help="Directory to crawl. Defaults to current directory.") +@click.option( + "--directory", "-d", default=None, help="Directory to crawl. Defaults to current directory." +) @click.option("--recursive", "-r", is_flag=True, help="Explore all levels of the directory") @click.option("--format", "-f", default=None, help="Formatting keys (default only atm)") # TODO: write output as an option; format kwarg? def crawl(directory=None, recursive=False, format=None): import glob, os, code + # from rich.console import Console from rich.live import Live from rich.table import Table @@ -72,12 +76,22 @@ def _parse_entry(i, relpath): nvars = len(wt5.variables) nchan = len(wt5.channels) elif isinstance(wt5, wt.Collection): - shape = axes = nvars = nchan = "---" + shape = axes = nvars = nchan = "---" return [ - str(i), relpath, f"{size:0.1f}", created, name, str(shape), str(axes), str(nvars), str(nchan) + str(i), + relpath, + f"{size:0.1f}", + created, + name, + str(shape), + str(axes), + str(nvars), + str(nchan), ] - table = Table(title=directory + f" ({len(paths)} wt5 file{'s' if len(paths) != 1 else None} found)") + table = Table( + title=directory + f" ({len(paths)} wt5 file{'s' if len(paths) != 1 else None} found)" + ) table.add_column("", justify="right") # index table.add_column("path", max_width=60, no_wrap=True) table.add_column("size (MB)", justify="center") @@ -92,15 +106,17 @@ def _parse_entry(i, relpath): for i, path in enumerate(paths): table.add_row(*_parse_entry(i, path)) live.update(table) - + # give option to interact shell = code.InteractiveConsole() - msg = shell.raw_input("Do you wish to load an entry? (specify an index to load, or don't and exit) ") + msg = shell.raw_input( + "Do you wish to load an entry? (specify an index to load, or don't and exit) " + ) try: valid = 0 < int(msg) + 1 < len(paths) except ValueError: print("invalid index") - return + return if valid: _interact(shell, os.path.join(directory, paths[int(msg)])) From bae841e1c11d88eb7e460d01e85aa23c591159cb Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Thu, 1 Feb 2024 19:13:50 -0600 Subject: [PATCH 09/33] entry point crawl revision --- WrightTools/__main__.py | 62 ++++++++++++------------------------- WrightTools/kit/__init__.py | 2 ++ WrightTools/kit/_glob.py | 37 ++++++++++++++++++++++ setup.py | 1 + 4 files changed, 60 insertions(+), 42 deletions(-) create mode 100644 WrightTools/kit/_glob.py diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index c507c3013..972a017ce 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -36,9 +36,7 @@ def tree(path, internal_path, depth=9, verbose=False): def load(path): import code - # def raise_sys_exit(): - # raise SystemExit - shell = code.InteractiveConsole() # locals={"exit": raise_sys_exit, "quit": raise_sys_exit}) + shell = code.InteractiveConsole() _interact(shell, path) @@ -46,48 +44,16 @@ def load(path): @click.option( "--directory", "-d", default=None, help="Directory to crawl. Defaults to current directory." ) -@click.option("--recursive", "-r", is_flag=True, help="Explore all levels of the directory") -@click.option("--format", "-f", default=None, help="Formatting keys (default only atm)") -# TODO: write output as an option; format kwarg? -def crawl(directory=None, recursive=False, format=None): +# TODO: formatting options (e.g. json)? +def crawl(directory=None): import glob, os, code - - # from rich.console import Console from rich.live import Live from rich.table import Table if directory is None: directory = os.getcwd() - paths = glob.glob("**/*.wt5", root_dir=directory, recursive=recursive) - - def _parse_entry(i, relpath): - size = os.path.getsize(os.path.join(directory, relpath)) / 1e6 - wt5 = wt.open(os.path.join(directory, relpath)) - name = wt5.natural_name - try: - created = wt5.created.human - except: # likely an old timestamp that cannot be parsed - created = wt5.attrs["created"] - - if isinstance(wt5, wt.Data): - shape = wt5.shape - axes = wt5.axis_expressions - nvars = len(wt5.variables) - nchan = len(wt5.channels) - elif isinstance(wt5, wt.Collection): - shape = axes = nvars = nchan = "---" - return [ - str(i), - relpath, - f"{size:0.1f}", - created, - name, - str(shape), - str(axes), - str(nvars), - str(nchan), - ] + paths = list(wt.kit.find_wt5s(directory)) table = Table( title=directory + f" ({len(paths)} wt5 file{'s' if len(paths) != 1 else None} found)" @@ -104,7 +70,20 @@ def _parse_entry(i, relpath): with Live(table) as live: for i, path in enumerate(paths): - table.add_row(*_parse_entry(i, path)) + desc = wt.kit.describe_wt5(path) + desc["filesize"] = f"{os.path.getsize(path) / 1e6:.1f}" + desc["path"] = str(path.relative_to(directory)) + row = [str(i)] + [str(desc[k]) for k in [ + "path", + "filesize", + "created", + "name", + "shape", + "axes", + "nvars", + "nchan" + ]] + table.add_row(*row) live.update(table) # give option to interact @@ -113,12 +92,11 @@ def _parse_entry(i, relpath): "Do you wish to load an entry? (specify an index to load, or don't and exit) " ) try: - valid = 0 < int(msg) + 1 < len(paths) + valid = 0 <= int(msg) < len(paths) except ValueError: - print("invalid index") return if valid: - _interact(shell, os.path.join(directory, paths[int(msg)])) + _interact(shell, str(paths[int(msg)])) def _interact(shell, path): diff --git a/WrightTools/kit/__init__.py b/WrightTools/kit/__init__.py index a1966fbe1..0a2978e9c 100644 --- a/WrightTools/kit/__init__.py +++ b/WrightTools/kit/__init__.py @@ -13,3 +13,5 @@ from ._timestamp import * from ._unicode import * from ._utilities import * +from ._glob import * + diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py new file mode 100644 index 000000000..115cb22a1 --- /dev/null +++ b/WrightTools/kit/_glob.py @@ -0,0 +1,37 @@ +import pathlib +import os +from typing import Union +from ..data import Data +from ..collection import Collection +from .._open import open + + +__all__ = ["describe_wt5", "find_wt5s"] + + +def describe_wt5(path: Union[str, os.PathLike]): + """report useful general information about a wt5 file""" + wt5 = open(path) + desc = dict() + desc["name"] = wt5.natural_name + try: + desc["created"] = wt5.created.human + except: # likely an old timestamp that cannot be parsed + desc["created"] = wt5.attrs["created"] + + if isinstance(wt5, Data): + desc["shape"] = wt5.shape + desc["axes"] = wt5.axis_expressions + desc["nvars"] = len(wt5.variables) + desc["nchan"] = len(wt5.channels) + elif isinstance(wt5, Collection): + for k in ["shape", "axes", "nvars", "nchan"]: + desc[k] = "---" + wt5.close() + return desc + + +def glob_wt5s(directory: Union[str,os.PathLike]): + """find all wt5 files in a directory""" + return pathlib.Path(directory).glob("**/*.wt5") + diff --git a/setup.py b/setup.py index 6c08e3258..dba6f42d0 100755 --- a/setup.py +++ b/setup.py @@ -46,6 +46,7 @@ def read(fname): "scipy", "click", "tidy_headers>=1.0.0", + "rich", ], extras_require={ "docs": docs_require, From 59984c6d069d99e1d0958ea47b352997bc873330 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 2 Feb 2024 01:14:06 +0000 Subject: [PATCH 10/33] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- WrightTools/__main__.py | 14 ++++---------- WrightTools/kit/__init__.py | 1 - WrightTools/kit/_glob.py | 3 +-- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index 972a017ce..656824e63 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -73,16 +73,10 @@ def crawl(directory=None): desc = wt.kit.describe_wt5(path) desc["filesize"] = f"{os.path.getsize(path) / 1e6:.1f}" desc["path"] = str(path.relative_to(directory)) - row = [str(i)] + [str(desc[k]) for k in [ - "path", - "filesize", - "created", - "name", - "shape", - "axes", - "nvars", - "nchan" - ]] + row = [str(i)] + [ + str(desc[k]) + for k in ["path", "filesize", "created", "name", "shape", "axes", "nvars", "nchan"] + ] table.add_row(*row) live.update(table) diff --git a/WrightTools/kit/__init__.py b/WrightTools/kit/__init__.py index 0a2978e9c..4144d9074 100644 --- a/WrightTools/kit/__init__.py +++ b/WrightTools/kit/__init__.py @@ -14,4 +14,3 @@ from ._unicode import * from ._utilities import * from ._glob import * - diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index 115cb22a1..01cd3206c 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -31,7 +31,6 @@ def describe_wt5(path: Union[str, os.PathLike]): return desc -def glob_wt5s(directory: Union[str,os.PathLike]): +def glob_wt5s(directory: Union[str, os.PathLike]): """find all wt5 files in a directory""" return pathlib.Path(directory).glob("**/*.wt5") - From ce1a822e4660b49bf652fda19856f9b1f29cbdf8 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Fri, 2 Feb 2024 09:12:09 -0600 Subject: [PATCH 11/33] Update _glob.py fix typo --- WrightTools/kit/_glob.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index 01cd3206c..3d19e7470 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -6,10 +6,10 @@ from .._open import open -__all__ = ["describe_wt5", "find_wt5s"] +__all__ = ["describe_wt5", "glob_wt5s"] -def describe_wt5(path: Union[str, os.PathLike]): +def describe_wt5(path: Union[str, os.PathLike])->dict: """report useful general information about a wt5 file""" wt5 = open(path) desc = dict() From b47e82a4f1f4ad8bc8c9757b91c00e5321e6b474 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 2 Feb 2024 15:12:50 +0000 Subject: [PATCH 12/33] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- WrightTools/kit/_glob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index 3d19e7470..ca806e45f 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -9,7 +9,7 @@ __all__ = ["describe_wt5", "glob_wt5s"] -def describe_wt5(path: Union[str, os.PathLike])->dict: +def describe_wt5(path: Union[str, os.PathLike]) -> dict: """report useful general information about a wt5 file""" wt5 = open(path) desc = dict() From e6953faa30bee5abf2df12cd6897b2e82a0a6ec2 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:36:22 -0600 Subject: [PATCH 13/33] wt-tree -> wtools --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index dba6f42d0..bba80f06a 100755 --- a/setup.py +++ b/setup.py @@ -68,7 +68,7 @@ def read(fname): license="MIT", url="http://wright.tools", keywords="spectroscopy science multidimensional visualization", - entry_points={"console_scripts": ["wt-tree=WrightTools.__main__:cli"]}, + entry_points={"console_scripts": ["wtools=WrightTools.__main__:cli"]}, classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Science/Research", From 82fe3c1afffa1554c7b8aa51e0e83d45b12ef91e Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Fri, 2 Feb 2024 12:36:41 -0600 Subject: [PATCH 14/33] crawl -> scan --- WrightTools/__main__.py | 55 +++++++++++++++++++++++++++------------- WrightTools/kit/_glob.py | 6 +++-- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index 656824e63..942648496 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -40,23 +40,22 @@ def load(path): _interact(shell, path) -@cli.command(name="crawl", help="Crawl a directory and survey the wt5 objects found.") +@cli.command(name="scan", help="scan a directory and survey the wt5 objects found.") @click.option( - "--directory", "-d", default=None, help="Directory to crawl. Defaults to current directory." + "--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 crawl(directory=None): - import glob, os, code +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() - paths = list(wt.kit.find_wt5s(directory)) - table = Table( - title=directory + f" ({len(paths)} wt5 file{'s' if len(paths) != 1 else None} found)" + title=directory ) table.add_column("", justify="right") # index table.add_column("path", max_width=60, no_wrap=True) @@ -68,8 +67,12 @@ def crawl(directory=None): table.add_column("variables") table.add_column("channels") + 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(paths): + for i, path in enumerate(wt.kit.glob_wt5s(directory, not no_recursion)): + paths.append(path) desc = wt.kit.describe_wt5(path) desc["filesize"] = f"{os.path.getsize(path) / 1e6:.1f}" desc["path"] = str(path.relative_to(directory)) @@ -77,20 +80,36 @@ def crawl(directory=None): 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 - shell = code.InteractiveConsole() - msg = shell.raw_input( - "Do you wish to load an entry? (specify an index to load, or don't and exit) " - ) - try: - valid = 0 <= int(msg) < len(paths) - except ValueError: - return - if valid: - _interact(shell, str(paths[int(msg)])) + 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: + _interact(shell, str(paths[int(msg)])) + continue def _interact(shell, path): diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index ca806e45f..f4b04f87a 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -31,6 +31,8 @@ def describe_wt5(path: Union[str, os.PathLike]) -> dict: return desc -def glob_wt5s(directory: Union[str, os.PathLike]): +def glob_wt5s(directory: Union[str, os.PathLike], recursive=True): """find all wt5 files in a directory""" - return pathlib.Path(directory).glob("**/*.wt5") + pattern = "**/*.wt5" if recursive else "*.wt5" + print(pattern) + return pathlib.Path(directory).glob(pattern) From 0de18ce50bf7c952b3bfcd02cee26152f4c67227 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 2 Feb 2024 18:36:57 +0000 Subject: [PATCH 15/33] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- WrightTools/__main__.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index 942648496..674e7d892 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -54,9 +54,7 @@ def scan(directory=None, no_recursion=False): if directory is None: directory = os.getcwd() - table = Table( - title=directory - ) + table = Table(title=directory) table.add_column("", justify="right") # index table.add_column("path", max_width=60, no_wrap=True) table.add_column("size (MB)", justify="center") @@ -80,7 +78,7 @@ def scan(directory=None, no_recursion=False): str(desc[k]) for k in ["path", "filesize", "created", "name", "shape", "axes", "nvars", "nchan"] ] - table.title = update_title(i+1) + table.title = update_title(i + 1) table.add_row(*row) live.update(table) @@ -88,17 +86,18 @@ def scan(directory=None, no_recursion=False): def raise_sys_exit(): raise SystemExit - shell = code.InteractiveConsole(locals={ - "exit": raise_sys_exit, - "quit": raise_sys_exit - }) + 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.", - ])) + 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 From b797ef76b8509f05320ab615e076841166869fc9 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Sat, 17 Feb 2024 12:49:00 -0600 Subject: [PATCH 16/33] change entry points --- WrightTools/__main__.py | 29 ++++++++++++++++------------- WrightTools/kit/_glob.py | 3 +-- setup.py | 6 +++++- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index 674e7d892..d00c9fb94 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -40,7 +40,7 @@ def load(path): _interact(shell, path) -@cli.command(name="scan", help="scan a directory and survey the wt5 objects found.") +@cli.command(name="glob", help="Scan a directory and survey the wt5 objects found.") @click.option( "--directory", "-d", default=None, help="Directory to scan. Defaults to current directory." ) @@ -56,25 +56,28 @@ def scan(directory=None, no_recursion=False): table = Table(title=directory) table.add_column("", justify="right") # index - table.add_column("path", max_width=60, no_wrap=True) - table.add_column("size (MB)", justify="center") - table.add_column("created", max_width=30) - table.add_column("name") - table.add_column("shape") - table.add_column("axes", max_width=50) - table.add_column("variables") - table.add_column("channels") + 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)): - paths.append(path) desc = wt.kit.describe_wt5(path) desc["filesize"] = f"{os.path.getsize(path) / 1e6:.1f}" - desc["path"] = str(path.relative_to(directory)) - row = [str(i)] + [ + path = path.relative_to(directory) + print(path.parent) + 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"] ] @@ -93,7 +96,7 @@ def raise_sys_exit(): " ".join( [ "Specify an index to load that entry.", - "Use 't' to rerender table.", + "Use `t` to rerender table.", "Use no argument to exit.", ] ) diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index f4b04f87a..90c2caadc 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -33,6 +33,5 @@ def describe_wt5(path: Union[str, os.PathLike]) -> dict: def glob_wt5s(directory: Union[str, os.PathLike], recursive=True): """find all wt5 files in a directory""" - pattern = "**/*.wt5" if recursive else "*.wt5" - print(pattern) + pattern = "**/*.wt5" if recursive else f"*.wt5" return pathlib.Path(directory).glob(pattern) diff --git a/setup.py b/setup.py index bba80f06a..341ae67fe 100755 --- a/setup.py +++ b/setup.py @@ -68,7 +68,11 @@ def read(fname): license="MIT", url="http://wright.tools", keywords="spectroscopy science multidimensional visualization", - entry_points={"console_scripts": ["wtools=WrightTools.__main__:cli"]}, + entry_points={"console_scripts": [ + "wt-tree=WrightTools.__main__:tree", + "wt5=WrightTools.__main__:wt5", + "wt-convert=WrightTools.__main__:convert" + ]}, classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Science/Research", From 6c59e2a5e2b32c92f7550b04370401f6f5509a88 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 17 Feb 2024 18:49:22 +0000 Subject: [PATCH 17/33] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- WrightTools/__main__.py | 8 ++++++-- setup.py | 12 +++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/WrightTools/__main__.py b/WrightTools/__main__.py index d00c9fb94..81c03f19a 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/__main__.py @@ -74,8 +74,12 @@ def scan(directory=None, no_recursion=False): desc["filesize"] = f"{os.path.getsize(path) / 1e6:.1f}" path = path.relative_to(directory) print(path.parent) - 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={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]) diff --git a/setup.py b/setup.py index 6918a0ee8..8a1fb9739 100755 --- a/setup.py +++ b/setup.py @@ -68,11 +68,13 @@ def read(fname): license="MIT", url="http://wright.tools", keywords="spectroscopy science multidimensional visualization", - entry_points={"console_scripts": [ - "wt-tree=WrightTools.__main__:tree", - "wt5=WrightTools.__main__:wt5", - "wt-convert=WrightTools.__main__:convert" - ]}, + entry_points={ + "console_scripts": [ + "wt-tree=WrightTools.__main__:tree", + "wt5=WrightTools.__main__:wt5", + "wt-convert=WrightTools.__main__:convert", + ] + }, classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Science/Research", From 28ebbb213b943ab905935be3b7bbe53ea3573f27 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 12:40:08 -0600 Subject: [PATCH 18/33] refactor cli using multiple entry points --- WrightTools/cli/__init__.py | 3 ++ WrightTools/cli/_tree.py | 36 ++++++++++++++++ WrightTools/cli/_units.py | 53 ++++++++++++++++++++++++ WrightTools/{__main__.py => cli/_wt5.py} | 52 ----------------------- setup.py | 6 +-- 5 files changed, 95 insertions(+), 55 deletions(-) create mode 100644 WrightTools/cli/__init__.py create mode 100644 WrightTools/cli/_tree.py create mode 100644 WrightTools/cli/_units.py rename WrightTools/{__main__.py => cli/_wt5.py} (65%) diff --git a/WrightTools/cli/__init__.py b/WrightTools/cli/__init__.py new file mode 100644 index 000000000..b1f623521 --- /dev/null +++ b/WrightTools/cli/__init__.py @@ -0,0 +1,3 @@ +from . import _tree +from . import _units +from . import _wt5 \ No newline at end of file diff --git a/WrightTools/cli/_tree.py b/WrightTools/cli/_tree.py new file mode 100644 index 000000000..5710fe509 --- /dev/null +++ b/WrightTools/cli/_tree.py @@ -0,0 +1,36 @@ +# --- import -------------------------------------------------------------------------------------- + + +import click +import WrightTools as wt + + +# --- define -------------------------------------------------------------------------------------- + + +@click.group() +@click.version_option(wt.__version__) +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) + + + +if __name__ == "__main__": + cli() diff --git a/WrightTools/cli/_units.py b/WrightTools/cli/_units.py new file mode 100644 index 000000000..14ddd8ea8 --- /dev/null +++ b/WrightTools/cli/_units.py @@ -0,0 +1,53 @@ +# --- import -------------------------------------------------------------------------------------- + + +import click +import WrightTools as wt + + +# --- define -------------------------------------------------------------------------------------- + + +@click.group() +@click.version_option(wt.__version__) +def cli(): + pass + + +@cli.command(name="convert") +@click.argument("number", type=float, nargs=1) +@click.argument("unit", nargs=1) +@click.argument("destination_unit", default=None, nargs=-1) +def convert(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 + + 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 wt.units.is_valid_conversion(unit, destination_unit): + raise wt.exceptions.UnitsError(wt.units.get_valid_conversions(unit), destination_unit) + new = wt.units.convert(number, unit, destination_unit) + print(f"{number} {unit} = {fmt(new)} {destination_unit}") + else: + valid_units = wt.units.get_valid_conversions(unit) + for d_unit in valid_units: + new = wt.units.convert(number, unit, d_unit) + print(f"{fmt(new)} {d_unit}") + + +if __name__ == "__main__": + cli() diff --git a/WrightTools/__main__.py b/WrightTools/cli/_wt5.py similarity index 65% rename from WrightTools/__main__.py rename to WrightTools/cli/_wt5.py index 81c03f19a..3aeb30c86 100644 --- a/WrightTools/__main__.py +++ b/WrightTools/cli/_wt5.py @@ -14,23 +14,6 @@ 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): @@ -135,40 +118,5 @@ def _interact(shell, path): pass -@cli.command(name="convert") -@click.argument("number", type=float, nargs=1) -@click.argument("unit", nargs=1) -@click.argument("destination_unit", default=None, nargs=-1) -def convert(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 - - 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 wt.units.is_valid_conversion(unit, destination_unit): - raise wt.exceptions.UnitsError(wt.units.get_valid_conversions(unit), destination_unit) - new = wt.units.convert(number, unit, destination_unit) - print(f"{number} {unit} = {fmt(new)} {destination_unit}") - else: - valid_units = wt.units.get_valid_conversions(unit) - for d_unit in valid_units: - new = wt.units.convert(number, unit, d_unit) - print(f"{fmt(new)} {d_unit}") - - if __name__ == "__main__": cli() diff --git a/setup.py b/setup.py index 8a1fb9739..53dbb4a4d 100755 --- a/setup.py +++ b/setup.py @@ -70,9 +70,9 @@ def read(fname): keywords="spectroscopy science multidimensional visualization", entry_points={ "console_scripts": [ - "wt-tree=WrightTools.__main__:tree", - "wt5=WrightTools.__main__:wt5", - "wt-convert=WrightTools.__main__:convert", + "wt-tree=WrightTools.cli._tree:cli", + "wt5=WrightTools.cli._wt5:cli", + "wt-convert=WrightTools.cli._units:cli", ] }, classifiers=[ From a097b4296572ee85ac629f30368f356a4c536283 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 12:41:04 -0600 Subject: [PATCH 19/33] Update _glob.py incorporate attrs filter in glob methods --- WrightTools/kit/_glob.py | 63 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index 90c2caadc..08d411683 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -1,15 +1,15 @@ import pathlib -import os -from typing import Union +from os import PathLike +from typing import Union, List, Iterator from ..data import Data from ..collection import Collection from .._open import open -__all__ = ["describe_wt5", "glob_wt5s"] +__all__ = ["describe_wt5", "filter_wt5s", "glob_wt5s", "search_for_attrs",] -def describe_wt5(path: Union[str, os.PathLike]) -> dict: +def describe_wt5(path: Union[str, PathLike]) -> dict: """report useful general information about a wt5 file""" wt5 = open(path) desc = dict() @@ -31,7 +31,58 @@ def describe_wt5(path: Union[str, os.PathLike]) -> dict: return desc -def glob_wt5s(directory: Union[str, os.PathLike], recursive=True): - """find all wt5 files in a directory""" +def glob_wt5s(directory: Union[str, PathLike], recursive=True) -> Iterator: + """glob all wt5 files in a directory""" pattern = "**/*.wt5" if recursive else f"*.wt5" return pathlib.Path(directory).glob(pattern) + + +def search_for_attrs( + directory: Union[str, PathLike], + recursive=True, + **kwargs + ) -> List[pathlib.Path]: + """ + Find wt5 file(s) by matching data attrs items. + + Parameters + ---------- + directory : path-like + directory to search + recursive : boolean (default True) + whether or not recursively search the directory + + kwargs + ------ + key value pairs to filter the attrs with + + Returns + ------- + paths : list + list of pathlib.Path objects that match + + Example + ------- + To find a scan based on scan parameters in the bluesky-cmds: + >>> search_wt5_by_attr(os.environ["WT5_DATA_DIR"], name="primary", shape=[136,101], ) + """ + return filter_wt5s(glob_wt5s(directory, recursive), **kwargs) + + +def filter_wt5s( + paths:List[Union[str, PathLike]], + **kwargs + ) -> List[Union[str, PathLike]]: + """fillter wt5s by attrs + """ + return [p for p in filter(_gen_filter_by_attrs(**kwargs), paths)] + + +def _gen_filter_by_attrs(**kwargs): + def fil(x): + attrs = open(x).attrs + if all([key in attrs for key in kwargs.keys()]): + return all([attrs[key] == kwargs[key] for key in kwargs]) + else: + return False + return fil From b8e93a9dd284e63e0017e5faa859cf5530cae6d0 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:44:08 -0600 Subject: [PATCH 20/33] refactor kit path/glob utils try to use pathlib over os --- WrightTools/kit/_glob.py | 28 +++++++++++++++-- WrightTools/kit/_path.py | 65 +++++++++------------------------------- 2 files changed, 40 insertions(+), 53 deletions(-) diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index 08d411683..a1e91ff6e 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -6,7 +6,7 @@ from .._open import open -__all__ = ["describe_wt5", "filter_wt5s", "glob_wt5s", "search_for_attrs",] +__all__ = ["describe_wt5", "filter_wt5s", "glob_handler", "glob_wt5s", "search_for_attrs",] def describe_wt5(path: Union[str, PathLike]) -> dict: @@ -37,6 +37,30 @@ def glob_wt5s(directory: Union[str, PathLike], recursive=True) -> Iterator: return pathlib.Path(directory).glob(pattern) +def glob_handler(extension, folder=None, identifier=None, recursive=True) -> List[pathlib.Path]: + """Return a list of all files matching specified inputs. + + Parameters + ---------- + extension : string + File extension. + folder : string (optional) + Folder to search within. Default is None (current working + directory). + identifier : string + Unique identifier. Default is None. + recursive : bool + When true, searches folder and all subfolders for identifier + + Returns + ------- + list of pathlib.Path objects + path objects for matching files. + """ + pattern = f"**/*.{extension}" if recursive else f"*.{extension}" + return [x for x in filter(lambda x: identifier in str(x), pathlib.Path(folder).glob(pattern))] + + def search_for_attrs( directory: Union[str, PathLike], recursive=True, @@ -63,7 +87,7 @@ def search_for_attrs( Example ------- - To find a scan based on scan parameters in the bluesky-cmds: + To find a scan from scan parameters in the bluesky-cmds: >>> search_wt5_by_attr(os.environ["WT5_DATA_DIR"], name="primary", shape=[136,101], ) """ return filter_wt5s(glob_wt5s(directory, recursive), **kwargs) diff --git a/WrightTools/kit/_path.py b/WrightTools/kit/_path.py index 9e386b615..cf3def9c0 100644 --- a/WrightTools/kit/_path.py +++ b/WrightTools/kit/_path.py @@ -3,78 +3,41 @@ # --- import -------------------------------------------------------------------------------------- -import os -import glob +import pathlib # --- define -------------------------------------------------------------------------------------- -__all__ = ["get_path_matching", "glob_handler"] +__all__ = ["get_path_matching"] # --- functions ----------------------------------------------------------------------------------- -def get_path_matching(name): - """Get path matching a name. +def get_path_matching(name:str) -> pathlib.Path: + """ + Non-recursive search for path to the folder "name". + Searches the user directory, then looks up the cwd for a parent folder that matches. Parameters ---------- name : string - Name to search for. + name of directory to search for. Returns ------- - string - Full filepath. + pathlib.Path + Full filepath to directory name. + """ # first try looking in the user folder - p = os.path.join(os.path.expanduser("~"), name) + p = pathlib.Path.home() / name # then try expanding upwards from cwd - if not os.path.isdir(p): + if not p.is_dir(): p = None - drive, folders = os.path.splitdrive(os.getcwd()) - folders = folders.split(os.sep) - folders.insert(0, os.sep) + drive, *folders = pathlib.Path.cwd().parts if name in folders: - p = os.path.join(drive, *folders[: folders.index(name) + 1]) + p = pathlib.Path(drive).joinpath(*folders[:folders.index(name)+1]) # TODO: something more robust to catch the rest of the cases? return p - - -def glob_handler(extension, folder=None, identifier=None): - """Return a list of all files matching specified inputs. - - Parameters - ---------- - extension : string - File extension. - folder : string (optional) - Folder to search within. Default is None (current working - directory). - identifier : string - Unique identifier. Default is None. - - Returns - ------- - list of strings - Full path of matching files. - """ - filepaths = [] - if folder: - # comment out [ and ]... - folder = folder.replace("[", "?") - folder = folder.replace("]", "*") - folder = folder.replace("?", "[[]") - folder = folder.replace("*", "[]]") - glob_str = os.path.join(folder, "*" + extension) - else: - glob_str = "*" + extension + "*" - for filepath in glob.glob(glob_str): - if identifier: - if identifier in filepath: - filepaths.append(filepath) - else: - filepaths.append(filepath) - return filepaths From 8e4fbc2d5db65ad12623bf2e88ae31a22099bdf5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 19:44:23 +0000 Subject: [PATCH 21/33] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- WrightTools/cli/__init__.py | 2 +- WrightTools/cli/_tree.py | 1 - WrightTools/kit/_glob.py | 27 ++++++++++++++------------- WrightTools/kit/_path.py | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/WrightTools/cli/__init__.py b/WrightTools/cli/__init__.py index b1f623521..c8efc90b5 100644 --- a/WrightTools/cli/__init__.py +++ b/WrightTools/cli/__init__.py @@ -1,3 +1,3 @@ from . import _tree from . import _units -from . import _wt5 \ No newline at end of file +from . import _wt5 diff --git a/WrightTools/cli/_tree.py b/WrightTools/cli/_tree.py index 5710fe509..e52d51dee 100644 --- a/WrightTools/cli/_tree.py +++ b/WrightTools/cli/_tree.py @@ -31,6 +31,5 @@ def tree(path, internal_path, depth=9, verbose=False): obj.print_tree(verbose=verbose, depth=depth) - if __name__ == "__main__": cli() diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index a1e91ff6e..c0d051b14 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -6,7 +6,13 @@ from .._open import open -__all__ = ["describe_wt5", "filter_wt5s", "glob_handler", "glob_wt5s", "search_for_attrs",] +__all__ = [ + "describe_wt5", + "filter_wt5s", + "glob_handler", + "glob_wt5s", + "search_for_attrs", +] def describe_wt5(path: Union[str, PathLike]) -> dict: @@ -62,12 +68,10 @@ def glob_handler(extension, folder=None, identifier=None, recursive=True) -> Lis def search_for_attrs( - directory: Union[str, PathLike], - recursive=True, - **kwargs - ) -> List[pathlib.Path]: + directory: Union[str, PathLike], recursive=True, **kwargs +) -> List[pathlib.Path]: """ - Find wt5 file(s) by matching data attrs items. + Find wt5 file(s) by matching data attrs items. Parameters ---------- @@ -84,7 +88,7 @@ def search_for_attrs( ------- paths : list list of pathlib.Path objects that match - + Example ------- To find a scan from scan parameters in the bluesky-cmds: @@ -93,12 +97,8 @@ def search_for_attrs( return filter_wt5s(glob_wt5s(directory, recursive), **kwargs) -def filter_wt5s( - paths:List[Union[str, PathLike]], - **kwargs - ) -> List[Union[str, PathLike]]: - """fillter wt5s by attrs - """ +def filter_wt5s(paths: List[Union[str, PathLike]], **kwargs) -> List[Union[str, PathLike]]: + """fillter wt5s by attrs""" return [p for p in filter(_gen_filter_by_attrs(**kwargs), paths)] @@ -109,4 +109,5 @@ def fil(x): return all([attrs[key] == kwargs[key] for key in kwargs]) else: return False + return fil diff --git a/WrightTools/kit/_path.py b/WrightTools/kit/_path.py index cf3def9c0..d7c558bea 100644 --- a/WrightTools/kit/_path.py +++ b/WrightTools/kit/_path.py @@ -15,7 +15,7 @@ # --- functions ----------------------------------------------------------------------------------- -def get_path_matching(name:str) -> pathlib.Path: +def get_path_matching(name: str) -> pathlib.Path: """ Non-recursive search for path to the folder "name". Searches the user directory, then looks up the cwd for a parent folder that matches. @@ -38,6 +38,6 @@ def get_path_matching(name:str) -> pathlib.Path: p = None drive, *folders = pathlib.Path.cwd().parts if name in folders: - p = pathlib.Path(drive).joinpath(*folders[:folders.index(name)+1]) + p = pathlib.Path(drive).joinpath(*folders[: folders.index(name) + 1]) # TODO: something more robust to catch the rest of the cases? return p From 7757bbbd84ced93e264739a382df6f0f3b1744dc Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:24:31 -0600 Subject: [PATCH 22/33] Update _wt5.py --- WrightTools/cli/_wt5.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WrightTools/cli/_wt5.py b/WrightTools/cli/_wt5.py index 3aeb30c86..a8473c060 100644 --- a/WrightTools/cli/_wt5.py +++ b/WrightTools/cli/_wt5.py @@ -56,7 +56,7 @@ def scan(directory=None, no_recursion=False): desc = wt.kit.describe_wt5(path) desc["filesize"] = f"{os.path.getsize(path) / 1e6:.1f}" path = path.relative_to(directory) - print(path.parent) + paths.append(path) desc["path"] = ( f"[link={path.parent}]{path.parent}[/link]" + r"\\" if str(path.parent) != "." @@ -97,6 +97,7 @@ def raise_sys_exit(): except ValueError: break if valid: + print("interacting...") _interact(shell, str(paths[int(msg)])) continue From acc6b366b5d5a9e23d1681c698636a27346ecb44 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 15:50:52 -0600 Subject: [PATCH 23/33] Update _glob.py --- WrightTools/kit/_glob.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index c0d051b14..01be2a54e 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -98,16 +98,16 @@ def search_for_attrs( def filter_wt5s(paths: List[Union[str, PathLike]], **kwargs) -> List[Union[str, PathLike]]: - """fillter wt5s by attrs""" + """fillter a list of wt5 paths by attrs""" return [p for p in filter(_gen_filter_by_attrs(**kwargs), paths)] def _gen_filter_by_attrs(**kwargs): - def fil(x): + def filter(x): attrs = open(x).attrs if all([key in attrs for key in kwargs.keys()]): return all([attrs[key] == kwargs[key] for key in kwargs]) else: return False - return fil + return filter From 2c4de2cdb20b84692d98c7f683a5e1dfc5e2d79f Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:01:43 -0600 Subject: [PATCH 24/33] tree and convert work --- WrightTools/cli/_tree.py | 9 ++------- WrightTools/cli/_units.py | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/WrightTools/cli/_tree.py b/WrightTools/cli/_tree.py index e52d51dee..15114333c 100644 --- a/WrightTools/cli/_tree.py +++ b/WrightTools/cli/_tree.py @@ -8,20 +8,15 @@ # --- define -------------------------------------------------------------------------------------- -@click.group() +@click.command(name="tree", help="Print a given data tree.") @click.version_option(wt.__version__) -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): +def cli(path, internal_path, depth=9, verbose=False): # open the object obj = wt.open(path)[internal_path] diff --git a/WrightTools/cli/_units.py b/WrightTools/cli/_units.py index 14ddd8ea8..20b021411 100644 --- a/WrightTools/cli/_units.py +++ b/WrightTools/cli/_units.py @@ -8,17 +8,12 @@ # --- define -------------------------------------------------------------------------------------- -@click.group() +@click.command() @click.version_option(wt.__version__) -def cli(): - pass - - -@cli.command(name="convert") @click.argument("number", type=float, nargs=1) @click.argument("unit", nargs=1) @click.argument("destination_unit", default=None, nargs=-1) -def convert(number, unit, destination_unit=None): +def cli(number, unit, destination_unit=None): """Convert numbers to different units.""" if int(number) == number: From fd0ddc5c25c3f746d2c068670a9363870fd6961f Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:57:19 -0600 Subject: [PATCH 25/33] cleanup --- WrightTools/cli/__init__.py | 1 - WrightTools/cli/_tree.py | 30 ------------------------------ WrightTools/cli/_units.py | 18 ++++++++++-------- WrightTools/cli/_wt5.py | 20 +++++++++++++++++++- setup.py | 1 - 5 files changed, 29 insertions(+), 41 deletions(-) delete mode 100644 WrightTools/cli/_tree.py diff --git a/WrightTools/cli/__init__.py b/WrightTools/cli/__init__.py index c8efc90b5..c534ccce2 100644 --- a/WrightTools/cli/__init__.py +++ b/WrightTools/cli/__init__.py @@ -1,3 +1,2 @@ -from . import _tree from . import _units from . import _wt5 diff --git a/WrightTools/cli/_tree.py b/WrightTools/cli/_tree.py deleted file mode 100644 index 15114333c..000000000 --- a/WrightTools/cli/_tree.py +++ /dev/null @@ -1,30 +0,0 @@ -# --- import -------------------------------------------------------------------------------------- - - -import click -import WrightTools as wt - - -# --- define -------------------------------------------------------------------------------------- - - -@click.command(name="tree", help="Print a given data tree.") -@click.version_option(wt.__version__) -@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 cli(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) - - -if __name__ == "__main__": - cli() diff --git a/WrightTools/cli/_units.py b/WrightTools/cli/_units.py index 20b021411..fd5f8eb2d 100644 --- a/WrightTools/cli/_units.py +++ b/WrightTools/cli/_units.py @@ -2,14 +2,16 @@ import click -import WrightTools as wt +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() -@click.version_option(wt.__version__) +@click.command(name="convert", help="convert numbers to different units.") +@click.version_option(__wt_version__, package_name="WrightTools") @click.argument("number", type=float, nargs=1) @click.argument("unit", nargs=1) @click.argument("destination_unit", default=None, nargs=-1) @@ -33,14 +35,14 @@ def fmt(new): if len(destination_unit): # units provided destination_unit = destination_unit[0] - if not wt.units.is_valid_conversion(unit, destination_unit): - raise wt.exceptions.UnitsError(wt.units.get_valid_conversions(unit), destination_unit) - new = wt.units.convert(number, unit, destination_unit) + 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 = wt.units.get_valid_conversions(unit) + valid_units = get_valid_conversions(unit) for d_unit in valid_units: - new = wt.units.convert(number, unit, d_unit) + new = convert(number, unit, d_unit) print(f"{fmt(new)} {d_unit}") diff --git a/WrightTools/cli/_wt5.py b/WrightTools/cli/_wt5.py index a8473c060..75fe8ed2c 100644 --- a/WrightTools/cli/_wt5.py +++ b/WrightTools/cli/_wt5.py @@ -9,11 +9,29 @@ @click.group() -@click.version_option(wt.__version__) +@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): diff --git a/setup.py b/setup.py index 53dbb4a4d..d4fe3588a 100755 --- a/setup.py +++ b/setup.py @@ -70,7 +70,6 @@ def read(fname): keywords="spectroscopy science multidimensional visualization", entry_points={ "console_scripts": [ - "wt-tree=WrightTools.cli._tree:cli", "wt5=WrightTools.cli._wt5:cli", "wt-convert=WrightTools.cli._units:cli", ] From b380fcd1e0512e64e9c5a9a1f2b23966e9e580ac Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:57:31 -0600 Subject: [PATCH 26/33] docs --- docs/cli.rst | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ docs/index.rst | 1 + 2 files changed, 59 insertions(+) create mode 100644 docs/cli.rst diff --git a/docs/cli.rst b/docs/cli.rst new file mode 100644 index 000000000..ea5d5db84 --- /dev/null +++ b/docs/cli.rst @@ -0,0 +1,58 @@ +.. _cli: + +Command Line Interface (CLI) +============================ + +Most of the CLI interface is new as of v3.5.2 and under active depelopment. +The commands here may change. +Currently, there are two supported CLI calls to use: `wt-units`, and `wt5`. +For usage hints, use the `--help` argument. + +wt-units +---------- + +Use wt-units to explore the WrightTools units system and the conversions of units. + +.. code-block:: shell + > wt-units 1330 nm wn + 7692.3 wn + 0.95372 eV + 953.72 meV + 2.306096e+14 Hz + 230.61 THz + 230610 GHz + +wt5 +--- + +The wt5 command is meant to provide easy access to wt5 files and some basic wt5 properties. + +Use `wt5 glob` to quickly probe a folder for wt5s contained inside + +.. code-block:: shell + + > wt5 glob -d path/to/datasets + " + ┏━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━┓ + ┃ ┃ path ┃ size (MB) ┃ created ┃ name ┃ shape ┃ axes ┃ variables ┃ channels ┃ + ┡━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━┩ + │ 0 │ tests\dataset\max_cached.wt5 │ 0.0 │ 2020-11-16 23:49:27 │ data │ (3,) │ () │ 1 │ 0 │ + │ 1 │ WrightTools\datasets\wt5\v1.0.0\perovskite_TA.wt5 │ 3.4 │ 2016.03.28 21_15_20 │ perovskite_TA │ (52, 52, 13) │ ('w1=wm', 'w2', 'd2') │ 27 │ 10 │ + │ 2 │ WrightTools\datasets\wt5\v1.0.1\MoS2_TrEE_movie.wt5 │ 2.3 │ 2018-06-11 16:41:47 │ _001_dat │ (41, 41, 23) │ ('w2', 'w1=wm', 'd2') │ 7 │ 6 │ + └───┴─────────────────────────────────────────────────────┴───────────┴─────────────────────┴───────────────┴──────────────┴───────────────────────┴───────────┴──────────┘ + Specify an index to load that entry. Use `t` to rerender table. Use no argument to exit. + " + +Use `wt5 load` to quickly open an interactive python console with your wt5 data pre-loaded. + +Use `wt5 tree` to see a quick tree structure of a wt5 file. + +.. code-block:: shell + > wt5 tree path\to\data + " + / (...\felu75fe.wt5) (25, 256) + ├── axes (2): w2 (wn), w2-wa (wn) + ├── constants (0): + └── channels (1): array_signal + " + diff --git a/docs/index.rst b/docs/index.rst index 82c408986..89b9a2568 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -55,6 +55,7 @@ Contents datasets contributing wt5 + cli api/modules auto_examples/index citation From f7d44a62066f95535b72706ec9f8fa4009899d9d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 22:57:48 +0000 Subject: [PATCH 27/33] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- WrightTools/cli/_wt5.py | 1 - docs/cli.rst | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/WrightTools/cli/_wt5.py b/WrightTools/cli/_wt5.py index 75fe8ed2c..f1d9e1e38 100644 --- a/WrightTools/cli/_wt5.py +++ b/WrightTools/cli/_wt5.py @@ -31,7 +31,6 @@ def tree(path, internal_path, depth=9, verbose=False): 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): diff --git a/docs/cli.rst b/docs/cli.rst index ea5d5db84..d103d2caa 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -43,7 +43,7 @@ Use `wt5 glob` to quickly probe a folder for wt5s contained inside Specify an index to load that entry. Use `t` to rerender table. Use no argument to exit. " -Use `wt5 load` to quickly open an interactive python console with your wt5 data pre-loaded. +Use `wt5 load` to quickly open an interactive python console with your wt5 data pre-loaded. Use `wt5 tree` to see a quick tree structure of a wt5 file. From ba91121ff4247f9daf98db16a8fe617348a5a656 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 18:40:17 -0600 Subject: [PATCH 28/33] Update wt_tree.py --- tests/entry_points/wt_tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/entry_points/wt_tree.py b/tests/entry_points/wt_tree.py index 6ab6bf221..f9a3f5e02 100644 --- a/tests/entry_points/wt_tree.py +++ b/tests/entry_points/wt_tree.py @@ -11,7 +11,7 @@ def test_no_change(): before = hashlib.sha1() with open("test_no_change.wt5", "rb") as f: before.update(f.read()) - subprocess.call(["wt-tree", "test_no_change.wt5"]) + subprocess.call(["wt5", "tree", "test_no_change.wt5"]) after = hashlib.sha1() with open("test_no_change.wt5", "rb") as f: after.update(f.read()) From f6c2b00c683d4d0ad551f13537be851a0708326c Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Mon, 19 Feb 2024 18:41:38 -0600 Subject: [PATCH 29/33] Update _units.py --- WrightTools/cli/_units.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WrightTools/cli/_units.py b/WrightTools/cli/_units.py index fd5f8eb2d..93044877a 100644 --- a/WrightTools/cli/_units.py +++ b/WrightTools/cli/_units.py @@ -11,7 +11,7 @@ @click.command(name="convert", help="convert numbers to different units.") -@click.version_option(__wt_version__, package_name="WrightTools") +@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) From 28a6befe707071bcf4775aae575ec85c0003d1d4 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Tue, 20 Feb 2024 10:42:36 -0600 Subject: [PATCH 30/33] Update _glob.py directory is optional argument for most methods --- WrightTools/kit/_glob.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index 01be2a54e..dd2b1a359 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -37,20 +37,22 @@ def describe_wt5(path: Union[str, PathLike]) -> dict: return desc -def glob_wt5s(directory: Union[str, PathLike], recursive=True) -> Iterator: +def glob_wt5s(directory: Union[str, PathLike, None]=None, recursive=True) -> Iterator: """glob all wt5 files in a directory""" + if directory is None: + directory = pathlib.Path.cwd() pattern = "**/*.wt5" if recursive else f"*.wt5" return pathlib.Path(directory).glob(pattern) -def glob_handler(extension, folder=None, identifier=None, recursive=True) -> List[pathlib.Path]: +def glob_handler(extension, directory=None, identifier=None, recursive=True) -> List[pathlib.Path]: """Return a list of all files matching specified inputs. Parameters ---------- extension : string File extension. - folder : string (optional) + directory : string (optional) Folder to search within. Default is None (current working directory). identifier : string @@ -63,12 +65,14 @@ def glob_handler(extension, folder=None, identifier=None, recursive=True) -> Lis list of pathlib.Path objects path objects for matching files. """ + if directory is None: + directory = pathlib.Path.cwd() pattern = f"**/*.{extension}" if recursive else f"*.{extension}" - return [x for x in filter(lambda x: identifier in str(x), pathlib.Path(folder).glob(pattern))] + return [x for x in filter(lambda x: identifier in str(x), pathlib.Path(directory).glob(pattern))] def search_for_attrs( - directory: Union[str, PathLike], recursive=True, **kwargs + directory: Union[str, PathLike, None]=None, recursive=True, **kwargs ) -> List[pathlib.Path]: """ Find wt5 file(s) by matching data attrs items. @@ -76,7 +80,7 @@ def search_for_attrs( Parameters ---------- directory : path-like - directory to search + directory to search. Defaults to cwd. recursive : boolean (default True) whether or not recursively search the directory From fae48aed283ce3d84443cc334b822fac7a95e29d Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Tue, 20 Feb 2024 12:55:03 -0600 Subject: [PATCH 31/33] wt5 glob and explore --- WrightTools/cli/_wt5.py | 12 +++++++++++- docs/cli.rst | 23 +++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/WrightTools/cli/_wt5.py b/WrightTools/cli/_wt5.py index f1d9e1e38..9cd94b351 100644 --- a/WrightTools/cli/_wt5.py +++ b/WrightTools/cli/_wt5.py @@ -40,7 +40,17 @@ def load(path): _interact(shell, path) -@cli.command(name="glob", help="Scan a directory and survey the wt5 objects found.") +@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." ) diff --git a/docs/cli.rst b/docs/cli.rst index d103d2caa..2ef596a2a 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -5,13 +5,13 @@ Command Line Interface (CLI) Most of the CLI interface is new as of v3.5.2 and under active depelopment. The commands here may change. -Currently, there are two supported CLI calls to use: `wt-units`, and `wt5`. +Currently, there are two supported CLI calls to use: `wt-convert`, and `wt5`. For usage hints, use the `--help` argument. -wt-units +wt-convert ---------- -Use wt-units to explore the WrightTools units system and the conversions of units. +Use `wt-convert`` to explore the WrightTools units system and the conversions of units. .. code-block:: shell > wt-units 1330 nm wn @@ -28,10 +28,17 @@ wt5 The wt5 command is meant to provide easy access to wt5 files and some basic wt5 properties. Use `wt5 glob` to quickly probe a folder for wt5s contained inside - .. code-block:: shell > wt5 glob -d path/to/datasets + tests\dataset\max_cached.wt5 + WrightTools\datasets\wt5\v1.0.0\perovskite_TA.wt5 + WrightTools\datasets\wt5\v1.0.1\MoS2_TrEE_movie.wt5 + +Use `wt5 explore` to see details of wt5s within a folder, as the option of quick load a wt5. +.. code-block:: shell + + > wt5 explore -d path/to/data/folders " ┏━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━┓ ┃ ┃ path ┃ size (MB) ┃ created ┃ name ┃ shape ┃ axes ┃ variables ┃ channels ┃ @@ -44,6 +51,14 @@ Use `wt5 glob` to quickly probe a folder for wt5s contained inside " Use `wt5 load` to quickly open an interactive python console with your wt5 data pre-loaded. +.. code-block:: shell + > wt5 load path\to\data_file.wt5 + --- INTERACTING --- (to continue, call exit() or quit()) + >>> import WrightTools as wt + >>> import matplotlib.pyplot as plt + >>> d = wt.open(r'path/to/data_file.wt5') + >>> + Use `wt5 tree` to see a quick tree structure of a wt5 file. From a1f118d2f011dd7588d6e7ff8dae781c2d8ca597 Mon Sep 17 00:00:00 2001 From: Daniel Kohler <11864045+ddkohler@users.noreply.github.com> Date: Tue, 20 Feb 2024 12:56:15 -0600 Subject: [PATCH 32/33] Update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c295dfdbf..34ec9f87b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 From a05f6b32dc89c44f727e308dbf43093ccda0e7de Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 18:57:49 +0000 Subject: [PATCH 33/33] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- WrightTools/kit/_glob.py | 8 +++++--- docs/cli.rst | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/WrightTools/kit/_glob.py b/WrightTools/kit/_glob.py index dd2b1a359..1f6bbdc17 100644 --- a/WrightTools/kit/_glob.py +++ b/WrightTools/kit/_glob.py @@ -37,7 +37,7 @@ def describe_wt5(path: Union[str, PathLike]) -> dict: return desc -def glob_wt5s(directory: Union[str, PathLike, None]=None, recursive=True) -> Iterator: +def glob_wt5s(directory: Union[str, PathLike, None] = None, recursive=True) -> Iterator: """glob all wt5 files in a directory""" if directory is None: directory = pathlib.Path.cwd() @@ -68,11 +68,13 @@ def glob_handler(extension, directory=None, identifier=None, recursive=True) -> if directory is None: directory = pathlib.Path.cwd() pattern = f"**/*.{extension}" if recursive else f"*.{extension}" - return [x for x in filter(lambda x: identifier in str(x), pathlib.Path(directory).glob(pattern))] + return [ + x for x in filter(lambda x: identifier in str(x), pathlib.Path(directory).glob(pattern)) + ] def search_for_attrs( - directory: Union[str, PathLike, None]=None, recursive=True, **kwargs + directory: Union[str, PathLike, None] = None, recursive=True, **kwargs ) -> List[pathlib.Path]: """ Find wt5 file(s) by matching data attrs items. diff --git a/docs/cli.rst b/docs/cli.rst index 2ef596a2a..1b576ff15 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -32,7 +32,7 @@ Use `wt5 glob` to quickly probe a folder for wt5s contained inside > wt5 glob -d path/to/datasets tests\dataset\max_cached.wt5 - WrightTools\datasets\wt5\v1.0.0\perovskite_TA.wt5 + WrightTools\datasets\wt5\v1.0.0\perovskite_TA.wt5 WrightTools\datasets\wt5\v1.0.1\MoS2_TrEE_movie.wt5 Use `wt5 explore` to see details of wt5s within a folder, as the option of quick load a wt5. @@ -57,7 +57,7 @@ Use `wt5 load` to quickly open an interactive python console with your wt5 data >>> import WrightTools as wt >>> import matplotlib.pyplot as plt >>> d = wt.open(r'path/to/data_file.wt5') - >>> + >>> Use `wt5 tree` to see a quick tree structure of a wt5 file.