diff --git a/src/Platform/Paths.h b/src/Platform/Paths.h index fdda25a..b19b09f 100644 --- a/src/Platform/Paths.h +++ b/src/Platform/Paths.h @@ -6,6 +6,7 @@ namespace platform { public: static std::string datasets() { return "datasets/"; } static std::string results() { return "results/"; } + static std::string excel() { return "excel/"; } }; } #endif \ No newline at end of file diff --git a/src/Platform/ReportBase.cc b/src/Platform/ReportBase.cc index f22a89f..24125f8 100644 --- a/src/Platform/ReportBase.cc +++ b/src/Platform/ReportBase.cc @@ -33,6 +33,5 @@ namespace platform { { header(); body(); - footer(); } } \ No newline at end of file diff --git a/src/Platform/ReportBase.h b/src/Platform/ReportBase.h index 2d8a072..2acbbc7 100644 --- a/src/Platform/ReportBase.h +++ b/src/Platform/ReportBase.h @@ -14,12 +14,10 @@ namespace platform { void show(); protected: json data; - double totalScore; // Total score of all results in a report string fromVector(const string& key); string fVector(const string& title, const json& data, const int width, const int precision); virtual void header() = 0; virtual void body() = 0; - virtual void footer() = 0; }; }; #endif \ No newline at end of file diff --git a/src/Platform/ReportConsole.cc b/src/Platform/ReportConsole.cc index 910b0df..2e3ed0c 100644 --- a/src/Platform/ReportConsole.cc +++ b/src/Platform/ReportConsole.cc @@ -10,6 +10,7 @@ namespace platform { char do_thousands_sep() const { return '.'; } string do_grouping() const { return "\03"; } }; + string ReportConsole::headerLine(const string& text) { int n = MAXL - text.length() - 3; @@ -38,7 +39,7 @@ namespace platform { cout << Colors::GREEN() << "Dataset Sampl. Feat. Cls Nodes Edges States Score Time Hyperparameters" << endl; cout << "============================== ====== ===== === ========= ========= ========= =============== ================== ===============" << endl; json lastResult; - totalScore = 0; + double totalScore = 0.0; bool odd = true; for (const auto& r : data["results"]) { auto color = odd ? Colors::CYAN() : Colors::BLUE(); @@ -69,9 +70,11 @@ namespace platform { cout << headerLine(fVector("Train times: ", lastResult["times_train"], 10, 3)); cout << headerLine(fVector("Test times: ", lastResult["times_test"], 10, 3)); cout << string(MAXL, '*') << endl; + } else { + footer(totalScore); } } - void ReportConsole::footer() + void ReportConsole::footer(double totalScore) { cout << Colors::MAGENTA() << string(MAXL, '*') << endl; auto score = data["score_name"].get(); diff --git a/src/Platform/ReportConsole.h b/src/Platform/ReportConsole.h index 57e0024..5c795b7 100644 --- a/src/Platform/ReportConsole.h +++ b/src/Platform/ReportConsole.h @@ -16,7 +16,7 @@ namespace platform { string headerLine(const string& text); void header() override; void body() override; - void footer() override; + void footer(double totalScore); }; }; #endif \ No newline at end of file diff --git a/src/Platform/ReportExcel.cc b/src/Platform/ReportExcel.cc index 275248a..bb51dfb 100644 --- a/src/Platform/ReportExcel.cc +++ b/src/Platform/ReportExcel.cc @@ -7,79 +7,103 @@ namespace platform { struct separated : numpunct { char do_decimal_point() const { return ','; } + char do_thousands_sep() const { return '.'; } + string do_grouping() const { return "\03"; } }; - string headerLine(const string& text) + + void ReportExcel::createFile() { - int n = MAXLL - text.length() - 3; - n = n < 0 ? 0 : n; - return "* " + text + string(n, ' ') + "*\n"; + doc.create(Paths::excel() + "some_results.xlsx"); + wks = doc.workbook().worksheet("Sheet1"); + wks.setName(data["model"].get()); } - + + void ReportExcel::closeFile() + { + doc.save(); + doc.close(); + } + void ReportExcel::header() { locale mylocale(cout.getloc(), new separated); locale::global(mylocale); cout.imbue(mylocale); stringstream oss; - cout << Colors::MAGENTA() << string(MAXLL, '*') << endl; - cout << headerLine("Report " + data["model"].get() + " ver. " + data["version"].get() + " with " + to_string(data["folds"].get()) + " Folds cross validation and " + to_string(data["seeds"].size()) + " random seeds. " + data["date"].get() + " " + data["time"].get()); - cout << headerLine(data["title"].get()); - cout << headerLine("Random seeds: " + fromVector("seeds") + " Stratified: " + (data["stratified"].get() ? "True" : "False")); - oss << "Execution took " << setprecision(2) << fixed << data["duration"].get() << " seconds, " << data["duration"].get() / 3600 << " hours, on " << data["platform"].get(); - cout << headerLine(oss.str()); - cout << headerLine("Score is " + data["score_name"].get()); - cout << string(MAXLL, '*') << endl; - cout << endl; + wks.cell("A1").value().set( + "Report " + data["model"].get() + " ver. " + data["version"].get() + " with " + + to_string(data["folds"].get()) + " Folds cross validation and " + to_string(data["seeds"].size()) + + " random seeds. " + data["date"].get() + " " + data["time"].get()); + wks.cell("A2").value() = data["title"].get(); + wks.cell("A3").value() = "Random seeds: " + fromVector("seeds") + " Stratified: " + + (data["stratified"].get() ? "True" : "False"); + oss << "Execution took " << setprecision(2) << fixed << data["duration"].get() << " seconds, " + << data["duration"].get() / 3600 << " hours, on " << data["platform"].get(); + wks.cell("A4").value() = oss.str(); + wks.cell("A5").value() = "Score is " + data["score_name"].get(); } + void ReportExcel::body() { - cout << Colors::GREEN() << "Dataset Sampl. Feat. Cls Nodes Edges States Score Time Hyperparameters" << endl; - cout << "============================== ====== ===== === ========= ========= ========= =============== ================== ===============" << endl; + auto header = vector( + { "Dataset", "Samples", "Features", "Classes", "Nodes", "Edges", "States", "Score", "Score Std.", "Time", + "Time Std.", "Hyperparameters" }); + int col = 1; + for (const auto& item : header) { + wks.cell(8, col++).value() = item; + } + int row = 9; + col = 1; json lastResult; - totalScore = 0; - bool odd = true; + double totalScore = 0.0; + string hyperparameters; for (const auto& r : data["results"]) { - auto color = odd ? Colors::CYAN() : Colors::BLUE(); - cout << color << setw(30) << left << r["dataset"].get() << " "; - cout << setw(6) << right << r["samples"].get() << " "; - cout << setw(5) << right << r["features"].get() << " "; - cout << setw(3) << right << r["classes"].get() << " "; - cout << setw(9) << setprecision(2) << fixed << r["nodes"].get() << " "; - cout << setw(9) << setprecision(2) << fixed << r["leaves"].get() << " "; - cout << setw(9) << setprecision(2) << fixed << r["depth"].get() << " "; - cout << setw(8) << right << setprecision(6) << fixed << r["score"].get() << "±" << setw(6) << setprecision(4) << fixed << r["score_std"].get() << " "; - cout << setw(11) << right << setprecision(6) << fixed << r["time"].get() << "±" << setw(6) << setprecision(4) << fixed << r["time_std"].get() << " "; + wks.cell(row, col).value() = r["dataset"].get(); + wks.cell(row, col + 1).value() = r["samples"].get(); + wks.cell(row, col + 2).value() = r["features"].get(); + wks.cell(row, col + 3).value() = r["classes"].get(); + wks.cell(row, col + 4).value() = r["nodes"].get(); + wks.cell(row, col + 5).value() = r["leaves"].get(); + wks.cell(row, col + 6).value() = r["depth"].get(); + wks.cell(row, col + 7).value() = r["score"].get(); + wks.cell(row, col + 8).value() = r["score_std"].get(); + wks.cell(row, col + 9).value() = r["time"].get(); + wks.cell(row, col + 10).value() = r["time_std"].get(); try { - cout << r["hyperparameters"].get(); + hyperparameters = r["hyperparameters"].get(); } catch (const exception& err) { - cout << r["hyperparameters"]; + stringstream oss; + oss << r["hyperparameters"]; + hyperparameters = oss.str(); } - cout << endl; + wks.cell(row, col + 11).value() = hyperparameters; lastResult = r; totalScore += r["score"].get(); - odd = !odd; + row++; } if (data["results"].size() == 1) { - cout << string(MAXLL, '*') << endl; - cout << headerLine(fVector("Train scores: ", lastResult["scores_train"], 14, 12)); - cout << headerLine(fVector("Test scores: ", lastResult["scores_test"], 14, 12)); - cout << headerLine(fVector("Train times: ", lastResult["times_train"], 10, 3)); - cout << headerLine(fVector("Test times: ", lastResult["times_test"], 10, 3)); - cout << string(MAXLL, '*') << endl; + for (const string& group : { "scores_train", "scores_test", "times_train", "times_test" }) { + row++; + col = 1; + wks.cell(row, col).value() = group; + for (double item : lastResult[group]) { + wks.cell(row, ++col).value() = item; + } + } + } else { + footer(totalScore, row); } } - void ReportExcel::footer() + + void ReportExcel::footer(double totalScore, int row) { - cout << Colors::MAGENTA() << string(MAXLL, '*') << endl; auto score = data["score_name"].get(); if (score == BestResult::scoreName()) { - stringstream oss; - oss << score << " compared to " << BestResult::title() << " .: " << totalScore / BestResult::score(); - cout << headerLine(oss.str()); + wks.cell(row + 2, 1).value() = score + " compared to " + BestResult::title() + " .: "; + wks.cell(row + 2, 5).value() = totalScore / BestResult::score(); } - cout << string(MAXLL, '*') << endl << Colors::RESET(); } } \ No newline at end of file diff --git a/src/Platform/ReportExcel.h b/src/Platform/ReportExcel.h index e19dca9..3700681 100644 --- a/src/Platform/ReportExcel.h +++ b/src/Platform/ReportExcel.h @@ -1,18 +1,25 @@ #ifndef REPORTEXCEL_H #define REPORTEXCEL_H +#include #include "ReportBase.h" +#include "Paths.h" #include "Colors.h" namespace platform { using namespace std; + using namespace OpenXLSX; const int MAXLL = 128; class ReportExcel : public ReportBase{ public: - explicit ReportExcel(json data_) : ReportBase(data_) {}; - virtual ~ReportExcel() = default; + explicit ReportExcel(json data_) : ReportBase(data_) {createFile();}; + virtual ~ReportExcel() {closeFile();}; private: + void createFile(); + void closeFile(); + XLDocument doc; + XLWorksheet wks; void header() override; void body() override; - void footer() override; + void footer(double totalScore, int row); }; }; #endif // !REPORTEXCEL_H \ No newline at end of file