diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 195144b..957316b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -36,7 +36,7 @@ add_executable(b_grid ${grid_sources} target_link_libraries(b_grid ${MPI_CXX_LIBRARIES} "${PyClassifiers}" "${BayesNet}" ArffFiles mdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy) # b_list -set(list_sources b_list.cpp DatasetsExcel.cpp ResultsDataset.cpp) +set(list_sources b_list.cpp DatasetsExcel.cpp ResultsDataset.cpp ResultsDatasetExcel.cpp) list(TRANSFORM list_sources PREPEND list/) add_executable(b_list ${list_sources} common/Datasets.cpp common/Dataset.cpp diff --git a/src/list/DatasetsExcel.cpp b/src/list/DatasetsExcel.cpp index 7a0c89c..d82d8a7 100644 --- a/src/list/DatasetsExcel.cpp +++ b/src/list/DatasetsExcel.cpp @@ -1,8 +1,5 @@ -#include -#include "common/Paths.h" #include "DatasetsExcel.h" - namespace platform { DatasetsExcel::DatasetsExcel() { diff --git a/src/list/DatasetsExcel.h b/src/list/DatasetsExcel.h index a362bf4..dbfbc8f 100644 --- a/src/list/DatasetsExcel.h +++ b/src/list/DatasetsExcel.h @@ -1,7 +1,5 @@ #pragma once -#include -#include #include #include "reports/ExcelFile.h" diff --git a/src/list/ResultsDataset.cpp b/src/list/ResultsDataset.cpp index 2cc285d..74ed878 100644 --- a/src/list/ResultsDataset.cpp +++ b/src/list/ResultsDataset.cpp @@ -42,6 +42,9 @@ namespace platform { { sort(files.begin(), files.end(), [](const Result& a, const Result& b) { if (a.getModel() == b.getModel()) { + if (a.getDate() == b.getDate()) { + return a.getTime() > b.getTime(); + } return a.getDate() > b.getDate(); } return a.getModel() < b.getModel(); diff --git a/src/list/ResultsDatasetExcel.cpp b/src/list/ResultsDatasetExcel.cpp new file mode 100644 index 0000000..1775fbe --- /dev/null +++ b/src/list/ResultsDatasetExcel.cpp @@ -0,0 +1,49 @@ +#include "ResultsDatasetExcel.h" +#include +namespace platform { + ResultsDatasetExcel::ResultsDatasetExcel() + { + file_name = "some_results.xlsx"; + workbook = workbook_new(getFileName().c_str()); + createFormats(); + setProperties("Results"); + } + ResultsDatasetExcel::~ResultsDatasetExcel() + { + workbook_close(workbook); + } + void ResultsDatasetExcel::report(json& data) + { + worksheet = workbook_add_worksheet(workbook, data["dataset"].get().c_str()); + // Header + std::string title = "Results of dataset " + data["dataset"].get() + " - for " + data["model"].get() + " model"; + worksheet_merge_range(worksheet, 0, 0, 0, 5, title.c_str(), styles["headerFirst"]); + // Body header + row = 2; + int col = 0; + for (const auto& name : { "NÂș", "Model", "Date", "Time", "Score", "Hyperparameters" }) { + writeString(row, col++, name, "bodyHeader"); + } + // Body + double maxResult = data["maxResult"].get(); + for (const auto& item : data["results"]) { + row++; + col = 0; + std::string style = item["score"] == data["maxResult"] ? "_bold" : ""; + writeInt(row, col++, row - 3, "ints" + style); + writeString(row, col++, item["model"], "text" + style); + writeString(row, col++, item["date"], "text" + style); + writeString(row, col++, item["time"], "text" + style); + writeDouble(row, col++, item["score"], "result" + style); + writeString(row, col++, item["hyperparameters"].get().c_str(), "text" + style); + } + // Format columns + worksheet_freeze_panes(worksheet, 3, 2); + auto modelSize = data["maxModel"].get(); + auto hyperSize = data["maxHyper"].get(); + std::vector columns_sizes = { 5, modelSize + 3, 12, 9, 11, hyperSize + 10 }; + for (int i = 0; i < columns_sizes.size(); ++i) { + worksheet_set_column(worksheet, i, i, columns_sizes.at(i), NULL); + } + } +} \ No newline at end of file diff --git a/src/list/ResultsDatasetExcel.h b/src/list/ResultsDatasetExcel.h new file mode 100644 index 0000000..373a4f7 --- /dev/null +++ b/src/list/ResultsDatasetExcel.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include "reports/ExcelFile.h" + +using json = nlohmann::json; + +namespace platform { + + class ResultsDatasetExcel : public ExcelFile { + public: + ResultsDatasetExcel(); + ~ResultsDatasetExcel(); + void report(json& data); + }; +} diff --git a/src/list/b_list.cpp b/src/list/b_list.cpp index b40307d..9fa50c6 100644 --- a/src/list/b_list.cpp +++ b/src/list/b_list.cpp @@ -10,6 +10,7 @@ #include "common/Datasets.h" #include "DatasetsExcel.h" #include "ResultsDataset.h" +#include "ResultsDatasetExcel.h" #include "config.h" const int BALANCE_LENGTH = 75; @@ -80,6 +81,7 @@ void list_results(argparse::ArgumentParser& program) auto dataset = program.get("dataset"); auto score = program.get("score"); auto model = program.get("model"); + auto excel = program.get("excel"); auto results = platform::ResultsDataset(dataset, model, score); results.load(); results.sortModel(); @@ -91,30 +93,50 @@ void list_results(argparse::ArgumentParser& program) // List data // int maxModel = results.maxModelSize(); - int maxFileName = results.maxFileSize(); int maxHyper = results.maxHyperSize(); double maxResult = results.maxResultScore(); - std::cout << Colors::GREEN() << "Results for dataset " << dataset << std::endl; + std::cout << Colors::GREEN() << "Results of dataset " << dataset << " - for " << model << " model" << std::endl; std::cout << "There are " << results.size() << " results" << std::endl; - std::cout << Colors::GREEN() << " # " << std::setw(maxModel + 1) << std::left << "Model" << "Date Score " << std::setw(maxFileName) << "File" << " Hyperparameters" << std::endl; - std::cout << "=== " << std::string(maxModel, '=') << " ========== =========== " << std::string(maxFileName, '=') << " " << std::string(maxHyper, '=') << std::endl; + std::cout << Colors::GREEN() << " # " << std::setw(maxModel + 1) << std::left << "Model" << "Date Time Score Hyperparameters" << std::endl; + std::cout << "=== " << std::string(maxModel, '=') << " ========== ======== =========== " << std::string(maxHyper, '=') << std::endl; auto i = 0; + json data = json::object(); + data["results"] = json::array(); for (const auto& result : results) { - auto data = result.getData(); - for (const auto& item : data["results"]) { + auto results = result.getData(); + for (const auto& item : results["results"]) { if (item["dataset"] == dataset) { auto color = (i % 2) ? Colors::BLUE() : Colors::CYAN(); color = item["score"].get() == maxResult ? Colors::RED() : color; std::cout << color << std::setw(3) << std::fixed << std::right << i++ << " "; std::cout << std::setw(maxModel) << std::left << result.getModel() << " "; std::cout << color << result.getDate() << " "; + std::cout << color << result.getTime() << " "; std::cout << std::setw(11) << std::setprecision(9) << std::fixed << item["score"].get() << " "; - std::cout << std::setw(maxFileName) << result.getFilename() << " "; std::cout << item["hyperparameters"].dump() << std::endl; + // Store data for Excel report + json res = json::object(); + res["date"] = result.getDate(); + res["time"] = result.getTime(); + res["model"] = result.getModel(); + res["score"] = item["score"].get(); + res["hyperparameters"] = item["hyperparameters"].dump(); + data["results"].push_back(res); break; } } } + if (excel) { + data["dataset"] = dataset; + data["score"] = score; + data["model"] = model; + data["maxModel"] = maxModel; + data["maxHyper"] = maxHyper; + data["maxResult"] = maxResult; + auto report = platform::ResultsDatasetExcel(); + report.report(data); + std::cout << std::endl << Colors::GREEN() << "Output saved in " << report.getFileName() << std::endl; + } } int main(int argc, char** argv) @@ -125,10 +147,7 @@ int main(int argc, char** argv) // argparse::ArgumentParser datasets_command("datasets"); datasets_command.add_description("List datasets available in the platform."); - datasets_command.add_argument("--excel") - .help("Output in Excel format") - .default_value(false) - .implicit_value(true); + datasets_command.add_argument("--excel").help("Output in Excel format").default_value(false).implicit_value(true); // // results subparser // @@ -160,7 +179,9 @@ int main(int argc, char** argv) throw std::runtime_error("Model must be one of " + platform::Models::instance()->toString() + " or any"); } ); + results_command.add_argument("--excel").help("Output in Excel format").default_value(false).implicit_value(true); results_command.add_argument("-s", "--score").default_value("accuracy").help("Filter results of the score name supplied"); + // Add subparsers program.add_subparser(datasets_command); program.add_subparser(results_command); diff --git a/src/main/Result.h b/src/main/Result.h index 2756f7d..6d361cd 100644 --- a/src/main/Result.h +++ b/src/main/Result.h @@ -21,6 +21,7 @@ namespace platform { std::string to_string(int maxModel) const; std::string getFilename() const; std::string getDate() const { return data["date"].get(); }; + std::string getTime() const { return data["time"].get(); }; double getScore() const { return score; }; std::string getTitle() const { return data["title"].get(); }; double getDuration() const { return data["duration"]; }; diff --git a/src/reports/ExcelFile.cpp b/src/reports/ExcelFile.cpp index ec87ee9..41dcc55 100644 --- a/src/reports/ExcelFile.cpp +++ b/src/reports/ExcelFile.cpp @@ -84,6 +84,7 @@ namespace platform { void ExcelFile::createStyle(const std::string& name, lxw_format* style, bool odd) { addColor(style, odd); + auto color_bold = 0xFF0000; if (name == "textCentered") { format_set_align(style, LXW_ALIGN_CENTER); format_set_font_size(style, normalSize); @@ -94,6 +95,13 @@ namespace platform { format_set_border(style, LXW_BORDER_THIN); format_set_align(style, LXW_ALIGN_VERTICAL_CENTER); format_set_text_wrap(style); + } else if (name == "text_bold") { + format_set_font_size(style, normalSize); + format_set_border(style, LXW_BORDER_THIN); + format_set_align(style, LXW_ALIGN_VERTICAL_CENTER); + format_set_font_color(style, lxw_color_t(color_bold)); + format_set_bold(style); + format_set_text_wrap(style); } else if (name == "bodyHeader") { format_set_bold(style); format_set_font_size(style, normalSize); @@ -106,6 +114,13 @@ namespace platform { format_set_align(style, LXW_ALIGN_VERTICAL_CENTER); format_set_border(style, LXW_BORDER_THIN); format_set_num_format(style, "0.0000000"); + } else if (name == "result_bold") { + format_set_font_size(style, normalSize); + format_set_align(style, LXW_ALIGN_VERTICAL_CENTER); + format_set_border(style, LXW_BORDER_THIN); + format_set_bold(style); + format_set_font_color(style, lxw_color_t(color_bold)); + format_set_num_format(style, "0.0000000"); } else if (name == "time") { format_set_font_size(style, normalSize); format_set_border(style, LXW_BORDER_THIN); @@ -116,6 +131,13 @@ namespace platform { format_set_num_format(style, "###,##0"); format_set_align(style, LXW_ALIGN_VERTICAL_CENTER); format_set_border(style, LXW_BORDER_THIN); + } else if (name == "ints_bold") { + format_set_font_size(style, normalSize); + format_set_num_format(style, "###,##0"); + format_set_align(style, LXW_ALIGN_VERTICAL_CENTER); + format_set_bold(style); + format_set_font_color(style, lxw_color_t(color_bold)); + format_set_border(style, LXW_BORDER_THIN); } else if (name == "floats") { format_set_border(style, LXW_BORDER_THIN); format_set_align(style, LXW_ALIGN_VERTICAL_CENTER); @@ -131,7 +153,7 @@ namespace platform { void ExcelFile::createFormats() { - auto styleNames = { "text", "textCentered", "bodyHeader", "result", "time", "ints", "floats", "percentage" }; + auto styleNames = { "text", "text_bold", "textCentered", "bodyHeader", "result", "result_bold", "time", "ints", "ints_bold", "floats", "percentage" }; lxw_format* style; for (std::string name : styleNames) { lxw_format* style = workbook_add_format(workbook);