Feature Selection Toolbox FST4
UTIA · Czech Academy of Sciences
Loading...
Searching...
No Matches
data_file_TRN.hpp
Go to the documentation of this file.
1#ifndef FSTDATAFILETRN_H
2#define FSTDATAFILETRN_H
3 /*
30=========================================================================
31Copyright and license:
32 * FST4 software (with the exception of any bundled or externally linked
33 third-party components) is Copyright (C) 2000-present Institute of
34 Information Theory and Automation of the Czech Academy of Sciences (UTIA).
35 * FST4 is free software: you can redistribute it and/or modify it under
36 the terms of the GNU Affero General Public License as published by the
37 Free Software Foundation, version 3. The full text of the license is in
38 the file LICENSE in the distribution root and at
39 https://www.gnu.org/licenses/agpl-3.0.html.
40 * FST4 is distributed in the hope that it will be useful, but WITHOUT ANY
41 WARRANTY; without even the implied warranty of MERCHANTABILITY or
42 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
43 License for more details.
44 * Closed-source use without the AGPL's copyleft obligations requires a
45 commercial license from UTIA; in case of interest write to
46 utia@utia.cas.cz. LICENSING.md in the distribution root explains both
47 options, the contributor license agreement that every contribution
48 requires, and the contacts (technical questions and pull requests:
49 somol@utia.cas.cz, with "FST" in the subject line).
50========================================================================== */
51
52#include <memory>
53#include <iostream>
54#include <vector>
55#include <cstdio>
56#include <cstring>
57#include "error.hpp"
58#include "global.hpp"
59
60/*============== Template parameter type naming conventions ==============
61--------- Numeric types: -------------------------------------------------
62DATATYPE - data sample values - usually real numbers (but may be integers
63 in text processing etc.)
64REALTYPE - must be real numbers - for representing intermediate results of
65 calculations like mean, covariance etc.
66IDXTYPE - index values for enumeration of data samples - (nonnegative) integers,
67 extent depends on numbers of samples in data
68DIMTYPE - index values for enumeration of features (dimensions), or classes (not
69 class sizes) - (nonnegative) integers, usually lower extent than IDXTYPE,
70 but be aware of expressions like _classes*_features*_features !
71 in linearized representations of feature matrices for all classes
72BINTYPE - feature selection marker type - represents ca. <10 different feature
73 states (selected, deselected, sel./desel. temporarily 1st nested loop, 2nd...)
74RETURNTYPE - criterion value: real value, but may be extended in future to support
75 multiple values
76--------- Class types: ---------------------------------------------------
77SUBSET - class of class type Subset
78CLASSIFIER - class implementing interface defined in abstract class Classifier
79EVALUATOR - class implementing interface defined in abstract class Sequential_Step
80DISTANCE - class implementing interface defined in abstract class Distance
81DATAACCESSOR - class implementing interface defined in abstract class Data_Accessor
82INTERVALCONTAINER - class of class type Data_Intervaller
83CONTAINER - STL container of class type Data_Interval
84========================================================================== */
85
86namespace FST {
87
135template<typename DATATYPE, typename IDXTYPE>
136class Data_File_TRN {
137public:
138 Data_File_TRN() {_filename=""; _title=""; _no_of_features=0; _no_of_classes=0; _valid=false; _file=nullptr;}
139 ~Data_File_TRN() {close();}
140 void open(const std::string& filename);
141 void close() {if(_file!=nullptr) {fclose(_file); _file=nullptr;}}
142 const unsigned int getNoOfFeatures() const {return _no_of_features;}
143 const unsigned int getNoOfClasses() const {return _no_of_classes;}
144 const IDXTYPE getClassSize(const unsigned int cidx) const {if(cidx<_no_of_classes) return _class_sizes[cidx]; else return 0;}
146 bool read_val(DATATYPE& target); // does not throw
148 DATATYPE read_val();// throws
149private:
150 Data_File_TRN(const Data_File_TRN&);
151protected:
163 void GetFileParams();
164 std::string _filename;
165 std::string _title;
166 unsigned int _no_of_features;
167 unsigned int _no_of_classes;
168 std::vector<IDXTYPE> _class_sizes;
169 IDXTYPE _datastart;
170 int _valid;
171 FILE *_file;
172};
173
174template<typename DATATYPE, typename IDXTYPE>
175void Data_File_TRN<DATATYPE,IDXTYPE>::open(const std::string& filename)
176{
177 _filename=filename;
178 _class_sizes.clear();
181}
182
183template<typename DATATYPE, typename IDXTYPE>
185{
186 const unsigned int ONUMCOM=5; // max no. of header keywords
187 const unsigned int OHEADSTRLEN=1000; // max header line size
188 const unsigned int OFILENAMELENGTH=500;
189 const std::string ONOTITLE="no title";
190 const char *command[ONUMCOM]={"#datafile",
191 "#title",
192 "#features",
193 "#classes",
194 "#data"};
195 char s[OHEADSTRLEN]; /* each header line is read into this */
196 char word[OHEADSTRLEN];/* the first word of that line is copied here */
197 char *s2; /* points at the start of the header keyword, if present */
198 char *s3; /* points at the data following the keyword */
199 int empty=0; /* empty file? (convention inherited from Optima) - FALSE */
200 int header_done=0; /* whole-header-read indicator */
201 unsigned int i;
202 int scanned;
203 /* Keyword bookkeeping. Each keyword of command[] owns one bit, in table order:
204 1 = #datafile, 2 = #title, 4 = #features, 8 = #classes, 16 = #data.
205 "seen" is the running OR of the keywords seen so far, so (seen&1) reads as "#datafile has
206 been seen", (seen&4) as "#features has been seen", and so on; a keyword whose bit is already
207 set in seen is a duplicate. "keyword" holds the bit of the keyword found on the current line,
208 or 0 when the line is not a keyword at all -- which, once #datafile and #features are in,
209 means the header is over and the line is the first row of data. "mask" is the walking mask
210 that assigns those bit values while the command[] table is scanned. */
211 int seen=0; /* bit record of which header keywords occurred so far */
212 int keyword=0; /* bit value of the recognized keyword */
213 int mask; /* bit mask for reading/writing bits of seen */
214
215 _valid = false;
216 // error check
217 if((_file=fopen(_filename.c_str(),"r"))==nullptr) {throw fst_error("Data_File_TRN file read problem.",1);}
218 empty=1; /* TRUE - empty file */
219 _title=ONOTITLE;
220
221 while((!feof(_file))&&(!header_done))
222 {
223 _datastart=ftell(_file);
224 if(fgets(s,OHEADSTRLEN,_file)==nullptr) break; /* end of file (or a read error) inside the header */
225
226 scanned=sscanf(s,"%s",word); /* did it read anything at all? */
227 if((scanned)&&(scanned!=EOF)&&(word[0]!=';')&&(word[0]!=0))
228 {
229 empty=0; /* FALSE */
230 mask=1;
231 keyword=0;
232 s3=nullptr;
233 for(i=0;(i<ONUMCOM)&&(!keyword);i++) /* is it one of *command[]? */
234 {
235 s2=strstr(word,command[i]);
236 if(s2!=nullptr)
237 {
238 keyword=mask;
239 s3=strstr(s,word)+strlen(command[i]); /* point s3 into s past the keyword */
240 }
241 mask<<=1;
242 }
243 if(s3==nullptr)
244 {
245 // error check
246 // an unrecognized line is acceptable only once #datafile and #features are in, in which
247 // case it is the first data row and case 0 below ends the header
248 if(!((seen&1)&&(seen&4)))
249 {throw fst_error("Data_File_TRN file read problem.",10);}
250 }
251 else for(i=0;s3[i]!=0;i++)if(s3[i]==',')s3[i]=' ';
252
253 // error check: keyword seen twice
254 if((keyword)&&(seen&keyword)) {throw fst_error("Data_File_TRN file read problem.",5);}
255 else
256 {
257 switch(keyword)
258 { // error check
259 case 0: if((seen&1)&&(seen&4)) /* data row (without the #data keyword) */
260 {
261 header_done=1;
262 // the #data keyword is optional: this first data row has already been
263 // consumed by the header scan, so seek back to its start (_datastart
264 // is recorded before each header line is read)
265 fseek(_file,(long)_datastart,SEEK_SET);
266 }
267 else {throw fst_error("Data_File_TRN file read problem.",6);}
268 break;
269 // error check
270 case 2: if(!(seen&1)) {throw fst_error("Data_File_TRN file read problem.",6);}
271 else { /* title */
272 s2=strstr(s3,"\n"); if(s2!=nullptr) s2[0]=0; // erase the newline
273 while((s3[0]!=0)&&((s3[0]==' ')||(s3[0]=='\t'))) s3++;
274 // error check
275 if(strlen(s3)>=OFILENAMELENGTH) // a longer title is silently truncated
276 s3[OFILENAMELENGTH-1]=0;
277 _title=s3;
278 }
279 break;
280 // error check
281 case 4: if(!(seen&1)) {throw fst_error("Data_File_TRN file read problem.",6);}
282 else { /* features */
283 int tmp_scan=0; // sscanf %d needs an int-sized target
284 scanned=sscanf(s3,"%d",&tmp_scan); _no_of_features=tmp_scan;
285 // error check
286 if((!scanned)||(scanned==EOF))
287 {
289 throw fst_error("Data_File_TRN file read problem.",7);
290 }
291 }
292 break;
293 // error check
294 case 8: if(!(seen&1)) {throw fst_error("Data_File_TRN file read problem.",6);}
295 else { /*classes */
296 int tmp_scan=0; // sscanf %d needs an int-sized target
297 scanned=sscanf(s3,"%d",&tmp_scan); _no_of_classes=tmp_scan;
298 // error check
299 if((!scanned)||(scanned==EOF))
300 {
302 throw fst_error("Data_File_TRN file read problem.",8);
303 }
304 else
305 {
306 if(_no_of_classes>0)
307 {
308 _class_sizes.clear();
309 }
310 sscanf(s3,"%s",word);
311 s3=strstr(s3,word)+strlen(word);
312 for(i=0;i<_no_of_classes;i++)
313 {
314 IDXTYPE temp;
315 int tmp_scan=0; // scan into an int and convert: %d into a template-typed IDXTYPE would be wrong for any IDXTYPE that is not int-sized
316 scanned=sscanf(s3,"%d",&tmp_scan); temp=(IDXTYPE)tmp_scan;
317 // error check
318 if((!scanned)||(scanned==EOF))
319 {
320 throw fst_error("Data_File_TRN file read problem.",9);
321 }
322 else
323 {
324 _class_sizes.push_back(temp);
325 sscanf(s3,"%s",word);
326 s3=strstr(s3,word)+strlen(word);
327 }
328 }
329 }
330 }
331 break;
332 // error check
333 case 16: if((seen&1)&&(seen&4)) /*data*/
334 {
335 header_done=1;
336 _datastart=ftell(_file);
337 }
338 else {throw fst_error("Data_File_TRN file read problem.",6);}
339 break;
340 default: ;
341 }
342 seen|=keyword;
343 }
344 }
345 }
346 // error check: empty file
347 if(empty) {throw fst_error("Data_File_TRN file read problem.",11);}
348 // error check: the file ended inside the header (no data row and no #data line)
349 if(!header_done) {throw fst_error("Data_File_TRN file read problem.",12);}
350
351 if(!(seen&8)) // class count undefined
352 {
353 _no_of_classes = 0; // undefined
354 throw fst_error("Data_File_TRN file read problem.",8); // report via the error message that this is not a usual data file
355 }
356 if(_no_of_classes!=_class_sizes.size()) {throw fst_error("Data_File_TRN file read problem.",88);}
357 if(_no_of_classes<1) {throw fst_error("Data_File_TRN file read problem.",100);}
358 if(_no_of_features<1) {throw fst_error("Data_File_TRN file read problem.",101);}
359 for(i=0;i<_no_of_classes;i++) if(_class_sizes[i]<1) {throw fst_error("Data_File_TRN file read problem.",102);}
360
361 _valid = true;
362}
363
364template<typename DATATYPE, typename IDXTYPE>
366{
367 if(_valid) {
368 double dbltmp; int err;
369 err=fscanf(_file,"%lf",&dbltmp);
370 if(err>0) {
371 target=dbltmp;
372 return true;
373 }
374 }
375 return false;
376}
377
378template<typename DATATYPE, typename IDXTYPE>
380{
381 if(_valid) {
382 double dbltmp; int err;
383 err=fscanf(_file,"%lf",&dbltmp);
384 if(err>0) return DATATYPE(dbltmp); else throw fst_error("Data_File_TRN::read_val() problem.",200);
385 }
386 throw fst_error("Data_File_TRN::read_val() problem.",201);
387}
388
389} // namespace
390#endif // FSTDATAFILETRN_H ///:~
int _valid
indicates the state, when header is successfully read and file open and ready to be read for actual d...
Definition data_file_TRN.hpp:170
const unsigned int getNoOfFeatures() const
data dimensionality, as read from the header's #features line
Definition data_file_TRN.hpp:142
void close()
closes TRN file if it is open
Definition data_file_TRN.hpp:141
const unsigned int getNoOfClasses() const
number of classes, as read from the header's #classes line
Definition data_file_TRN.hpp:143
const IDXTYPE getClassSize(const unsigned int cidx) const
Definition data_file_TRN.hpp:144
Data_File_TRN(const Data_File_TRN &)
declared, not defined -> prevents pass-by-value/copy (predates the C++11 =delete idiom used elsewhere...
std::vector< IDXTYPE > _class_sizes
per-class sample counts, indexed by class index
Definition data_file_TRN.hpp:168
FILE * _file
the open TRN file handle, or nullptr if none is open
Definition data_file_TRN.hpp:171
IDXTYPE _datastart
file offset of the start of data past the header
Definition data_file_TRN.hpp:169
void GetFileParams()
parses the TRN header (opens _filename, reads #datafile/#title/#features/#classes keywords,...
Definition data_file_TRN.hpp:184
std::string _filename
input data file name, as passed to open()
Definition data_file_TRN.hpp:164
DATATYPE read_val()
Reads and returns the next value from the data section; throws fst_error on EOF/parse failure,...
Definition data_file_TRN.hpp:379
unsigned int _no_of_features
number of features (read from the header)
Definition data_file_TRN.hpp:166
std::string _title
optional data title (part of the data file); defaults to "no title" if the header omits #title
Definition data_file_TRN.hpp:165
void open(const std::string &filename)
opens TRN file and reads header
Definition data_file_TRN.hpp:175
unsigned int _no_of_classes
number of classes (read from the header)
Definition data_file_TRN.hpp:167
FST4 specific error passing class.
Definition error.hpp:61
FST4 specific error passing class.
Global definitions.
The Feature Selection Toolbox 4 library: every library component – data access, criteria and classifi...
Definition data_accessor.hpp:80
Copyright © 2000–present ÚTIA, Institute of Information Theory and Automation of the Czech Academy of Sciences · Contacts · This site sets no cookies and uses no analytics.