EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
import.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file import.cxx
1 /* -------------------------------------------------------------------------- */
2 /* import.cc */
3 /* */
4 /* 'mgrid' package import routines. */
5 /* */
6 /* A.Kisselev, PNPI, St.Petersburg, Russia. */
7 /* e-mail: kisselev@hermes.desy.de */
8 /* -------------------------------------------------------------------------- */
9 
10 #include <cstdio>
11 #include <cstdlib>
12 #include <cassert>
13 #include <cstring>
14 
15 #include <ayk.h>
16 #include <Splitter.h>
17 #include <Mgrid.h>
18 
19 // Coordinates will be rounded in convert_cell_list_to_mgrid()
20 // (see source code) before doing anything else; well, in fact this
21 // rounding only affects step[] calculation; 1um is Ok?;
22 #define _COORD_ROUNDING_ (1E-4)
23 
24 /* ========================================================================== */
25 /* Later will have to rewrite this slightly, so that the whole file is read */
26 /* in and 'cell' pointer is assigned appropriately by hand; this way array */
27 /* may be used as a piece of shared memory; */
28 
29 Mgrid *import_field_map(char *file_name)
30 {
31  FILE *fin;
32  Mgrid *mgrid;
33 
34  // Check sizes of basic types;
35  if (!basic_types_match()) return NULL;
36 
37  // Of course file should be opened only once;
38  fin = fopen(file_name, "r");
39  if (!fin) return NULL;
40 
41  // All the rest is done recursively;
42  mgrid = new Mgrid(fin);
43 
44  fclose(fin);
45 
46  // Yes, it can be zero; no sense to check;
47  return mgrid;
48 } /* import_field_map */
49 
50 /* ========================================================================== */
51 /* Want them as functions, since they are explicitely used as extra arguments */
52 /* to import_ascii_map; */
53 
54 static double tesla2kgs_fun(double val)
55 {
56  return tesla2kgs(val);
57 } /* tesla2kgs_fun */
58 
59 /* -------------------------------------------------------------------------- */
60 
61 static double m2cm_fun(double val)
62 {
63  return m2cm(val);
64 } /* m2cm_fun */
65 
66 /* ========================================================================== */
67 /* Well, this intermeaidte call is a small slowdown; don't care; */
68 
69 static double import_value(const char *string, conversionfun fun)
70 {
71  double value = atof(string);
72 
73  if (fun) value = fun(value);
74 
75  return value;
76 } /* import_value */
77 
78 /* ========================================================================== */
79 /* 'coord_num' is needed because for instance in a 4-column file there is no */
80 /* way to decide whether it's 1 component in XYZ coordinates or say RZ */
81 /* component in RZ coordinates; 'component_num' is needed since like in */
82 /* recoil MC file there is an extra (unused) column; no memory clean up on */
83 /* error, sorry; */
84 
86 {
87  MgridCell *cell = cells, *bff;
88 
89  while (cell)
90  {
91  bff = cell->next;
92 
93  free(cell);
94 
95  cell = bff;
96  } /*while*/
97 } /* release_cell_list_ram */
98 
99 /* ========================================================================== */
100 /* This routine only cares to restore the correct order (ie XYZ/RFZ); */
101 /* 2->3 mapping and stuff like this will be done in */
102 /* calculate_expansion_rules() later; routine is inefficient, don't care; */
103 
104 static void calculate_swapping_rules(t_ascii_coord *coord, int swap[])
105 {
106  char buffer[coord->coord_num], bff;
107 
108  // Fill out intermediate array of characters to be ordered;
109  for(int ii=0; ii<coord->coord_num; ii++)
110  buffer[ii] = coord->coord_names[ii];
111 
112  // Reorder buffer[] array;
113  for(int ii=0; ii<coord->coord_num-1; ii++)
114  for(int ik=0; ik<coord->coord_num-1; ik++)
115  {
116  t_coord_name *left = find_coord_by_name(coord->system_type, buffer[ik]);
117  t_coord_name *right = find_coord_by_name(coord->system_type, buffer[ik+1]);
118  // Should not happen, since create_coord_system()
119  // succeeded few lines above on the same 'coord' frame;
120  assert(left && right);
121 
122  if (left->id > right->id)
123  {
124  bff = buffer[ik];
125  buffer[ik] = buffer[ik+1];
126  buffer[ik+1] = bff;
127  } /*if*/
128  } /*for..for*/
129 
130  // Now check out the correct order and assign swap[] array;
131  for(int ii=0; ii<coord->coord_num; ii++)
132  for(int ik=0; ik<coord->coord_num; ik++)
133  {
134  if (coord->coord_names[ii] == buffer[ik])
135  {
136  swap[ii] = ik;
137  break;
138  } /*if*/
139  } /*for..for*/
140 } /* calculate_swapping_rules */
141 
142 /* ========================================================================== */
143 /* NB: this procedure expects that only non-fake xx[] are put in cell */
144 /* frames (and this is done in a proper sequence - for instance RZ coordinates*/
145 /* are put in this sequence and not as ZR); so all arrays here are compressed */
146 /* accordingly; */
147 
149  CoordSystem *field, int split_mode, unsigned cell_contents_bits)
150 {
151  // Well, need to adapt to TVector3 and debug at some point;
152  assert(0);
153 #if _APR2014_
154  int idx, linear;
155  MgridCell *cell = cells, *out;
156  MgridDirection *fdir[coord->getCoordNum()];
157  int dim[coord->getCoordNum()];
158  double min[coord->getCoordNum()], max[coord->getCoordNum()];
159  double next_to_min[coord->getCoordNum()], *xx, step[coord->getCoordNum()];
160 
161  Mgrid *mgrid;
162  char chname[MGRID_NAME_LENGTH_MAX];
163  CoordSystem chfield;
164  double chmin[3], chmax[3];
165 
166  // Well, I guess I should require this?;
167  if (!(cell_contents_bits & _FIELD_COMPONENT_VALUES_)) return NULL;
168 
169  // Loop through all cells and figure out min/max points;
170  while (cell)
171  {
172  // Yes, to this moment mgrid->cell_xx_shift is not
173  // known --> calculate manually; and assume that cells in the list
174  // do not contain anything but field and coordinate values;
175  xx = cell->B + field->getCoordNum();
176 
177  // Ignore fake directions in all loops;
178  for(unsigned ik=0; ik<coord->getCoordNum(); ik++)
179  {
180  // Change limits if needed;
181  if (cell == cells || xx[ik] < min[ik]) min[ik] = xx[ik];
182  if (cell == cells || xx[ik] > max[ik]) max[ik] = xx[ik];
183  } /*for*/
184 
185  cell = cell->next;
186  } /*while*/
187 
188  // Figure out grid step (cell size); loop once again and figure
189  // out next to min point; is it more efficient than reordering
190  // during first while?; hmm;
191  for(unsigned ik=0; ik<coord->getCoordNum(); ik++)
192  next_to_min[ik] = max[ik];
193  cell = cells;
194  while (cell)
195  {
196  xx = cell->B + field->getCoordNum();
197 
198  for(unsigned ik=0; ik<coord->getCoordNum(); ik++)
199  // if (xx[ik] < next_to_min[ik] && xx[ik] != min[ik])
200  if (xx[ik] < next_to_min[ik] && (xx[ik] - min[ik]) > _COORD_ROUNDING_)
201  next_to_min[ik] = xx[ik];
202 
203  cell = cell->next;
204  } /*while*/
205  for(unsigned ik=0; ik<coord->getCoordNum(); ik++)
206  {
207  // NB: step will be calculated once again in initialize_mgrid();
208  // since there it will be (max-min)/dim, this minimizes impact
209  // of possible rounding errors in ASCII file had too short
210  // float format;
211  // NB: this will FAIL if there is a gap between min and next_to_min of
212  // more than 1 cell; what a piece of shit this code is!;
213  step[ik] = next_to_min[ik] - min[ik];
214  if (!step[ik]) step[ik] = 1.;
215 
216  // Shift min&max half-step outside (so
217  // that nodes are sitting cell centers;
218  min[ik] -= step[ik]/2.;
219  max[ik] += step[ik]/2.;
220 
221  // Well, no checks that all points are really sitting on a grid
222  // with this step&dim; user should bother himself;
223  dim[ik] = (int)rint((max[ik] - min[ik])/step[ik]);
224  } /*for*/
225 
226  // In case of a non-skewed grid create just a single mgrid; otherwise
227  // create a separate mgrid for each field component (even if 1);
228  if (split_mode == _SPLIT_ON_)
229  {
230  // Allocate and initialize mgrid HEAP header;
232  if (!mgrid || mgrid->initializeAsHeap()) return NULL;
233 
234  // Initialize children (component) mgrids;
235  assert(field->getCoordNum() == 3);
236  for(int ch=0; ch<3; ch++)
237  {
238  // Recalculate field coordinate system frame for 1 component;
239  // also here full 3D/XYZ case assumed;
240  chfield = *field;
241  chfield.setCoordNum(1);
242  for(int ik=0; ik<3; ik++)
243  if (ik != ch)
244  chfield.fake[ik] = 1;
245 
246  // Create direction frames; NB: all this works only
247  // in full 3D/XYZ case => no worries about remapping;
248  for(int ik=0; ik<3; ik++)
249  {
250  assert(!coord->fake[ik]);
251 
252  chmin[ik] = min[ik];
253  chmax[ik] = max[ik];
254 
255  //fdir[ik] = create_mgrid_direction(dim[ik], min[ik], max[ik]);
256  //if (!fdir[ik]) return NULL;
257  fdir[ik] = new MgridDirection(dim[ik], min[ik], max[ik]);
258  } /*for*/
259 
260  snprintf(chname, MGRID_NAME_LENGTH_MAX, "%s#%03d", mgrid->getName(), ch);
261  {
262  Mgrid *child = create_single_mgrid_header(chname, coord, &chfield,
263  fdir, cell_contents_bits);
264  // Do all the necessary initializations; '0': RAM cell size
265  // should match useful cell size;
266  if (!child || child->initializeAsSingleMgrid(0)) return NULL;
267 
268  //if (attach_mgrid_to_heap(mgrid, child)) return NULL;
269  if (child->attachToHeap(mgrid)) return NULL;
270  }
271  } /*for*/
272 
273  // Eventually loop through all the cells and allocate data;
274  cell = cells;
275  while (cell)
276  {
277  xx = cell->B + field->getCoordNum();
278 
279  for(int ch=0; ch<3; ch++)
280  {
281  Mgrid *child = mgrid->children[ch];
282 
283  linear = child->compressedCoordToLinearAddr(xx);
284  // Should not happen; be paranoid;
285  assert(linear != -1);
286  out = child->linearAddrToCellPtr(linear);
287 
288  // Copy necessary cell fractions only;
289  out->B[0] = cell->B[ch];
290 
291  // Properties are stored in a separate array;
292  // of course, nothing bad happened up to now;
293  //child->properties[linear] = _SAFE_CELL_;
294  child->markCellAsSafe(linear);
295  } /*for*/
296 
297  cell = cell->next;
298  } /*while*/
299  }
300  else
301  {
302  // Create direction frames; all 3 must be present!; NB: xx[]
303  // were in correct order --> just skip few (no swapping needed);
304  idx = 0;
305  for(int ik=0; ik<3; ik++)
306  if (coord->fake[ik])
307  fdir[ik] = NULL;
308  else
309  {
310  //fdir[ik] = create_mgrid_direction(dim[idx], min[idx], max[idx]);
311  //if (!fdir[ik]) return NULL;
312  fdir[ik] = new MgridDirection(dim[idx], min[idx], max[idx]);
313 
314  idx++;
315  } /*if..for*/
316 
317  mgrid = create_single_mgrid_header(name, coord, field, fdir, cell_contents_bits);
318  // Do all the necessary initializations; '0': RAM cell size
319  // should match useful cell size;
320  if (!mgrid || mgrid->initializeAsSingleMgrid(0)) return NULL;
321 
322  // And eventually copy over useful fraction of
323  // temporary cell frames to their proper location;
324  cell = cells;
325  while (cell)
326  {
327  xx = cell->B + field->getCoordNum();
328 
329  linear = mgrid->compressedCoordToLinearAddr(xx);
330  // Should not happen; be paranoid;
331  assert(linear != -1);
332  out = mgrid->linearAddrToCellPtr(linear);
333 
334  // Copy necessary cell fractions only;
335  // assume that only field values need to be stored;
336  for(unsigned ik=0; ik<field->getCoordNum(); ik++)
337  out->B[ik] = cell->B[ik];
338  // memcpy(out, cell, mgrid->ram_cell_size);
339 
340  // Properties are stored in a separate array;
341  // of course, nothing bad happened up to now;
342  //mgrid->properties[linear] = _SAFE_CELL_;
343  mgrid->markCellAsSafe(linear);
344 
345  cell = cell->next;
346  } /*while*/
347  } /*if*/
348 
349  return mgrid;
350 #endif
351 } /* convert_cell_list_to_mgrid */
352 
353 /* ========================================================================== */
354 /* NB: this procedure puts only non-fake xx[] components in cell frames; */
355 /* it takes care itself to (possibly) swap the coordinates and field */
356 /* components so that they are in a proper /XYZ or RFZ/ sequence (for instance*/
357 /* if input file has colums in ZR sequence, cell->B[] will contain numbers in */
358 /* RZ sequence); */
359 
360 //
361 // -> this routine has never been checked since Splitter class introduction;
362 //
363 
364 Mgrid *import_ascii_field_map(char *file_name, char *mgrid_name, t_ascii_coord *coord,
365  t_ascii_coord *field, int lines_to_skip)
366 {
367  int ik, cswap[3], fswap[3], line_counter = 0;
368  //char buffer[STRING_LEN_MAX];
369  FILE *fmap;
370  int expected_column_num = coord->coord_num + field->coord_num;
371  Mgrid *mgrid;
372  MgridCell *cells = NULL, **tail = &cells, *cell;
373  double *xx;
374  CoordSystem *csystem, *fsystem;
375  Splitter *splitter = new Splitter();
376 
377  // This is clear, I need enough storage space; otherwise
378  // please increase _CELL_DATA_DIM_MAX_ and recompile;
379  assert(_CELL_DATA_DIM_MAX_ >= expected_column_num);
380 
381  // Create and verify coordinate system frames;
382  csystem = new CoordSystem(coord->system_type, coord->coord_num, coord->coord_names);
383  fsystem = new CoordSystem(field->system_type, field->coord_num, field->coord_names);
384  if (!csystem || !fsystem) return NULL;
385 
386  // Calculate remapping (swapping) arrays;
387  calculate_swapping_rules(coord, cswap);
388  calculate_swapping_rules(field, fswap);
389 
390  fmap = fopen(file_name, "r");
391  if (!fmap) return NULL;
392 
393  // Prefer to import everything, and only after this start
394  // handling data;
395  //while (fgets(buffer, STRING_LEN_MAX-1, fmap))
396  while (splitter->splitNextString(fmap) >= 0)
397  {
398  line_counter++;
399  if (line_counter <= lines_to_skip) continue;
400 
401  //if (split_string(buffer)) continue;
402 
403  // Well, may be MORE columns (like in recoil MC map);
404  if (splitter->getArgn() < expected_column_num) return NULL;
405 
406  // Allocate new cell;
407  cell = *tail = (MgridCell*)calloc(1, sizeof(MgridCell));
408  if (!cell) return NULL;
409 
410  // NB: want field components first in cell->B[];
411  for(ik=0; ik<field->coord_num; ik++)
412  cell->B[fswap[ik]] =
413  import_value(splitter->getArgp(coord->coord_num+ik), field->convfun);
414  // For a better readability;
415  xx = cell->B + field->coord_num;
416  for(ik=0; ik<coord->coord_num; ik++)
417  xx[cswap[ik]] = import_value(splitter->getArgp(ik), coord->convfun);
418 
419  tail = &cell->next;
420  } /*while*/
421 
422  fclose(fmap);
423 
424  // Now when all the lines are read in and are sitting in a linked
425  // list, call a general routine which works on this list; this
426  // routine can be called after one does a custom format file import;
427  mgrid = convert_cell_list_to_mgrid(cells, mgrid_name, csystem, fsystem,
429 
430  if (mgrid) mgrid->setCreationMethod(_ASCII_INPUT_);
431 
432  // Release linked list memory;
433  release_cell_list_ram(cells);
434 
435  delete splitter;
436 
437  return mgrid;
438 } /* import_ascii_field_map */
439 
440 /* ========================================================================== */