Fix Excel files

This commit is contained in:
2023-06-06 17:25:47 +02:00
parent 8e29948809
commit 8c576f8f2c
19 changed files with 182 additions and 339 deletions

Binary file not shown.

View File

@@ -7,9 +7,6 @@ load_dotenv(os.path.join(basedir, dotenv_file))
class Config(object):
FRAMEWORKS = ["bootstrap", "bulma"]
FRAMEWORK = os.environ.get("FRAMEWORK") or FRAMEWORKS[0]
OUTPUT = os.environ.get("OUTPUT") or "local" # local or docker
COMPARE = os.environ.get("COMPARE") == "True" or False
TEMPLATES_AUTO_RELOAD = True
SECRET_KEY = os.environ.get("SECRET_KEY") or "really-hard-to-guess-key"

View File

@@ -1,3 +1 @@
OUTPUT="local"
FRAMEWORK="bulma"
COMPARE="True"
COMPARE=True

View File

@@ -1,3 +1,5 @@
import os
from benchmark.utils import Files
from flask import (
Blueprint,
render_template,
@@ -24,6 +26,10 @@ def index():
benchmarks = Benchmark.query.all()
else:
benchmarks = [current_user.benchmark]
for benchmark in benchmarks:
os.chdir(benchmark.folder)
benchmark.num_files = len(Files.get_all_results(hidden=False))
os.chdir(current_user.benchmark.folder)
else:
benchmarks = []
return render_template("index.html", benchmarks=benchmarks)

View File

@@ -1,16 +1,21 @@
import os
import json
from benchmark.Utils import Files, Folders
from benchmark.ResultsBase import StubReport
from benchmark.Datasets import Datasets
from flask_login import current_user
from flask import Blueprint, current_app, send_file
from flask import render_template, current_app, request, redirect, url_for
from flask_login import login_required
import os
import shutil
# import shutil
# import xlsxwriter
# from benchmark.ResultsFiles import Excel, ReportDatasets
import xlsxwriter
from benchmark.Datasets import Datasets
from benchmark.ResultsBase import StubReport
from benchmark.ResultsFiles import Excel, ReportDatasets
from benchmark.Utils import Files, Folders
from flask import (
Blueprint,
current_app,
render_template,
request,
send_file,
url_for,
)
from flask_login import current_user, login_required
results = Blueprint("results", __name__, template_folder="templates")
@@ -36,7 +41,7 @@ class AjaxResponse:
@results.route("/select")
@login_required
def select(compare="False"):
def select():
# Get a list of files in a directory
files = {}
os.chdir(current_user.benchmark.folder)
@@ -49,14 +54,9 @@ def select(compare="False"):
"score": report.score,
"title": report.title,
}
candidate = current_app.config["FRAMEWORKS"].copy()
candidate.remove(current_app.config["FRAMEWORK"])
return render_template(
"select.html",
files=files,
candidate=candidate[0],
framework=current_app.config["FRAMEWORK"],
compare=compare.capitalize() == "True",
)
@@ -85,7 +85,10 @@ def best(file_name):
"created yet! or...",
error=str(e),
)
return render_template("best.html", data=data)
info = file_name.split("_")
model = info[3].split(".")[0]
title = f"Best results obtained with {model} on {info[2]}"
return render_template("best.html", data=data, title=title)
@results.route("/set_compare", methods=["POST"])
@@ -99,6 +102,7 @@ def set_compare():
@login_required
def report(file_name):
os.chdir(current_user.benchmark.folder)
back = request.args.get("url") or ""
with open(os.path.join(Folders.results, file_name)) as f:
data = json.load(f)
try:
@@ -106,10 +110,7 @@ def report(file_name):
except Exception as e:
return render_template("error.html", message=str(e))
return render_template(
"report.html",
data=data,
file=file_name,
summary=summary,
"report.html", data=data, file=file_name, summary=summary, back=back
)
@@ -128,3 +129,51 @@ def process_data(file_name, compare, data):
for key, value in report._compare_totals.items():
summary[key] = (report._status_meaning(key), value)
return summary
@results.route("/excel", methods=["post"])
@login_required
def excel():
os.chdir(current_user.benchmark.folder)
selected_files = request.json["selectedFiles"]
if selected_files[0] == "datasets":
# Create a list of datasets
report = ReportDatasets(excel=True, output=False)
report.report()
return AjaxResponse(True, Files.datasets_report_excel).to_string()
try:
# create a spreadsheet with the selected files
book = None
for file_name in selected_files:
file_name_result = os.path.join(Folders.results, file_name)
if book is None:
file_excel = os.path.join(Folders.excel, Files.be_list_excel)
book = xlsxwriter.Workbook(
file_excel, {"nan_inf_to_errors": True}
)
excel = Excel(
file_name=file_name_result,
book=book,
compare=current_app.config["COMPARE"],
)
excel.report()
except Exception as e:
if book is not None:
book.close()
return AjaxResponse(
False, "Could not create excel file, " + str(e)
).to_string()
if book is not None:
book.close()
return AjaxResponse(True, Files.be_list_excel).to_string()
@results.route("/download/<file_name>")
@login_required
def download(file_name):
os.chdir(current_user.benchmark.folder)
src = os.path.join(current_user.benchmark.folder, Folders.excel, file_name)
dest = os.path.join("static", "excel", file_name)
os.chdir(current_app.root_path)
shutil.copyfile(src, dest)
return send_file(dest, as_attachment=True)

View File

@@ -1,212 +0,0 @@
#!/usr/bin/env python
# import os
# import json
# import shutil
# import xlsxwriter
# from benchmark.Utils import Files, Folders
# from benchmark.Arguments import EnvData
# from benchmark.ResultsBase import StubReport
# from benchmark.ResultsFiles import Excel, ReportDatasets
# from benchmark.Datasets import Datasets
# from flask import Blueprint, current_app, send_file
# from flask import render_template, request, redirect, url_for
from flask import Blueprint, render_template
results = Blueprint("results", __name__, template_folder="results")
# FRAMEWORK = "framework"
# FRAMEWORKS = "frameworks"
# OUTPUT = "output"
# TEST = "test"
# class AjaxResponse:
# def __init__(self, success, file_name, code=200):
# self.success = success
# self.file_name = file_name
# self.code = code
# def to_string(self):
# return (
# json.dumps(
# {
# "success": self.success,
# "file": self.file_name,
# "output": current_app.config[OUTPUT],
# }
# ),
# self.code,
# {"ContentType": "application/json"},
# )
# def process_data(file_name, compare, data):
# report = StubReport(
# os.path.join(Folders.results, file_name), compare=compare
# )
# new_list = []
# for result in data["results"]:
# symbol = report._compute_status(result["dataset"], result["score"])
# result["symbol"] = symbol if symbol != " " else "&nbsp;"
# new_list.append(result)
# data["results"] = new_list
# # Compute summary with explanation of symbols
# summary = {}
# for key, value in report._compare_totals.items():
# summary[key] = (report._status_meaning(key), value)
# return summary
@results.route("/results/<compare>")
def results(compare="False"):
# # Get a list of files in a directory
# files = {}
# names = Files.get_all_results(hidden=False)
# for name in names:
# report = StubReport(os.path.join(Folders.results, name))
# report.report()
# files[name] = {
# "duration": report.duration,
# "score": report.score,
# "title": report.title,
# }
# candidate = current_app.config[FRAMEWORKS].copy()
# candidate.remove(current_app.config[FRAMEWORK])
# return render_template(
# "select.html",
# files=files,
# candidate=candidate[0],
# framework=current_app.config[FRAMEWORK],
# compare=compare.capitalize() == "True",
# )
return render_template("test.html")
"""
@results.route("/datasets/<compare>")
@results.route("datasets")
def datasets(compare=False):
dt = Datasets()
datos = []
for dataset in dt:
datos.append(dt.get_attributes(dataset))
return render_template(
"datasets.html",
datasets=datos,
compare=compare,
framework=current_app.config[FRAMEWORK],
)
@results.route("/showfile/<file_name>/<compare>")
def showfile(file_name, compare, back=None):
compare = compare.capitalize() == "True"
back = request.args["url"] if back is None else back
print(f"back [{back}]")
with open(os.path.join(Folders.results, file_name)) as f:
data = json.load(f)
try:
summary = process_data(file_name, compare, data)
except Exception as e:
return render_template("error.html", message=str(e), compare=compare)
return render_template(
"report.html",
data=data,
file=file_name,
summary=summary,
framework=current_app.config[FRAMEWORK],
back=back,
)
@results.route("/show", methods=["post"])
def show():
selected_file = request.form["selected-file"]
compare = request.form["compare"]
return showfile(
file_name=selected_file,
compare=compare,
back=url_for(
"main.index", compare=compare, output=current_app.config[OUTPUT]
),
)
@results.route("/excel", methods=["post"])
def excel():
selected_files = request.json["selectedFiles"]
compare = request.json["compare"]
book = None
if selected_files[0] == "datasets":
# Create a list of datasets
report = ReportDatasets(excel=True, output=False)
report.report()
excel_name = os.path.join(Folders.excel, Files.datasets_report_excel)
if current_app.config[OUTPUT] == "local":
Files.open(excel_name, test=current_app.config[TEST])
return AjaxResponse(True, Files.datasets_report_excel).to_string()
try:
for file_name in selected_files:
file_name_result = os.path.join(Folders.results, file_name)
if book is None:
file_excel = os.path.join(Folders.excel, Files.be_list_excel)
book = xlsxwriter.Workbook(
file_excel, {"nan_inf_to_errors": True}
)
excel = Excel(
file_name=file_name_result,
book=book,
compare=compare,
)
excel.report()
except Exception as e:
if book is not None:
book.close()
return AjaxResponse(
False, "Could not create excel file, " + str(e)
).to_string()
if book is not None:
book.close()
if current_app.config[OUTPUT] == "local":
Files.open(file_excel, test=current_app.config[TEST])
return AjaxResponse(True, Files.be_list_excel).to_string()
@results.route("/download/<file_name>")
def download(file_name):
src = os.path.join(Folders.current, Folders.excel, file_name)
dest = os.path.join(
Folders.src(), "scripts", "app", "static", "excel", file_name
)
shutil.copyfile(src, dest)
return send_file(dest, as_attachment=True)
@results.route("/config/<framework>/<compare>")
def config(framework, compare):
if framework not in current_app.config[FRAMEWORKS]:
message = f"framework {framework} not supported"
return render_template("error.html", message=message)
env = EnvData()
env.load()
env.args[FRAMEWORK] = framework
env.save()
current_app.config[FRAMEWORK] = framework
return redirect(url_for("main.index", compare=compare))
@results.route("/best_results/<file>/<compare>")
def best_results(file, compare):
compare = compare.capitalize() == "True"
try:
with open(os.path.join(Folders.results, file)) as f:
data = json.load(f)
except Exception as e:
return render_template("error.html", message=str(e), compare=compare)
return render_template(
"report_best.html",
data=data,
compare=compare,
framework=current_app.config[FRAMEWORK],
)
"""

View File

@@ -1,4 +1,4 @@
<table id="file-table"
<table id="report-table"
class="table table-striped table-hover table-bordered bg-light">
<thead>
<tr class="bg-primary text-white">

View File

@@ -1,4 +1,15 @@
{% from "macros.html" import excel_button %}
<div id="app">
{% if back %}
<button type="button"
class="btn btn-primary position-relative"
onclick="location.href='{{ back }}'">
Back to Best Results Report
<span class="position-absolute top-0 start-100 translate-middle p-2 bg-danger border border-light rounded-circle">
<span class="visually-hidden">Back to Best Results Report</span>
</span>
</button>
{% endif %}
<section class="section">
<div class="container-fluid">
<div>
@@ -39,11 +50,7 @@
</tr>
</thead>
</table>
<div>
<button class="{{ button }}" onclick="excelFile()">
<i class="mdi mdi-file-excel"></i> Excel
</button>
</div>
<div>{{ excel_button([ file ]) }}</div>
<table id="report-table"
class="table table-striped table-hover table-bordered bg-light">
<thead>
@@ -53,7 +60,7 @@
<th class="text-center">Features</th>
<th class="text-center">Classes</th>
<th class="text-center">Nodes</th>
<th class="text-center">{{ data.score_name|capitalize }}</th>
<th class="text-center" colspan="2">{{ data.score_name|capitalize }}</th>
<th class="text-center">Time</th>
<th class="text-center">hyperparameters</th>
</tr>
@@ -62,13 +69,14 @@
{% for item in data.results %}
<tr>
<td>{{ item.dataset }}</td>
<td class="{{ right }}">{{ '{:,}'.format(item.samples) }}</td>
<td class="{{ right }}">{{"%d" % item.features}}</td>
<td class="{{ right }}">{{"%d" % item.classes}}</td>
<td class="{{ right }}">{{ '{:,.2f}'.format(item.nodes) }}</td>
<td class="{{ right }}">{{"%.6f±%.4f" % (item.score, item.score_std)}} {{ item.symbol|safe }}</td>
<td class="{{ right }}">{{"%.6f±%.4f" % (item.time, item.time_std)}}</td>
<td class="{{ center }}">{{ item.hyperparameters }}</td>
<td class="text-end">{{ '{:,}'.format(item.samples) }}</td>
<td class="text-end">{{"%d" % item.features}}</td>
<td class="text-end">{{"%d" % item.classes}}</td>
<td class="text-end">{{ '{:,.2f}'.format(item.nodes) }}</td>
<td class="text-end">{{"%.6f±%.4f" % (item.score, item.score_std)}}</td>
<td class="text-center">{{ item.symbol|safe }}</td>
<td class="text-end">{{"%.6f±%.4f" % (item.time, item.time_std)}}</td>
<td class="text-center">{{ item.hyperparameters }}</td>
</tr>
{% endfor %}
</tbody>
@@ -86,11 +94,9 @@
<tbody>
{% for key, value in summary.items() %}
<tr>
<td class="{{ center }}">{{ key }}</td>
<td class="text-center">{{ key }}</td>
<td>{{ value[0] }}</td>
<td class={{ right }}>
{{ '{:,}'.format(value[1]) }}
</td>
<td class=text-end>{{ '{:,}'.format(value[1]) }}</td>
</tr>
</tbody>
{% endfor %}

View File

@@ -1,7 +1,11 @@
<div class="float-right">
{% from "macros.html" import excel_button %}
<div class="d-flex justify-content-between">
{{ excel_button('', 'excel_select') }}
<div>
<input type="checkbox" id="compare" name="compare" {% if config["COMPARE"] %}{{ "checked" }}{% endif %}>
<span class="badge bg-info bg-small" onclick="$('#compare').click()">Comparing with best results</span>
</div>
</div>
<table id="file-table"
class="table table-striped table-hover table-bordered">
<thead>

View File

@@ -1,5 +1,7 @@
{% extends "base.html" %}
{% block content %}
<div class="alert alert-primary" role="alert">
<h3>{{ title }}</h3>
<table id="report-table"
class="table table-striped table-hover table-bordered bg-light">
<thead>
@@ -24,6 +26,7 @@
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
{% block jscript %}
{{ super() }}

View File

@@ -1,26 +1,11 @@
{% from "macros.html" import excel_button %}
{% extends "base.html" %}
{% block content %}
{{ excel_button(["datasets"]) }}
{% include "_table_datasets.html" %}
{% endblock %}
{% block jscript %}
{{ super() }}
<script>
$(document).ready(function () {
$(document).ajaxStart(function(){
$("body").addClass('ajaxLoading');
});
$(document).ajaxStop(function(){
$("body").removeClass('ajaxLoading');
});
});
// Check if row is selected
$('#file-table tbody').on('click', 'tr', function () {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
} else {
$('#file-table tbody tr.selected').removeClass("selected")
$(this).addClass('selected');
}
});
</script>
<script src="{{ url_for('static', filename="js/report.js") }}"></script>
<script src="{{ url_for('static', filename="js/excelFiles.js") }}"></script>
{% endblock %}

View File

@@ -0,0 +1,12 @@
{% macro excel_button(files, function="excelSend") %}
{% if files %}
{% set call %}
{{ function }}({{ files }})
{% endset %}
{% else %}
{% set call = function + "()" %}
{% endif %}
<button class="btn btn-primary btn-small" onclick="{{ call }}">
<i class="mdi mdi-file-excel"></i> Excel
</button>
{% endmacro %}

View File

@@ -5,4 +5,5 @@
{% block jscript %}
{{ super() }}
<script src="{{ url_for('static', filename="js/report.js") }}"></script>
<script src="{{ url_for('static', filename="js/excelFiles.js") }}"></script>
{% endblock %}

View File

@@ -13,4 +13,5 @@
<script rel="stylesheet"
href="https://cdn.datatables.net/1.13.4/js/dataTables.bootstrap5.min.js"></script>
<script src="{{ url_for('static', filename="js/select.js") }}"></script>
<script src="{{ url_for('static', filename="js/excelFiles.js") }}"></script>
{% endblock %}

1
app/static/excel/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.xlsx

View File

@@ -1,29 +1,37 @@
function excelFiles(selectedFiles, compare) {
function excel_select() {
var checkbox = document.getElementsByName("selected_files");
var selectedFiles = [];
for (var i = 0; i < checkbox.length; i++) {
if (checkbox[i].checked) {
selectedFiles.push(checkbox[i].value);
}
}
if (selectedFiles.length == 0) {
alert("Select at least one file");
return;
}
excelSend(selectedFiles);
}
function excelSend(selectedFiles) {
var data = {
"selectedFiles": selectedFiles,
"compare": compare
};
// send data to server with ajax post
$.ajax({
type:'POST',
url:'/excel',
url:'/results/excel',
data: JSON.stringify(data),
contentType: "application/json",
dataType: 'json',
success: function(data){
if (data.success) {
if (data.output == "local") {
alert("Se ha generado el archivo " + data.file);
} else {
window.open('/download/' + data.file, "_blank");
}
window.open('/results/download/' + data.file, "_blank");
} else {
alert(data.file);
}
},
error: function (xhr, ajaxOptions, thrownError) {
var mensaje = JSON.parse(xhr.responseText || '{\"mensaje\": \"Error indeterminado\"}');
alert(mensaje.mensaje);
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.responseText);
}
});
}

View File

@@ -73,30 +73,9 @@ $(document).ready(function () {
function showFile(selectedFile) {
location.href = "/results/show/" + selectedFile;
}
function excel() {
var checkbox = document.getElementsByName("selected_files");
var selectedFiles = [];
for (var i = 0; i < checkbox.length; i++) {
if (checkbox[i].checked) {
selectedFiles.push(checkbox[i].value);
}
}
if (selectedFiles.length == 0) {
alert("Select at least one file");
return;
}
var compare = $("#compare").is(":checked");
excelFiles(selectedFiles, compare);
}
function setCheckBoxes(value) {
var checkbox = document.getElementsByName("selected_files");
for (i = 0; i < checkbox.length; i++) {
checkbox[i].checked = value;
}
}
function redirectDouble(route, parameter) {
location.href = "/"+ route + "/" + parameter + "/" + $("#compare").is(":checked");
}
function redirectSimple(route) {
location.href = "/" + route + "/" + $("#compare").is(":checked");
}

View File

@@ -3,7 +3,13 @@
<div class="list-group">
{% for benchmark in benchmarks %}
<a href="{{ url_for('main.set_benchmark', benchmark_id=benchmark.id) }}"
class="list-group-item list-group-item-action {% if benchmark == current_user.benchmark %}active{% endif %}">{{ benchmark.name + " - " + benchmark.description }}</a>
class="list-group-item list-group-item-action flex-column align-items-start {% if benchmark == current_user.benchmark %}active{% endif %}">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{ benchmark.name }}</h5>
<small>{{ benchmark.num_files }} files</small>
</div>
<p class="mb-1">{{ benchmark.description }}</p>
</a>
{% endfor %}
</div>
</div>

View File

@@ -28,7 +28,6 @@
{% else %}
{{ render_nav_item('main.login', 'Login') }}
{% endif %}
</ul>
</div>
</div>
</div>