www.mooseframework.org
FileRangeBuilder.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "FileRangeBuilder.h"
11 
12 // MOOSE includes
13 #include "InputParameters.h"
14 
15 #include "libmesh/int_range.h"
16 #include "pcrecpp.h"
17 #include "tinydir.h"
18 
21 {
23  params.addParam<FileName>("file",
24  "Name of single image file to extract mesh parameters from. "
25  "If provided, a 2D mesh is created.");
26  params.addParam<FileNameNoExtension>("file_base",
27  "Image file base to open, use this option when "
28  "a stack of images must be read (ignored if "
29  "'file' is given)");
30  params.addParam<std::vector<unsigned int>>(
31  "file_range",
32  "Range of images to analyze, used with 'file_base' (ignored if 'file' is given)");
33  params.addParam<std::string>("file_suffix", "Suffix of the file to open, e.g. 'png'");
34  return params;
35 }
36 
38 {
39  bool has_file = params.isParamValid("file"), has_file_base = params.isParamValid("file_base"),
40  has_file_range = params.isParamValid("file_range"),
41  has_file_suffix = params.isParamValid("file_suffix");
42 
43  // Variables to be (possibly) used below...
44  std::string file;
45  std::string file_base;
46  std::vector<unsigned int> file_range;
47 
48  if (has_file)
49  {
50  file = params.get<FileName>("file");
51 
52  // Set the file_suffix parameter in the passed-in params object based on the input filename
53  _file_suffix = file.substr(file.find_last_of(".") + 1);
54  }
55  if (has_file_base)
56  file_base = params.get<FileNameNoExtension>("file_base");
57  if (has_file_range)
58  file_range = params.get<std::vector<unsigned int>>("file_range");
59  if (has_file_suffix)
60  _file_suffix = params.get<std::string>("file_suffix");
61 
62  // Check that the combination of params provided is valid
63 
64  // 1.) Provided both a filename and a file base
65  if (has_file && has_file_base)
66  {
67  _status = 1;
68  return;
69  }
70 
71  // 2.) Provided neither a filename nor a file base
72  if (!has_file && !has_file_base)
73  {
74  _status = 2;
75  return;
76  }
77 
78  // 3.) Provided a file base but not a suffix
79  if (has_file_base && !has_file_suffix)
80  {
81  _status = 3;
82  return;
83  }
84 
85  // 4.) Provided a filename and a range, warn that the range will be ignored.
86  if (has_file && has_file_range)
87  mooseWarning("Warning: file_range was ignored since a filename was provided.");
88 
89  // 5.) Provided a file_base but not a file_range, we'll create one
90  if (has_file_base && !has_file_range)
91  {
92  file_range.push_back(0);
93  file_range.push_back(std::numeric_limits<unsigned int>::max());
94  }
95 
96  // 6.) Provided a file_range with a single entry, so repeat it for
97  // them. This signifies a single image (i.e. 2D Mesh) is to be
98  // used.
99  if (has_file_range && file_range.size() == 1)
100  file_range.push_back(file_range[0]);
101 
102  // 7.) Provided a file_range with too many entries, print a
103  // warning and truncate the extra values.
104  if (has_file_range && file_range.size() != 2)
105  {
106  mooseWarning("A maximum of two values are allowed in the file_range, extra values truncated.");
107  file_range.resize(2);
108  }
109 
110  // Make sure that the range is in ascending order
111  std::sort(file_range.begin(), file_range.end());
112 
113  // Build up the filenames parameter, and inject it into the InputParameters object
114  if (has_file)
115  _filenames.push_back(file);
116 
117  else if (has_file_base)
118  {
119  // Separate the file base from the path
120  std::pair<std::string, std::string> split_file = MooseUtils::splitFileName(file_base);
121 
122  // Create directory object
123  tinydir_dir dir;
124  tinydir_open_sorted(&dir, split_file.first.c_str());
125 
126  // This regex will capture the file_base and any number of digits when used with FullMatch()
127  std::ostringstream oss;
128  oss << "(" << split_file.second << ".*?(\\d+))\\..*";
129  pcrecpp::RE file_base_and_num_regex(oss.str());
130 
131  // Loop through the files in the directory
132  for (const auto i : make_range(dir.n_files))
133  {
134  // Update the current file
135  tinydir_file file;
136  tinydir_readfile_n(&dir, &file, i);
137 
138  // Store the file if it has proper extension as in numeric range
139  if (!file.is_dir && MooseUtils::hasExtension(file.name, _file_suffix))
140  {
141  std::string the_base;
142  unsigned int file_num = 0;
143  file_base_and_num_regex.FullMatch(file.name, &the_base, &file_num);
144 
145  if (!the_base.empty() && file_num >= file_range[0] && file_num <= file_range[1])
146  _filenames.push_back(split_file.first + "/" + file.name);
147  }
148  }
149  tinydir_close(&dir);
150  }
151 
152  else
153  mooseError("We'll never get here!");
154 
155  // If we made it here, there were no errors
156 }
157 
158 void
160 {
161  switch (_status)
162  {
163  case 0:
164  return;
165  case 1:
166  mooseError("Cannot provide both file and file_base parameters");
167  break;
168  case 2:
169  mooseError("You must provide a valid value for either the 'file' parameter or the "
170  "'file_base' parameter.");
171  break;
172  case 3:
173  mooseError(
174  "If you provide a 'file_base', you must also provide a valid 'file_suffix', e.g. 'png'.");
175  break;
176  default:
177  mooseError("Unknown error code!");
178  }
179 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:299
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition: MooseError.h:333
std::pair< std::filesystem::path, std::filesystem::path > splitFileName(const T &full_file)
Function for splitting path and filename.
Definition: MooseUtils.h:231
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
static InputParameters validParams()
InputParameters emptyInputParameters()
auto max(const L &left, const R &right)
bool hasExtension(const std::string &filename, std::string ext, bool strip_exodus_ext=false)
Function tests if the supplied filename as the desired extension.
Definition: MooseUtils.C:389
IntRange< T > make_range(T beg, T end)
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object...
FileRangeBuilder(const InputParameters &params)
std::string _file_suffix
std::vector< std::string > _filenames
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another, i.e.