The read_table-lib library provides functionalities for reading text (and binary) data files. To use this library, add a %include "read_table-lib" in your component definition DECLARE or SHARE section. Tables are structures of type t_Table (see read_table-lib.h file for details):
1 /* t_Table structure (most important members) */ 2 double *data; /* Use Table_Index(Table, i j) to extract [i,j] element */ 3 long rows; /* number of rows */ 4 long columns; /* number of columns */ 5 char *header; /* the header with comments */ 6 char *filename; /* file name or title */ 7 double min_x; /* minimum value of 1st column/vector */ 8 double max_x; /* maximum value of 1st column/vector */
Available functions to read a single vector/matrix are:
Table_Init(&\(Table\), \(rows\), \(columns\)) returns an allocated Table structure. Use \(rows=columns=0\) not to allocate memory and return an empty table. Calls to Table_Init are optional, since initialization is being performed by other functions already.
Table_Read(&\(Table\), \(filename\), \(block\)) reads numerical block number \(block\) (0 to catenate all) data from text file \(filename\) into \(Table\), which is as well initialized in the process. The block number changes when the numerical data changes its size, or a comment is encoutered (lines starting by ’# ; % /’). If the data could not be read, then \(Table.data\) is NULL and \(Table.rows = 0\). You may then try to read it using Table_Read_Offset_Binary. Return value is the number of elements read.
Table_Read_Offset(&\(Table\), \(filename\), \(block\), &offset, \(n_{rows}\)) does the same as Table_Read except that it starts at offset offset (0 means begining of file) and reads \(n_{rows}\) lines (0 for all). The offset is returned as the final offset reached after reading the \(n_{rows}\) lines.
Table_Read_Offset_Binary(&\(Table\), \(filename\), \(type\), \(block\), &offset, \(n_{rows}\), \(n_{columns}\)) does the same as Table_Read_Offset, but also specifies the \(type\) of the file (may be ”float” or ”double”), the number \(n_{rows}\) of rows to read, each of them having \(n_{columns}\) elements. No text header should be present in the file.
Table_Rebin(&\(Table\)) rebins all \(Table\) rows with increasing, evenly spaced first column (index 0), e.g. before using Table_Value. Linear interpolation is performed for all other columns. The number of bins for the rebinned table is determined from the smallest first column step.
Table_Info\((Table)\) print information about the table \(Table\).
Table_Index(\(Table, m, n\)) reads the \(Table[m][n]\) element.
Table_Value(\(Table, x, n\)) looks for the closest \(x\) value in the first column (index 0), and extracts in this row the \(n\)-th element (starting from 0). The first column is thus the ’x’ axis for the data.
Table_Free(&\(Table\)) free allocated memory blocks.
Table_Value2d(\(Table\), \(X\), \(Y\)) Uses 2D linear interpolation on a Table, from (X,Y) coordinates and returns the corresponding value.
Available functions to read an array of vectors/matrices in a text file are:
Table_Read_Array(\(File\), &\(n\)) read and split \(file\) into as many blocks as necessary and return a t_Table array. Each block contains a single vector/matrix. This only works for text files. The number of blocks is put into \(n\).
Table_Free_Array(&\(Table\)) free the \(Table\) array.
Table_Info_Array(&\(Table\)) display information about all data blocks.
The format of text files is free. Lines starting by ’# ; % /’ characters are considered to be comments, and stored in \(Table.header\). Data blocks are vectors and matrices. Block numbers are counted starting from 1, and changing when a comment is found, or the column number changes. For instance, the file ’MCXTRACE/data/Rh.txt’ (Material data for Rhodium) looks like:
1#Rh (Z 45) 2#Atomic weight: A[r] 102.9055 3#Nominal density: rho 1.2390E+01 4# sigma[a](barns/atom) = [mu/rho](cm\^2 g\^-1) . 1.70879E+02 5# E(eV) [mu/rho](cm\^2 g\^-1) = f[2](e atom\^-1) . 4.08922E+05 6# 14 edges. Edge energies (keV): 7# 8# 9# K 2.32199E+01 L I 3.41190E+00 L II 3.14610E+00 L III 3.00380E+00 10# M I 6.27100E-01 M II 5.21000E-01 M III 4.96200E-01 M IV 3.11700E-01 11# M V 3.07000E-01 N I 8.10000E-02 N II 4.79000E-02 N III 4.79000E-02 12# N IV 2.50000E-03 N V 2.50000E-03 13# 14# Relativistic correction estimate f[rel] (H82,3/5CL) = -4.0814E-01, 15# -2.5440E-01 e atom\^-1 16# Nuclear Thomson correction f[NT] = -1.0795E-02 e atom\^-1 17# 18#------------------------------------------------------------------------------- 19#Form Factors, Attenuation and Scattering Cross-sections 20#Z=45, E = 0.001 - 433 keV 21# 22# E f[1] f[2] [mu/rho] [sigma/rho] [mu/rho] [mu/rho][K] lambda 23# Photoelectric Coh+inc Total 24# keV e atom\^-1 e atom\^-1 cm\^2 g\^-1 cm\^2 g\^-1 cm\^2 g\^-1 cm\^2 g\^-1 nm 251.069000E-02 1.89417E+00 4.8055E+00 1.8382E+05 1.1514E-04 1.8382E+05 0.000E+00 1.160E+02 261.142761E-02 2.09662E+00 5.1028E+00 1.8260E+05 1.5865E-04 1.8260E+05 0.000E+00 1.085E+02 271.221612E-02 2.32705E+00 5.4019E+00 1.8082E+05 2.1741E-04 1.8082E+05 0.000E+00 1.015E+02 281.305903E-02 2.58575E+00 5.6998E+00 1.7848E+05 2.9628E-04 1.7848E+05 0.000E+00 9.494E+01 291.396010E-02 2.87263E+00 5.9931E+00 1.7555E+05 4.0158E-04 1.7555E+05 0.000E+00 8.881E+01 301.492335E-02 3.18714E+00 6.2786E+00 1.7204E+05 5.4136E-04 1.7204E+05 0.000E+00 8.308E+01 311.595306E-02 3.52819E+00 6.5531E+00 1.6797E+05 7.2588E-04 1.6797E+05 0.000E+00 7.772E+01 321.705382E-02 3.89415E+00 6.8134E+00 1.6337E+05 9.6809E-04 1.6337E+05 0.000E+00 7.270E+01 33 ...
Binary files should be of type ”float” (i.e. REAL*32) and ”double” (i.e. REAL*64), and should not contain text header lines. These files are platform dependent (little or big endian).
The \(filename\) is first searched into the current directory (and all user additional locations specified using the -I option, see the ’Running McXtrace ’ chapter in the User Manual), and if not found, in the data sub-directory of the MCXTRACE library location. This way, you do not need to have local copies of the McXtrace Library Data files (see table 1.1).
A usage example for this library part may be:
1 t_Table Table; // declare a t_Table structure 2 char file[]="Rh.txt"; // a file name 3 double x,y; 4 5 Table_Read(&Table, file, 1); // initialize and read the first numerical block 6 Table_Info(Table); // display table informations 7 ... 8 x = Table_Index(Table, 2,5); // read the 3rd row, 6th column element 9 // of the table. Indexes start at zero in C. 10 y = Table_Value(Table, 1.45,1); // look for value 1.45 in 1st column (x axis) 11 // and extract 2nd column value of that row 12 Table_Free(&Table); // free allocated memory for table
Additionally, if the block number (3rd) argument of Table_Read is 0, all blocks will be catenated. The Table_Value function assumes that the ’x’ axis is the first column (index 0). Other functions are used the same way with a few additional parameters, e.g. specifying an offset for reading files, or reading binary data.
This other example for text files shows how to read many data blocks:
1 t_Table *Table; // declare a t_Table structure array 2 long n; 3 double y; 4 5 Table = Table_Read_Array("file.dat", &n); // initialize and read the all numerical block 6 n = Table_Info_Array(Table); // display informations for all blocks (also returns n) 7 8 y = Table_Index(Table[0], 2,5); // read in 1st block the 3rd row, 6th column element 9 // ONLY use Table[i] with i < n ! 10 Table_Free_Array(Table); // free allocated memory for Table
You may look into, for instance, the source files for Lens_parab or Filter for other implementation examples.