- Integrated the file import into the main interface (not as a plugin anymore)
[mldemos:mldemos.git] / Core / dataImporter.cpp
1 /*********************************************************************\r
2 MLDemos: A User-Friendly visualization toolkit for machine learning\r
3 Copyright (C) 2011 Chrstophe Paccolat\r
4 Contact: mldemos@b4silio.com\r
5 \r
6 This library is free software; you can redistribute it and/or\r
7 modify it under the terms of the GNU Lesser General Public License,\r
8 version 3 as published by the Free Software Foundation.\r
9 \r
10 This library is distributed in the hope that it will be useful, but\r
11 WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
13 Lesser General Public License for more details.\r
14 \r
15 You should have received a copy of the GNU Lesser General Public\r
16 License along with this library; if not, write to the Free\r
17 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
18 *********************************************************************/\r
19 \r
20 #include "dataImporter.h"\r
21 #include "ui_dataImport.h"\r
22 \r
23 DataImporter::DataImporter()\r
24     : guiDialog(0), gui(0), inputParser(0)\r
25 {\r
26 }\r
27 \r
28 DataImporter::~DataImporter()\r
29 {\r
30     if(gui && guiDialog) guiDialog->hide();\r
31     DEL(inputParser);\r
32 }\r
33 \r
34 void DataImporter::Start()\r
35 {\r
36     if(!gui)\r
37     {\r
38         gui = new Ui::DataImporterDialog();\r
39         gui->setupUi(guiDialog = new QDialog());\r
40         guiDialog->setWindowTitle("CVS Import");\r
41         connect(gui->closeButton, SIGNAL(clicked()), this, SLOT(Closing()));\r
42         connect(guiDialog, SIGNAL(finished(int)), this, SLOT(Closing()));\r
43         connect(gui->classColumnSpin, SIGNAL(valueChanged(int)), this, SLOT(classColumnChanged(int)));\r
44         connect(gui->headerCheck, SIGNAL(clicked()), this, SLOT(headerChanged()));\r
45         connect(gui->loadFile, SIGNAL(clicked()), this, SLOT(LoadFile())); // file loader\r
46         connect(gui->dumpButton, SIGNAL(clicked()),this,SLOT(SendData()));\r
47         connect(gui->classIgnoreCheck, SIGNAL(clicked()), this, SLOT(classIgnoreChanged()));\r
48         guiDialog->show();\r
49     }\r
50     else guiDialog->show();\r
51     if(!inputParser) inputParser = new CSVParser();\r
52 }\r
53 \r
54 void DataImporter::Stop()\r
55 {\r
56     guiDialog->hide();\r
57 }\r
58 \r
59 void DataImporter::Closing()\r
60 {\r
61     guiDialog->hide();\r
62     emit(Done(this));\r
63 }\r
64 \r
65 bool DataImporter::saveFile(const QString &filename, QIODevice *data)\r
66 {\r
67     QFile file(filename);\r
68     if (!file.open(QIODevice::WriteOnly)) {\r
69         qDebug() << "Could not open " << qPrintable(filename) << " for writing: " << qPrintable(file.errorString());\r
70         return false;\r
71     }\r
72 \r
73     file.write(data->readAll());\r
74     file.close();\r
75 \r
76     return true;\r
77 }\r
78 \r
79 void DataImporter::LoadFile()\r
80 {\r
81         QString filename = QFileDialog::getOpenFileName(NULL, tr("Load Data"), QDir::currentPath(), tr("dataset files (*.data *.csv);;All files (*.*)"));\r
82     if(filename.isEmpty()) return;\r
83     Parse(filename);\r
84 }\r
85 \r
86 void DataImporter::Parse(QString filename)\r
87 {\r
88     if(filename.isEmpty()) return;\r
89     headers.clear();\r
90     inputParser->clear();\r
91     inputParser->parse(filename.toStdString().c_str());\r
92     vector<vector<string> > rawData = inputParser->getRawData();\r
93     if(rawData.size() < 2) return;\r
94     bool bUseHeader = gui->headerCheck->isChecked();\r
95 \r
96     gui->tableWidget->clear();\r
97     gui->tableWidget->setRowCount(rawData.size());\r
98     gui->tableWidget->setColumnCount(rawData[0].size());\r
99     if(bUseHeader)\r
100     {\r
101         QStringList headerLabels;\r
102         FOR(i, rawData[0].size())\r
103         {\r
104             headers << rawData[0][i].c_str();\r
105             headerLabels <<  QString("%1:").arg(i+1) + rawData[0][i].c_str();\r
106         }\r
107         gui->tableWidget->setHorizontalHeaderLabels(headerLabels);\r
108     }\r
109     for(size_t r = 0; r < rawData.size(); r++)\r
110     {\r
111         if(!r && bUseHeader) continue;\r
112         for(size_t c = 0; c < rawData[r].size(); c++)\r
113         {\r
114             QTableWidgetItem *newItem = new  QTableWidgetItem(QString(rawData[r][c].c_str()));\r
115             gui->tableWidget->setItem(r-bUseHeader, c, newItem);\r
116         }\r
117     }\r
118     gui->classColumnSpin->setRange(1,rawData[0].size());\r
119 }\r
120 \r
121 void DataImporter::FetchResults(std::vector<fvec> results)\r
122 {\r
123 \r
124 }\r
125 \r
126 void DataImporter::classIgnoreChanged()\r
127 {\r
128     classColumnChanged(0);\r
129 }\r
130 \r
131 void DataImporter::headerChanged()\r
132 {\r
133     headers.clear();\r
134     vector<vector<string> > rawData = inputParser->getRawData();\r
135     if(rawData.size() < 2) return;\r
136     bool bUseHeader = gui->headerCheck->isChecked();\r
137 \r
138     gui->tableWidget->clear();\r
139     gui->tableWidget->setRowCount(rawData.size());\r
140     gui->tableWidget->setColumnCount(rawData[0].size());\r
141     if(bUseHeader)\r
142     {\r
143         QStringList headerLabels;\r
144         FOR(i, rawData[0].size())\r
145         {\r
146             headers << rawData[0][i].c_str();\r
147             headerLabels <<  QString("%1:").arg(i+1) + rawData[0][i].c_str();\r
148         }\r
149         gui->tableWidget->setHorizontalHeaderLabels(headerLabels);\r
150     }\r
151     for(size_t r = 0; r < rawData.size(); r++)\r
152     {\r
153         if(!r && bUseHeader) continue;\r
154         for(size_t c = 0; c < rawData[r].size(); c++)\r
155         {\r
156             QTableWidgetItem *newItem = new  QTableWidgetItem(QString(rawData[r][c].c_str()));\r
157             gui->tableWidget->setItem(r-bUseHeader, c, newItem);\r
158         }\r
159     }\r
160     gui->classColumnSpin->setRange(1,rawData[0].size());\r
161 }\r
162 \r
163 void DataImporter::classColumnChanged(int value)\r
164 {\r
165     if(gui->classIgnoreCheck->isChecked())\r
166     {\r
167         inputParser->setOutputColumn(-1);\r
168     }\r
169     else  inputParser->setOutputColumn(value-1);\r
170 }\r
171 \r
172 void DataImporter::SendData()\r
173 {\r
174     ivec excludeIndices;\r
175     vector<bool> bExcluded(gui->tableWidget->columnCount(), false);\r
176     QModelIndexList indexes = gui->tableWidget->selectionModel()->selection().indexes();\r
177     FOR(i, indexes.count())\r
178     {\r
179         QModelIndex index = indexes.at(i);\r
180         bExcluded[index.column()] = true;\r
181     }\r
182     FOR(i, bExcluded.size())\r
183     {\r
184         if(bExcluded[i]) excludeIndices.push_back(i);\r
185     }\r
186     inputParser->setFirstRowAsHeader(gui->headerCheck->isChecked());\r
187         pair<vector<fvec>,ivec> data = inputParser->getData(excludeIndices, 1000);\r
188     emit(SetData(data.first, data.second, vector<ipair>(), false));\r
189     emit(SetDimensionNames(headers));\r
190 }\r