updated examples layout and flagging output tracking

This commit is contained in:
Ali Abid 2021-02-23 11:44:09 -08:00
parent d2a9da1490
commit 953ddffd06
17 changed files with 352 additions and 114 deletions

View File

@ -1,3 +1,7 @@
import os
import shutil
from gradio import processing_utils
class Component(): class Component():
""" """
A class for defining the methods that all gradio input and output components should have. A class for defining the methods that all gradio input and output components should have.
@ -19,12 +23,34 @@ class Component():
""" """
return {} return {}
def rebuild(self, dir, data): def save_flagged(self, dir, label, data):
""" """
All interfaces should define a method that rebuilds the flagged input when it's passed back (i.e. rebuilds image from base64) Saves flagged data from component
""" """
return data return data
def restore_flagged(self, data):
"""
Restores flagged data from logs
"""
return data
def save_flagged_file(self, dir, label, data):
file = processing_utils.decode_base64_to_file(data)
old_file_name = file.name
output_dir = os.path.join(dir, label)
if os.path.exists(output_dir):
file_index = len(os.listdir(output_dir))
else:
os.mkdir(output_dir)
file_index = 0
new_file_name = str(file_index)
if "." in old_file_name:
uploaded_format = old_file_name.split(".")[-1].lower()
new_file_name += "." + uploaded_format
shutil.move(old_file_name, os.path.join(dir, label, new_file_name))
return label + "/" + new_file_name
@classmethod @classmethod
def get_all_shortcut_implementations(cls): def get_all_shortcut_implementations(cls):
shortcuts = {} shortcuts = {}

View File

@ -7,6 +7,7 @@ automatically added to a registry, which allows them to be easily referenced in
import datetime import datetime
import json import json
import os import os
import shutil
import time import time
import warnings import warnings
from gradio.component import Component from gradio.component import Component
@ -466,6 +467,14 @@ class CheckboxGroup(InputComponent):
else: else:
raise ValueError("Unknown type: " + str(self.type) + ". Please choose from: 'value', 'index'.") raise ValueError("Unknown type: " + str(self.type) + ". Please choose from: 'value', 'index'.")
def save_flagged(self, dir, label, data):
"""
Returns: (List[str]])
"""
return json.dumps(data)
def restore_flagged(self, data):
return json.loads(data)
class Radio(InputComponent): class Radio(InputComponent):
@ -713,15 +722,11 @@ class Image(InputComponent):
im = processing_utils.resize_and_crop(im, (shape[0], shape[1])) im = processing_utils.resize_and_crop(im, (shape[0], shape[1]))
return np.asarray(im).flatten() return np.asarray(im).flatten()
def rebuild(self, dir, data): def save_flagged(self, dir, label, data):
""" """
Default rebuild method to decode a base64 image Returns: (str) path to image file
""" """
im = processing_utils.decode_base64_to_image(data) return self.save_flagged_file(dir, label, data)
timestamp = datetime.datetime.now()
filename = f'input_{timestamp.strftime("%Y-%m-%d-%H-%M-%S")}.png'
im.save(f'{dir}/{filename}', 'PNG')
return filename
class Video(InputComponent): class Video(InputComponent):
@ -766,6 +771,12 @@ class Video(InputComponent):
def preprocess_example(self, x): def preprocess_example(self, x):
return processing_utils.encode_file_to_base64(x) return processing_utils.encode_file_to_base64(x)
def save_flagged(self, dir, label, data):
"""
Returns: (str) path to video file
"""
return self.save_flagged_file(dir, label, data)
class Audio(InputComponent): class Audio(InputComponent):
""" """
Component accepts audio input files. Component accepts audio input files.
@ -865,6 +876,12 @@ class Audio(InputComponent):
else: else:
raise ValueError("Unknown type: " + str(self.type) + ". Please choose from: 'numpy', 'mfcc', 'file'.") raise ValueError("Unknown type: " + str(self.type) + ". Please choose from: 'numpy', 'mfcc', 'file'.")
def save_flagged(self, dir, label, data):
"""
Returns: (str) path to audio file
"""
return self.save_flagged_file(dir, label, data)
class File(InputComponent): class File(InputComponent):
""" """
@ -906,6 +923,12 @@ class File(InputComponent):
def embed(self, x): def embed(self, x):
raise NotImplementedError("File doesn't currently support embeddings") raise NotImplementedError("File doesn't currently support embeddings")
def save_flagged(self, dir, label, data):
"""
Returns: (str) path to file
"""
return self.save_flagged_file(dir, label, data["data"])
class Dataframe(InputComponent): class Dataframe(InputComponent):
""" """
@ -1000,6 +1023,15 @@ class Dataframe(InputComponent):
def embed(self, x): def embed(self, x):
raise NotImplementedError("DataFrame doesn't currently support embeddings") raise NotImplementedError("DataFrame doesn't currently support embeddings")
def save_flagged(self, dir, label, data):
"""
Returns: (List[List[Union[str, float]]]) 2D array
"""
return json.dumps(data)
def restore_flagged(self, data):
return json.loads(data)
####################### #######################
# DEPRECATED COMPONENTS # DEPRECATED COMPONENTS
@ -1050,7 +1082,7 @@ class Sketchpad(InputComponent):
def process_example(self, example): def process_example(self, example):
return processing_utils.encode_file_to_base64(example) return processing_utils.encode_file_to_base64(example)
def rebuild(self, dir, data): def save_flagged(self, dir, label, data):
""" """
Default rebuild method to decode a base64 image Default rebuild method to decode a base64 image
""" """
@ -1089,7 +1121,7 @@ class Webcam(InputComponent):
im, (self.image_width, self.image_height)) im, (self.image_width, self.image_height))
return np.array(im) return np.array(im)
def rebuild(self, dir, data): def save_flagged(self, dir, label, data):
""" """
Default rebuild method to decode a base64 image Default rebuild method to decode a base64 image
""" """
@ -1131,7 +1163,7 @@ class Microphone(InputComponent):
return signal return signal
def rebuild(self, dir, data): def save_flagged(self, dir, label, data):
inp = data.split(';')[1].split(',')[1] inp = data.split(';')[1].split(',')[1]
wav_obj = base64.b64decode(inp) wav_obj = base64.b64decode(inp)
timestamp = datetime.datetime.now() timestamp = datetime.datetime.now()

View File

@ -222,14 +222,8 @@ class Interface:
except ValueError: except ValueError:
pass pass
if self.examples is not None: if self.examples is not None and not isinstance(self.examples, str):
processed_examples = [] config["examples"] = self.examples
for example_set in self.examples:
processed_set = []
for iface, example in zip(self.input_interfaces, example_set):
processed_set.append(example)
processed_examples.append(processed_set)
config["examples"] = processed_examples
return config return config
def run_prediction(self, processed_input, return_duration=False): def run_prediction(self, processed_input, return_duration=False):

View File

@ -82,6 +82,8 @@ def get_first_available_port(initial, final):
@app.route("/", methods=["GET"]) @app.route("/", methods=["GET"])
def main(): def main():
if isinstance(app.interface.examples, str):
return redirect("/from_dir/" + app.interface.examples)
return render_template("index.html", return render_template("index.html",
config=app.interface.config, config=app.interface.config,
vendor_prefix=(GRADIO_STATIC_ROOT if app.interface.share else ""), vendor_prefix=(GRADIO_STATIC_ROOT if app.interface.share else ""),
@ -100,13 +102,16 @@ def main_from_dir(path):
with open(log_file) as logs: with open(log_file) as logs:
examples = list(csv.reader(logs)) examples = list(csv.reader(logs))
examples = examples[1:] #remove header examples = examples[1:] #remove header
input_examples = [example[:len(app.interface.input_interfaces)] for example in examples] for i, example in enumerate(examples):
for j, (interface, cell) in enumerate(zip(app.interface.input_interfaces + app.interface.output_interfaces, example)):
examples[i][j] = interface.restore_flagged(cell)
examples = [example[:len(app.interface.input_interfaces) + len(app.interface.output_interfaces)] for example in examples]
return render_template("index.html", return render_template("index.html",
config=app.interface.config, config=app.interface.config,
vendor_prefix=(GRADIO_STATIC_ROOT if app.interface.share else ""), vendor_prefix=(GRADIO_STATIC_ROOT if app.interface.share else ""),
css=app.interface.css, css=app.interface.css,
path=path, path=path,
examples=input_examples examples=examples
) )
@ -217,11 +222,13 @@ def predict_examples():
return jsonify(output) return jsonify(output)
def flag_data(data): def flag_data(input_data, output_data):
flag_path = os.path.join(app.cwd, app.interface.flagging_dir) flag_path = os.path.join(app.cwd, app.interface.flagging_dir)
output = [app.interface.input_interfaces[i].rebuild( csv_data = []
flag_path, component_data) for i, interface in enumerate(app.interface.input_interfaces):
for i, component_data in enumerate(data)] csv_data.append(interface.save_flagged(flag_path, app.interface.config["input_interfaces"][i][1]["label"], input_data[i]))
for i, interface in enumerate(app.interface.output_interfaces):
csv_data.append(interface.save_flagged(flag_path, app.interface.config["output_interfaces"][i][1]["label"], output_data[i]))
log_fp = "{}/log.csv".format(flag_path) log_fp = "{}/log.csv".format(flag_path)
is_new = not os.path.exists(log_fp) is_new = not os.path.exists(log_fp)
@ -230,15 +237,16 @@ def flag_data(data):
writer = csv.writer(csvfile) writer = csv.writer(csvfile)
if is_new: if is_new:
headers = [interface[1]["label"] for interface in app.interface.config["input_interfaces"]] headers = [interface[1]["label"] for interface in app.interface.config["input_interfaces"]]
headers += [interface[1]["label"] for interface in app.interface.config["output_interfaces"]]
writer.writerow(headers) writer.writerow(headers)
writer.writerow(output) writer.writerow(csv_data)
@app.route("/api/flag/", methods=["POST"]) @app.route("/api/flag/", methods=["POST"])
def flag(): def flag():
log_feature_analytics('flag') log_feature_analytics('flag')
data = request.json['data']['input_data'] input_data, output_data = request.json['data']['input_data'], request.json['data']['output_data']
flag_data(data) flag_data(input_data, output_data)
return jsonify(success=True) return jsonify(success=True)

View File

@ -118,12 +118,21 @@ class Label(OutputComponent):
"label": {}, "label": {},
} }
def rebuild(self, dir, data): def save_flagged(self, dir, label, data):
""" """
Default rebuild method for label Returns: (Union[str, Dict[str, number]]): Either a string representing the main category label, or a dictionary with category keys mapping to confidence levels.
""" """
# return json.loads(data) if "confidences" in data:
return data return json.dumps({example["label"]: example["confidence"] for example in data["confidences"]})
else:
return data["label"]
def restore_flagged(self, data):
try:
data = json.loads(data)
return data
except:
return data
class Image(OutputComponent): class Image(OutputComponent):
''' '''
@ -186,15 +195,12 @@ class Image(OutputComponent):
raise ValueError("Unknown type: " + dtype + ". Please choose from: 'numpy', 'pil', 'file', 'plot'.") raise ValueError("Unknown type: " + dtype + ". Please choose from: 'numpy', 'pil', 'file', 'plot'.")
return out_y, coordinates return out_y, coordinates
def rebuild(self, dir, data): def save_flagged(self, dir, label, data):
""" """
Default rebuild method to decode a base64 image Returns: (str) path to image file
""" """
im = processing_utils.decode_base64_to_image(data) return self.save_flagged_file(dir, label, data[0])
timestamp = datetime.datetime.now()
filename = 'output_{}_{}.png'.format(self.label, timestamp.strftime("%Y-%m-%d-%H-%M-%S"))
im.save('{}/{}'.format(dir, filename), 'PNG')
return filename
class Video(OutputComponent): class Video(OutputComponent):
''' '''
@ -218,6 +224,12 @@ class Video(OutputComponent):
def postprocess(self, y): def postprocess(self, y):
return processing_utils.encode_file_to_base64(y, type="video") return processing_utils.encode_file_to_base64(y, type="video")
def save_flagged(self, dir, label, data):
"""
Returns: (str) path to image file
"""
return self.save_flagged_file(dir, label, data)
class KeyValues(OutputComponent): class KeyValues(OutputComponent):
''' '''
@ -246,6 +258,12 @@ class KeyValues(OutputComponent):
return { return {
"key_values": {}, "key_values": {},
} }
def save_flagged(self, dir, label, data):
return json.dumps(data)
def restore_flagged(self, data):
return json.loads(data)
class HighlightedText(OutputComponent): class HighlightedText(OutputComponent):
@ -279,6 +297,12 @@ class HighlightedText(OutputComponent):
def postprocess(self, y): def postprocess(self, y):
return y return y
def save_flagged(self, dir, label, data):
return json.dumps(data)
def restore_flagged(self, data):
return json.loads(data)
class Audio(OutputComponent): class Audio(OutputComponent):
''' '''
@ -316,6 +340,12 @@ class Audio(OutputComponent):
else: else:
raise ValueError("Unknown type: " + self.type + ". Please choose from: 'numpy', 'file'.") raise ValueError("Unknown type: " + self.type + ". Please choose from: 'numpy', 'file'.")
def save_flagged(self, dir, label, data):
"""
Returns: (str) path to audio file
"""
return self.save_flagged_file(dir, label, data)
class JSON(OutputComponent): class JSON(OutputComponent):
''' '''
@ -343,6 +373,12 @@ class JSON(OutputComponent):
"json": {}, "json": {},
} }
def save_flagged(self, dir, label, data):
return json.dumps(data)
def restore_flagged(self, data):
return json.loads(data)
class HTML(OutputComponent): class HTML(OutputComponent):
''' '''
@ -392,6 +428,12 @@ class File(OutputComponent):
"data": processing_utils.encode_file_to_base64(y, header=False) "data": processing_utils.encode_file_to_base64(y, header=False)
} }
def save_flagged(self, dir, label, data):
"""
Returns: (str) path to image file
"""
return self.save_flagged_file(dir, label, data["data"])
class Dataframe(OutputComponent): class Dataframe(OutputComponent):
""" """
@ -446,3 +488,12 @@ class Dataframe(OutputComponent):
return {"data": y} return {"data": y}
else: else:
raise ValueError("Unknown type: " + self.type + ". Please choose from: 'pandas', 'numpy', 'array'.") raise ValueError("Unknown type: " + self.type + ". Please choose from: 'pandas', 'numpy', 'array'.")
def save_flagged(self, dir, label, data):
"""
Returns: (List[List[Union[str, float]]]) 2D array
"""
return json.dumps(data["data"])
def restore_flagged(self, data):
return json.loads(data)

View File

@ -68,13 +68,16 @@ def resize_and_crop(img, size, crop_type='center'):
################## ##################
def decode_base64_to_binary(encoding): def decode_base64_to_binary(encoding):
header, data = encoding.split(",")
header = header[5:]
if ";base64" in header:
header = header[0:header.index(";base64")]
extension = None extension = None
if "/" in header: if "," in encoding:
extension = header[header.index("/") + 1:] header, data = encoding.split(",")
header = header[5:]
if ";base64" in header:
header = header[0:header.index(";base64")]
if "/" in header:
extension = header[header.index("/") + 1:]
else:
data = encoding
return base64.b64decode(data), extension return base64.b64decode(data), extension
def decode_base64_to_file(encoding): def decode_base64_to_file(encoding):

View File

@ -74,15 +74,40 @@ h4 {
.close_explain { .close_explain {
cursor: pointer; cursor: pointer;
} }
.examples > button { .backward {
display: inline-block;
-moz-transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
transform: scale(-1, 1);
}
.examples_control button {
padding: 8px 16px; padding: 8px 16px;
border-radius: 2px; border-radius: 2px;
margin-right: 4px; margin-right: 8px;
background-color: whitesmoke; background-color: whitesmoke;
} }
.examples_control {
display: flex;
}
.examples_control > div {
display: flex;
align-items: stretch;
}
.examples_control button small {
display: block;
font-weight: bold;
}
.examples_control_right {
padding-left: 8px;
border-left: solid 2px whitesmoke;
}
.examples_control_right .current {
background-color: #e67e22;
color: white;
}
.examples > table { .examples > table {
border-collapse: collapse; border-collapse: collapse;
font-family: monospace;
padding: 8px; padding: 8px;
background-color: whitesmoke; background-color: whitesmoke;
border-right: solid 4px whitesmoke; border-right: solid 4px whitesmoke;
@ -90,6 +115,20 @@ h4 {
border-bottom: solid 4px whitesmoke; border-bottom: solid 4px whitesmoke;
margin-top: 8px; margin-top: 8px;
} }
.examples > table.gallery {
background-color: white;
border: none;
}
.examples > table.gallery > thead {
display: none;
}
.examples > table.gallery > tbody > tr {
padding: 4px;
border-radius: 4px;
margin: 0 8px 8px 0;
background-color: whitesmoke;
display: inline-block;
}
.examples > table th { .examples > table th {
padding: 8px 16px; padding: 8px 16px;
text-align: left; text-align: left;
@ -118,7 +157,7 @@ h4 {
background-color: lightgray; background-color: lightgray;
} }
.examples_body > tr.current_example { .examples_body > tr.current_example {
background-color: #ffb573; background-color: lightgray !important;
} }
#credit { #credit {
text-align: center; text-align: center;

View File

@ -48,13 +48,25 @@ function gradio(config, fn, target, example_file_path) {
</div> </div>
<div class="examples invisible"> <div class="examples invisible">
<h4>Examples</small></h4> <h4>Examples</small></h4>
<button class="run_examples examples-content">Run All</button> <div class="examples_control">
<button class="load_prev examples-content">Load Previous <em>(CTRL + &larr;)</em></button> <div class="examples_control_left">
<button class="load_next examples-content">Load Next <em>(CTRL + &rarr;)</em></button> <button class="run_examples examples-content">Run All</button>
<button class="order_similar examples-content embedding">Order by Similarity</button> <button class="load_prev examples-content">Load Previous <small>CTRL + <span class="backward">&#10140;</span></small></button>
<button class="view_embeddings examples-content embedding">View Embeddings</button> <button class="load_next examples-content">Load Next <small>CTRL + &#10140;</small></button>
<button class="update_embeddings embeddings-content invisible">Update Embeddings</button> <button class="order_similar examples-content embedding">Order by Similarity</button>
<button class="view_examples embeddings-content invisible">View Examples</button> <button class="view_embeddings examples-content embedding">View Embeddings</button>
<button class="update_embeddings embeddings-content invisible">Update Embeddings</button>
<button class="view_examples embeddings-content invisible">View Examples</button>
</div>
<div class="examples_control_right">
<button class="table_examples">
<svg width="40" height="24"><rect x="0" y="0" width="40" height="6"></rect><rect x="0" y="9" width="40" height="6"></rect><rect x="0" y="18" width="40" height="6"></rect></svg>
</button>
<button class="gallery_examples current">
<svg width="40" height="24"><rect x="0" y="0" width="18" height="40"></rect><rect x="22" y="0" width="18" height="40"></rect></svg>
</button>
</div>
</div>
<div class="pages invisible">Page:</div> <div class="pages invisible">Page:</div>
<table class="examples-content"> <table class="examples-content">
</table> </table>
@ -201,7 +213,7 @@ function gradio(config, fn, target, example_file_path) {
target.find(".clear").click(clear_all); target.find(".clear").click(clear_all);
if (!config["allow_embedding"]) { if (!config["allow_embedding"]) {
target.find(".embedding").css("visibility", "hidden"); target.find(".embedding").hide();
} }
if (!config["allow_screenshot"] && config["allow_flagging"] !== true && !config["allow_interpretation"]) { if (!config["allow_screenshot"] && config["allow_flagging"] !== true && !config["allow_interpretation"]) {
target.find(".screenshot, .record, .flag, .interpret").css("visibility", "hidden"); target.find(".screenshot, .record, .flag, .interpret").css("visibility", "hidden");
@ -224,20 +236,24 @@ function gradio(config, fn, target, example_file_path) {
target.find(".interpretation_explained .close_explain").click(function() { target.find(".interpretation_explained .close_explain").click(function() {
target.find(".interpretation_explained").remove(); target.find(".interpretation_explained").remove();
}); });
if (config["examples"]) {
target.find(".examples").removeClass("invisible");
let html = "<thead>"
for (let i = 0; i < config["input_interfaces"].length; i++) {
label = config["input_interfaces"][i][1]["label"];
html += "<th>" + label + "</th>";
}
}
} }
} }
function load_example(example_id) { function load_example(example_id) {
clear_all(); clear_all();
if (!(example_id in config["examples"])) {
return;
}
for (let [i, value] of config["examples"][example_id].entries()) { for (let [i, value] of config["examples"][example_id].entries()) {
input_interfaces[i].load_example(value); if (i < input_interfaces.length) {
input_interfaces[i].load_example(value);
} else if (i - input_interfaces.length < output_interfaces.length) {
let output_interface = output_interfaces[i - input_interfaces.length];
if ("load_example" in output_interface) {
output_interface.load_example(value);
} else {
output_interface.output(value)
}
}
}; };
if (io_master.loaded_examples && example_id in io_master.loaded_examples) { if (io_master.loaded_examples && example_id in io_master.loaded_examples) {
io_master.output({"data": io_master.loaded_examples[example_id]}); io_master.output({"data": io_master.loaded_examples[example_id]});
@ -293,8 +309,15 @@ function gradio(config, fn, target, example_file_path) {
html += "<tr row=" + example_id + ">"; html += "<tr row=" + example_id + ">";
for (let [j, col] of example.entries()) { for (let [j, col] of example.entries()) {
let new_col = JSON.parse(JSON.stringify(col)) let new_col = JSON.parse(JSON.stringify(col))
if (input_interfaces[j].load_example_preview) { if (j < input_interfaces.length) {
new_col = input_interfaces[j].load_example_preview(new_col); if (input_interfaces[j].load_example_preview) {
new_col = input_interfaces[j].load_example_preview(new_col);
}
} else {
let k = j - input_interfaces.length;
if (k < output_interfaces.length && output_interfaces[k].load_example_preview) {
new_col = output_interfaces[k].load_example_preview(new_col);
}
} }
html += "<td>" + new_col + "</td>"; html += "<td>" + new_col + "</td>";
} }
@ -316,9 +339,13 @@ function gradio(config, fn, target, example_file_path) {
if (config["examples"]) { if (config["examples"]) {
target.find(".examples").removeClass("invisible"); target.find(".examples").removeClass("invisible");
let html = "<thead>" let html = "<thead>"
for (let i = 0; i < config["input_interfaces"].length; i++) { for (let input_interface of config["input_interfaces"]) {
label = config["input_interfaces"][i][1]["label"]; html += "<th>" + input_interface[1]["label"] + "</th>";
html += "<th>" + label + "</th>"; }
if (config["examples"].length > 0 && config["examples"][0].length > config["input_interfaces"].length) {
for (let output_interface of config["output_interfaces"]) {
html += "<th>" + output_interface[1]["label"] + "</th>";
}
} }
html += "</thead>"; html += "</thead>";
html += "<tbody class='examples_body'></tbody>"; html += "<tbody class='examples_body'></tbody>";
@ -346,6 +373,23 @@ function gradio(config, fn, target, example_file_path) {
io_master.current_page = page_num; io_master.current_page = page_num;
load_page(); load_page();
}) })
set_table_mode = function() {
target.find(".examples-content").removeClass("gallery");
target.find(".examples_control_right button").removeClass("current");
target.find(".table_examples").addClass("current");
}
set_gallery_mode = function() {
target.find(".examples-content").addClass("gallery");
target.find(".examples_control_right button").removeClass("current");
target.find(".gallery_examples").addClass("current");
}
target.on("click", ".table_examples", set_table_mode);
target.on("click", ".gallery_examples", set_gallery_mode);
if (config["examples"].length > 0 && config["examples"][0].length > 1) {
set_table_mode();
} else {
set_gallery_mode();
}
target.find(".load_prev").click(prev_example); target.find(".load_prev").click(prev_example);
target.find(".load_next").click(next_example); target.find(".load_next").click(next_example);
target.find(".order_similar").click(function() { target.find(".order_similar").click(function() {
@ -518,7 +562,7 @@ function gradio(config, fn, target, example_file_path) {
target.find(".flag").click(function() { target.find(".flag").click(function() {
if (io_master.last_output) { if (io_master.last_output) {
target.find(".flag").addClass("flagged"); target.find(".flag").addClass("flagged");
window.setTimeout(() => {target.find(".flag").removeClass("flagged");}, 100); window.setTimeout(() => {target.find(".flag").removeClass("flagged");}, 500);
io_master.flag(); io_master.flag();
} }
}) })

View File

@ -81,8 +81,8 @@ const dataframe_input = {
interpretation_logic: "Highlights the output contribution of each cell in dataframe.", interpretation_logic: "Highlights the output contribution of each cell in dataframe.",
load_example_preview: function(data) { load_example_preview: function(data) {
let data_copy = []; let data_copy = [];
for (let row of data.splice(0,3)) { for (let row of data.slice(0,3)) {
new_row = row.splice(0,3) new_row = row.slice(0,3)
if (row.length > 3) { if (row.length > 3) {
new_row.push("..."); new_row.push("...");
} }

View File

@ -80,29 +80,14 @@ const video_input = {
io.state = "VIDEO_LOADED" io.state = "VIDEO_LOADED"
} }
}, },
load_example_preview: function(data) {
return "<video src='"+this.io_master.example_file_path+data+"' height=100>"
},
load_example: function(example_data) { load_example: function(example_data) {
example_data = this.io_master.example_file_path + example_data; example_data = this.io_master.example_file_path + example_data;
let io = this; let io = this;
toDataURL(example_data, function(data) { toDataURL(example_data, function(data) {
if (io.source == "canvas") { io.target.find(".upload_zone").hide();
io.clear(); io.target.find(".image_display").removeClass("hide");
let ctx = this.context; io.set_video_data(data, /*update_editor=*/true);
var img = new Image; io.state = "VIDEO_LOADED";
let dimension = io.target.find(".canvas_holder canvas").width();
img.onload = function(){
ctx.clearRect(0,0,dimension,dimension);
ctx.drawImage(img,0,0,dimension,dimension);
};
img.src = data;
} else {
io.target.find(".upload_zone").hide();
io.target.find(".image_display").removeClass("hide");
io.set_video_data(data, /*update_editor=*/true);
io.state = "VIDEO_LOADED";
}
}) })
} }
} }

View File

@ -31,7 +31,14 @@ const audio_output = {
this.wavesurfer.stop(); this.wavesurfer.stop();
} }
}, },
load_example_preview: function(data) { load_example: function(example_data) {
return "[audio]"; example_data = this.io_master.example_file_path + example_data;
let io = this;
if (io.state == "NO_AUDIO" || io.state == "RECORDED") {
io.clear();
toDataURL(example_data, function(data) {
io.output(data);
})
}
}, },
} }

View File

@ -24,11 +24,14 @@ const dataframe_output = {
jexcel.destroy(this.target.find(".dataframe")[0]); jexcel.destroy(this.target.find(".dataframe")[0]);
this.table = null; this.table = null;
}, },
load_example: function(data) {
this.output({"data": data});
},
load_example_preview: function(data) { load_example_preview: function(data) {
data = JSON.parse(JSON.stringify(data["data"])) data = JSON.parse(JSON.stringify(data))
let data_copy = []; let data_copy = [];
for (let row of data.splice(0,3)) { for (let row of data.slice(0,3)) {
new_row = row.splice(0,3) new_row = row.slice(0,3)
if (row.length > 3) { if (row.length > 3) {
new_row.push("..."); new_row.push("...");
} }

View File

@ -25,7 +25,12 @@ const file_output = {
.removeAttr("href") .removeAttr("href")
.removeAttr("download"); .removeAttr("download");
}, },
load_example_preview: function(data) { load_example: function(example_data) {
return data.name; example_path = this.io_master.example_file_path + example_data;
}, this.target.find(".file_name").text(example_data);
this.target.find(".file_size").empty();
this.target.find(".interface_mini_box")
.attr("href", example_path)
.attr("download", example_data);
}
} }

View File

@ -46,7 +46,16 @@ const image_output = {
this.target.find(".output_image").attr('src', "") this.target.find(".output_image").attr('src', "")
}, },
load_example_preview: function(data) { load_example_preview: function(data) {
return "<img src='"+data[0]+"' height=100>" data = this.io_master.example_file_path + data;
return "<img src='"+data+"' height=100>"
}, },
load_example: function(example_data) {
example_data = this.io_master.example_file_path + example_data;
let io = this;
toDataURL(example_data, function(data) {
io.target.find(".upload_zone").hide();
io.target.find(".image_display").removeClass("hide");
io.output([data, []]);
})
}
} }

View File

@ -22,15 +22,42 @@ const label_output = {
} }
} }
}, },
load_example: function(data) {
this.output(this.convert_example_to_output(data));
},
load_example_preview: function(data) { load_example_preview: function(data) {
if ("confidences" in data) { let output = this.convert_example_to_output(data);
for (let confidence_set of data["confidences"]) { if ("confidences" in output) {
if (confidence_set["label"] == data["label"]) { if (typeof data == "string") {
return data["label"] + " (" + (100*confidence_set["confidence"]).toFixed(1) + "%)"; try {
data = JSON.parse(data);
} catch (e) {
return output["label"]
} }
} }
return output["label"] + " (" + (100 * data[output["label"]]).toFixed(2) + "%)";
} }
return data["label"]; return output["label"]
},
convert_example_to_output: function(data) {
if (typeof data == "string") {
try {
data = JSON.parse(data);
} catch (e) {
return {"label": data};
}
}
let [max_label, max_confidence] = ["", 0]
let output = {"confidences": []}
for (let [label, confidence] of Object.entries(data)) {
output["confidences"].push({"label": label, "confidence": confidence});
if (confidence > max_confidence) {
max_confidence = confidence;
max_label = label;
}
}
output["label"] = max_label;
return output;
}, },
clear: function() { clear: function() {
this.target.find(".output_class").empty(); this.target.find(".output_class").empty();

View File

@ -11,7 +11,7 @@ const textbox_output = {
this.target.find(".output_text").empty(); this.target.find(".output_text").empty();
}, },
load_example_preview: function(data) { load_example_preview: function(data) {
if (data.length > 20) { if (typeof data == "string" && data.length > 20) {
return data.substring(0,20) + "..."; return data.substring(0,20) + "...";
} }
return data; return data;

View File

@ -20,8 +20,13 @@ const video_output = {
this.target.find(".output_image_holder").addClass("hide"); this.target.find(".output_image_holder").addClass("hide");
this.target.find(".output_image").attr('src', "") this.target.find(".output_image").attr('src', "")
}, },
load_example_preview: function(data) { load_example: function(example_data) {
return "<video controls src='"+data[0]+"' height=100>" example_data = this.io_master.example_file_path + example_data;
}, let io = this;
toDataURL(example_data, function(data) {
io.target.find(".upload_zone").hide();
io.target.find(".image_display").removeClass("hide");
io.output(data);
})
}
} }