whiteboxgui module¶
Main module.
build_toolbox(tools_dict, max_width='1080px', max_height='600px', sandbox_path=None)
¶
Build the toolbox for WhiteboxTools.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
tools_dict |
dict |
A dictionary containing information for all tools. |
required |
max_width |
str |
The maximum width of the widget. |
'1080px' |
max_height |
str |
The maximum height of the widget. |
'600px' |
sandbox_path |
str |
The path to the sandbox folder. Defaults to None. |
None |
Returns:
Type | Description |
---|---|
object |
An ipywidget representing the toolbox. |
Source code in whiteboxgui/whiteboxgui.py
def build_toolbox(
tools_dict, max_width="1080px", max_height="600px", sandbox_path=None
):
"""Build the toolbox for WhiteboxTools.
Args:
tools_dict (dict): A dictionary containing information for all tools.
max_width (str, optional): The maximum width of the widget.
max_height (str, optional): The maximum height of the widget.
sandbox_path (str, optional): The path to the sandbox folder. Defaults to None.
Returns:
object: An ipywidget representing the toolbox.
"""
left_widget = widgets.VBox(layout=widgets.Layout(min_width="175px"))
center_widget = widgets.VBox(
layout=widgets.Layout(min_width="200px", max_width="200px")
)
right_widget = widgets.Output(
layout=widgets.Layout(width="630px", max_height=max_height)
)
full_widget = widgets.HBox(
[left_widget, center_widget, right_widget],
layout=widgets.Layout(max_width=max_width, max_height=max_height),
)
search_widget = widgets.Text(
placeholder="Search tools ...", layout=widgets.Layout(width="170px")
)
label_widget = widgets.Label(layout=widgets.Layout(width="170px"))
label_widget.value = f"{len(tools_dict)} Available Tools"
close_btn = widgets.Button(
description="Close Toolbox", icon="close", layout=widgets.Layout(width="170px")
)
categories = {}
categories["All Tools"] = []
for key in tools_dict.keys():
category = tools_dict[key]["category"]
if category not in categories.keys():
categories[category] = []
categories[category].append(tools_dict[key]["name"])
categories["All Tools"].append(tools_dict[key]["name"])
options = list(categories.keys())
all_tools = categories["All Tools"]
all_tools.sort()
category_widget = widgets.Select(
options=options, layout=widgets.Layout(width="170px", height="175px")
)
tools_widget = widgets.Select(
options=[], layout=widgets.Layout(width="195px", height="400px")
)
def category_selected(change):
if change["new"]:
selected = change["owner"].value
options = categories[selected]
options.sort()
tools_widget.options = options
label_widget.value = f"{len(options)} Available Tools"
category_widget.observe(category_selected, "value")
def tool_selected(change):
if change["new"]:
selected = change["owner"].value
tool_dict = tools_dict[selected]
with right_widget:
right_widget.clear_output()
display(
tool_gui(
tool_dict, max_height=max_height, sandbox_path=sandbox_path
)
)
tools_widget.observe(tool_selected, "value")
def search_changed(change):
if change["new"]:
keyword = change["owner"].value
if len(keyword) > 0:
selected_tools = []
for tool in all_tools:
if (
keyword.lower() in tool.lower()
or keyword.lower() in tools_dict[tool]["description"]
):
selected_tools.append(tool)
if len(selected_tools) > 0:
tools_widget.options = selected_tools
label_widget.value = f"{len(selected_tools)} Available Tools"
else:
tools_widget.options = all_tools
label_widget.value = f"{len(tools_dict)} Available Tools"
search_widget.observe(search_changed, "value")
def close_btn_clicked(b):
full_widget.close()
close_btn.on_click(close_btn_clicked)
category_widget.value = list(categories.keys())[0]
tools_widget.options = all_tools
left_widget.children = [category_widget,
search_widget, label_widget, close_btn]
center_widget.children = [tools_widget]
return full_widget
build_toolbox_tree(tools_dict, folder_icon='folder', tool_icon='wrench', sandbox_path=None)
¶
Build the toolbox for WhiteboxTools.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
tools_dict |
dict |
A dictionary containing information for all tools. |
required |
folder_icon |
str |
The font-awesome icon for tool categories. Defaults to "folder". |
'folder' |
tool_icon |
str |
The font-awesome icon for tools. Defaults to "wrench". |
'wrench' |
sandbox_path |
str |
The path to the sandbox folder. Defaults to None. |
None |
Returns:
Type | Description |
---|---|
object |
An ipywidget representing the toolbox. |
Source code in whiteboxgui/whiteboxgui.py
def build_toolbox_tree(
tools_dict, folder_icon="folder", tool_icon="wrench", sandbox_path=None
):
"""Build the toolbox for WhiteboxTools.
Args:
tools_dict (dict): A dictionary containing information for all tools.
folder_icon (str, optional): The font-awesome icon for tool categories. Defaults to "folder".
tool_icon (str, optional): The font-awesome icon for tools. Defaults to "wrench".
sandbox_path (str, optional): The path to the sandbox folder. Defaults to None.
Returns:
object: An ipywidget representing the toolbox.
"""
left_widget = widgets.VBox()
right_widget = widgets.VBox()
full_widget = widgets.HBox([left_widget, right_widget])
search_description = f"{len(tools_dict)} tools available. Search tools ..."
search_box = widgets.Text(placeholder=search_description)
search_box.layout.width = "270px"
close_btn = widgets.Button(
icon="close", layout=widgets.Layout(width="32px"))
def close_btn_clicked(b):
full_widget.close()
close_btn.on_click(close_btn_clicked)
tree_widget = widgets.Output()
tree_widget.layout.max_width = "310px"
tree_widget.overflow = "auto"
left_widget.children = [widgets.HBox([search_box, close_btn]), tree_widget]
output = widgets.Output(layout=widgets.Layout(max_width="760px"))
right_widget.children = [output]
tree = Tree(multiple_selection=False)
tree_dict = {}
def search_box_callback(text):
with tree_widget:
if text.value == "":
print("Loading...")
tree_widget.clear_output(wait=True)
display(tree)
else:
tree_widget.clear_output()
print("Searching...")
tree_widget.clear_output(wait=True)
sub_tree = search_api_tree(text.value, tree_dict, tools_dict)
display(sub_tree)
search_box.on_submit(search_box_callback)
root_name = "WhiteboxTools"
root_node = Node(root_name)
tree.add_node(root_node)
categories = {}
def handle_tool_clicked(event):
if event["new"]:
cur_node = event["owner"]
tool_name = cur_node.name
with output:
output.clear_output()
tool_ui = tool_gui(
tools_dict[tool_name], sandbox_path=sandbox_path)
display(tool_ui)
for key in tools_dict.keys():
category = tools_dict[key]["category"]
if category not in categories.keys():
category_node = Node(category, icon=folder_icon, opened=False)
root_node.add_node(category_node)
categories[category] = category_node
tool_node = Node(key, icon=tool_icon)
category_node.add_node(tool_node)
tree_dict[key] = tool_node
tool_node.observe(handle_tool_clicked, "selected")
else:
category_node = categories[category]
tool_node = Node(key, icon=tool_icon)
category_node.add_node(tool_node)
tree_dict[key] = tool_node
tool_node.observe(handle_tool_clicked, "selected")
with tree_widget:
tree_widget.clear_output()
display(tree)
return full_widget
clone_repo(out_dir='.', unzip=True)
¶
Clones the whiteboxgui GitHub repository.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
out_dir |
str |
Output folder for the repo. Defaults to '.'. |
'.' |
unzip |
bool |
Whether to unzip the repository. Defaults to True. |
True |
Source code in whiteboxgui/whiteboxgui.py
def clone_repo(out_dir=".", unzip=True):
"""Clones the whiteboxgui GitHub repository.
Args:
out_dir (str, optional): Output folder for the repo. Defaults to '.'.
unzip (bool, optional): Whether to unzip the repository. Defaults to True.
"""
url = "https://github.com/opengeos/whiteboxgui/archive/master.zip"
filename = "whiteboxgui-master.zip"
download_from_url(url, out_file_name=filename,
out_dir=out_dir, unzip=unzip)
create_code_cell(code='', where='below')
¶
Creates a code cell in the IPython Notebook.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
code |
str |
Code to fill the new code cell with. Defaults to ''. |
'' |
where |
str |
Where to add the new code cell. It can be one of the following: above, below, at_bottom. Defaults to 'below'. |
'below' |
Source code in whiteboxgui/whiteboxgui.py
def create_code_cell(code="", where="below"):
"""Creates a code cell in the IPython Notebook.
Args:
code (str, optional): Code to fill the new code cell with. Defaults to ''.
where (str, optional): Where to add the new code cell. It can be one of the following: above, below, at_bottom. Defaults to 'below'.
"""
import base64
from IPython.display import Javascript, display
encoded_code = (base64.b64encode(str.encode(code))).decode()
display(
Javascript(
"""
var code = IPython.notebook.insert_cell_{0}('code');
code.set_text(atob("{1}"));
""".format(
where, encoded_code
)
)
)
download_from_url(url, out_file_name=None, out_dir='.', unzip=True, verbose=False)
¶
Download a file from a URL (e.g., https://github.com/opengeos/whitebox/raw/master/examples/testdata.zip)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
url |
str |
The HTTP URL to download. |
required |
out_file_name |
str |
The output file name to use. Defaults to None. |
None |
out_dir |
str |
The output directory to use. Defaults to '.'. |
'.' |
unzip |
bool |
Whether to unzip the downloaded file if it is a zip file. Defaults to True. |
True |
verbose |
bool |
Whether to display or not the output of the function. Defaults to False. |
False |
Source code in whiteboxgui/whiteboxgui.py
def download_from_url(url, out_file_name=None, out_dir=".", unzip=True, verbose=False):
"""Download a file from a URL (e.g., https://github.com/opengeos/whitebox/raw/master/examples/testdata.zip)
Args:
url (str): The HTTP URL to download.
out_file_name (str, optional): The output file name to use. Defaults to None.
out_dir (str, optional): The output directory to use. Defaults to '.'.
unzip (bool, optional): Whether to unzip the downloaded file if it is a zip file. Defaults to True.
verbose (bool, optional): Whether to display or not the output of the function. Defaults to False.
"""
import tarfile
import urllib.request
import zipfile
in_file_name = os.path.basename(url)
if out_file_name is None:
out_file_name = in_file_name
out_file_path = os.path.join(os.path.abspath(out_dir), out_file_name)
if verbose:
print("Downloading {} ...".format(url))
try:
urllib.request.urlretrieve(url, out_file_path)
except Exception:
raise Exception("The URL is invalid. Please double check the URL.")
final_path = out_file_path
if unzip:
# if it is a zip file
if ".zip" in out_file_name:
if verbose:
print("Unzipping {} ...".format(out_file_name))
with zipfile.ZipFile(out_file_path, "r") as zip_ref:
zip_ref.extractall(out_dir)
final_path = os.path.join(
os.path.abspath(out_dir), out_file_name.replace(".zip", "")
)
# if it is a tar file
if ".tar" in out_file_name:
if verbose:
print("Unzipping {} ...".format(out_file_name))
with tarfile.open(out_file_path, "r") as tar_ref:
def is_within_directory(directory, target):
abs_directory = os.path.abspath(directory)
abs_target = os.path.abspath(target)
prefix = os.path.commonprefix([abs_directory, abs_target])
return prefix == abs_directory
def safe_extract(tar, path=".", members=None, *, numeric_owner=False):
for member in tar.getmembers():
member_path = os.path.join(path, member.name)
if not is_within_directory(path, member_path):
raise Exception("Attempted Path Traversal in Tar File")
tar.extractall(path, members, numeric_owner=numeric_owner)
safe_extract(tar_ref, out_dir)
final_path = os.path.join(
os.path.abspath(out_dir), out_file_name.replace(".tart", "")
)
if verbose:
print("Data downloaded to: {}".format(final_path))
return
get_book_url(tool_name, category)
¶
Get the link to the help documentation of the tool.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
tool_name |
str |
The name of the tool. |
required |
category |
str |
The category of the tool. |
required |
Returns:
Type | Description |
---|---|
str |
The URL to help documentation. |
Source code in whiteboxgui/whiteboxgui.py
def get_book_url(tool_name, category):
"""Get the link to the help documentation of the tool.
Args:
tool_name (str): The name of the tool.
category (str): The category of the tool.
Returns:
str: The URL to help documentation.
"""
prefix = "https://www.whiteboxgeo.com/manual/wbt_book/available_tools"
if category == "Math and Stats Tools":
category = "Mathand Stats Tools"
url = "{}/{}.html#{}".format(
prefix, category.lower().replace(" ", "_"), to_camelcase(tool_name)
)
return url
get_ext_dict(verbose=True, reset=False)
¶
Generate a dictionary containing information for the general extension tools.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
verbose |
bool |
Whether to print out description info. Defaults to True. |
True |
reset |
bool |
Whether to recreate the json file containing the dictionary. Defaults to False. |
False |
Returns:
Type | Description |
---|---|
dict |
The dictionary containing information for general extension tools. |
Source code in whiteboxgui/whiteboxgui.py
def get_ext_dict(verbose=True, reset=False):
"""Generate a dictionary containing information for the general extension tools.
Args:
verbose (bool, optional): Whether to print out description info. Defaults to True.
reset (bool, optional): Whether to recreate the json file containing the dictionary. Defaults to False.
Returns:
dict: The dictionary containing information for general extension tools.
"""
import glob
import shutil
import urllib
import zipfile
os_links = {
"Windows": "https://www.whiteboxgeo.com/GTE_Windows/GeneralToolsetExtension_win.zip",
"Darwin": "https://www.whiteboxgeo.com/GTE_Darwin/GeneralToolsetExtension_MacOS_Intel.zip",
"Linux": "https://www.whiteboxgeo.com/GTE_Linux/GeneralToolsetExtension_linux.zip",
}
pkg_dir = os.path.dirname(
pkg_resources.resource_filename("whitebox", "whitebox.py")
)
plugin_dir = os.path.join(pkg_dir, "plugins")
ext_dir = os.path.join(pkg_dir, "GeneralToolsetExtension")
url = os_links[platform.system()]
zip_name = os.path.join(pkg_dir, os.path.basename(url))
if reset:
if os.path.exists(zip_name):
os.remove(zip_name)
if not os.path.exists(zip_name):
if verbose:
print("Downloading General Toolset Extension, please wait ...")
request = urllib.request.urlopen(url, timeout=500)
with open(zip_name, "wb") as f:
f.write(request.read())
if verbose:
print("Decompressing {} ...".format(os.path.basename(url)))
with zipfile.ZipFile(zip_name, "r") as zip_ref:
zip_ref.extractall(pkg_dir)
shutil.copytree(ext_dir, plugin_dir, dirs_exist_ok=True)
shutil.rmtree(ext_dir)
files = glob.glob(os.path.join(plugin_dir, "*.json"))
files.sort()
ext_dict = {}
for file in files:
tool_dict = {}
with open(file, encoding='utf-8') as f:
tool = json.load(f)
name = tool["exe"]
tool_dict["name"] = tool["tool_name"]
tool_dict["tool_name"] = name
tool_dict["category"] = tool["toolbox"].split("/")[0]
tool_dict["label"] = to_label(name)
tool_dict["description"] = tool["short_description"]
tool_dict["github"] = get_github_url(name)
tool_dict["book"] = get_book_url(name, tool["toolbox"])
params_dict = {}
params = tool["parameters"]
for param in params:
flags = param["flags"]
if isinstance(flags, list):
if flags == ["-i", "--input"]:
flag = "i"
else:
flag = flags[-1].replace("-", "")
else:
flag = flags.replace("-", "")
params_dict[flag] = param
tool_dict["parameters"] = params_dict
ext_dict[tool["tool_name"]] = tool_dict
return ext_dict
get_github_url(tool_name)
¶
Get the link to the source code of the tool on GitHub.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
tool_name |
str |
The name of the tool. |
required |
Returns:
Type | Description |
---|---|
str |
The URL to source code. |
Source code in whiteboxgui/whiteboxgui.py
def get_github_url(tool_name):
"""Get the link to the source code of the tool on GitHub.
Args:
tool_name (str): The name of the tool.
Returns:
str: The URL to source code.
"""
print(tool_name)
url = wbt.view_code(tool_name).strip()
if "RUST_BACKTRACE" in url:
url = "https://github.com/jblindsay/whitebox-tools/tree/master/whitebox-tools-app/src/tools"
return url
get_tool_params(tool_name)
¶
Get parameters for a tool.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
tool_name |
str |
The name of the tool. |
required |
Returns:
Type | Description |
---|---|
dict |
The tool parameters as a dictionary. |
Source code in whiteboxgui/whiteboxgui.py
def get_tool_params(tool_name):
"""Get parameters for a tool.
Args:
tool_name (str): The name of the tool.
Returns:
dict: The tool parameters as a dictionary.
"""
params_dict = {}
params = json.loads(wbt.tool_parameters(
tool_name).replace("\n", ""))["parameters"]
for param in params:
flags = param["flags"]
if isinstance(flags, list):
if flags == ["-i", "--input"]:
flag = "i"
else:
flag = flags[-1].replace("-", "")
else:
flag = flags.replace("-", "")
params_dict[flag] = param
return params_dict
get_wbt_dict(reset=False)
¶
Generate a dictionary containing information for all tools.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
reset |
bool |
Whether to recreate the json file containing the dictionary. Defaults to False. |
False |
Returns:
Type | Description |
---|---|
dict |
The dictionary containing information for all tools. |
Source code in whiteboxgui/whiteboxgui.py
def get_wbt_dict(reset=False):
"""Generate a dictionary containing information for all tools.
Args:
reset (bool, optional): Whether to recreate the json file containing the dictionary. Defaults to False.
Returns:
dict: The dictionary containing information for all tools.
"""
pkg_dir = os.path.dirname(
pkg_resources.resource_filename("whiteboxgui", "whiteboxgui.py")
)
wbt_dict_json = os.path.join(pkg_dir, "data/whitebox_tools.json")
if (not os.path.exists(wbt_dict_json)) or reset:
wbt_dict = {}
tools = wbt.list_tools()
category_dict = tool_categories()
for tool in tools.keys():
tool_dict = {}
name = to_snakecase(tool)
tool_dict["name"] = to_camelcase(name)
tool_dict["tool_name"] = name
tool_dict["category"] = category_dict[name]
tool_dict["label"] = to_label(name)
tool_dict["description"] = tools[tool]
tool_dict["github"] = get_github_url(name)
tool_dict["book"] = get_book_url(name, category_dict[name])
tool_dict["parameters"] = get_tool_params(name)
wbt_dict[to_camelcase(name)] = tool_dict
wbt_dict.update(get_ext_dict())
with open(wbt_dict_json, "w", encoding='utf-8') as fp:
json.dump(wbt_dict, fp, indent=4)
else:
with open(wbt_dict_json, encoding='utf-8') as fp:
wbt_dict = json.load(fp)
return wbt_dict
in_colab_shell()
¶
Tests if the code is being executed within Google Colab.
Source code in whiteboxgui/whiteboxgui.py
def in_colab_shell():
"""Tests if the code is being executed within Google Colab."""
import sys
if "google.colab" in sys.modules:
return True
else:
return False
search_api_tree(keywords, api_tree, tools_dict)
¶
Search the WhiteboxTools API and return functions containing the specified keywords
Parameters:
Name | Type | Description | Default |
---|---|---|---|
keywords |
str |
The keywords to search for. |
required |
api_tree |
dict |
The dictionary containing the WhiteboxTools API tree. |
required |
tools_dict |
dict |
The dictionary containing the dict of all tools. |
required |
Returns:
Type | Description |
---|---|
object |
An ipytree object/widget. |
Source code in whiteboxgui/whiteboxgui.py
def search_api_tree(keywords, api_tree, tools_dict):
"""Search the WhiteboxTools API and return functions containing the specified keywords
Args:
keywords (str): The keywords to search for.
api_tree (dict): The dictionary containing the WhiteboxTools API tree.
tools_dict (dict): The dictionary containing the dict of all tools.
Returns:
object: An ipytree object/widget.
"""
import warnings
warnings.filterwarnings("ignore")
sub_tree = Tree()
for key in api_tree.keys():
if (keywords.lower() in key.lower()) or (
keywords.lower() in tools_dict[key]["description"].lower()
):
sub_tree.add_node(api_tree[key])
return sub_tree
show(verbose=True, tree=False, reset=False, sandbox_path=None)
¶
Show the toolbox GUI.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
verbose |
bool |
Whether to show progress info when the tool is running. Defaults to True. |
True |
tree |
bool |
Whether to use the tree mode toolbox built using ipytree rather than ipywidgets. Defaults to False. |
False |
reset |
bool |
Whether to regenerate the json file with the dictionary containing the information for all tools. Defaults to False. |
False |
sandbox_path |
str |
The path to the sandbox directory. Defaults to None. |
None |
Returns:
Type | Description |
---|---|
object |
A toolbox GUI. |
Source code in whiteboxgui/whiteboxgui.py
def show(verbose=True, tree=False, reset=False, sandbox_path=None):
"""Show the toolbox GUI.
Args:
verbose (bool, optional): Whether to show progress info when the tool is running. Defaults to True.
tree (bool, optional): Whether to use the tree mode toolbox built using ipytree rather than ipywidgets. Defaults to False.
reset (bool, optional): Whether to regenerate the json file with the dictionary containing the information for all tools. Defaults to False.
sandbox_path (str, optional): The path to the sandbox directory. Defaults to None.
Returns:
object: A toolbox GUI.
"""
tools_dict = get_wbt_dict(reset=reset)
if verbose:
wbt.verbose = True
else:
wbt.verbose = False
# if in_colab_shell():
# tree = False
if tree:
return build_toolbox_tree(tools_dict, sandbox_path=sandbox_path)
else:
return build_toolbox(tools_dict, sandbox_path=sandbox_path)
to_camelcase(name)
¶
Convert snake_case name to CamelCase name.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str |
The name of the tool. |
required |
Returns:
Type | Description |
---|---|
str |
The CamelCase name of the tool. |
Source code in whiteboxgui/whiteboxgui.py
def to_camelcase(name):
"""Convert snake_case name to CamelCase name.
Args:
name (str): The name of the tool.
Returns:
str: The CamelCase name of the tool.
"""
return "".join(x.title() for x in name.split("_"))
to_label(name)
¶
Convert snake_case name to Title case label.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str |
The name of the tool. |
required |
Returns:
Type | Description |
---|---|
str |
The Title case name of the tool. |
Source code in whiteboxgui/whiteboxgui.py
def to_label(name):
"""Convert snake_case name to Title case label.
Args:
name (str): The name of the tool.
Returns:
str: The Title case name of the tool.
"""
return " ".join(x.title() for x in name.split("_"))
to_snakecase(name)
¶
Convert CamelCase name to snake_case name.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str |
The name of the tool. |
required |
Returns:
Type | Description |
---|---|
str |
The snakecase name of the tool. |
Source code in whiteboxgui/whiteboxgui.py
def to_snakecase(name):
"""Convert CamelCase name to snake_case name.
Args:
name (str): The name of the tool.
Returns:
str: The snakecase name of the tool.
"""
s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
tool_categories()
¶
Generate a dictionary containing the toolbox corresponds to each tool.
Returns:
Type | Description |
---|---|
dict |
a dictionary containing the toolbox corresponds to each tool. |
Source code in whiteboxgui/whiteboxgui.py
def tool_categories():
"""Generate a dictionary containing the toolbox corresponds to each tool.
Returns:
dict: a dictionary containing the toolbox corresponds to each tool.
"""
category_dict = {}
tools = wbt.toolbox().split("\n")
for tool in tools[:-1]:
name = tool.split(":")[0]
category = tool.split(":")[1].strip().split("/")[0]
category_dict[to_snakecase(name)] = category
return category_dict
tool_gui(tool_dict, max_width='420px', max_height='600px', sandbox_path=None)
¶
Create a GUI for a tool based on the tool dictionary.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
tool_dict |
dict |
The dictionary containing the tool info. |
required |
max_width |
str |
The max width of the tool dialog. |
'420px' |
max_height |
str |
The max height of the tool dialog. |
'600px' |
sandbox_path |
str |
The path to the sandbox directory. Defaults to None. |
None |
Returns:
Type | Description |
---|---|
object |
An ipywidget object representing the tool interface. |
Source code in whiteboxgui/whiteboxgui.py
def tool_gui(tool_dict, max_width="420px", max_height="600px", sandbox_path=None):
"""Create a GUI for a tool based on the tool dictionary.
Args:
tool_dict (dict): The dictionary containing the tool info.
max_width (str, optional): The max width of the tool dialog.
max_height (str, optional): The max height of the tool dialog.
sandbox_path (str, optional): The path to the sandbox directory. Defaults to None.
Returns:
object: An ipywidget object representing the tool interface.
"""
tool_widget = widgets.VBox(
layout=widgets.Layout(max_width=max_width, max_height=max_height)
)
children = []
args = {}
required_inputs = []
style = {"description_width": "initial"}
max_width = str(int(max_width.replace("px", "")) - 10) + "px"
header_width = str(int(max_width.replace("px", "")) - 104) + "px"
header = widgets.Label(
value=f'Current Tool: {tool_dict["name"]}',
style=style,
layout=widgets.Layout(width=header_width),
)
code_btn = widgets.Button(
description="View Code", layout=widgets.Layout(width="100px")
)
children.append(widgets.HBox([header, code_btn]))
desc = widgets.Textarea(
value=f'Description: {tool_dict["description"]}',
layout=widgets.Layout(width="410px", max_width=max_width),
disabled=True,
)
children.append(desc)
params = tool_dict["parameters"]
for param in params:
items = params[param]
required = ""
if items["optional"] == "false" or (not items["optional"]):
required = "*"
required_inputs.append(param)
label = items["name"] + required
param_type = items["parameter_type"]
default_value = None
if items["default_value"] is not None:
if (items["default_value"] != "null") and (len(items["default_value"]) > 0):
if "false" in items["default_value"]:
default_value = False
elif "true" in items["default_value"]:
default_value = True
else:
default_value = items["default_value"].replace('"', "")
layout = widgets.Layout(width="500px", max_width=max_width)
if isinstance(param_type, str):
# display(data_types[param_type])
if param_type == "Boolean":
var_widget = widgets.Checkbox(
description=label, style=style, layout=layout, value=default_value
)
elif param_type in [
"Directory",
"ExistingFile",
"ExistingFileOrFloat",
"FileList",
"NewFile",
]:
var_widget = FileChooser(
title=label, sandbox_path=sandbox_path)
else:
var_widget = widgets.Text(
description=label, style=style, layout=layout)
if default_value is not None:
var_widget.value = str(default_value)
args[param] = var_widget
children.append(var_widget)
elif isinstance(param_type, dict):
if "OptionList" in param_type:
var_widget = widgets.Dropdown(
options=param_type["OptionList"],
description=label,
style=style,
layout=layout,
)
elif list(param_type.keys())[0] in [
"Directory",
"ExistingFile",
"ExistingFileOrFloat",
"FileList",
"NewFile",
]:
var_widget = FileChooser(
title=label, sandbox_path=sandbox_path)
else:
var_widget = FileChooser(
title=label, sandbox_path=sandbox_path)
args[param] = var_widget
children.append(var_widget)
run_btn = widgets.Button(
description="Run", layout=widgets.Layout(width="100px"))
cancel_btn = widgets.Button(
description="Cancel", layout=widgets.Layout(width="100px")
)
help_btn = widgets.Button(
description="Help", layout=widgets.Layout(width="100px"))
import_btn = widgets.Button(
description="Import",
tooltip="Import the script to a new cell",
layout=widgets.Layout(width="98px"),
)
tool_output = widgets.Output(
layout=widgets.Layout(max_height="200px", overflow="scroll")
)
children.append(widgets.HBox([run_btn, cancel_btn, help_btn, import_btn]))
children.append(tool_output)
tool_widget.children = children
def run_button_clicked(b):
tool_output.clear_output()
required_params = required_inputs.copy()
args2 = []
for arg in args:
line = ""
if isinstance(args[arg], FileChooser):
if arg in required_params and args[arg].selected is None:
with tool_output:
print(f"Please provide inputs for required parameters.")
break
elif arg in required_params:
required_params.remove(arg)
if args[arg].selected is not None:
if arg == "i":
line = f"-{arg}={args[arg].selected}"
else:
line = f"--{arg}={args[arg].selected}"
elif isinstance(args[arg], widgets.Text):
if arg in required_params and len(args[arg].value) == 0:
with tool_output:
print(f"Please provide inputs for required parameters.")
break
elif arg in required_params:
required_params.remove(arg)
if args[arg].value is not None and len(args[arg].value) > 0:
line = f"--{arg}={args[arg].value}"
elif isinstance(args[arg], widgets.Checkbox):
line = f"--{arg}={args[arg].value}"
args2.append(line)
if len(required_params) == 0:
with tool_output:
wbt.run_tool(tool_dict["name"], args2)
def help_button_clicked(b):
import webbrowser
tool_output.clear_output()
with tool_output:
html = widgets.HTML(
value=f'<a href={tool_dict["book"]} target="_blank">{tool_dict["book"]}</a>'
)
display(html)
webbrowser.open_new_tab(tool_dict["book"])
def code_button_clicked(b):
import webbrowser
with tool_output:
if "RUST_BACKTRACE" in tool_dict["github"]:
tool_dict[
"github"
] = "https://github.com/jblindsay/whitebox-tools/tree/master/whitebox-tools-app/src/tools"
html = widgets.HTML(
value=f'<a href={tool_dict["github"]} target="_blank">{tool_dict["github"]}</a>'
)
display(html)
webbrowser.open_new_tab(tool_dict["github"])
def cancel_btn_clicked(b):
tool_output.clear_output()
def import_button_clicked(b):
tool_output.clear_output()
required_params = required_inputs.copy()
args2 = []
args3 = []
for arg in args:
line = ""
if isinstance(args[arg], FileChooser):
if arg in required_params and args[arg].selected is None:
with tool_output:
print(f"Please provide inputs for required parameters.")
break
elif arg in required_params:
required_params.remove(arg)
if arg == "i":
line = f"-{arg}={args[arg].selected}"
else:
line = f"--{arg}={args[arg].selected}"
if args[arg].selected is not None:
args3.append(f"{arg}='{args[arg].selected}'")
elif isinstance(args[arg], widgets.Text):
if arg in required_params and len(args[arg].value) == 0:
with tool_output:
print(f"Please provide inputs for required parameters.")
break
elif arg in required_params:
required_params.remove(arg)
if args[arg].value is not None and len(args[arg].value) > 0:
line = f"--{arg}={args[arg].value}"
args3.append(f"{arg}='{args[arg].value}'")
elif isinstance(args[arg], widgets.Checkbox):
line = f"--{arg}={args[arg].value}"
args3.append(f"{arg}={args[arg].value}")
args2.append(line)
if len(required_params) == 0:
content = []
content.append("import whitebox")
content.append("wbt = whitebox.WhiteboxTools()")
content.append(
f"wbt.{to_snakecase(tool_dict['name'])}({', '.join(args3)})")
with tool_output:
for line in content:
print(line)
create_code_cell("\n".join(content))
import_btn.on_click(import_button_clicked)
run_btn.on_click(run_button_clicked)
help_btn.on_click(help_button_clicked)
code_btn.on_click(code_button_clicked)
cancel_btn.on_click(cancel_btn_clicked)
return tool_widget
update_package()
¶
Updates the whiteboxgui package from the GitHub repository without the need to use pip or conda. In this way, I don't have to keep updating pypi and conda-forge with every minor update of the package.
Source code in whiteboxgui/whiteboxgui.py
def update_package():
"""Updates the whiteboxgui package from the GitHub repository without the need to use pip or conda.
In this way, I don't have to keep updating pypi and conda-forge with every minor update of the package.
"""
import shutil
try:
download_dir = os.getcwd()
clone_repo(out_dir=download_dir)
pkg_dir = os.path.join(download_dir, "whiteboxgui-master")
work_dir = os.getcwd()
os.chdir(pkg_dir)
if shutil.which("pip") is None:
cmd = "pip3 install ."
else:
cmd = "pip install ."
os.system(cmd)
os.chdir(work_dir)
os.remove(pkg_dir + ".zip")
shutil.rmtree(pkg_dir)
print(
"\nPlease comment out 'whiteboxgui.update_package()' and restart the kernel to take effect:\nJupyter menu -> Kernel -> Restart & Clear Output"
)
except Exception as e:
raise Exception(e)