icedb  version 0.5.1
Snow particle scattering database API
Namespaces | Classes | Typedefs | Functions
icedb::Examples::Shapes Namespace Reference

Namespaces

 ScopedHandles
 This makes it much easier to automatically close HDF5 handles that are no longer used.
 

Classes

struct  ShapeCommonOptionalData
 
struct  ShapeDataBasic
 
struct  ShapeRequiredData
 

Typedefs

typedef std::vector< uint64_t > IntData_t
 
typedef std::vector< uint8_t > Int8Data_t
 
typedef std::vector< float > FloatData_t
 
typedef std::vector< std::string > StringData_t
 
typedef hid_t MatchType_t
 

Functions

ShapeDataBasic readTextFile (const std::string &filename)
 
void readHeader (const char *in, std::string &desc, size_t &np, size_t &headerEnd)
 
void readDDSCATtextContents (const char *iin, size_t numExpectedPoints, size_t headerEnd, ShapeDataBasic &p)
 Read ddscat text contents. More...
 
ShapeDataBasic readDDSCAT (const char *in)
 
void writeDDSCAT (const std::string &filename, const ShapeDataBasic &p)
 
ShapeDataBasic readRawText (const char *iin)
 
void writeTextRaw (const std::string &filename, const ShapeDataBasic &p)
 
size_t strints_array_to_floats (const char *in, const size_t inlen, float *out, const size_t outlen, float &max_element)
 
size_t array_to_floats (const char *in, const size_t inlen, float *out, const size_t outlen)
 
template<class T >
m_atof (const char *x, size_t len)
 
template<class T >
m_atoi (const char *x, size_t len)
 
template<class DataType >
MatchType_t MatchType ()
 
template<>
MatchType_t MatchType< int32_t > ()
 
template<>
MatchType_t MatchType< float > ()
 
template<typename T >
void readDataset (hid_t file_id, const char *dataset_name, std::vector< T > &outdata)
 
ShapeDataBasic readPSUfile (const std::string &filename)
 Reads a Penn State-style geometry file. More...
 

Typedef Documentation

◆ FloatData_t

typedef std::vector< float > icedb::Examples::Shapes::FloatData_t

Definition at line 13 of file shape.hpp.

◆ Int8Data_t

typedef std::vector< uint8_t > icedb::Examples::Shapes::Int8Data_t

Definition at line 12 of file shape.hpp.

◆ IntData_t

typedef std::vector< uint64_t > icedb::Examples::Shapes::IntData_t

Definition at line 11 of file shape.hpp.

◆ MatchType_t

Definition at line 75 of file shapeIOpsu.cpp.

◆ StringData_t

typedef std::vector< std::string > icedb::Examples::Shapes::StringData_t

Definition at line 14 of file shape.hpp.

Function Documentation

◆ array_to_floats()

size_t icedb::Examples::Shapes::array_to_floats ( const char *  in,
const size_t  inlen,
float *  out,
const size_t  outlen 
)

Definition at line 47 of file shapeIOtextParsers2.cpp.

49  {
50  size_t curout = 0;
51  // Accepts numbers of the form: (+- )[0-9]*.[0-9]*(eE)(+- )[0-9]*.[0-9]*
52  bool isNegative = false;
53  bool inExponent = false;
54  bool expIsNeg = false;
55  bool pastDecimal = false;
56 
57  uint64_t numerator, numeratorExp;
58  uint64_t digits_denom, digits_denom_Exp;
59  auto resetNum = [&]()
60  {numerator = 0; digits_denom = 0;
61  numeratorExp = 0; digits_denom_Exp = 0;
62  isNegative = false; inExponent = false;
63  expIsNeg = false; pastDecimal = false; };
64  resetNum();
65 
66  const char* cur = in;
67  const char* end = in + inlen;
68  // Advance to the start of a number
69  assert(cur);
70  const char* numbers = "0123456789-+.eE";
71  const char* whitespace = " \t\n";
72  const char* numEnd = nullptr;
73  auto isNumber = [](char c) -> bool {
74  if (c >= '0' && c <= '9') return true;
75  if (c == '-' || c == '+' || c == '.' || c == 'e' || c == 'E') return true;
76  return false;
77  };
78  auto isControl = [](char c) -> bool {
79  if (c == '-' || c == '+' || c == '.' || c == 'e' || c == 'E') return true;
80  return false;
81  };
82  auto advanceToNumber = [](const char* in, const char* end) -> const char* {
83  while (in < end) {
84  if (*in >= '0' && *in <= '9') return in;
85  else if (*in == '-' || *in == '+' || *in == '.' || *in == 'e' || *in == 'E') return in;
86  else ++in;
87  }
88  return in;
89  };
90  while ((cur < end) && (curout < outlen)) {
91  //cur = strpbrk(cur, numbers);
92  cur = advanceToNumber(cur, end);
93  while (isNumber(*cur)) {
94  if (!isControl(*cur)) {
95  if (!inExponent) {
96  numerator *= 10;
97  numerator += (*cur - '0');
98  if (pastDecimal) digits_denom++;
99  } else {
100  numeratorExp *= 10;
101  numeratorExp += (*cur - '0');
102  if (pastDecimal) digits_denom_Exp++;
103  }
104  } else {
105  if (*cur == '.') pastDecimal = true;
106  if (*cur == '-' && !inExponent) isNegative = true;
107  if (*cur == '-' && inExponent) expIsNeg = true;
108  if (*cur == 'e' || *cur == 'E') {
109  inExponent = true; pastDecimal = false; isNegative = false;
110  }
111  }
112  ++cur;
113  }
114  if (!numerator) continue;
115 
116  // Number is loaded. Assign and advance.
117  float exponent = 0;
118  if (numeratorExp) {
119  exponent = static_cast<float>(numeratorExp);
120  if (digits_denom_Exp) exponent /= powf(10.f, static_cast<float>(digits_denom_Exp));
121  if (expIsNeg) exponent *= -1;
122  }
123 
124  float num = 0;
125  num = static_cast<float>(numerator);
126  if (digits_denom) num /= powf(10.f, static_cast<float>(digits_denom));
127  if (isNegative) num *= -1;
128 
129  float fnum = num;
130  if (numeratorExp) fnum *= powf(10.f, exponent);
131 
132  out[curout] = fnum;
133  resetNum();
134  curout++;
135 
136  ++cur;
137  }
138  return curout;
139  }

◆ m_atof()

template<class T >
T icedb::Examples::Shapes::m_atof ( const char *  x,
size_t  len 
)

Definition at line 142 of file shapeIOtextParsers2.cpp.

143  {
144  T res = 0;
145  unsigned int remainder = 0;
146  unsigned int rembase = 1;
147  unsigned int digit = 0;
148  // Sign false indicates positive. True is negative
149  bool sign = false;
150  bool expsign = false;
151  unsigned int expi = 0;
152  const char* p = x; // Set pointer to beginning of character stream
153  bool exponent = false;
154  bool decimal = false;
155  size_t i = 0;
156  while (*p != '\0' && ((len) ? i<len : true))
157  {
158  // Do digit checks here (no calls to isdigit)
159  // Ignore whitespace
160  if (*p == 'e' || *p == 'E')
161  {
162  exponent = true;
163  }
164  else if (*p == '.') {
165  decimal = true;
166  }
167  else if (*p == '-') {
168  if (!exponent)
169  {
170  sign = true;
171  }
172  else {
173  expsign = true;
174  }
175  }
176  else if (*p == '+') {
177  if (!exponent)
178  {
179  sign = false;
180  }
181  else {
182  expsign = false;
183  }
184  }
185  else if (*p == ' ' || *p == '\t') {
186  // Ignore whitespace (but disallow endlines)
187  }
188  else {
189  // It's a digit!
190  switch (*p)
191  {
192  case '0':
193  digit = 0;
194  break;
195  case '1':
196  digit = 1;
197  break;
198  case '2':
199  digit = 2;
200  break;
201  case '3':
202  digit = 3;
203  break;
204  case '4':
205  digit = 4;
206  break;
207  case '5':
208  digit = 5;
209  break;
210  case '6':
211  digit = 6;
212  break;
213  case '7':
214  digit = 7;
215  break;
216  case '8':
217  digit = 8;
218  break;
219  case '9':
220  digit = 9;
221  break;
222  default:
223  // Invalid input
224  p++;
225  continue;
226  break;
227  }
228  // Digit is set. Next, see what to do with it
229  if (!decimal && !exponent)
230  {
231  res *= 10;
232  res += digit;
233  }
234  else if (decimal && !exponent) {
235  remainder *= 10;
236  rembase *= 10;
237  remainder += digit;
238  }
239  else if (exponent) {
240  expi *= 10;
241  expi += digit;
242  }
243  }
244 
245  p++;
246  i++;
247  }
248  // Iterated through the string
249  // Now, to combine the elements into my double
250  res += (T)remainder / (T)rembase;
251  if (sign) res *= -1;
252  if (exponent)
253  {
254  if (!expsign)
255  {
256  res *= (T)std::pow(10, (T)expi);
257  }
258  else {
259  res *= (T)std::pow(10, -1.0 * (T)expi);
260  }
261  }
262  return res;
263  }

◆ m_atoi()

template<class T >
T icedb::Examples::Shapes::m_atoi ( const char *  x,
size_t  len 
)

Definition at line 266 of file shapeIOtextParsers2.cpp.

References icedb::Examples::Shapes::ShapeCommonOptionalData::hint_max_scattering_element_dimension, icedb::Examples::Shapes::ShapeRequiredData::number_of_particle_constituents, icedb::Examples::Shapes::ShapeRequiredData::number_of_particle_scattering_elements, icedb::Examples::Shapes::ShapeDataBasic::optional, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_constituent_number, icedb::Examples::Shapes::ShapeRequiredData::particle_id, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_scattering_element_composition_whole, icedb::Examples::Shapes::ShapeRequiredData::particle_scattering_element_coordinates, icedb::Examples::Shapes::ShapeRequiredData::particle_scattering_element_coordinates_are_integral, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_scattering_element_number, readDDSCAT(), readDDSCATtextContents(), readHeader(), readRawText(), readTextFile(), icedb::Examples::Shapes::ShapeDataBasic::required, and strints_array_to_floats().

267  {
268  T res = 0;
269  int digit = 0;
270  bool sign = false; // false is pos, true is neg
271  bool done = false;
272  size_t i = 0;
273  const char* p = x; // Set pointer to beginning of character stream
274  while (*p != '\0' && done == false && ((len) ? i<len : true))
275  {
276  if (*p == '-') {
277  sign = true;
278  }
279  else if (*p == '+') {
280  sign = false;
281  }
282  else if (*p == ' ' || *p == '\t') {
283  // Ignore whitespace (but disallow endlines)
284  }
285  else {
286  // It's a digit!
287  switch (*p)
288  {
289  case '0':
290  digit = 0;
291  break;
292  case '1':
293  digit = 1;
294  break;
295  case '2':
296  digit = 2;
297  break;
298  case '3':
299  digit = 3;
300  break;
301  case '4':
302  digit = 4;
303  break;
304  case '5':
305  digit = 5;
306  break;
307  case '6':
308  digit = 6;
309  break;
310  case '7':
311  digit = 7;
312  break;
313  case '8':
314  digit = 8;
315  break;
316  case '9':
317  digit = 9;
318  break;
319  default:
320  // Invalid input
321  done = true;
322  break;
323  }
324  // Digit is set. Next, see what to do with it
325  if (done) break;
326  res *= 10;
327  res += digit;
328  }
329  p++;
330  i++;
331  }
332 
333  // Return the value
334  if (sign) res *= -1;
335  return res;
336  }
Here is the call graph for this function:

◆ MatchType()

template<class DataType >
MatchType_t icedb::Examples::Shapes::MatchType ( )

Definition at line 77 of file shapeIOpsu.cpp.

References ICEDB_throw, and icedb::error::xUnimplementedFunction.

78  {
80  .add("Reason", "Unsupported type during conversion.");
81  }
#define ICEDB_throw(x)
Definition: error.hpp:88

◆ MatchType< float >()

Definition at line 85 of file shapeIOpsu.cpp.

85  {
86  return H5T_NATIVE_FLOAT;
87  }

◆ MatchType< int32_t >()

Definition at line 82 of file shapeIOpsu.cpp.

82  {
83  return H5T_NATIVE_INT32;
84  }

◆ readDataset()

template<typename T >
void icedb::Examples::Shapes::readDataset ( hid_t  file_id,
const char *  dataset_name,
std::vector< T > &  outdata 
)

Definition at line 90 of file shapeIOpsu.cpp.

References icedb::error::xError::add(), icedb::Examples::Shapes::ScopedHandles::ScopedHandle< HandleType, InvalidValueClass, CloseMethod >::h, ICEDB_throw, icedb::Examples::Shapes::ScopedHandles::ScopedHandle< HandleType, InvalidValueClass, CloseMethod >::valid(), and icedb::error::xBadInput.

Referenced by readPSUfile().

91  {
92  try {
93  ScopedHandles::H5D_handle hData(H5Dopen(file_id, dataset_name, H5P_DEFAULT));
95  // Get dimensionality
96  ScopedHandles::H5DS_handle hSpace(H5Dget_space(hData.h));
98  int rank = H5Sget_simple_extent_ndims(hSpace.h);
99  if (rank == 0 || rank > 2) ICEDB_throw(icedb::error::error_types::xBadInput);
100  hssize_t numElems = H5Sget_simple_extent_npoints(hSpace.h);
101 
102  // Verify that the dataset has the expected type
103  ScopedHandles::H5T_handle hDatatype(H5Dget_type(hData.h));
104  MatchType_t funcDataType = MatchType<T>();
105  if (H5Tequal(funcDataType, hDatatype.h) <= 0) ICEDB_throw(icedb::error::error_types::xBadInput);
106  // If this conversion fails, then either we are trying to open a dataset with
107  // the wrong data type (i.e. float vs int32 vs int16), or the architecture
108  // between the systems used to store and read the data are _very_ different,
109  // which is highly unlikely.
110 
111  // Resize output vector
112  outdata.resize(numElems);
113 
114  // Read the data
115  if (H5Dread(
116  hData.h, // dataset
117  hDatatype.h, // in-memory data type
118  H5S_ALL, // memory data space; reading the entire dataset
119  H5S_ALL, // file data space; reading the entire dataset
120  H5P_DEFAULT, // default transfer properties
121  (void*)outdata.data()) // the output buffer (pre-sized)
123 
124  }
125  catch (icedb::error::xError &err) {
126  err
127  .add("Reason", "Cannot open an HDF5 dataspace.")
128  .add("Dataset", dataset_name);
129  throw err; // rethrow
130  }
131  }
ScopedHandle< hid_t, InvalidHDF5Handle, CloseHDF5Datatype > H5T_handle
Definition: shapeIOpsu.cpp:71
#define ICEDB_throw(x)
Definition: error.hpp:88
xError & add(const std::string &key, const T value)
Definition: error.cpp:271
ScopedHandle< hid_t, InvalidHDF5Handle, CloseHDF5Dataset > H5D_handle
Definition: shapeIOpsu.cpp:69
ScopedHandle< hid_t, InvalidHDF5Handle, CloseHDF5Dataspace > H5DS_handle
Definition: shapeIOpsu.cpp:70
Here is the call graph for this function:
Here is the caller graph for this function:

◆ readDDSCAT()

ShapeDataBasic icedb::Examples::Shapes::readDDSCAT ( const char *  in)

Definition at line 238 of file shapeIOtextParsers.cpp.

References readDDSCATtextContents(), and readHeader().

Referenced by m_atoi(), and readTextFile().

239  {
240  using namespace std;
241  ShapeDataBasic res;
242 
243  std::string str(in);
244  std::string desc; // Currently unused
245  size_t headerEnd = 0, numPoints = 0;
246  readHeader(str.c_str(), desc, numPoints, headerEnd);
247  //res.required.particle_id = desc;
248  //data->resize((int)numPoints, ::scatdb::shape::backends::NUM_SHAPECOLS);
249  readDDSCATtextContents(str.c_str(), numPoints, headerEnd, res);
250  return res;
251  }
STL namespace.
void readDDSCATtextContents(const char *iin, size_t numExpectedPoints, size_t headerEnd, ShapeDataBasic &p)
Read ddscat text contents.
void readHeader(const char *in, std::string &desc, size_t &np, size_t &headerEnd)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ readDDSCATtextContents()

void icedb::Examples::Shapes::readDDSCATtextContents ( const char *  iin,
size_t  numExpectedPoints,
size_t  headerEnd,
ShapeDataBasic p 
)

Read ddscat text contents.

Read ddscat text contents - the stuff after the header.

Definition at line 187 of file shapeIOtextParsers.cpp.

References icedb::Examples::Shapes::ShapeRequiredData::number_of_particle_constituents, icedb::Examples::Shapes::ShapeRequiredData::number_of_particle_scattering_elements, icedb::Examples::Shapes::ShapeDataBasic::optional, anonymous_namespace{shapeIOtextParsers.cpp}::parse_shapefile_entries(), icedb::Examples::Shapes::ShapeCommonOptionalData::particle_constituent_number, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_scattering_element_composition_whole, icedb::Examples::Shapes::ShapeRequiredData::particle_scattering_element_coordinates, icedb::Examples::Shapes::ShapeRequiredData::particle_scattering_element_coordinates_are_integral, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_scattering_element_number, and icedb::Examples::Shapes::ShapeDataBasic::required.

Referenced by m_atoi(), and readDDSCAT().

188  {
189  using namespace std;
190 
191  //Eigen::Vector3f crdsm, crdsi; // point location and diel entries
192  const char* pa = &iin[headerEnd];
193  const char* pb = strchr(pa + 1, '\0');
194 
195  std::vector<float> parser_vals; //(numPoints*8);
196  parser_vals.reserve(7 * numExpectedPoints);
197  parse_shapefile_entries(pa, pb, parser_vals);
198  assert(parser_vals.size() % 7 == 0);
199  size_t &numPoints = p.required.number_of_particle_scattering_elements;
200  numPoints = parser_vals.size() / 7;
201  assert(numPoints == numExpectedPoints);
202  p.optional.particle_scattering_element_number.resize(numPoints);
203  p.required.particle_scattering_element_coordinates.resize(numPoints * 3);
204  std::set<uint8_t> constituents;
205 
206  for (size_t i = 0; i < numPoints; ++i)
207  {
208  size_t pIndex = 7 * i;
209  p.optional.particle_scattering_element_number[i] = static_cast<uint64_t>(parser_vals[pIndex]);
210  p.required.particle_scattering_element_coordinates[3*i] = parser_vals[pIndex+1];
211  p.required.particle_scattering_element_coordinates[(3 * i)+1] = parser_vals[pIndex + 2];
212  p.required.particle_scattering_element_coordinates[(3 * i)+2] = parser_vals[pIndex + 3];
213 
214  constituents.emplace(static_cast<uint8_t>(parser_vals[pIndex + 4]));
215  //p.required.particle_scattering_element_composition[i] = parser_vals[pIndex + 4]; //! Redo pass later and map
216 
217  }
218  p.optional.particle_constituent_number = Int8Data_t(constituents.begin(), constituents.end());
219  p.optional.particle_scattering_element_composition_whole.resize(numPoints);
220  if (constituents.size() >= UINT8_MAX) throw (std::invalid_argument("Shape has too many constituents."));
221  p.required.number_of_particle_constituents = static_cast<uint8_t>(constituents.size());
222 
223  for (size_t i = 0; i < numPoints; ++i)
224  {
225  size_t pIndex = 7 * i;
226  uint64_t substance_id = static_cast<uint64_t>(parser_vals[pIndex + 4]);
227  size_t offset = 0;
228  for (auto it = constituents.cbegin(); it != constituents.cend(); ++it, ++offset) {
229  if ((*it) == substance_id) break;
230  }
231  size_t idx = (i*constituents.size()) + offset;
232  p.optional.particle_scattering_element_composition_whole[idx] = 1;
233  }
234  p.required.particle_scattering_element_coordinates_are_integral = 1;
235  }
std::vector< uint8_t > Int8Data_t
Definition: shape.hpp:12
STL namespace.
bool parse_shapefile_entries(Iterator first, Iterator last, std::vector< float > &v)
Parses space-separated shapefile entries.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ readHeader()

void icedb::Examples::Shapes::readHeader ( const char *  in,
std::string &  desc,
size_t &  np,
size_t &  headerEnd 
)

Definition at line 113 of file shapeIOtextParsers.cpp.

Referenced by m_atoi(), and readDDSCAT().

115  {
116  using namespace std;
117 
118  // Do header processing using istreams.
119  // The previous method used strings, but this didn't work with compressed reads.
120  //size_t &pend = headerEnd;
121  const char* pend = in;
122  const char* pstart = in;
123 
124  // The header is seven lines long
125  for (size_t i = 0; i < 7; i++)
126  {
127  pstart = pend;
128  pend = strchr(pend, '\n');
129  pend++; // Get rid of the newline
130  //pend = in.find_first_of("\n", pend+1);
131  string lin(pstart, pend - pstart - 1);
132  if (*(lin.rbegin()) == '\r') lin.pop_back();
133  //std::getline(in,lin);
134 
135  size_t posa = 0, posb = 0;
136  //Eigen::Array3f *v = nullptr;
137  switch (i)
138  {
139  case 0: // Title line
140  desc = lin;
141  break;
142  case 1: // Number of dipoles
143  {
144  // Seek to first nonspace character
145  posa = lin.find_first_not_of(" \t\n", posb);
146  // Find first space after this position
147  posb = lin.find_first_of(" \t\n", posa);
148  size_t len = posb - posa;
149  string s = lin.substr(posa, len);
150  np = boost::lexical_cast<size_t>(s);
151  //np = macros::m_atoi<size_t>(&(lin.data()[posa]), len);
152  }
153  break;
154  case 6: // Junk line
155  default:
156  break;
157  case 2: // a1
158  case 3: // a2
159  case 4: // d
160  case 5: // x0
161  // These all have the same structure. Read in three doubles, then assign.
162  /*
163  {
164  Eigen::Array3f v;
165  for (size_t j = 0; j < 3; j++)
166  {
167  // Seek to first nonspace character
168  posa = lin.find_first_not_of(" \t\n,", posb);
169  // Find first space after this position
170  posb = lin.find_first_of(" \t\n,", posa);
171  size_t len = posb - posa;
172  string s = lin.substr(posa, len);
173  v(j) = boost::lexical_cast<float>(s);
174  //v(j) = macros::m_atof<float>(&(lin.data()[posa]), len);
175  }
176  hdr->block<3, 1>(0, i - 2) = v;
177 
178  }
179  */
180  break;
181  }
182  }
183 
184  headerEnd = (pend - in) / sizeof(char);
185  }
STL namespace.
Here is the caller graph for this function:

◆ readPSUfile()

ShapeDataBasic icedb::Examples::Shapes::readPSUfile ( const std::string &  filename)

Reads a Penn State-style geometry file.

Todo:
Convert to using my "HDF for Humans" interface once it is ready.

VARIABLE: Cartesian coordinates of the center of each scattering element Written in form of x_1, y_1, z_1, x_2, y_2, z_2, ... Dimensions of [number_of_particle_scattering_elements][axis]

Definition at line 137 of file shapeIOpsu.cpp.

References icedb::Examples::Shapes::ScopedHandles::ScopedHandle< HandleType, InvalidValueClass, CloseMethod >::h, ICEDB_throw, icedb::Examples::Shapes::ShapeRequiredData::number_of_particle_constituents, icedb::Examples::Shapes::ShapeRequiredData::number_of_particle_scattering_elements, icedb::Examples::Shapes::ShapeDataBasic::optional, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_constituent_single_name, icedb::Examples::Shapes::ShapeRequiredData::particle_id, icedb::Examples::Shapes::ShapeRequiredData::particle_scattering_element_coordinates, icedb::Examples::Shapes::ShapeRequiredData::particle_scattering_element_coordinates_are_integral, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_scattering_element_radius, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_scattering_element_spacing, readDataset(), icedb::Examples::Shapes::ShapeDataBasic::required, icedb::Examples::Shapes::ScopedHandles::ScopedHandle< HandleType, InvalidValueClass, CloseMethod >::valid(), icedb::error::xAssert, and icedb::error::xBadInput.

Referenced by main().

138  {
139  using namespace std;
140  ShapeDataBasic shpdata;
141  // The particle index is not specific enough. Let's use the filename for an id.
142  boost::filesystem::path p(filename);
143  auto pfile = p.filename();
144 #if BOOST_VERSION < 104600
145  string id = pfile.c_str(); // Needed for older RHEL machines
146 #else
147  string id = pfile.string().c_str(); // Totally assuming a lack of non-Latin characters in the path.
148 #endif
149 
150  ScopedHandles::H5F_handle hFile(H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT));
152  .add("Reason", "Cannot open a netCDF/HDF5 file.")
153  .add("Filename", filename);
154 
155  // A valid PSU file has these tables: particle_index, sphere_index, r, x, y, z.
156  // particle_index has one row, one column.
157  // The rest have one column, and a number of rows that correspond to the number of spheres used to represent the particle.
158 
159  auto verifyDatasetExists = [](hid_t file_id, const char* dataset_name) -> bool {
160  if ((H5Lexists(file_id, dataset_name, H5P_DEFAULT) <= 0)) return false;
161  H5O_info_t objinfo;
162  if ((H5Oget_info_by_name(file_id, dataset_name, &objinfo, H5P_DEFAULT) < 0)) return false;
163  if (objinfo.type != H5O_TYPE_DATASET) return false;
164  return true;
165  };
166 
167  if (!verifyDatasetExists(hFile.h, "/particle_index")
168  || !verifyDatasetExists(hFile.h, "/sphere_index")
169  || !verifyDatasetExists(hFile.h, "/r")
170  || !verifyDatasetExists(hFile.h, "/x")
171  || !verifyDatasetExists(hFile.h, "/y")
172  || !verifyDatasetExists(hFile.h, "/z"))
174  .add("Reason", "This file does not have the proper structure for a Penn State geometry file.")
175  .add("Filename", filename);
176 
177  // Open all of the datasets. Make sure that they have the correct dimensionality.
178  // Read the data into vectors. Verify that the data have the appropriate sizes.
179  vector<float> xs, ys, zs, rs;
180  vector<int32_t> sphere_indices;
181 
182  // No need to read particle_index. Not being used.
183  readDataset<int32_t>(hFile.h, "/sphere_index", sphere_indices);
184  readDataset<float>(hFile.h, "/r", rs);
185  readDataset(hFile.h, "/x", xs);
186  readDataset(hFile.h, "/y", ys);
187  readDataset(hFile.h, "/z", zs);
188 
189  // Check that the read arrays have matching sizes.
190  const size_t numPoints = rs.size();
191  if (numPoints != xs.size()) ICEDB_throw(icedb::error::error_types::xAssert);
192  if (numPoints != ys.size()) ICEDB_throw(icedb::error::error_types::xAssert);
193  if (numPoints != zs.size()) ICEDB_throw(icedb::error::error_types::xAssert);
194  if (numPoints != sphere_indices.size()) ICEDB_throw(icedb::error::error_types::xAssert);
195 
196  // Finally, pack the data in the shpdata structure.
197  shpdata.required.number_of_particle_scattering_elements = static_cast<uint64_t>(numPoints);
198  shpdata.required.number_of_particle_constituents = 1;
199  shpdata.required.particle_id = filename; // TODO: improve this
200  shpdata.required.particle_scattering_element_coordinates_are_integral = false;
201 
205  shpdata.required.particle_scattering_element_coordinates.resize(3 * numPoints);
206  for (size_t i = 0; i < numPoints; ++i) {
207  shpdata.required.particle_scattering_element_coordinates[(3 * i) + 0] = xs[i];
208  shpdata.required.particle_scattering_element_coordinates[(3 * i) + 1] = ys[i];
209  shpdata.required.particle_scattering_element_coordinates[(3 * i) + 2] = zs[i];
210  }
211 
212  shpdata.optional.particle_constituent_single_name = "ice";
213  shpdata.optional.particle_scattering_element_spacing = 0.001f; // 1 mm
214  shpdata.optional.particle_scattering_element_radius = rs;
215 
216 
217  return shpdata;
218  }
void readDataset(hid_t file_id, const char *dataset_name, std::vector< T > &outdata)
Definition: shapeIOpsu.cpp:90
STL namespace.
#define ICEDB_throw(x)
Definition: error.hpp:88
ScopedHandle< hid_t, InvalidHDF5Handle, CloseHDF5File > H5F_handle
Definition: shapeIOpsu.cpp:68
Here is the call graph for this function:
Here is the caller graph for this function:

◆ readRawText()

ShapeDataBasic icedb::Examples::Shapes::readRawText ( const char *  iin)

Simple file assuming one substance, with 3-column rows, each representing a single point. ADDA allows comment lines at the beginning of the file. Each line starts with a '#'.

Definition at line 317 of file shapeIOtextParsers.cpp.

References icedb::Examples::Shapes::ShapeRequiredData::number_of_particle_constituents, icedb::Examples::Shapes::ShapeRequiredData::number_of_particle_scattering_elements, icedb::Examples::Shapes::ShapeDataBasic::optional, anonymous_namespace{shapeIOtextParsers.cpp}::parse_shapefile_entries(), icedb::Examples::Shapes::ShapeCommonOptionalData::particle_constituent_number, icedb::Examples::Shapes::ShapeRequiredData::particle_id, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_scattering_element_composition_whole, icedb::Examples::Shapes::ShapeRequiredData::particle_scattering_element_coordinates, icedb::Examples::Shapes::ShapeRequiredData::particle_scattering_element_coordinates_are_integral, and icedb::Examples::Shapes::ShapeDataBasic::required.

Referenced by m_atoi(), and readTextFile().

318  {
319  using namespace std;
320  ShapeDataBasic res;
321  //Eigen::Vector3f crdsm, crdsi; // point location and diel entries
322  const char* pa = iin; // Start of the file
323  const char* pb = strchr(pa + 1, '\0'); // End of the file
324  const char* pNumStart = pa;
325  // Search for the first line that is not a comment.
326  // Nmat lines for ADDA are also ignored.
327  while ((pNumStart[0] == '#' || pNumStart[0] == 'N' || pNumStart[0] == 'n') && pNumStart < pb) {
328  const char* lineEnd = strchr(pNumStart + 1, 'n');
329  pNumStart = lineEnd + 1;
330  }
331  if (pNumStart >= pb) throw(std::invalid_argument("Cannot find any points in a shapefile."));
332 
333  const char* firstLineEnd = strchr(pNumStart + 1, '\n'); // End of the first line containing numberic data.
334  // Attempt to guess the number of points based on the number of lines in the file.
335  int guessNumPoints = std::count(pNumStart, pb, '\n');
336  std::vector<float> firstLineVals; //(numPoints*8);
337  //std::vector<float> &parser_vals = res.required.particle_scattering_element_coordinates;
338  std::vector<float> parser_vals;
339  parser_vals.reserve(guessNumPoints * 4);
340  parse_shapefile_entries(pNumStart, pb, parser_vals);
341  const void* floatloc = memchr(pNumStart, '.', pb - pNumStart);
342  res.required.particle_scattering_element_coordinates_are_integral = (floatloc) ? 0 : 1;
343 
344  parse_shapefile_entries(pNumStart, firstLineEnd, firstLineVals);
345 
346  size_t numCols = firstLineVals.size();
347  bool good = false;
348  if (numCols == 3) good = true; // Three columns, x, y and z
349  if (numCols == 4) good = true; // Four columns, x, y, z and material
350  if (!good) throw (std::invalid_argument("Bad read"));
351  if (parser_vals.size() == 0) throw (std::invalid_argument("Bad read"));
352 
353  size_t actualNumPoints = parser_vals.size() / numCols;
354  assert(actualNumPoints == guessNumPoints);
355 
356  res.required.number_of_particle_scattering_elements = actualNumPoints;
357  if (numCols == 3) {
358  res.required.number_of_particle_constituents = 1;
359  res.required.particle_scattering_element_coordinates = parser_vals;
360  }
361  else if (numCols == 4) {
362  // Count the number of distinct materials
363  uint8_t max_constituent = 1;
364  for (size_t i = 0; i < actualNumPoints; ++i) {
365  auto constit = parser_vals[(4 * i) + 3];
366  assert(static_cast<uint8_t>(constit) < UINT8_MAX);
367  if (static_cast<uint8_t>(constit) > max_constituent)
368  max_constituent = static_cast<uint8_t>(constit);
369  }
370  res.required.number_of_particle_constituents = max_constituent;
371  res.optional.particle_constituent_number.resize(max_constituent);
372  for (size_t i = 0; i < max_constituent; ++i)
373  res.optional.particle_constituent_number[i] = static_cast<uint8_t>(i + 1); // assert-checked before
374 
375  res.required.particle_scattering_element_coordinates.resize(actualNumPoints * 3);
376  res.optional.particle_scattering_element_composition_whole.resize(actualNumPoints);
377  for (size_t i = 0; i < actualNumPoints; ++i) {
378  size_t crdindex = (3 * i);
379  size_t parserindex = (4 * i);
380  res.required.particle_scattering_element_coordinates[crdindex + 0] = parser_vals[parserindex + 0];
381  res.required.particle_scattering_element_coordinates[crdindex + 1] = parser_vals[parserindex + 1];
382  res.required.particle_scattering_element_coordinates[crdindex + 2] = parser_vals[parserindex + 2];
383  res.optional.particle_scattering_element_composition_whole[i] = static_cast<uint8_t>(parser_vals[parserindex + 3]);
384  }
385  }
386 
387  res.required.particle_id = "";
388 
389  return res;
390  }
STL namespace.
bool parse_shapefile_entries(Iterator first, Iterator last, std::vector< float > &v)
Parses space-separated shapefile entries.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ readTextFile()

ShapeDataBasic icedb::Examples::Shapes::readTextFile ( const std::string &  filename)

Definition at line 405 of file shapeIOtextParsers.cpp.

References readDDSCAT(), and readRawText().

Referenced by m_atoi(), main(), and readtask().

406  {
407  // Open the file and copy to a string. Check the first few lines to see if any
408  // alphanumeric characters are present. If there are, treat it as a DDSCAT file.
409  // Otherwise, treat as a raw text file.
410  std::ifstream in(filename.c_str());
411  std::ostringstream so;
412  boost::iostreams::copy(in, so);
413  std::string s = so.str();
414 
415  auto end = s.find_first_of("\n\0");
416  Expects(end != std::string::npos);
417  std::string ssub = s.substr(0,end);
418  auto spos = ssub.find_first_not_of("0123456789. \t\n");
419 
420  if (std::string::npos == spos) // This is a raw text file
421  return readRawText(s.c_str());
422  else return readDDSCAT(s.c_str()); // This is a DDSCAT file
423  //if ((std::string::npos != spos) && (spos < end)) {
424  // return readDDSCAT(s.c_str());
425  //}
426  //else {
427  // return readTextRaw(s.c_str());
428  //}
429  }
ShapeDataBasic readRawText(const char *iin)
ShapeDataBasic readDDSCAT(const char *in)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ strints_array_to_floats()

size_t icedb::Examples::Shapes::strints_array_to_floats ( const char *  in,
const size_t  inlen,
float *  out,
const size_t  outlen,
float &  max_element 
)

Definition at line 18 of file shapeIOtextParsers2.cpp.

Referenced by m_atoi().

20  {
21  max_element = 0;
22  size_t curout = 0;
23  // Accepts numbers of the form: [0-9]*
24  // No negatives, exponents or decimals.
25 
26  float numerator = 0;
27  assert(in);
28  const char* end = in + inlen;
29  bool readnums = false;
30  for (const char* cur = in; (cur <= end) && (curout < outlen); ++cur) {
31  if ((*cur <= '9') && (*cur >= '0')) {
32  numerator *= 10;
33  numerator += (*cur - '0');
34  readnums = true;
35  } else if(readnums){
36  out[curout] = numerator;
37  if (numerator > max_element) max_element = numerator;
38  curout++;
39  numerator = 0;
40  readnums = false;
41  }
42  }
43  return curout;
44  }
Here is the caller graph for this function:

◆ writeDDSCAT()

void icedb::Examples::Shapes::writeDDSCAT ( const std::string &  filename,
const ShapeDataBasic p 
)

Definition at line 255 of file shapeIOtextParsers.cpp.

References icedb::Examples::Shapes::ShapeRequiredData::number_of_particle_constituents, icedb::Examples::Shapes::ShapeRequiredData::number_of_particle_scattering_elements, icedb::Examples::Shapes::ShapeDataBasic::optional, icedb::Examples::Shapes::ShapeRequiredData::particle_id, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_scattering_element_composition_fractional, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_scattering_element_composition_whole, icedb::Examples::Shapes::ShapeRequiredData::particle_scattering_element_coordinates, icedb::Examples::Shapes::ShapeCommonOptionalData::particle_scattering_element_number, anonymous_namespace{shapeIOtextParsers.cpp}::print_shapefile_entries(), and icedb::Examples::Shapes::ShapeDataBasic::required.

256  {
257  using namespace std;
258  std::ofstream out(filename.c_str());
259 
260  out << p.required.particle_id << endl;
261  out << p.required.number_of_particle_scattering_elements << "\t= Number of lattice points" << endl;
262 
263  out << "1.0\t1.0\t1.0\t= target vector a1 (in TF)" << endl;
264  out << "0.0\t1.0\t0.0\t= target vector a2 (in TF)" << endl;
265  out << "1.0\t1.0\t1.0\t= d_x/d d_y/d d_x/d (normally 1 1 1)" << endl;
266 
267  //out << (*hdr)(X0, 0) << "\t" << (*hdr)(X0, 1) << "\t" << (*hdr)(X0, 2);
268  out << "0.0\t0.0\t0.0\t= X0(1-3) = location in lattice of target origin" << endl;
269  out << "\tNo.\tix\tiy\tiz\tICOMP(x, y, z)" << endl;
270  //size_t i = 1;
271 
272  const size_t numPoints = p.required.number_of_particle_scattering_elements;
273  std::vector<float> oi(numPoints * 7);
274 
275  for (size_t j = 0; j < numPoints; j++)
276  {
277  const float &x = p.required.particle_scattering_element_coordinates[j * 3+0];
278  const float &y = p.required.particle_scattering_element_coordinates[j * 3+1];
279  const float &z = p.required.particle_scattering_element_coordinates[j * 3+2];
280  if (p.optional.particle_scattering_element_number.empty()) {
281  oi[j * 7 + 0] = j+1;
282  }
283  else {
284  oi[j * 7 + 0] = p.optional.particle_scattering_element_number[j];
285  }
286  oi[j * 7 + 1] = x;
287  oi[j * 7 + 2] = y;
288  oi[j * 7 + 3] = z;
289 
290  uint64_t comp = 1;
291  if (p.required.number_of_particle_constituents > 1) {
292  if (p.optional.particle_scattering_element_composition_whole.size()) {
293  comp = p.optional.particle_scattering_element_composition_whole[j];
294  }
295  if (p.optional.particle_scattering_element_composition_fractional.size()) {
296  throw(std::invalid_argument("Cannot write a DDSCAT shape file with this type of dielectric!"));
297  }
298  }
299  oi[j * 7 + 4] = comp;
300  oi[j * 7 + 5] = comp;
301  oi[j * 7 + 6] = comp;
302  }
303 
304  std::string generated;
305  std::back_insert_iterator<std::string> sink(generated);
306  if (!print_shapefile_entries(sink, oi))
307  {
308  throw(std::invalid_argument("Somehow unable to print the shape points properly."));
309  }
310  out << generated;
311  }
bool print_shapefile_entries(OutputIterator &sink, Container const &v)
Used in quickly printing shapefile.
STL namespace.
Here is the call graph for this function:

◆ writeTextRaw()

void icedb::Examples::Shapes::writeTextRaw ( const std::string &  filename,
const ShapeDataBasic p 
)

Definition at line 392 of file shapeIOtextParsers.cpp.

References icedb::Examples::Shapes::ShapeRequiredData::particle_scattering_element_coordinates, anonymous_namespace{shapeIOtextParsers.cpp}::print_shapefile_pts(), and icedb::Examples::Shapes::ShapeDataBasic::required.

393  {
394  using namespace std;
395  std::ofstream out(filename.c_str());
396  std::string generated;
397  std::back_insert_iterator<std::string> sink(generated);
398  if (!print_shapefile_pts(sink, p.required.particle_scattering_element_coordinates))
399  {
400  throw(std::invalid_argument("Somehow unable to print the shape points properly."));
401  }
402  out << generated;
403  }
STL namespace.
bool print_shapefile_pts(OutputIterator &sink, Container const &v)
Here is the call graph for this function: