ATLAS Offline Software
Arrayrep.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // $Id: Arrayrep.cxx,v 1.3 2009-04-08 21:12:44 ssnyder Exp $
14 #include "CxxUtils/Arrayrep.h"
15 #include "CxxUtils/ArrayScanner.h"
16 #include <stdexcept>
17 #include <cassert>
18 #include <sstream>
19 
20 
21 namespace CaloRec {
22 
23 
34 void Arrayrep::init_sizes (bool resize_data /*= false*/)
35 {
36  // Don't do anything if we've already done this, or if the array
37  // is empty.
38  if (m_sizes.size() < m_shape.size())
39  {
40  // Calculate the m_sizes array.
41  unsigned int sz = 1;
42  unsigned int dim = m_shape.size();
43  m_sizes.resize (dim);
44  m_sizes[0] = 1;
45  for (unsigned int i=0; i < dim; i++) {
46  m_sizes[i] = sz;
47  sz *= m_shape[dim-1 - i];
48  }
49 
50  if (resize_data) {
51  // Resize m_data to the proper size.
52  m_data.resize (sz);
53  }
54  else {
55  // Check that m_data has the correct size.
56  assert (sz == m_data.size());
57  }
58  }
59 }
60 
61 
69 Arrayrep::Arrayrep (const std::vector<unsigned int>& shape)
70  : m_shape (shape)
71 {
72  // Set up m_sizes.
73  init_sizes (true);
74 }
75 
76 
86 Arrayrep::Arrayrep (const unsigned int shape[], unsigned int n)
87 {
88  // Copy the data into m_shape.
89  m_shape.reserve (n);
90  for (unsigned int i=0; i < n; i++)
91  m_shape.push_back (shape[i]);
92 
93  // Set up m_sizes.
94  init_sizes (true);
95 }
96 
97 
98 namespace {
99 
100 
108 void error (const std::string& context,
109  const std::string& msg)
110 {
111  throw std::runtime_error (msg + ": " + context);
112 }
113 
114 
127 void read_array (Arrayrep& rep,
128  ArrayScanner& s,
129  unsigned int nest,
130  const std::string& context)
131 {
132  // The first time we handle a subarray at a given nesting, we don't
133  // know the size for that dimension, so we should just take what
134  // we're given. After that, though, we should be sure that the
135  // size matches what was used before (a rectangular array).
136  bool know_size = false;
137  if (rep.m_shape.size() > nest) {
138  // We know what the size should be.
139  know_size = true;
140  }
141  else {
142  // We don't know the size yet. Go ahead and push a dummy
143  // entry in m_shape; we'll update it later.
144  rep.m_shape.push_back (0);
145  }
146 
147  // Number of array elements (each of which could be a subarray)
148  // which we're read.
149  unsigned int n = 0;
150 
151  // Are we now looking at plain elements or at a nested subarray?
152  if (s.at_open()) {
153  // A nested subarray.
154  // Disallow constructions like
155  // [[1], [[2]]]
156  // Maximum nesting must be the same in all subarrays.
157  if (rep.m_data.size() > 0 && nest >= rep.m_shape.size())
158  error (context, "Bad array nesting");
159 
160  // Read the subarrays as long as we keep seeing more.
161  do {
162  read_array (rep, s, nest+1, context);
163  ++n;
164  } while (s.at_open());
165  }
166  else {
167  // Plain elements. Read them as long as we keep seeing them.
168  Arrayelt elt;
169  while (s.at_num (elt)) {
170  rep.m_data.push_back (elt);
171  ++n;
172  }
173  }
174 
175  // We should now be at a closing bracket.
176  if (!s.at_close())
177  error (context, "Missing close bracket");
178 
179  if (!know_size) {
180  // We didn't yet know the size for this dimension. Fill it in now.
181  rep.m_shape[nest] = n;
182  }
183  else if (rep.m_shape[nest] != n) {
184  // What we got doesn't match the size for this dimension we've
185  // seen earlier. Complain.
186  error (context, "Array not rectangular");
187  }
188 }
189 
190 
191 } // anonymous namespace
192 
193 
202 Arrayrep::Arrayrep (const std::string& str, const std::string& context /*=""*/)
203 {
204  // Special cases for True and False.
205  if (str == "True")
206  m_data.push_back (1);
207  else if (str == "False")
208  m_data.push_back (0);
209  else {
210  // Make the token stream from which we're reading.
211  std::istringstream is (str);
212  ArrayScanner s (is);
213 
214  // If we're looking at an open bracket, consume it, and proceed
215  // to read an array.
216  if (s.at_open())
217  read_array (*this, s, 0, context);
218  else {
219  // Otherwise, we're reading a scalar. So read a single number.
220  Arrayelt elt;
221  if (!s.at_num (elt))
222  error (context, "Number expected");
223  m_data.push_back (elt);
224  }
225 
226  // We should now be at the end of the stream.
227  if (!s.at_end())
228  error (context, "End of vector before end of string");
229  }
230 
231  // Set up the m_sizes vector.
232  init_sizes();
233 }
234 
235 
245 void Arrayrep::write_array(std::ostream& stream) const {
246  if (!m_data.size()) {//Empty array
247  stream << "[ ]" << std::endl;
248  return;
249  }
250 
251  if (!m_shape.size()) {//Single element
252  stream << m_data[0] << std::endl;
253  return;
254  }
255 
256  //All other cases: Array of dimension>=1
257  //check consistency of Array
258  unsigned totSize=m_shape[0];
259  for (unsigned i=1;i<m_shape.size();i++)
260  totSize=totSize*m_shape[i];
261  if (totSize!=m_data.size())
262  error("","Array is inconsistent!");
263 
264  std::vector<Arrayelt>::size_type dataIndex=0;
265  write_subarray(stream,dataIndex,0);
266  stream << "]" << std::endl;
267  return;
268 }
269 
270 
279 void Arrayrep::write_subarray(std::ostream& stream, std::vector<Arrayelt>::size_type& idx, unsigned dimIndex) const {
280  if (dimIndex<(m_shape.size()-1)) {
281  stream << "[\n ";
282  for (unsigned i=0;i<m_shape[dimIndex];i++) {
283  write_subarray(stream,idx,dimIndex+1);
284  if (i==m_shape[dimIndex]-1)
285  stream << "]\n ";
286  else
287  stream << "],\n ";
288  }
289  }
290  else { // last dimension
291  stream << "[" << m_data[idx++];
292  for (unsigned i=1;i<m_shape[dimIndex];i++)
293  stream << ", " << m_data[idx++];
294  }
295  return;
296 }
297 
298 
299 
300 } // namespace CxxUtils
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
yodamerge_tmp.dim
dim
Definition: yodamerge_tmp.py:239
fitman.sz
sz
Definition: fitman.py:527
make_hlt_rep.rep
rep
Definition: make_hlt_rep.py:32
AthenaPoolTestWrite.stream
string stream
Definition: AthenaPoolTestWrite.py:12
CxxUtils::ArrayScanner
Helper class for converting strings to Array's.
Definition: ArrayScanner.h:40
CaloRec::Arrayrep::m_data
std::vector< Arrayelt > m_data
The array data, stored using the C array ordering.
Definition: Control/CxxUtils/CxxUtils/Arrayrep.h:102
lumiFormat.i
int i
Definition: lumiFormat.py:92
CaloRec::Arrayrep::m_sizes
std::vector< unsigned int > m_sizes
Subarray sizes, for faster access.
Definition: Control/CxxUtils/CxxUtils/Arrayrep.h:110
Arrayrep.h
Representation class for Array's.
beamspotman.n
n
Definition: beamspotman.py:731
CaloRec::Arrayrep::init_sizes
void init_sizes(bool resize_data=false)
Initialize the m_sizes vector from the m_shape vector.
Definition: Arrayrep.cxx:34
CaloRec::Arrayrep::write_subarray
void write_subarray(std::ostream &stream, std::vector< Arrayelt >::size_type &idx, unsigned dimIndex) const
Helper function for write_array.
Definition: Arrayrep.cxx:279
CaloRec::Arrayelt
float Arrayelt
The type of an element of an Array.
Definition: Control/CxxUtils/CxxUtils/Arrayrep.h:26
CaloRec::Arrayrep::m_shape
std::vector< unsigned int > m_shape
The array shape.
Definition: Control/CxxUtils/CxxUtils/Arrayrep.h:106
CaloRec
Namespace for helper functions.
Definition: CaloCellFactor.h:22
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
str
Definition: BTagTrackIpAccessor.cxx:11
CaloRec::Arrayrep::write_array
void write_array(std::ostream &stream) const
Creates a text representation of the array content.
Definition: Arrayrep.cxx:245
get_generator_info.error
error
Definition: get_generator_info.py:40
CaloRec::Arrayrep::Arrayrep
Arrayrep()
Default constructor.
Definition: Control/CxxUtils/CxxUtils/Arrayrep.h:68
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
ArrayScanner.h
Helper class for converting strings to Array's.