ArmNN
 21.02
ImageCSVFileGenerator.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include <Filesystem.hpp>
7 #include <cxxopts/cxxopts.hpp>
8 
9 #include <algorithm>
10 #include <fstream>
11 #include <iostream>
12 #include <string>
13 
14 namespace
15 {
16 
17 // parses the command line to extract
18 // * the directory -i to look through .raw files from (must exist)
19 // * the name of the file -o the output CSV file path (must not already exist)
20 class CommandLineProcessor
21 {
22 public:
23  bool ParseOptions(cxxopts::ParseResult& result)
24  {
25  // indir is mandatory, dir could possibly be changed.
26  if (result.count("indir"))
27  {
28  std::string dir = result["indir"].as<std::string>();
29 
30  if (!ValidateDirectory(dir))
31  {
32  return false;
33  }
34 
35  m_InputDirectory = dir;
36  }
37  else
38  {
39  std::cerr << "-i/--indir parameter is mandatory." << std::endl;
40  return false;
41  }
42 
43  // outfile is mandatory
44  if (result.count("outfile"))
45  {
46  if (!ValidateOutputFile(result["outfile"].as<std::string>()))
47  {
48  return false;
49  }
50  }
51  else
52  {
53  std::cerr << "-o/--outfile parameter is mandatory." << std::endl;
54  return false;
55  }
56 
57  if (result.count("layer-binding-id"))
58  {
59  if(!ValidateBindingId(result["layer-binding-id"].as<std::string>()))
60  {
61  return false;
62  }
63  }
64  return true;
65  }
66 
67  bool ValidateDirectory(std::string& dir)
68  {
69  if (dir.empty())
70  {
71  std::cerr << "No directory specified" << std::endl;
72  return false;
73  }
74 
75  if (dir[dir.length() - 1] != '/')
76  {
77  dir += "/";
78  }
79 
80  if (!fs::exists(dir))
81  {
82  std::cerr << "Directory [" << dir << "] does not exist" << std::endl;
83  return false;
84  }
85 
86  if (!fs::is_directory(dir))
87  {
88  std::cerr << "Given directory [" << dir << "] is not a directory" << std::endl;
89  return false;
90  }
91 
92  return true;
93  }
94 
95  bool ValidateOutputFile(const std::string& outputFileName)
96  {
97  if (outputFileName.empty())
98  {
99  std::cerr << "No output file name specified" << std::endl;
100  return false;
101  }
102 
103  if (fs::exists(outputFileName))
104  {
105  std::cerr << "Output file [" << outputFileName << "] already exists" << std::endl;
106  return false;
107  }
108 
109  if (fs::is_directory(outputFileName))
110  {
111  std::cerr << "Output file [" << outputFileName << "] is a directory" << std::endl;
112  return false;
113  }
114 
115  fs::path outputPath(outputFileName);
116  if (!fs::exists(outputPath.parent_path()))
117  {
118  std::cerr << "Directory [" << outputPath.parent_path().c_str() << "] does not exist" << std::endl;
119  return false;
120  }
121 
122  return true;
123  }
124 
125  bool ValidateBindingId(const std::string& id)
126  {
127  if (!std::all_of(id.begin(), id.end(), ::isdigit))
128  {
129  std::cerr << "Invalid input binding Id" << std::endl;
130  return false;
131  }
132 
133  return true;
134  }
135 
136  bool ProcessCommandLine(int argc, char* argv[])
137  {
138  try
139  {
140  cxxopts::Options options("ImageCSVFileGenerator",
141  "Program for creating a CSV file that "
142  "contains a list of .raw tensor files. "
143  "These .raw tensor files can be generated using the ImageTensorGenerator");
144 
145  options.add_options()
146  ("h,help", "Display help messages")
147  ("i,indir",
148  "Directory that .raw files are stored in",
149  cxxopts::value<std::string>(m_InputDirectory))
150  ("o,outfile",
151  "Output CSV file path",
152  cxxopts::value<std::string>(m_OutputFileName))
153  ("l, layer-binding-id",
154  "Input layer binding Id, Defaults to 0",
155  cxxopts::value<std::string>(m_InputBindingId)->default_value("0"));
156 
157  auto result = options.parse(argc, argv);
158 
159  if (result.count("help"))
160  {
161  std::cout << options.help() << std::endl;
162  return false;
163  }
164 
165  // Check for mandatory parameters and validate inputs
166  if(!ParseOptions(result)){
167  return false;
168  }
169  }
170  catch (const cxxopts::OptionException& e)
171  {
172  std::cerr << e.what() << std::endl << std::endl;
173  return false;
174  }
175  catch (const std::exception& e)
176  {
177  std::cerr << "Fatal internal error: [" << e.what() << "]" << std::endl;
178  return false;
179  }
180 
181  return true;
182  }
183 
184  std::string GetInputDirectory() {return m_InputDirectory;}
185  std::string GetOutputFileName() {return m_OutputFileName;}
186  std::string GetInputBindingId() {return m_InputBindingId;}
187 
188 private:
189  std::string m_InputDirectory;
190  std::string m_OutputFileName;
191  std::string m_InputBindingId;
192 };
193 
194 } // namespace anonymous
195 
196 int main(int argc, char* argv[])
197 {
198  CommandLineProcessor cmdline;
199  if (!cmdline.ProcessCommandLine(argc, argv))
200  {
201  return -1;
202  }
203 
204  const std::string fileFormat(".raw");
205 
206  const std::string rawDirectory(cmdline.GetInputDirectory());
207  const std::string outputPath(cmdline.GetOutputFileName());
208  const std::string bindingId(cmdline.GetInputBindingId());
209 
210  std::vector<fs::path> rawFiles;
211  for (auto& entry : fs::directory_iterator(rawDirectory))
212  {
213  if (entry.path().extension().c_str() == fileFormat)
214  {
215  rawFiles.push_back(entry.path());
216  }
217  }
218 
219  if (!rawFiles.empty())
220  {
221  unsigned int pass = 0;
222  std::ofstream refinementData;
223  refinementData.open(outputPath, std::ofstream::out);
224  if (refinementData.is_open())
225  {
226  for (auto const& raw : rawFiles)
227  {
228  refinementData << pass << ", " << bindingId << ", " << raw.c_str() << "\n";
229  if (!refinementData)
230  {
231  std::cerr << "Failed to write to output file: " << outputPath << std::endl;
232  continue;
233  }
234  ++pass;
235  }
236  refinementData.close();
237  }
238  else
239  {
240  std::cerr << "Failed to open output file: " << outputPath << std::endl;
241  return -1;
242  }
243  }
244  else
245  {
246  std::cerr << "No matching files with the \".raw\" extension found in the directory: "
247  << rawDirectory << std::endl;
248  return -1;
249  }
250 
251  return 0;
252 }
void ParseOptions(const std::vector< BackendOptions > &options, BackendId backend, F f)
int main(int argc, char *argv[])
bool ValidateDirectory(std::string &dir)