6 #ifndef VISUALIZATION_HPP
7 #define VISUALIZATION_HPP
13 #if __has_include(<filesystem>)
15 namespace fs = std::filesystem;
16 #elif __has_include(<experimental/filesystem>)
17 #include <experimental/filesystem>
18 namespace fs = std::experimental::filesystem;
20 error
"Missing the <filesystem> header."
22 #define PLOT_FOLDER "plottemp"
27 #include "ufjfmltk/visual/gnuplot_i.hpp"
38 template <
typename T =
double >
44 std::map<std::string, std::string> configs;
46 std::string plot_folder;
47 std::vector<std::string> plot_folders;
48 std::vector<std::string> temp_fnames;
49 bool is_shared, keep_temp_files;
50 static size_t n_plots;
56 using AxisRanges = std::array<AxisRange, 3>;
62 std::vector<std::string> createTempFiles(std::string plot_folder=
"");
69 bool valid_file(std::string file);
75 std::vector<std::string> getTempFilesNames(
bool append_path=
false);
80 void removeTempFiles();
82 void configurePlot(
const std::string& outname,
const std::string& format,
const std::string& title,
bool save=
false,
83 const std::string& x_label=
"",
const std::string& y_label=
"",
const std::string& z_label=
"");
85 AxisRanges configureRange(
double scale = 1.0,
int x = -1,
int y = -1,
int z = -1);
89 std::string prepareScript(std::string
cmd);
91 std::vector<std::string> sortLabels(std::vector<std::string>& files,
const std::string& type=
"scatter");
93 std::string fetchConfigs();
95 void create_plotfolder();
99 explicit Visualization (
bool shared_session=
true,
bool keep_temp_files=
false);
105 void setTerminal(
const std::string& terminal){ configs[
"terminal"] = terminal;}
125 std::string execute_command(
const std::string&
cmd,
bool fetch_configs=
true);
138 std::string
plot1DRegresion(
int x=0,
bool save=
false,
double scale = 1.0,
139 const std::string& title=
"",
140 const std::string& format=
"svg",
141 const std::string& x_label=
"x",
const std::string& y_label=
"y");
156 const std::string& title=
"",
157 const std::string& format=
"svg",
158 const std::string& x_label=
"x",
const std::string& y_label=
"y");
172 std::string
plot2D(
int x = 0,
int y=1,
bool save=
false,
double scale = 1.0,
173 const std::string& title=
"",
174 const std::string& format=
"svg",
175 const std::string& x_label=
"x",
const std::string& y_label=
"y");
178 const std::string& title=
"",
179 const std::string& format=
"svg",
180 const std::string& x_label=
"x",
const std::string& y_label=
"y");
196 const std::string& title=
"",
197 const std::string& format=
"svg",
198 const std::string& x_label=
"x",
const std::string& y_label=
"y");
213 std::string
plot2DRegresion(
int x=0,
int y=1,
bool save=
false,
double scale = 1.0,
214 const std::string& title=
"",
215 const std::string& format=
"svg",
216 const std::string& x_label=
"x",
const std::string& y_label=
"y",
217 const std::string& z_label=
"z");
234 const std::string& title=
"",
235 const std::string& format=
"svg",
236 const std::string& x_label=
"x",
const std::string& y_label=
"y",
237 const std::string& z_label=
"z");
253 std::string
plot3D(
int x=0,
int y=1,
int z=2,
bool save=
false,
double scale = 1.0,
254 const std::string& title=
"",
255 const std::string& format=
"svg",
256 const std::string& x_label=
"x",
const std::string& y_label=
"y",
const std::string& z_label=
"z");
259 const std::string& title=
"",
260 const std::string& format=
"svg",
261 const std::string& x_label=
"x",
const std::string& y_label=
"y",
const std::string& z_label=
"z");
278 const std::string& title=
"",
279 const std::string& format=
"svg",
280 const std::string& x_label=
"x",
const std::string& y_label=
"y",
281 const std::string& z_label=
"z");
300 template<
class Learner>
304 const std::string& title=
"",
305 const std::string& format=
"svg",
306 const std::string& x_label=
"x",
const std::string& y_label=
"y");
311 static void cmd(
const std::string& command);
323 is_shared(shared_session),
324 keep_temp_files(keep_temp_files) {
326 shared_session =
false;
328 configs[
"terminal"] =
"wxt";
329 if(shared_session) g =
new Gnuplot();
333 Visualization< T >::Visualization(
Data<T> &sample,
bool shared_session,
bool keep_temp_files):
334 is_shared(shared_session),
335 keep_temp_files(keep_temp_files) {
337 shared_session =
false;
340 configs[
"terminal"] =
"wxt";
341 if(shared_session) g =
new Gnuplot();
347 void Visualization<T>::create_plotfolder() {
349 this->plot_folder = PLOT_FOLDER+std::to_string(n_plots)+
"/";
350 if(std::find(plot_folders.begin(), plot_folders.end(), this->plot_folder) == plot_folders.end()) {
351 plot_folders.push_back(this->plot_folder);
354 }
while(fs::exists(this->plot_folder));
356 fs::create_directory(this->plot_folder);
358 catch (fs::filesystem_error
const& ex) {
360 <<
"what(): " << ex.what() <<
'\n'
361 <<
"path1(): " << ex.path1() <<
'\n'
362 <<
"path2(): " << ex.path2() <<
'\n'
363 <<
"code().value(): " << ex.code().value() <<
'\n'
364 <<
"code().message(): " << ex.code().message() <<
'\n'
365 <<
"code().category(): " << ex.code().category().name() <<
'\n';
371 configs[
"title"] = std::move(title);
376 configs[
"style"] = std::move(style);
381 size_t i, j, k, size = samples->size(), dim = samples->dim();
382 std::vector<std::string> file_names;
384 if(plot_folder.empty()) {
385 plot_folder = this->plot_folder;
388 if(samples->isClassification()) {
389 std::vector<std::string> class_names = samples->classesNames();
390 std::vector<int> classes = samples->classes();
391 std::vector<std::ofstream> temp_files(class_names.size());
393 for(i = 0; i < class_names.size(); i++){
394 std::string file_name = std::string(plot_folder)+class_names[i]+std::string(
".plt");
395 temp_files[i].open(file_name);
396 if(!temp_files[i].is_open()){
397 std::cerr <<
"Error opening the file " + file_name +
"." << std::endl;
399 file_names.push_back(file_name);
402 for (i = 0; i < size; i++) {
403 auto point = (*samples)(i);
404 auto class_pos = std::find(classes.begin(), classes.end(), point.Y()) - classes.begin();
405 auto class_name = class_names[class_pos];
407 for(
const auto& x: point) {
408 if(idx < point.size()-1) {
409 temp_files[class_pos] << x <<
" ";
411 temp_files[class_pos] << x << std::endl;
417 for(i = 0; i < temp_files.size(); i++){
418 temp_files[i].close();
421 std::ofstream samples_file(std::string(plot_folder) +
"samples.plt");
423 for (i = 0; i < size; i++) {
424 for (j = 0; j < dim; j++) {
425 samples_file << (double) (samples->point(i)->X()[j]) <<
" ";
427 samples_file << (double) (samples->point(i)->Y()) << std::endl;
430 samples_file.close();
431 std::string fname = (this->samples->name().empty())?
"samples.plt":this->samples->name()+
".plt";
432 file_names.emplace_back(std::string(plot_folder) + fname);
438 bool Visualization< T >::valid_file(std::string file){
443 if(file.empty() || file.size() < 4)
446 for(i = file.size()-1; i >= 0; i--){
447 if(file[i] ==
'.')
break;
448 std::string f(1, file[i]);
452 for(std::string type : types){
453 if(type == ext) flag =
true;
460 std::vector<std::string> Visualization< T >::getTempFilesNames(
bool append_path){
461 std::vector<std::string> files;
462 auto path = std::string(plot_folder);
468 dpdf = opendir(path.c_str());
470 while((epdf = readdir(dpdf))){
471 std::string file = std::string(epdf->d_name);
472 if(valid_file(file) && !file.empty()){
473 files.push_back((append_path)?(path+file):file);
477 std::cout <<
"Folder not found!" << std::endl;
483 WIN32_FIND_DATA data;
485 hFind = FindFirstFile((
".\\"+plot_folder+
"\\*.*").c_str(), &data);
486 if (hFind != INVALID_HANDLE_VALUE) {
488 std::string file_name(data.cFileName);
489 if(valid_file(file_name) && !file_name.empty()){
490 files.push_back((append_path) ? (path + file_name) : file_name);
492 }
while (FindNextFile(hFind, &data));
496 std::cerr <<
"Can't remove temporary files, please remove manually. (Unsupported System)." << std::endl;
503 void Visualization< T >::removeTempFiles(){
504 if(keep_temp_files) {
505 auto fname = this->plot_folder;
506 auto timestamp = mltk::utils::timestamp();
507 timestamp.erase(std::remove(timestamp.begin(), timestamp.end(),
':'));
508 fname.erase(std::remove(fname.begin(), fname.end(),
'/'), fname.end());
510 fs::rename(fname, fname +
"_saved_" + timestamp);
512 catch (fs::filesystem_error
const& ex) {
514 <<
"what(): " << ex.what() <<
'\n'
515 <<
"path1(): " << ex.path1() <<
'\n'
516 <<
"path2(): " << ex.path2() <<
'\n'
517 <<
"code().value(): " << ex.code().value() <<
'\n'
518 <<
"code().message(): " << ex.code().message() <<
'\n'
519 <<
"code().category(): " << ex.code().category().name() <<
'\n';
525 std::vector<std::string> temps;
527 temps = getTempFilesNames();
529 for(
const std::string& file : temps){
530 std::string _path = plot_folder + file;
531 if(fs::exists(_path)) fs::remove_all(_path);
533 if(fs::exists(plot_folder)) fs::remove_all(plot_folder);
534 if(!temp_fnames.empty()) {
535 for(
const auto& file: temp_fnames) {
536 if(fs::exists(file)) {
547 const std::string &x_label,
const std::string &y_label) {
548 std::string dims = utils::itos(x+1) +
":" + utils::itos(2);
549 std::string cmd(
"plot ");
550 std::vector<std::string> temp_files_names;
552 std::string out_name = (this->samples->name().empty())?
"2dplot_"+utils::itos(x)+
"_regression":
553 this->samples->name()+
"_2d_"+utils::itos(x)+
"_regression";
555 configureRange(scale, x);
556 configurePlot(out_name, format, title, save, x_label, y_label);
558 temp_files_names = getTempFilesNames(
true);
559 for(i = 0; i < temp_files_names.size() - 1; i++){
560 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" with points, ";
562 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" with points";
564 cmd = execute_command(cmd);
565 return prepareScript(cmd);
571 const std::string &format,
const std::string &x_label,
572 const std::string &y_label) {
573 std::string dims = utils::itos(x+1) +
":" + utils::itos(this->samples->dim()+1);
575 std::vector<std::string> temp_files_names;
577 std::string out_name = (this->samples->name().empty())?
"2dplot_"+utils::itos(x)+
"_regression":
578 this->samples->name()+
"_2d_"+utils::itos(x)+
"_regression";
580 configureRange(scale, x);
581 configurePlot(out_name, format, title, save, x_label, y_label);
583 fx =
"f(x) = " + utils::dtoa(s.
w[x]) +
"*x + " + utils::dtoa(s.
bias);
584 cmd = fx +
";" +
"plot ";
586 temp_files_names = getTempFilesNames(
true);
587 for(i = 0; i < temp_files_names.size() - 1; i++){
588 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" with points, ";
590 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" notitle with points, f(x) notitle with lines ls 1 lt rgb \"red\"";
591 cmd = fetchConfigs() + cmd;
593 cmd = execute_command(cmd);
594 return prepareScript(cmd);
599 const std::string& title,
600 const std::string& format,
601 const std::string& x_label,
const std::string& y_label){
602 std::string dims = utils::itos(x+1) +
":" + utils::itos(y+1);
603 std::string cmd(
"plot ");
604 std::vector<std::string> temp_files_names, class_names = samples->classesNames();
607 std::string out_name = (this->samples->name().empty())?
"2dplot_"+utils::itos(x)+
"_"+utils::itos(y):
608 this->samples->name()+
"_2d_"+utils::itos(x)+
"_"+utils::itos(y);
610 configureRange(scale, x, y);
611 configurePlot(out_name, format, title, save, x_label, y_label);
613 temp_files_names = getTempFilesNames(
true);
614 auto names = sortLabels(temp_files_names);
615 for(i = 0; i < temp_files_names.size() - 1; i++){
616 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" title \'" + names[i] +
"\' with points, ";
618 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" title \'" + names[i] +
"\' with points";
620 cmd = execute_command(cmd);
621 return prepareScript(cmd);
626 const std::string& title,
627 const std::string& format,
628 const std::string& x_label,
const std::string& y_label){
629 assert(x.
size() == y.
size() &&
"x and y must have the same size");
630 std::string cmd(
"plot ");
632 std::string out_name = (title.empty())?
"2dplot_":
"2dplot_"+title;
634 configureRange(scale, x, y);
635 configurePlot(out_name, format, title, save, x_label, y_label);
637 std::filesystem::path path{
"output" };
638 path /= out_name+
".dat";
639 std::filesystem::create_directories(path.parent_path());
641 std::ofstream ofs(path);
643 size_t size = x.
size();
645 for(
int i = 0; i < size; i++){
646 ofs << x[i] <<
" " << y[i] << std::endl;
651 cmd +=
"\'" + path.string() +
"\' using 1:2 with linespoints";
653 cmd = execute_command(cmd);
654 return prepareScript(cmd);
660 const std::string& title,
661 const std::string& format,
662 const std::string& x_label,
const std::string& y_label){
663 assert(samples->isClassification());
665 std::string feats = utils::itos(x+1) +
":" + utils::itos(y+1);
666 std::string fx, gx, hx, cmd;
667 std::vector<std::string> temp_files_names, class_names = samples->classesNames();
669 std::string out_name = (this->samples->name().empty())?
"2dplotsol_"+utils::itos(x)+
"_"+utils::itos(y):
670 this->samples->name()+
"_2dsol_"+utils::itos(x)+
"_"+utils::itos(y);
672 configureRange(scale, x, y);
673 configurePlot(out_name, format, title, save, x_label, y_label);
676 fx =
"f(x) = " + utils::dtoa(-s.
w[x]/s.
w[y]) +
"*x + " + utils::dtoa((s.
bias)/-s.
w[y]);
678 fx =
"f(x) = " + utils::dtoa(-s.
w[x]/s.
w[y]) +
"*x + " + utils::dtoa((s.
bias)/-s.
w[y]);
681 gx =
"g(x) = " + utils::dtoa(-s.
w[x]/s.
w[y]) +
"*x + " + utils::dtoa((s.
bias + s.
margin*s.
norm)/-s.
w[y]);
682 hx =
"h(x) = " + utils::dtoa(-s.
w[x]/s.
w[y]) +
"*x + " + utils::dtoa((s.
bias - s.
margin*s.
norm)/-s.
w[y]);
683 cmd = fx +
";"+ gx +
";"+ hx +
";plot ";
687 temp_files_names = getTempFilesNames(
true);
688 auto names = sortLabels(temp_files_names);
689 for(i = 0; i < class_names.size() - 1; i++){
690 cmd +=
"\'" + temp_files_names[i] +
"\' using " + feats +
" title \'" + names[i] +
"\' with points, ";
692 if(s.
margin != 0) cmd +=
"\'" + temp_files_names[i] +
"\' using " + feats +
" title \'" + names[i] +
"\' with points, f(x) notitle with lines ls 1, g(x) notitle with lines ls 2, h(x) notitle with lines ls 2";
693 else cmd +=
"\'" + temp_files_names[i] +
"\' using " + feats +
" title \'" + names[i] +
"\' with points, f(x) title \'h(x)\' with lines ls 2";
694 std::cout << cmd << std::endl;
696 cmd = execute_command(cmd);
697 return prepareScript(cmd);
703 const std::string &format,
const std::string &x_label,
704 const std::string &y_label,
const std::string &z_label) {
705 std::string dims = utils::itos(x+1) +
":" + utils::itos(y+1) +
":" + utils::itos(this->samples->dim()+1);
706 std::string fx, cmd(
"splot ");
707 std::vector<std::string> temp_files_names;
709 std::string out_name = (this->samples->name().empty())?
"2dplot_"+utils::itos(x)+
"_regression":
710 this->samples->name()+
"_2d_"+utils::itos(x)+
"_regression";
712 configureRange(scale, x);
713 configurePlot(out_name, format, title, save, x_label, y_label, z_label);
715 temp_files_names = getTempFilesNames(
true);
716 for(i = 0; i < temp_files_names.size() - 1; i++){
717 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" with points, ";
719 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" notitle with points";
720 cmd = execute_command(cmd);
721 return prepareScript(cmd);
726 const std::string &title,
const std::string &format,
727 const std::string &x_label,
const std::string &y_label,
728 const std::string &z_label) {
729 std::string dims = utils::itos(x+1) +
":" + utils::itos(y+1) +
":" + utils::itos(this->samples->dim()+1);
730 std::string fxy, cmd;
731 std::vector<std::string> temp_files_names;
733 std::string out_name = (this->samples->name().empty())?
"2dplot_"+utils::itos(x)+
"_regression":
734 this->samples->name()+
"_2d_"+utils::itos(x)+
"_regression";
736 configureRange(scale, x);
737 configurePlot(out_name, format, title, save, x_label, y_label, z_label);
739 fxy =
"f(x,y) = "+utils::dtoa(s.
w[x])+
"*x + "+utils::dtoa(s.
w[y])+
"*y + "+utils::dtoa(s.
bias);
740 cmd = fxy +
"; splot ";
742 temp_files_names = getTempFilesNames(
true);
743 for(i = 0; i < temp_files_names.size() - 1; i++){
744 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" with points, ";
746 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" notitle with points, f(x,y) notitle with lines ls 1 lt rgb \"red\"";
747 cmd = execute_command(cmd);
748 return prepareScript(cmd);
753 const std::string& title,
754 const std::string& format,
755 const std::string& x_label,
const std::string& y_label,
const std::string& z_label){
756 std::string dims = utils::itos(x+1) +
":" + utils::itos(y+1) +
":" + utils::itos(z+1);
757 std::string cmd(
"splot ");
758 std::vector<std::string> temp_files_names, class_names = samples->classesNames();
760 std::string out_name = (this->samples->name().empty())?
"3dplot_"+utils::itos(x)+
"_"+utils::itos(y)+
"_"+utils::itos(z):
761 this->samples->name()+
"_3d_"+utils::itos(x)+
"_"+utils::itos(y)+
"_"+utils::itos(z);
763 configureRange(scale, x, y, z);
764 configurePlot(out_name, format, title, save, x_label, y_label, z_label);
766 temp_files_names = getTempFilesNames(
true);
767 auto names = sortLabels(temp_files_names);
768 for(i = 0; i < class_names.size() - 1; i++){
769 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" title \'" + names[i] +
"\' with points, ";
771 cmd +=
"\'" + temp_files_names[i] +
"\' using " + dims +
" title \'" + names[i] +
"\' with points";
772 cmd = execute_command(cmd);
773 return prepareScript(cmd);
778 const std::string& title,
779 const std::string& format,
780 const std::string& x_label,
const std::string& y_label,
const std::string& z_label){
781 assert(x.
size() == y.
size() && y.
size() == z.
size() &&
"x and y must have the same size");
782 std::string cmd(
"splot ");
784 std::string out_name = (title.empty())?
"3dplot_":
"3dplot_"+title;
786 configureRange(scale, x, y);
787 configurePlot(out_name, format, title, save, x_label, y_label);
789 std::filesystem::path path{
"output" };
790 path /= out_name+
".dat";
791 std::filesystem::create_directories(path.parent_path());
793 std::ofstream ofs(path);
795 size_t size = x.
size();
797 for(
int i = 0; i < size; i++){
798 ofs << x[i] <<
" " << y[i] <<
" " << z[i] << std::endl;
803 cmd +=
"\'" + path.string() +
"\' using 1:2:3 with points";
805 cmd = execute_command(cmd);
806 return prepareScript(cmd);
811 const std::string& title,
812 const std::string& format,
813 const std::string& x_label,
const std::string& y_label,
814 const std::string& z_label){
815 assert(samples->isClassification());
816 std::string feats = utils::itos(x+1) +
":" + utils::itos(y+1) +
":" + utils::itos(z+1);
817 std::string fxy, gxy, hxy, cmd;
818 std::vector<std::string> temp_files_names, class_names = samples->classesNames();
820 std::string out_name = (this->samples->name().empty())?
"3dplotsol_"+utils::itos(x)+
"_"+utils::itos(y)+
"_"+utils::itos(z):
821 this->samples->name()+
"_3dsol_"+utils::itos(x)+
"_"+utils::itos(y)+
"_"+utils::itos(z);
823 configureRange(scale, x, y, z);
824 configurePlot(out_name, format, title, save, x_label, y_label, z_label);
826 gxy =
"g(x,y) = "+utils::dtoa(-s.
w[x]/s.
w[z])+
"*x + "+utils::dtoa(-s.
w[y]/s.
w[z])+
"*y + "+utils::dtoa((s.
bias + s.
margin * s.
norm)/-s.
w[z]);
827 fxy =
"f(x,y) = "+utils::dtoa(-s.
w[x]/s.
w[z])+
"*x + "+utils::dtoa(-s.
w[y]/s.
w[z])+
"*y + "+utils::dtoa(s.
bias/-s.
w[z]);
828 hxy =
"h(x,y) = "+utils::dtoa(-s.
w[x]/s.
w[z])+
"*x + "+utils::dtoa(-s.
w[y]/s.
w[z])+
"*y + "+utils::dtoa((s.
bias - s.
margin * s.
norm)/-s.
w[z]);
829 cmd = gxy +
";" + fxy +
";" + hxy +
"; splot ";
831 temp_files_names = getTempFilesNames(
true);
832 auto names = sortLabels(temp_files_names);
833 for(i = 0; i < class_names.size() - 1; i++){
834 cmd +=
"\'" + temp_files_names[i] +
"\' using " + feats +
" title \'" + names[i] +
"\' with points, ";
836 cmd +=
"\'" + temp_files_names[i] +
"\' using " + feats +
" title \'" + names[i] +
"\' with points, ";
837 cmd +=
"g(x,y) notitle with lines ls 1 lt rgb \"red\",";
838 cmd +=
"f(x,y) notitle with lines ls 1,";
839 cmd +=
"h(x,y) notitle with lines ls 1 lt rgb \"red\";";
840 execute_command(cmd);
841 return prepareScript(cmd);
845 template<
class Learner>
847 bool save,
const double scale,
const std::string& title,
const std::string& format,
848 const std::string& x_label,
const std::string& y_label){
849 assert(samples->isClassification());
850 configurePlot(
"contour_"+this->samples->name()+
"_"+mltk::utils::timestamp(), format, title, save,
852 AxisRanges axis_ranges = configureRange(scale, x, y);
854 mltk::Point xx = mltk::linspace(axis_ranges[0].
min, axis_ranges[0].
max, grid_dim);
855 mltk::Point yy = mltk::linspace(axis_ranges[1].
min, axis_ranges[1].
max, grid_dim);
857 auto data_copy = this->samples->selectFeatures({size_t(x+1), size_t(y+1)});
858 auto timestamp = mltk::utils::timestamp();
859 timestamp.erase(std::remove(timestamp.begin(), timestamp.end(),
':'), timestamp.end());
862 if(!is_trained) learner.
train();
864 std::string data_fname = this->plot_folder+data_copy.name()+
"_"+ timestamp +
".dat";
865 std::ofstream data_file(data_fname);
866 if(!data_file.is_open()){
867 std::cerr <<
"Error opening file (" << data_fname <<
")" << std::endl;
870 for(
int i = 0; i < grid.
size(); i++){
872 for(j = 0; j < grid.
dim(); j++){
874 data_file << xx[i] <<
" " << yy[j] <<
" " << std::to_string(grid(i)[j]) << std::endl;
876 data_file << std::endl;
880 std::string dims = utils::itos(1) +
":" + utils::itos(2)+
":(0)";
881 std::string scatter_cmd;
882 std::vector<std::string> temp_files_names, class_names = this->samples->classesNames();
883 std::vector<std::ofstream> classes_files(classes.
size());
885 for(
int i = 0; i < classes_files.size(); i++){
886 std::string fname = this->plot_folder+class_names[i]+
"_data"+ timestamp +
".dat";
887 classes_files[i].open(fname);
888 if (!classes_files[i].is_open()) {
889 std::cerr <<
"Error opening file (" << fname <<
")" << std::endl;
892 temp_files_names.push_back(fname);
895 for(
int i = 0; i < data_copy.size(); i++){
896 auto class_pos = std::find(classes.begin(), classes.end(), data_copy(i).Y()) - classes.begin();
897 classes_files[class_pos] << data_copy(i)[0] <<
" " << data_copy(i)[1] <<
" " << data_copy(i).Y() << std::endl;
899 for(
auto & classes_file : classes_files){
900 classes_file.close();
902 auto names = sortLabels(temp_files_names,
"decision");
903 for(
int i = 0; i < temp_files_names.size(); i++){
904 if(i < classes_files.size()-1) {
905 scatter_cmd +=
"'" + temp_files_names[i] +
"' title '"+ names[i] +
"' with points,";
907 scatter_cmd +=
"'" + temp_files_names[i] +
"' title '"+ names[i] +
"' with points;";
912 cmd += fetchConfigs();
913 cmd +=
"set pm3d map;";
914 cmd +=
"set pm3d interpolate 0,0;";
915 cmd +=
"set cbrange [" + std::to_string(
mltk::min(classes)) +
":" + std::to_string(
mltk::max(classes)) +
"];";
916 cmd +=
"set cbtics 1;";
917 cmd +=
"set palette rgbformulae 22,13,10;";
918 cmd +=
"splot '"+data_fname+
"', " + scatter_cmd;
919 temp_files_names.push_back(data_fname);
920 cmd = execute_command(cmd,
false);
921 temp_fnames.insert(temp_fnames.begin(), temp_files_names.begin(), temp_files_names.end());
922 return prepareScript(cmd);
927 this->samples = &sample;
928 if(fs::exists(plot_folder)) {
938 auto class_names = samples->classesNames();
939 std::vector<std::string> names(files.size());
940 std::transform(files.begin(), files.end(), names.begin(), [type](std::string& path){
941 if(type ==
"decision") {
942 auto res = mltk::utils::tokenize(mltk::utils::tokenize(path,
'_')[0],
'/');
943 return mltk::utils::tokenize(mltk::utils::tokenize(path,
'_')[0],
'/')[1];
945 return mltk::utils::tokenize(mltk::utils::tokenize(path,
'.')[0],
'/')[1];
948 std::sort(names.begin(), names.end(),[&class_names, &classes](
const auto& a,
const auto& b){
949 auto aclass_pos = std::find(class_names.begin(), class_names.end(), a) - class_names.begin();
950 auto bclass_pos = std::find(class_names.begin(), class_names.end(), b) - class_names.begin();
951 return classes[aclass_pos] < classes[bclass_pos];
953 std::sort(files.begin(), files.end(), [&class_names, &classes, &type](
const auto& a,
const auto& b){
954 if(type ==
"decision") {
955 auto aclass_pos = std::find(class_names.begin(), class_names.end(),
956 mltk::utils::tokenize(mltk::utils::tokenize(a,
'_')[0],
'/')[1]) - class_names.begin();
957 auto bclass_pos = std::find(class_names.begin(), class_names.end(),
958 mltk::utils::tokenize(mltk::utils::tokenize(b,
'_')[0],
'/')[1]) - class_names.begin();
959 return classes[aclass_pos] < classes[bclass_pos];
961 auto aclass_pos = std::find(class_names.begin(), class_names.end(),
962 mltk::utils::tokenize(mltk::utils::tokenize(a,
'.')[0],
'/')[1]) - class_names.begin();
963 auto bclass_pos = std::find(class_names.begin(), class_names.end(),
964 mltk::utils::tokenize(mltk::utils::tokenize(b,
'.')[0],
'/')[1]) - class_names.begin();
965 return classes[aclass_pos] < classes[bclass_pos];
973 Visualization<T>::configurePlot(
const std::string &outname,
const std::string &format,
const std::string &title,
bool save,
974 const std::string& x_label,
const std::string& y_label,
const std::string& z_label) {
975 configs[
"save"] = (save)?
"true":
"false";
976 configs[
"output_name"] = outname;
977 configs[
"output_format"] = format;
978 configs[
"title"] = (title.empty())?
"":title;
979 configs[
"x_label"] = (x_label.empty())?
"":x_label;
980 configs[
"y_label"] = (y_label.empty())?
"":y_label;
981 configs[
"z_label"] = (z_label.empty())?
"":z_label;
985 std::string Visualization<T>::fetchConfigs() {
987 if(configs[
"save"] ==
"true") {
988 confs += std::string(
"set terminal ") + configs[
"output_format"]+
"; ";
989 confs += std::string(
"set output '") + configs[
"output_name"] +
"." + configs[
"output_format"]+
"'; ";
990 }
else if(!configs[
"terminal"].empty()){
991 confs += std::string(
"set terminal ") + configs[
"terminal"]+
";";
993 confs += std::string(
"set terminal x11;");
995 if(!configs[
"title"].empty()) {
996 confs += std::string(
"set title '") + configs[
"title"] +
"';";
998 if(!configs[
"xrange"].empty()) {
999 confs +=
"set xrange " + configs[
"xrange"] +
";";
1000 configs[
"xrange"].clear();
1002 if(!configs[
"yrange"].empty()) {
1003 confs +=
"set yrange " + configs[
"yrange"] +
";";
1004 configs[
"yrange"].clear();
1006 if(!configs[
"zrange"].empty()) {
1007 confs +=
"set zrange " + configs[
"zrange"] +
";";
1008 configs[
"zrange"].clear();
1010 if(!configs[
"x_label"].empty()) {
1011 confs += std::string(
"set xlabel '") + configs[
"x_label"] +
"';";
1013 if(!configs[
"y_label"].empty()) {
1014 confs += std::string(
"set ylabel '") + configs[
"y_label"] +
"';";
1016 if(!configs[
"z_label"].empty()) {
1017 confs += std::string(
"set zlabel '") + configs[
"z_label"] +
"';";
1022 template<
typename T>
1023 Visualization< T >::~Visualization(){
1024 this->samples =
nullptr;
1028 for(
auto& pfolder: plot_folders) {
1030 if (fs::exists(pfolder)) {
1031 fs::remove_all(pfolder);
1034 catch (fs::filesystem_error
const& ex) {
1036 <<
"what(): " << ex.what() <<
'\n'
1037 <<
"path1(): " << ex.path1() <<
'\n'
1038 <<
"path2(): " << ex.path2() <<
'\n'
1039 <<
"code().value(): " << ex.code().value() <<
'\n'
1040 <<
"code().message(): " << ex.code().message() <<
'\n'
1041 <<
"code().category(): " << ex.code().category().name() <<
'\n';
1044 plot_folders.clear();
1047 template<
typename T>
1054 template<
typename T>
1056 const int y,
const int z) {
1057 AxisRanges axis_ranges;
1059 auto _x = this->samples->getFeature(x);
1061 x_min += (x_min > 0)?(1.0-scale)*x_min:-(1.0-scale)*x_min;
1062 axis_ranges[0].min = std::round(x_min);
1063 axis_ranges[0].max = std::round(x_max);
1064 configs[
"xrange"] =
"[" + std::to_string(axis_ranges[0].
min) +
":" + std::to_string(axis_ranges[0].
max) +
"]";
1067 auto _y = this->samples->getFeature(y);
1069 y_min += (y_min > 0)?(1.0-scale)*y_min:-(1.0-scale)*y_min;
1070 axis_ranges[1].min = std::round(y_min);
1071 axis_ranges[1].max = std::round(y_max);
1072 configs[
"yrange"] =
"[" + std::to_string(axis_ranges[1].
min) +
":" + std::to_string(axis_ranges[1].
max) +
"]";
1075 auto _z = this->samples->getFeature(z);
1077 z_min += (z_min > 0)?(1.0-scale)*z_min:-(1.0-scale)*z_min;
1078 axis_ranges[2].min = std::round(z_min);
1079 axis_ranges[2].max = std::round(z_max);
1080 configs[
"zrange"] =
"[" + std::to_string(axis_ranges[2].
min) +
":" + std::to_string(axis_ranges[2].
max) +
"]";
1085 template<
typename T>
1086 typename Visualization<T>::AxisRanges Visualization<T>::configureRange(
const double scale,
const mltk::Point<double> x,
1088 AxisRanges axis_ranges;
1092 x_min += (x_min > 0)?(1.0-scale)*x_min:-(1.0-scale)*x_min;
1093 axis_ranges[0].min = std::round(x_min);
1094 axis_ranges[0].max = std::round(x_max);
1095 if(axis_ranges[0].
min != axis_ranges[0].
max) configs[
"xrange"] =
"[" + std::to_string(axis_ranges[0].
min) +
":" + std::to_string(axis_ranges[0].
max) +
"]";
1100 y_min += (y_min > 0)?(1.0-scale)*y_min:-(1.0-scale)*y_min;
1101 axis_ranges[1].min = std::round(y_min);
1102 axis_ranges[1].max = std::round(y_max);
1103 if(axis_ranges[1].
min != axis_ranges[1].
max) configs[
"yrange"] =
"[" + std::to_string(axis_ranges[1].
min) +
":" + std::to_string(axis_ranges[1].
max) +
"]";
1108 z_min += (z_min > 0)?(1.0-scale)*z_min:-(1.0-scale)*z_min;
1109 axis_ranges[2].min = std::round(z_min);
1110 axis_ranges[2].max = std::round(z_max);
1111 if(axis_ranges[2].
min != axis_ranges[2].
max) configs[
"zrange"] =
"[" + std::to_string(axis_ranges[2].
min) +
":" + std::to_string(axis_ranges[2].
max) +
"]";
1116 template<
typename T>
1117 std::string Visualization<T>::prepareScript(std::string cmd) {
1118 std::replace(cmd.begin(), cmd.end(),
';',
'\n');
1122 template<
typename T>
1123 std::string Visualization<T>::execute_command(
const std::string& _cmd,
bool fetch_configs) {
1124 auto cmd = (fetch_configs)?fetchConfigs() + _cmd:_cmd;
1133 cmd =
"set terminal windows; " + cmd;
1134 cmd =
"echo " + cmd +
" | gnuplot -persist";
1135 system(cmd.c_str());
Definition: gnuplot_i.hpp:70
Gnuplot & cmd(const std::string &cmdstr)
send a command to gnuplot
Definition: gnuplot_i.cpp:891
size_t size() const
Returns the size of the dataset.
Definition: Data.hpp:208
size_t dim() const
Returns the dimension of the dataset.
Definition: Data.hpp:213
Definition: Learner.hpp:18
virtual void setSamples(const Data< T > &data)
setSamples Set the samples used by the Learner.
Definition: Learner.hpp:150
virtual bool train()=0
Function that execute the training phase of a Learner.
virtual double evaluate(const Point< T > &p, bool raw_value=false)=0
Returns the class of a feature point based on the trained Learner.
std::size_t size() const
Returns the dimension of the point.
Definition: Point.hpp:133
Definition: Solution.hpp:13
double bias
Bias of the solution.
Definition: Solution.hpp:23
double norm
Norm of the solution.
Definition: Solution.hpp:29
mltk::Point< double > w
Weights vector.
Definition: Solution.hpp:17
double margin
Margin generated from the classifier that generated the solution.
Definition: Solution.hpp:27
Class for data visualization.
Definition: Visualization.hpp:39
std::string plot2DwithHyperplane(int x, int y, Solution w, bool save=false, double scale=1.0, const std::string &title="", const std::string &format="svg", const std::string &x_label="x", const std::string &y_label="y")
Plot the data in 2D with the hyperplane in solution generated by a classifier.
Definition: Visualization.hpp:659
std::string plot3D(int x=0, int y=1, int z=2, bool save=false, double scale=1.0, const std::string &title="", const std::string &format="svg", const std::string &x_label="x", const std::string &y_label="y", const std::string &z_label="z")
Plot the selected features in 3D.
Definition: Visualization.hpp:752
void setStyle(std::string style)
Set plot style. (points, lines, etc.)
Definition: Visualization.hpp:375
std::string plot2D(int x=0, int y=1, bool save=false, double scale=1.0, const std::string &title="", const std::string &format="svg", const std::string &x_label="x", const std::string &y_label="y")
Plot the selected features in 2D.
Definition: Visualization.hpp:598
static void cmd(const std::string &command)
Execute a script on gnuplot.
Definition: Visualization.hpp:1048
std::string plot1DRegresion(int x=0, bool save=false, double scale=1.0, const std::string &title="", const std::string &format="svg", const std::string &x_label="x", const std::string &y_label="y")
Plot the data as a regression dataset with points values in the y-axis.
Definition: Visualization.hpp:546
std::string plotDecisionSurface2D(Learner &learner, int x=0, int y=1, bool is_trained=true, size_t grid_dim=50, bool save=false, double scale=1.0, const std::string &title="", const std::string &format="svg", const std::string &x_label="x", const std::string &y_label="y")
Plot the decision boundary of a classifier with the data points above it.
Definition: Visualization.hpp:846
std::string plot3DwithHyperplane(int x, int y, int z, Solution w, bool save=false, double scale=1.0, const std::string &title="", const std::string &format="svg", const std::string &x_label="x", const std::string &y_label="y", const std::string &z_label="z")
Plot the data in 2D with separated by the hyperplane in the solution.
Definition: Visualization.hpp:810
std::string plot2DRegresion(int x=0, int y=1, bool save=false, double scale=1.0, const std::string &title="", const std::string &format="svg", const std::string &x_label="x", const std::string &y_label="y", const std::string &z_label="z")
Plot the data as a regression dataset with points values in the z-axis.
Definition: Visualization.hpp:702
void setSample(Data< T > &sample)
Set sample to be visualized.
Definition: Visualization.hpp:926
std::string plot2DRegresionHyperplane(int x, int y, Solution s, bool save=false, double scale=1.0, const std::string &title="", const std::string &format="svg", const std::string &x_label="x", const std::string &y_label="y", const std::string &z_label="z")
Plot the data as a regression dataset with points values in the z-axis alongside with a regressor sol...
Definition: Visualization.hpp:725
std::string plot1DRegresionHyperplane(int x, Solution s, bool save=false, double scale=1.0, const std::string &title="", const std::string &format="svg", const std::string &x_label="x", const std::string &y_label="y")
Plot the data as a regression dataset with points values in the y-axis alongside with a regressor sol...
Definition: Visualization.hpp:570
void setTitle(std::string title)
Set plot title.
Definition: Visualization.hpp:370
Namespace for data visualization methods.
Definition: Visualization.hpp:34
T min(const Point< T, R > &p)
Returns the min value of the point.
Definition: Point.hpp:557
T max(const Point< T, R > &p)
Returns the max value of the point.
Definition: Point.hpp:544