CBICA Toolkit  1.0.0
cbicaUtilities.h
Go to the documentation of this file.
1 /**
2 \file cbicaUtilities.h
3 
4 \brief Some basic utility functions.
5 
6 This needs c++11 flag enabled in gcc < 5.
7 
8 https://www.med.upenn.edu/sbia/software/// <br>
9 software@cbica.upenn.edu
10 
11 Copyright (c) 2018 University of Pennsylvania. All rights reserved. <br>
12 See COPYING file or https://www.med.upenn.edu/cbica/software-agreement.html
13 
14 */
15 #pragma once
16 
17 #include <string>
18 #include <typeinfo>
19 #include <vector>
20 #include <set>
21 #include <algorithm>
22 #include <iostream>
23 #include <fstream>
24 #include <sstream>
25 #include <stdexcept>
26 #include <iterator>
27 #include <cmath>
28 #include <numeric>
29 #include <memory.h>
30 #include <map>
31 #include <random>
32 #include <iomanip>
33 #include <limits>
34 
35 #if _WIN32
36 #include <process.h>
37 #endif
38 
39 //#include <type_traits>
40 
41 /**
42 \struct CSVDict
43 
44 \brief A Dictionary structure to for CSV parsing
45 
46 The CSV File in question is basically a list file consisting of file names (or paths) and labels
47 */
48 struct CSVDict
49 {
50  //! Contains input image file names
51  std::vector< std::string > inputImages;
52 
53  //! Contains Labels that correspond to each file
54  std::vector< double > inputLabels;
55 
56  //! Constructor
57  CSVDict(const CSVDict &origin) :
59  { };
60 
61  //! Constructor
63  {
64  inputImages.resize(0);
65  inputLabels.resize(0);
66  }
67 
68  //! Constructor
69  CSVDict(const std::vector< std::string > &inputImagesVector, const std::vector< double > &inputLabelVector) :
70  inputImages(inputImagesVector), inputLabels(inputLabelVector) {};
71 };
72 
73 namespace cbica
74 {
75  //====================================== String stuff ====================================//
76 
77  /**
78  \brief Splits the input file name into its constituents
79 
80  \param dataFile The full file name which is the input
81  \param baseName Overwritten with file name without extension
82  \param extension Overwritten with extension without '.'
83  \param path Overwritten with path to file
84 
85  \return True if successful
86  */
87  bool splitFileName(const std::string &dataFile, std::string &path,
88  std::string &baseName, std::string &extension);
89 
90  /**
91  \brief Splits the string
92 
93  \param str String to split
94  \param delim Delimiter on the basis of which splitting is to be done
95  \return results Output in the form of vector of strings
96  */
97  std::vector<std::string> stringSplit(const std::string &str, const std::string &delim);
98 
99  /**
100  \brief Searches for smaller string in larger string and then replaces it with user-defined input
101 
102  \param entireString String to search
103  \param toReplace String to replace
104  \param replaceWith String to replace toReplace with
105 
106  \return std::string of result
107  */
108  std::string replaceString(const std::string &entireString,
109  const std::string &toReplace,
110  const std::string &replaceWith);
111 
112  /**
113  \brief Convert const char* to char*
114 
115  \param input constant std::string
116 
117  \return character pointer
118  */
119  char* constCharToChar(const std::string &input);
120 
121  /**
122  \brief Convert const char* to char*
123 
124  \param input constant character pointer
125 
126  \return character pointer
127  */
128  char* constCharToChar(const char *input);
129 
130  //======================================== OS stuff ======================================//
131 
132  /**
133  \brief Check if file exists using istream
134 
135  \param fName Filename to check
136  \return True if file exists
137  */
138  bool fileExists(const std::string &fName);
139 
140  /**
141  \brief Check if directory exists
142 
143  \param dName String to check
144  \return True if directory exists
145  */
146  bool directoryExists(const std::string &dName);
147 
148  /**
149  \brief Return True if path is an existing regular file
150 
151  Reimplementation for python's "os.path.isfile": This follows symbolic links,
152  so both islink() and isfile() can be true for the same path.
153 
154  [Wrap of cbica::fileExists()]
155 
156  \param path Filename of file to check
157 
158  \return True if path is an existing regular file
159  */
160  bool isFile(const std::string &path);
161 
162  /**
163  \brief Return True if path is an existing directory
164 
165  Reimplementation of python's "os.path.isdir": This follows symbolic links,
166  so both islink() and isdir() can be true for the same path.
167 
168  [Wrap of cbica::directoryExists()]
169 
170  \param path Directory name to check
171 
172  \return True of path is an existing directory
173  */
174  bool isDir(const std::string &path);
175 
176  /**
177  \brief Return True if path exists and false for broken symbolic links
178 
179  Reimplementation of python's "os.path.exists": On some platforms, this function may return False
180  if permission is not granted to execute os.stat() on the requested file, even if the
181  path physically exists.
182 
183  \param path Path to check
184 
185  \return True if path is valid and false for broken symbolic links
186  */
187  bool exists(const std::string &path);
188 
189  std::vector<std::string> getCWLFilesInApplicationDir();
190 
191  /**
192  \brief Create a temporary directory
193 
194  Creates a user-writable file using the following format: USER_HOME_DIR + EXE_NAME + tmp_ + processID;
195 
196  If this file is existing, for whatever reason, then a new is created which has the time stamp appended.
197 
198  \return Path of temporary directory
199  */
200  std::string createTmpDir();
201 
202  /**
203  \brief Create a temporary directory
204 
205  Wrap for createTmpDir()
206 
207  \return True if success
208  */
209  std::string createTemporaryDirectory();
210 
211  /**
212  \brief Create a temporary directory
213 
214  Wrap for createTmpDir()
215 
216  \return True if success
217  */
218  std::string makeTemporaryDirectory();
219 
220  /**
221  \brief Create a temporary directory
222 
223  Wrap for createTmpDir()
224 
225  \return True if success
226  */
227  std::string makeTempDir();
228 
229  /**
230  \brief Create a directory
231 
232  \param dir_name Name of directory to be created with full path
233 
234  \return True if success
235  */
236  bool createDir(const std::string &dir_name);
237 
238  /**
239  \brief Create a directory
240 
241  \param dir_name Name of directory to be created with full path
242  */
243  bool makeDir(const std::string &dir_name);
244 
245  /**
246  \brief Create a directory
247 
248  \param dir_name Name of directory to be created with full path
249 
250  \return True if success
251  */
252  bool createDirectory(const std::string &dir_name);
253 
254  /**
255  \brief Create a directory
256 
257  \param dir_name Name of directory to be created with full path
258  */
259  bool makeDirectory(const std::string &dir_name);
260 
261  /**
262  \brief Create a directory
263 
264  \param dir_name Name of directory to be created with full path
265 
266  \return True if success
267  */
268  bool createFolder(const std::string &dir_name);
269 
270  /**
271  \brief Create a directory
272 
273  \param dir_name Name of directory to be created with full path
274  */
275  bool makeFolder(const std::string &dir_name);
276 
277  /**
278  \brief Recursively delete a folder and contents [internal function]
279 
280  \param dirname Folder to delete
281 
282  \return true for success
283  */
284  int removeDirectoryRecursively(const std::string &dirname, bool bDeleteSubdirectories);
285 
286  /**
287  \brief Delete a folder and contents
288 
289  \param path Folder to delete
290 
291  \return true for success
292  */
293  bool removeDir(const std::string &path);
294 
295  /**
296  \brief Delete a folder and contents
297 
298  \param path Folder to delete
299 
300  \return true for success
301  */
302  bool deleteDir(const std::string &path);
303 
304  /**
305  \brief Copy a folder and if recursion enabled, all its contents
306 
307  https://msdn.microsoft.com/en-us/library/hh874694.aspx?f=255&MSPPError=-2147217396
308 
309  \param inputFolder Folder to copy
310  \param destination Where to copy to
311  \param recursion Do recursion and copy, defaults to true
312 
313  \return true for success
314  */
315  bool copyDir(const std::string &inputFolder, const std::string &destination, bool recursion = true);
316 
317  /**
318  \brief Copy a folder and if recursion enabled, all its contents
319 
320  https://msdn.microsoft.com/en-us/library/hh874694.aspx?f=255&MSPPError=-2147217396
321 
322  \param inputFolder Folder to copy
323  \param destination Where to copy to
324  \param recursion Do recursion and copy, defaults to true
325 
326  \return true for success
327  */
328  bool copyDirectory(const std::string &inputFolder, const std::string &destination, bool recursion = true);
329 
330  /**
331  \brief Copy a folder and if recursion enabled, all its contents
332 
333  https://msdn.microsoft.com/en-us/library/hh874694.aspx?f=255&MSPPError=-2147217396
334 
335  \param inputFolder Folder to copy
336  \param destination Where to copy to
337  \param recursion Do recursion and copy, defaults to true
338 
339  \return true for success
340  */
341  bool copyFolder(const std::string &inputFolder, const std::string &destination, bool recursion = true);
342 
343  /**
344  \brief Copy a folder and if recursion enabled, all its contents
345 
346  \param inputFile File to copy
347  \param destination Where to copy to
348  \return true for success
349  */
350  bool copyFile(const std::string &inputFile, const std::string &destination);
351 
352  /**
353  \brief Get the size of the file in bytes
354 
355  \param inputFile The input file
356  */
357  size_t getFileSize(const std::string &inputFile);
358 
359  /*
360  \brief Checks for the compatibility with the current project
361 
362  \param inputVersionFile The version file (in YAML) that contains the compatibility information
363  */
364  bool IsCompatible(const std::string inputVersionFile);
365 
366  /**
367  \brief Get the size of the folder
368 
369  \param rootFolder The input folder
370  */
371  size_t getFolderSize(const std::string &rootFolder);
372 
373  /**
374  \brief Get the size of the folder
375 
376  \param rootFolder The input folder
377  */
378  size_t getDirSize(const std::string &rootFolder);
379 
380  /**
381  \brief Get the size of the folder
382 
383  \param rootFolder The input folder
384  */
385  size_t getDirectorySize(const std::string &rootFolder);
386 
387  /**
388  \brief Gets the extension of the supplied file name using splitFileName()
389 
390  Prefer to use "/" as file path delimiter.
391 
392  \param filename The input filename
393  \param checkFile Checks existence of file using fileExists
394  \return std::string which has the file extension
395  */
396  std::string getFilenameExtension(const std::string &filename, bool checkFile = true);
397 
398  /**
399  \brief Gets the base of the supplied file name using splitFileName()
400 
401  Prefer to use "/" as file path delimiter.
402 
403  \param filename The input filename
404  \param checkFile Checks existence of file using fileExists
405  \return std::string which has the file extension
406  */
407  std::string getFilenameBase(const std::string &filename, bool checkFile = true);
408 
409  /**
410  \brief Gets the path of the supplied file name using splitFileName()
411 
412  Prefer to use "/" as file path delimiter.
413 
414  \param filename The input filename
415  \param checkFile Checks existence of file using fileExists
416  \return std::string which has the file extension
417  */
418  std::string getFilenamePath(const std::string &filename, bool checkFile = true);
419 
420  /**
421  \brief Get the name of the Executable which is calling the function
422 
423  \return exe name
424  */
425  std::string getExecutableName();
426 
427  /**
428  \brief Get the path of the Executable which is calling the function
429 
430  returns the path after calling splitFileName on getFullPath
431 
432  \return exe name
433  */
434  std::string getExecutablePath();
435 
436  /**
437  \brief Get the name of the Executable which is calling the function
438 
439  \return exe name
440  */
441  std::string getFullPath();
442 
443  /**
444  \brief Get the name of the user who is calling the function
445 
446  \return user name
447  */
448  std::string getUserName();
449 
450  /**
451  \brief Get the home directory of the user
452 
453  Windows - C:/Users/XYZ
454  Linux - /home/XYZ
455 
456  \return user directory
457  */
458  std::string getUserHomeDirectory();
459 
460  /**
461  \brief Get the current working directory
462 
463  [Wrap for cbica::getcwd()]
464 
465  \return Current working directory
466  */
467  std::string getCWD();
468 
469  /**
470  \brief Normalize a pathname by collapsing redundant separators and up-level references
471 
472  Reimplementation of python's "os.path.normpath": Normalize a pathname by collapsing redundant separators
473  and up-level references so that A//B, A/B/, A/./B and A/foo/../B all become A/B. This string
474  manipulation may change the meaning of a path that contains symbolic links. On Windows, it
475  converts forward slashes to backward slashes.
476 
477  \param path Path to normalize
478 
479  \return std::string Normalized path
480  */
481  std::string normPath(const std::string &path);
482 
483  /**
484  \brief Normalize a pathname by collapsing redundant separators and up-level references
485 
486  [Wrap for cbica::normPath()]
487 
488  \param path Path to normalize
489 
490  \return std::string Normalized path
491  */
492  std::string normalizePath(const std::string &path);
493 
494  /**
495  \brief Return a relative filepath to path
496 
497  Reimplementation for python's "os.path.relpath": Return a relative filepath to path either from the
498  current directory or from an optional start directory. This is a path computation: the
499  filesystem is not accessed to confirm the existence or nature of path or start.
500 
501  \param path Path to check
502  \param base Base file name
503 
504  \return Relative filepath to path either from current directory or from an optional start dir
505  */
506  std::string relPath(const std::string &path, const std::string &base);
507 
508  /**
509  \brief Return a relative filepath to path
510 
511  Wrap of cbica::relPath()
512 
513  \param path Path to check
514  \param base Base file name
515 
516  \return Relative filepath to path either from current directory or from an optional start dir
517  */
518  std::string relativePath(const std::string &path, const std::string &base);
519 
520  /**
521  \brief Return the canonical path of the specified filename
522 
523  Reimplementation of python's "os.path.realpath": Return the canonical path of the specified
524  filename, eliminating any symbolic links encountered in the path (if they are
525  supported by the operating system).
526 
527  \param path Filename to check
528 
529  \return canonical path of path
530  */
531  std::string realPath(const std::string &path);
532 
533  /**
534  \brief Return True if path refers to a directory entry that is a symbolic link
535 
536  Reimplementation of python's "os.path.islink": Always False if symbolic links are not
537  supported by the python runtime.
538 
539  \param path Path to check
540 
541  \return True if path is symbolic link
542  */
543  bool isLink(const std::string &path);
544 
545  /**
546  \brief Check if path refers to a symbolic entry
547 
548  [Wrap of cbica::isLink()]
549 
550  \param path Path to check
551 
552  \return True if path is symbolic link
553  */
554  bool isSymbolicLink(const std::string &path);
555 
556  /**
557  \brief Make a symbolic link from file to another
558 
559  \param input_fileName Input file name for which symbolic link needs to be created
560  \param output_fileName Output file name which is the symbolic link for input_fileName
561 
562  \return True if symbolic link successfully created
563  */
564  bool makeSymbolicLink(const std::string &input_fileName, const std::string &ouput_fileName);
565 
566  /**
567  \brief Sets the environment variable
568 
569  \param variable_name Name of the Variable
570  \param variable_value Value of variable_name
571 
572  \return True if successful
573  */
574  bool setEnvironmentVariable(const std::string &variable_name, const std::string &variable_value);
575 
576  /**
577  \brief Gets the value of the specified environment variable
578  */
579  std::string getEnvironmentVariableValue(const std::string &environmentVariable);
580 
581  /**
582  \brief Delete the environment variable
583 
584  \param variable_name Name of the Variable
585 
586  \return True if successful
587  */
588  bool deleteEnvironmentVariable(const std::string &variable_name);
589 
590  /**
591  \brief Find all files inside a directory
592 
593  \param dirName The directory to do the search in
594  */
595  std::vector< std::string > filesInDirectory(const std::string &dirName, bool returnFullPath = true);
596 
597  /**
598  \brief Find all sub-directories inside a directory
599 
600  \param dirName The directory to do the search in
601  \param recursiveSearch Whether to do a recursive search or on a single level
602  */
603  std::vector<std::string> subdirectoriesInDirectory(const std::string &dirName, bool recursiveSearch = false, bool returnFullPath = false);
604 
605  /**
606  \brief Find number of rows in CSV file
607  */
608  size_t numberOfRowsInFile(const std::string &csvFileName, const std::string &delim = "\n");
609 
610  /**
611  \brief Find number of cols in CSV file
612  */
613  size_t numberOfColsInFile(const std::string &csvFileName, const std::string &delim = ",");
614 
615  /**
616  \brief Parse the supplied CSV File and obtain Row and Column information.
617 
618  Assumptions:
619  1. Header information is in first row
620  2. Full paths of images are given
621  3. Image paths are either absolute (default behaviour) OR relative to the location of CSV file OR relative to CWD
622 
623  \param csvFileName The full path of the file to parse, all paths are absolute or relative to current working directory
624  \param inputColumns The string of input columns which contain the data to be used for further processing
625  \param inputLabels The string of input labels per subject based on which further processing is to be done; if this is empty, it is initialized as 1 for all subjects
626  \param checkFile Check the validity of the file; defaults to true
627  \param pathsRelativeToCSV The paths in the CSV file are relative to the location of CSV file otherwise, they are checked relative to the CWD
628  \param rowsDelimiter The delimiters used to distinguish rows in the file
629  \param colsDelimiter The delimiters used to distinguish cols in the file
630  \param optionsDelimiter The delimiters used in inputColumns and inputLabel
631  \return Vector of CSV Dictionary items: Collection of input images are respective labels
632  */
633  std::vector< CSVDict > parseCSVFile(const std::string &csvFileName, const std::string &inputColumns, const std::string &inputLabels, bool checkFile = true, bool pathsRelativeToCSV = false, const std::string &rowsDelimiter = "\n", const std::string &colsDelimiter = ",", const std::string &optionsDelimiter = ",");
634 
635  /**
636  \brief Read a CSV file which has no header information
637 
638  To read CSV file with header information, check parseCSVFile() function. This should not be used for obtaining strings
639 
640  \param csvFileName The full path of the file to parse, all paths are absolute or relative to current working directory
641  \param columnMajor If true, then return is a vector of all the columns; otherwise it is a vector of the rows
642  */
643  template< class TDataType = double >
644  std::vector< std::vector< TDataType > > readCSVDataFile(const std::string &csvFileName, bool columnMajor = false)
645  {
646  std::vector< std::vector< TDataType > > returnVector;
647  if (!cbica::isFile(csvFileName))
648  {
649  std::cerr << "Supplied file wasn't found.\n";
650  return returnVector;
651  }
652 
653  const size_t rows = numberOfRowsInFile(csvFileName);
654  const size_t cols = numberOfColsInFile(csvFileName);
655 
656  std::ifstream data(csvFileName.c_str());
657  std::string line, cell;
658 
659  if (columnMajor)
660  {
661  returnVector.resize(cols);
662  }
663  else
664  {
665  returnVector.resize(rows);
666  }
667 
668  size_t i = 0, j = 0;
669  while (std::getline(data, line))
670  {
671  j = 0;
672  if (!columnMajor)
673  {
674  returnVector[i].resize(cols);
675  }
676  std::stringstream lineStream(line);
677  while (std::getline(lineStream, cell, ','))
678  {
679  if (columnMajor && returnVector[j].empty())
680  {
681  returnVector[j].resize(rows);
682  }
683 
684  auto temp = static_cast<TDataType>(std::atof(cell.c_str()));
685 
686  if (columnMajor)
687  {
688  returnVector[j][i] = temp;
689  }
690  else
691  {
692  returnVector[i][j] = temp;
693  }
694  j++;
695  }
696  i++;
697  }
698 
699  return returnVector;
700  }
701 
702  /**
703  \brief Find the unique elements in a vector
704 
705  Implementation incorporated from the SO answer in https://stackoverflow.com/a/1041939/1228757
706 
707  \param inputVector The vector on which to search for unique elements
708  \return An std::vector with unique elements
709  */
710  template< class TDataType = std::string >
711  std::vector< TDataType > GetUniqueElements(const std::vector< TDataType > &inputVector)
712  {
713  std::set< TDataType > s;
714  std::vector< TDataType > returnVector;
715  for (size_t i = 0; i < inputVector.size(); i++)
716  {
717  s.insert(inputVector[i]);
718  }
719  returnVector.assign(s.begin(), s.end());
720 
721  return returnVector;
722  }
723 
724  /**
725  \brief Read a CSV file which has no header information
726 
727  To read CSV file with header information, check parseCSVFile() function. This should be used for obtaining strings
728 
729  \param csvFileName The full path of the file to parse, all paths are absolute or relative to current working directory
730  */
731  std::vector< std::vector< std::string > > readCSVDataFile(const std::string &csvFileName);
732 
733  /**
734  \brief Get current local time as string delineated as YYYY:MM:DD
735  */
736  std::string getCurrentLocalDate();
737 
738  /**
739  \brief Get current local time as string delineated as HH:MM:SS
740  */
741  std::string getCurrentLocalTime();
742 
743  /**
744  \brief Get current local time as string delineated as YYYY:MM:DD,HH:MM:SS
745  */
746  std::string getCurrentLocalDateAndTime();
747 
748  /**
749  \brief Get current GMT as string delineated as YYYY:MM:DD
750  */
751  std::string getCurrentGMTDate();
752 
753  /**
754  \brief Get current GMT as string delineated as HH:MM:SS
755  */
756  std::string getCurrentGMT();
757 
758  /**
759  \brief Get current GMT as string delineated as YYYY:MM:DD,HH:MM:SS
760  */
761  std::string getCurrentGMTDateAndTime();
762 
763  /**
764  \brief Get current Year as string delineated as YYYY
765  */
766  std::string getCurrentYear();
767 
768  /**
769  \brief Get the current process ID
770 
771  Provides wraps to _getpid() in OS-specific ways
772  */
773  std::string getCurrentProcessID();
774 
775  /**
776  \brief Cross platform sleep
777 
778  Defaults to "std::rand() % 1000 + 1"
779  */
780  void sleep(size_t ms = std::rand() % 1000 + 1);
781 
782  /**
783  \brief Ensuring files written using Windows don't mess stuff up
784 
785  Base implementation from https://www.digitalpeer.com/blog/simple-text-processing-with-cpp-dos2unix-example
786  */
787  void dos2unix(const std::string inputFile);
788 
789  //==================================== Template stuff ==================================//
790 
791  /**
792  \brief Searches for an element in a vector and returns true/false and position
793 
794  Templated function to take in any kind of vector and element.
795 
796  \param vector_to_search_in Vector to do the search in
797  \param element_to_search_for Element to search for
798  \param position Last position of found element in vector (-1) if not found
799 
800  \return True if found
801  \return Position if found (-1) if not
802  */
803  template<typename TContainerType = std::string >
804  std::pair<bool, int> findInVector(std::vector<TContainerType> &vector_to_search_in,
805  TContainerType element_to_search_for)
806  {
807  int position = -1;
808  //std::vector<int>::const_iterator
809  typename std::vector<TContainerType>::const_iterator iterator =
810  std::find(vector_to_search_in.begin(), vector_to_search_in.end(), element_to_search_for);
811  if (iterator != vector_to_search_in.end())
812  {
813  position = iterator - vector_to_search_in.begin();
814  return std::make_pair(true, position);
815  }
816  else
817  return std::make_pair(false, position);
818  }
819 
820  /**
821  \brief Convert first character to integer, double, unsigned int, etc.
822 
823  \param input_string Input character to be converted
824  \return Templated to the type of return required
825  */
826  template < typename TConvertType
827 #if (_MSC_VER >= 1800) || (__GNUC__ > 4)
828  = int
829 #endif
830 >
831 /*typename*/ TConvertType convertCharacter(const std::string &input_string)
832  {
833  return static_cast<TConvertType>(input_string[0]);
834  }
835 
836  /**
837  \brief Convert entire string to integer, double, unsigned int, etc.
838 
839  \param input_string Input character to be converted
840  \return Templated vector to the type of return required
841  */
842  template<typename TConvertType = int >
843  std::vector</*typename*/ TConvertType> convertString(const std::string &input_string)
844  {
845  std::vector</*typename*/TConvertType>return_vector;
846  for (int i = 0; i < input_string.length(); ++i)
847  return_vector.push_back(static_cast<TConvertType>(input_string[i]));
848 
849  return return_vector;
850  }
851 
852 #if (_MSC_VER >= 1800) || (__cplusplus >= 201103L)
853  /**
854  \brief Base for compareEqual(...)
855  */
856  template <typename A = int, typename B = A>
857  inline bool compareEqual(const A x, const B y)
858  {
859  return (x == y);
860  }
861 
862  /**
863  \brief Compare if equal for multiple inputs
864  */
865  template <typename A = int, typename B = A, typename... Others>
866  bool compareEqual(const A x, const B y, Others const ... args)
867  {
868  return (x == y) && compareEqual(y, args...);
869  }
870 
871  /**
872  \brief Base for compareGreater(...)
873  */
874  template <typename A = int, typename B = A>
875  inline bool compareGreater(const A x, const B y)
876  {
877  return (x > y);
878  }
879 
880  /**
881  \brief Compare if greater for multiple inputs
882  */
883  template <typename A = int, typename B = A, typename... Others>
884  bool compareGreater(const A x, const B y, Others const ... args)
885  {
886  return (x > y) && compareGreater(y, args...);
887  }
888 
889  /**
890  \brief Base for compareLesser(...)
891  */
892  template <typename A = int, typename B = A>
893  inline bool compareLesser(const A x, const B y)
894  {
895  return (x < y);
896  }
897 
898  /**
899  \brief Compare if lesser for multiple inputs
900  */
901  template <typename A = int, typename B = A, typename... Others>
902  bool compareLesser(const A x, const B y, Others const ... args)
903  {
904  return (x < y) && compareLesser(y, args...);
905  }
906 
907  /**
908  \brief Convert to string with precision
909 
910  Useful when std::to_string truncates doubles
911  */
912  template< typename TDataType = double >
913  std::string to_string_precision(const TDataType a_value, const int n = 10)
914  {
915  std::ostringstream out;
916  out << std::setprecision(n) << a_value;
917  return out.str();
918  }
919 
920 #endif
921 
922  //==================================== Statistical/Compute stuff ==================================//
923  /**
924  \brief Calculates the Confusion Matrix for a set of real and predicted labels
925 
926  Values returned: True Positive (TP), False Positive (FP), True Negative (TN), False Negative (FN), Real Positive (RP), Preditcted Positive (PP)
927 
928  \param inputRealLabels Vector structure containing real labels
929  \param inputPredictedLabels Vector structure containing predicted labels
930 
931  \return std::map< string, size_t > A map of string and corresponding non-negative values
932  */
933  std::map< std::string, size_t > ConfusionMatrix(const std::vector< float > &inputRealLabels, const std::vector< float > &inputPredictedLabels);
934 
935  /**
936  \brief Calculates the ROC Values (see https://en.wikipedia.org/wiki/Receiver_operating_characteristic of all estimates) for a set of real and predicted labels
937 
938  Values returned:
939  True Positive (TP), False Positive (FP), True Negative (TN), False Negative (FN), Real Positive (RP), Preditcted Positive (PP) [all from ConfusionMatrix()],
940  Accuracy, Positive Predictive Value (PPV) [aka Precision], False Discovery Rate (FDR), False Omission Rate (FOR),
941  Negative Predictive Value (NPV), Prevalence, True Positive Rate (TPR) [aka Sensitivity, Recall, Probability of Detection (POD)],
942  False Positive Rate (FPR) [aka Fall-out], False Negative Rate (FNR) [aka Miss Rate (MR)], True Negative Rate (TNR) [aka Specificity],
943  Positive Likelihood Ratio (LR+), Negative Likelihood Ratio (LR−), Diagnostic Odds Ratio (DOR), Dice Score (Dice), Jaccard ratio/index (JR)
944 
945  \param inputRealLabels Vector structure containing real labels
946  \param inputPredictedLabels Vector structure containing predicted labels
947 
948  \return std::map< string, size_t > A map of string and corresponding float values
949  */
950  std::map< std::string, float > ROC_Values(const std::vector< float > &inputRealLabels, const std::vector< float > &inputPredictedLabels);
951 
952  /**
953  \brief A good random number generator using c++11 that gives a random value within a range
954 
955  \param start Start value of range; defaults to 0
956  \param end End value of range; defaults to 1
957  \param sizeOfReturn Size of the returned vector
958  */
959  template< class TDataType = float >
960  std::vector< TDataType > randn(const TDataType start, const TDataType end, size_t sizeOfReturn = 1)
961  {
962  std::vector< TDataType > returnVec;
963  returnVec.resize(sizeOfReturn);
964  std::random_device rd; // obtain a random number from hardware
965  std::mt19937 eng(rd()); // seed the generator
966  std::normal_distribution< TDataType > distr(start, end); // define the range
967 
968  for (size_t i = 0; i < returnVec.size(); i++)
969  {
970  returnVec[i] = distr(eng);
971  }
972 
973  return returnVec;
974  }
975 
976  /**
977  \brief A good random number generator using c++11 that gives a random value within a range
978 
979  \param sizeOfReturn Size of the returned vector
980  */
981  template< class TDataType = float >
982  std::vector< TDataType > randn(size_t sizeOfReturn = 1)
983  {
984  std::vector< TDataType > returnVec;
985  returnVec.resize(sizeOfReturn);
986  std::random_device rd; // obtain a random number from hardware
987  std::mt19937 eng(rd()); // seed the generator
988  std::normal_distribution< TDataType > distr(); // define the range
989 
990  for (size_t i = 0; i < returnVec.size(); i++)
991  {
992  returnVec[i] = distr(eng);
993  }
994 
995  return returnVec;
996  }
997 
998 };
999 
1000 /**
1001 \struct FileNameParts
1002 
1003 \brief Holds the different parts of a file name (path, base and extension)
1004 
1005 This is a helper struct for uses concerning uses where different parts of a file (path, base, ext) need to be used multiple times.
1006 */
1008 {
1009  std::string fullFileName, path, base, extension;
1010 
1011  //! Default Constructor
1012  FileNameParts();
1013 
1014  /**
1015  \brief Constructor with input file string
1016 
1017  \param inputFileName The complete input file name
1018  */
1019  FileNameParts(const std::string &inputFileName) : fullFileName(inputFileName)
1020  {
1021  cbica::replaceString(fullFileName, "\\", "/");
1022  if (cbica::fileExists(inputFileName))
1023  cbica::splitFileName(fullFileName, path, base, extension);
1024  else
1025  {
1026  std::cerr << "The input file '" << inputFileName << "' wasn't found on disk.\n";
1027  }
1028  }
1029 
1030  /**
1031  \brief Member function to set the fullFileName
1032 
1033  \param inputFileName The complete input file name
1034  */
1035  void SetFileName(const std::string &inputFileName)
1036  {
1037  fullFileName = inputFileName;
1038  cbica::replaceString(fullFileName, "\\", "/");
1039  if (cbica::fileExists(fullFileName))
1040  cbica::splitFileName(fullFileName, path, base, extension);
1041  else
1042  {
1043  std::cerr << "The input file '" << inputFileName << "' wasn't found on disk.\n";
1044  }
1045  }
1046 };
size_t numberOfRowsInFile(const std::string &csvFileName, const std::string &delim="\n")
Find number of rows in CSV file.
bool setEnvironmentVariable(const std::string &variable_name, const std::string &variable_value)
Sets the environment variable.
std::map< std::string, size_t > ConfusionMatrix(const std::vector< float > &inputRealLabels, const std::vector< float > &inputPredictedLabels)
Calculates the Confusion Matrix for a set of real and predicted labels.
bool isDir(const std::string &path)
Return True if path is an existing directory.
bool makeFolder(const std::string &dir_name)
Create a directory.
bool isSymbolicLink(const std::string &path)
Check if path refers to a symbolic entry.
std::string makeTempDir()
Create a temporary directory.
std::vector< std::string > stringSplit(const std::string &str, const std::string &delim)
Splits the string.
bool makeSymbolicLink(const std::string &input_fileName, const std::string &ouput_fileName)
Make a symbolic link from file to another.
std::vector< std::string > inputImages
Contains input image file names.
Definition: cbicaUtilities.h:51
std::string getFilenameBase(const std::string &filename, bool checkFile=true)
Gets the base of the supplied file name using splitFileName()
std::string realPath(const std::string &path)
Return the canonical path of the specified filename.
CSVDict(const std::vector< std::string > &inputImagesVector, const std::vector< double > &inputLabelVector)
Constructor.
Definition: cbicaUtilities.h:69
size_t getFileSize(const std::string &inputFile)
Get the size of the file in bytes.
std::string getExecutablePath()
Get the path of the Executable which is calling the function.
size_t getDirectorySize(const std::string &rootFolder)
Get the size of the folder.
std::string replaceString(const std::string &entireString, const std::string &toReplace, const std::string &replaceWith)
Searches for smaller string in larger string and then replaces it with user-defined input.
bool isFile(const std::string &path)
Return True if path is an existing regular file.
TConvertType convertCharacter(const std::string &input_string)
Convert first character to integer, double, unsigned int, etc.
Definition: cbicaUtilities.h:831
size_t getFolderSize(const std::string &rootFolder)
Get the size of the folder.
bool fileExists(const std::string &fName)
Check if file exists using istream.
bool removeDir(const std::string &path)
Delete a folder and contents.
bool makeDir(const std::string &dir_name)
Create a directory.
bool directoryExists(const std::string &dName)
Check if directory exists.
Holds the different parts of a file name (path, base and extension)
Definition: cbicaUtilities.h:1007
std::string getUserHomeDirectory()
Get the home directory of the user.
std::vector< TConvertType > convertString(const std::string &input_string)
Convert entire string to integer, double, unsigned int, etc.
Definition: cbicaUtilities.h:843
std::vector< double > inputLabels
Contains Labels that correspond to each file.
Definition: cbicaUtilities.h:54
CSVDict(const CSVDict &origin)
Constructor.
Definition: cbicaUtilities.h:57
std::pair< bool, int > findInVector(std::vector< TContainerType > &vector_to_search_in, TContainerType element_to_search_for)
Searches for an element in a vector and returns true/false and position.
Definition: cbicaUtilities.h:804
size_t getDirSize(const std::string &rootFolder)
Get the size of the folder.
bool splitFileName(const std::string &dataFile, std::string &path, std::string &baseName, std::string &extension)
Splits the input file name into its constituents.
std::string normalizePath(const std::string &path)
Normalize a pathname by collapsing redundant separators and up-level references.
bool deleteEnvironmentVariable(const std::string &variable_name)
Delete the environment variable.
std::map< std::string, float > ROC_Values(const std::vector< float > &inputRealLabels, const std::vector< float > &inputPredictedLabels)
Calculates the ROC Values (see https://en.wikipedia.org/wiki/Receiver_operating_characteristic of all...
char * constCharToChar(const std::string &input)
Convert const char* to char*.
std::string createTemporaryDirectory()
Create a temporary directory.
bool makeDirectory(const std::string &dir_name)
Create a directory.
CSVDict()
Constructor.
Definition: cbicaUtilities.h:62
bool createDirectory(const std::string &dir_name)
Create a directory.
bool createFolder(const std::string &dir_name)
Create a directory.
std::vector< CSVDict > parseCSVFile(const std::string &csvFileName, const std::string &inputColumns, const std::string &inputLabels, bool checkFile=true, bool pathsRelativeToCSV=false, const std::string &rowsDelimiter="\n", const std::string &colsDelimiter=",", const std::string &optionsDelimiter=",")
Parse the supplied CSV File and obtain Row and Column information.
std::string getCWD()
Get the current working directory.
std::vector< std::string > filesInDirectory(const std::string &dirName, bool returnFullPath=true)
Find all files inside a directory.
std::string normPath(const std::string &path)
Normalize a pathname by collapsing redundant separators and up-level references.
bool exists(const std::string &path)
Return True if path exists and false for broken symbolic links.
std::string getFilenameExtension(const std::string &filename, bool checkFile=true)
Gets the extension of the supplied file name using splitFileName()
std::vector< TDataType > randn(const TDataType start, const TDataType end, size_t sizeOfReturn=1)
A good random number generator using c++11 that gives a random value within a range.
Definition: cbicaUtilities.h:960
A Dictionary structure to for CSV parsing.
Definition: cbicaUtilities.h:48
bool copyFolder(const std::string &inputFolder, const std::string &destination, bool recursion=true)
Copy a folder and if recursion enabled, all its contents.
bool copyFile(const std::string &inputFile, const std::string &destination)
Copy a folder and if recursion enabled, all its contents.
std::string getExecutableName()
Get the name of the Executable which is calling the function.
FileNameParts()
Default Constructor.
bool deleteDir(const std::string &path)
Delete a folder and contents.
size_t numberOfColsInFile(const std::string &csvFileName, const std::string &delim=",")
Find number of cols in CSV file.
std::string relPath(const std::string &path, const std::string &base)
Return a relative filepath to path.
std::string getFilenamePath(const std::string &filename, bool checkFile=true)
Gets the path of the supplied file name using splitFileName()
std::string getFullPath()
Get the name of the Executable which is calling the function.
void SetFileName(const std::string &inputFileName)
Member function to set the fullFileName.
Definition: cbicaUtilities.h:1035
std::string relativePath(const std::string &path, const std::string &base)
Return a relative filepath to path.
int removeDirectoryRecursively(const std::string &dirname, bool bDeleteSubdirectories)
Recursively delete a folder and contents [internal function].
std::string getUserName()
Get the name of the user who is calling the function.
FileNameParts(const std::string &inputFileName)
Constructor with input file string.
Definition: cbicaUtilities.h:1019
bool createDir(const std::string &dir_name)
Create a directory.
bool copyDir(const std::string &inputFolder, const std::string &destination, bool recursion=true)
Copy a folder and if recursion enabled, all its contents.
bool isLink(const std::string &path)
Return True if path refers to a directory entry that is a symbolic link.
bool copyDirectory(const std::string &inputFolder, const std::string &destination, bool recursion=true)
Copy a folder and if recursion enabled, all its contents.
std::vector< std::string > subdirectoriesInDirectory(const std::string &dirName, bool recursiveSearch=false, bool returnFullPath=false)
Find all sub-directories inside a directory.
std::string getEnvironmentVariableValue(const std::string &environmentVariable)
Gets the value of the specified environment variable.
std::vector< std::vector< TDataType > > readCSVDataFile(const std::string &csvFileName, bool columnMajor=false)
Read a CSV file which has no header information.
Definition: cbicaUtilities.h:644
std::string createTmpDir()
Create a temporary directory.
std::vector< TDataType > GetUniqueElements(const std::vector< TDataType > &inputVector)
Find the unique elements in a vector.
Definition: cbicaUtilities.h:711
std::string makeTemporaryDirectory()
Create a temporary directory.