iRoCS Toolbox  1.1.0
KFile_MULTBINARY.hh
Go to the documentation of this file.
1 /**************************************************************************
2  *
3  * Copyright (C) 2004-2015 Olaf Ronneberger, Florian Pigorsch, Jörg Mechnich,
4  * Thorsten Falk
5  *
6  * Image Analysis Lab, University of Freiburg, Germany
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  **************************************************************************/
23 
24 /**************************************************************************
25 ** Title: KFile_MULTBINARY.hh
26 ** $RCSfile$
27 ** $Revision: 741 $$Name$
28 ** $Date: 2005-07-21 08:34:49 +0200 (Thu, 21 Jul 2005) $
29 ** Copyright: LGPL $Author: haasdonk $
30 ** Description: Class for accessing complete kernel matrices from several
31 ** binary float files. In each file:
32 ** first int32 is expected to be the number of rows
33 ** second int32 is expected to be the number of columns
34 ** following array of floats is expected to be the
35 ** kernel data.
36 ** the filename is expected to be of type
37 ** somefilebase-rows-00-20-cols-400-500.kmf
38 ** all files in the directory passed by the option
39 ** -kmd are parsed like this and should be an "axis"-parallel
40 ** decomposition of the whole kernel matrix
41 **
42 **-------------------------------------------------------------------------
43 **
44 ** $Log$
45 ** Revision 1.3 2005/07/21 06:34:49 haasdonk
46 ** modified directory access in KFile_MULTBINARY.hh, now following
47 ** POSIX standard
48 **
49 ** Revision 1.2 2005/07/19 13:42:59 haasdonk
50 ** adapted header for automatic CVS-Information extraction
51 **
52 **
53 **************************************************************************/
54 
55 #ifndef KFILE_MULTBINARY_HH
56 #define KFILE_MULTBINARY_HH
57 
58 #ifdef HAVE_CONFIG_H
59 #include <config.hh>
60 #endif
61 
62 // std includes
63 #include <string>
64 #include <vector>
65 #include <iostream>
66 #include <sstream>
67 #include <algorithm>
68 #include <fstream>
69 #include "KFile_BINARY.hh"
70 #include <dirent.h>
71 
72 //#include <algorithm>
73 // libsvmtl includes
74 #include "svm_defines.hh"
75 //#include "SVMError.hh"
76 #include "ProgressReporter.hh"
77 
78 // requirements of template parameters
83 
84 namespace svt
85 {
87  {
88 
89  public:
91  {}
92 
94  {
95  operator=( orig);
96  }
97 
98 
99  void operator=( const KFile_MULTBINARY& orig)
100  {
101  kmatrix_dir = orig.kmatrix_dir;
102  kfile_bin = orig.kfile_bin;
103  }
104 
105  public:
106 
107 // ~KFile_MULTBINARY()
108 // {
109 // };
110 
111  template<typename STDATA>
112  void loadParameters( STDATA& stData)
113  {
115  stData.getValue("kmatrix_dir",kmatrix_dir);
116  };
117 
118  template<typename STDATA>
119  void saveParameters( STDATA& stData) const
120  {
122  stData.setValue( "kmatrix_dir", kmatrix_dir);
123  };
124 
125  static std::string name()
126  {
127  return std::string( "multbinary");
128  }
129 
130  static std::string description()
131  {
132  return std::string( "multiple binary format");
133  }
134 
135  static void getParamInfos( std::vector<ParamInfo>& p)
136  {
137  p.push_back(
138  ParamInfo( "kmatrix_dir", "kmd", "string",
139  "name of directory with float kernel-matrices"));
140  }
141 
142  // load float matrix from files into preallocated array.
143  // Assuming sorted lists of IDs!!!
144 
145  void load_matrix(float** rowStarts,
146  std::vector<unsigned int>& gIDs1,
147  std::vector<unsigned int>& gIDs2)
148  {
149 
150  // load all filenames from path
151 
152 // struct dirent **namelist;
153  DIR *dir;
154  struct dirent *current_name;
155 
156 // int n;
157 
158  // cut eventual "/" or "\" at end of path
159  while (( !kmatrix_dir.empty())
160  && ((kmatrix_dir[kmatrix_dir.size()-1] == '/' ) ||
161  (kmatrix_dir[kmatrix_dir.size()-1] == '\\' ) ))
162  kmatrix_dir.erase(kmatrix_dir.end()-1);
163 
164  dir = opendir(kmatrix_dir.c_str());
165 
166 // n = scandir(kmatrix_dir.c_str(), &namelist, 0, alphasort);
167  if (dir == NULL)
168  {
169  std::cerr << "error in reading kmf-directory\n";
170  exit(-1);
171  }
172  // extract filebase and initialize collection of index-ranges
173 
174  // search first file without leading "."
175  int find_min = -1;
176  std::string file1;
177  do
178  {
179  current_name = readdir(dir);
180  find_min +=1;
181 // file1 = std::string(namelist[find_min]->d_name);
182  file1 = std::string(current_name->d_name);
183 // std::cout << " processing file " <<
184 // current_name->d_name << " \n ";
185 // std::string fn(current_name->d_name);
186 
187  } while ((current_name!=NULL) &&
188  (file1.find("rows",0)==std::string::npos));
189  closedir(dir);
190 
191  // if (current_name != NULL)
192  // std::cout << " after closedir, found first kmf-file " <<
193  // current_name->d_name << "\n ";
194  // else
195  // std::cout << " after closedir, found no kmf-file !\n ";
196 
197  std::string::size_type pr = file1.find("rows",0);
198  std::string filebase = file1.substr(0,pr);
199  std::vector<unsigned int> min_rrange, max_rrange, min_crange,max_crange;
200  std::vector<unsigned int>::iterator IDi1,IDi2;
201  std::vector<std::vector<unsigned int> > gIDs1_parts, gIDs2_parts;
202  float** rowStarts_shifted;
203  rowStarts_shifted = new float*[gIDs1.size()];
204 
205  // for all files read in chunk of the matrix
206 
207  dir = opendir(kmatrix_dir.c_str());
208  while (current_name!=NULL) // is initially not NULL
209 // for (int fnumber=find_min;fnumber<n;fnumber++)
210  {
211  bool is_kmf_file;
212  do // search next filename with "rows" in it
213  {
214  is_kmf_file = false;
215  current_name = readdir(dir);
216  if (current_name!=NULL)
217  {
218 // std::cout << " processing dir entry " <<
219 // current_name->d_name << " \n ";
220  file1 = std::string(current_name->d_name);
221  if (file1.find("rows",0)!=std::string::npos)
222  is_kmf_file = true;
223  }
224 
225  } while ((current_name!=NULL) && !is_kmf_file);
226 
227  if (is_kmf_file) // found a following file
228  {
229  std::string fn(current_name->d_name);
230 
231  std::string::size_type pr = fn.find("rows",0);
232  std::string::size_type pc = fn.find("cols",0);
233  std::string::size_type pe = fn.find(".kmf",0);
234  if (pr==std::string::npos || pc==std::string::npos ||
235  pe==std::string::npos)
236  {
237  std::cerr << "KFile_MULTBINARY.hh: \n";
238  std::cerr << "error in getting index-ranges from filename "
239  << fn << "\n";
240  std::cerr << "required format of filename: \n";
241  std::cerr << filebase << "-rows-RMIN-RMAX-cols-CMIN-CMAX.kmf\n";
242  exit(-1);
243  }
244 
245  std::string rrange = fn.substr(pr+5,pc-pr-6);
246  std::string crange = fn.substr(pc+5,pe-pc-5);
247 
248  pr = rrange.find("-",0);
249  pc = crange.find("-",0);
250 
251  unsigned int rmin = atol(rrange.substr(0,pr).c_str());
252  unsigned int rmax = atol(rrange.substr(pr+1).c_str());
253  unsigned int cmin = atol(crange.substr(0,pc).c_str());
254  unsigned int cmax = atol(crange.substr(pc+1).c_str());
255 
256  // extract all 'ranges' in first direction
257  IDi1 = find(min_rrange.begin(),min_rrange.end(),rmin);
258  if (IDi1!=min_rrange.end()) // if already found
259  {
260  // check whether corresponding entries coincide
261  int po = IDi1-min_rrange.begin();
262  if ((max_rrange[po]!=rmax))
263  {
264  std::cerr << "error in loading files: " <<
265  "rows-ranges not coinciding: " <<
266  "old_rr = (" <<
267  min_rrange[po] << ","<< max_rrange[po] << "),"<<
268  "new_rr = (" <<
269  rmin << ","<< rmax << ")\n";
270  exit(-1);
271  }
272  }
273  else // insert into list
274  {
275  min_rrange.push_back(rmin);
276  max_rrange.push_back(rmax);
277  }
278 
279 
280  // extract all 'ranges' in second direction
281  IDi2 = find(min_crange.begin(),min_crange.end(),cmin);
282  if (IDi2!=min_crange.end()) // if already found
283  {
284  // check whether corresponding entries coincide
285  int po = IDi2-min_crange.begin();
286  if ((max_crange[po]!=cmax))
287  {
288  std::cerr << "error in loading files: " <<
289  "cols-ranges not coinciding: " <<
290  "old_cr = (" <<
291  min_crange[po] << ","<< max_crange[po] << "),"<<
292  "new_cr = (" <<
293  cmin << ","<< cmax << ")\n";
294  exit(-1);
295  }
296  }
297  else // insert into list
298  {
299  min_crange.push_back(cmin);
300  max_crange.push_back(cmax);
301  }
302  } // end current_name!=0
303 
304  } // end loop over files
305 
306  // determine all subvectors of gIDs1 in gIDs1_parts
307 
308  gIDs1_parts.resize(min_rrange.size());
309  for (unsigned int i=0;i<min_rrange.size();i++)
310  {
311  IDi1 = gIDs1.begin();
312  IDi2 = gIDs1.end();
313 
314  while (((*IDi1)<min_rrange[i]) && (IDi1!= gIDs1.end()))
315  IDi1++;
316  while (((*(IDi2-1))>max_rrange[i]) && ((IDi2-1)!= gIDs1.begin()))
317  IDi2--;
318 
319  if ((IDi2>IDi1) && (*IDi1)<=max_rrange[i])
320  {
321  gIDs1_parts[i].resize(IDi2-IDi1);
322  copy(IDi1,IDi2,gIDs1_parts[i].begin());
323 // for debugging:
324 // std::cout << "min = " << *(gIDs1_parts[i].begin()) <<
325 // ", max = " << *(gIDs1_parts[i].end()-1) << " in \n";
326 
327  }
328 // for debugging:
329 // std::cout << " next part of rranges ("<<
330 // min_rrange[i]<< "," << max_rrange[i] << ") = " <<
331 // gIDs1_parts[i].size() << " gIDs \n";
332 
333  }
334 
335  // determine all subvectors of gIDs2
336  gIDs2_parts.resize(min_crange.size());
337  for (unsigned int i=0;i<min_crange.size();i++)
338  {
339  IDi1 = gIDs2.begin();
340  IDi2 = gIDs2.end()-1;
341 
342  while (((*IDi1)<min_crange[i]) && (IDi1!= gIDs2.end()))
343  IDi1++;
344  while (((*IDi2)>max_crange[i]) && (IDi2!= gIDs2.begin()))
345  IDi2--;
346  IDi2++; // point behind the range to be copied
347 
348  if ((IDi2>IDi1) && (*IDi1)<=max_crange[i])
349  {
350  gIDs2_parts[i].resize(IDi2-IDi1);
351  copy(IDi1,IDi2,gIDs2_parts[i].begin());
352 // for debugging:
353 // std::cout << "min = " << *(gIDs2_parts[i].begin()) <<
354 // ", max = " << *(gIDs2_parts[i].end()-1) << " in\n";
355  }
356 // for debugging:
357 // std::cout << " next part of cranges ("<<
358 // min_crange[i]<< "," << max_crange[i] << ") = " <<
359 // gIDs2_parts[i].size() << " gIDs \n";
360  }
361 
362  // check that sum of all partial sequences equals input-sequences!!
363  unsigned int sum1 = 0;
364  for (unsigned int i=0;i<min_rrange.size();i++)
365  sum1 +=gIDs1_parts[i].size();
366 
367  unsigned int sum2 = 0;
368  for (unsigned int i=0;i<min_crange.size();i++)
369  sum2 +=gIDs2_parts[i].size();
370 
371  if ((sum1!=gIDs1.size()) || (sum2!=gIDs2.size()))
372  {
373  std::cerr << "error in determining gID subsequences!\n";
374  exit(-1);
375  }
376 
377  // for all ind2-ranges read in blocks from files
378  for (unsigned int i=0;i< gIDs2_parts.size();i++)
379  if (!gIDs2_parts[i].empty())
380  {
381  // generate temporary vector of pointers into array
382  unsigned int shift2;
383  IDi2 = find(gIDs2.begin(),gIDs2.end(),gIDs2_parts[i][0]);
384  shift2 = IDi2-gIDs2.begin();
385  for (unsigned int j=0;j<gIDs1.size();j++)
386  rowStarts_shifted[j]=rowStarts[j]+shift2;
387 
388  // for all ind1-ranges read corresponding submatrix
389  for (unsigned int j=0;j<gIDs1_parts.size();j++)
390  if (!gIDs1_parts[j].empty())
391  {
392  unsigned int shift1;
393  IDi1 = find(gIDs1.begin(),gIDs1.end(),
394  gIDs1_parts[j][0]);
395  shift1 = IDi1-gIDs1.begin();
396 
397  // set corresponding filename and read array
398  // load matrix
399  std::ostringstream o;
400  o << kmatrix_dir << "/" << filebase <<
401  "rows-" << min_rrange[j] << "-" << max_rrange[j] <<
402  "-cols-" << min_crange[i] << "-" << max_crange[i] <<
403  ".kmf";
404  std::string filename = o.str();
405 // for debugging
406 // std::cout << "reading matrix from file "<<
407 // filename << "\n";
408  kfile_bin.setKmatrix_file(filename);
409  kfile_bin.load_matrix(rowStarts_shifted+shift1,
410  gIDs1_parts[j],gIDs2_parts[i]);
411  }
412  } // end loop over gIDs2
413 
414  // cleanup temporary variables
415  delete[] rowStarts_shifted;
416 // for (int fnumber=0;fnumber<n;fnumber++)
417 // free(namelist[fnumber]);
418 // free(namelist);
419  }
420 
421  private:
422  std::string kmatrix_dir;
423  svt::KFile_BINARY kfile_bin;
424  };
425 
426 }
427 
428 #endif
static std::string description()
static std::string name()
#define CHECK_MEMBER_TEMPLATE(c)
void load_matrix(float **rowStarts, std::vector< unsigned int > &gIDs1, std::vector< unsigned int > &gIDs2)
void operator=(const KFile_MULTBINARY &orig)
void saveParameters(STDATA &stData) const
static void getParamInfos(std::vector< ParamInfo > &p)
void setKmatrix_file(std::string kmf)
void loadParameters(STDATA &stData)
void load_matrix(float **rowStarts, std::vector< unsigned int > &gIDs1, std::vector< unsigned int > &gIDs2)
The ParamInfo class contains informations about one parameter like key, help text, guiHints etc.
Definition: ParamInfo.hh:82
KFile_MULTBINARY(const KFile_MULTBINARY &orig)