LALSimulation  5.4.0.1-fe68b98
LALSimReadData.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2013 Jolien Creighton
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with with program; see the file COPYING. If not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 */
19 
20 #define _GNU_SOURCE /* for realpath() */
21 
22 #include <config.h>
23 #include <stdlib.h>
24 #include <limits.h>
25 #include <string.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #include <lal/FileIO.h>
30 #include <lal/LALStdlib.h>
31 #include <lal/LALString.h>
32 #include <lal/LALSimReadData.h>
33 
34 #ifndef PAGESIZE
35 #ifdef _SC_PAGE_SIZE
36 #define PAGESIZE _SC_PAGE_SIZE
37 #else
38 #define PAGESIZE 1024
39 #endif
40 #endif
41 #ifndef LINE_MAX
42 #ifdef _SC_LINE_MAX
43 #define LINE_MAX _SC_LINE_MAX
44 #else
45 #define LINE_MAX 1024
46 #endif
47 #endif
48 
49 
50 /**
51  * @brief Opens a specified data file, searching default path if necessary.
52  * @details Opens a data file for input with a specified path name.
53  * If the path name is an absolute path then this specific file is opened;
54  * otherwise, search for the file in paths given in the environment variable
55  * LAL_DATA_PATH, and finally search in the installed PKG_DATA_DIR path.
56  * @param[in] fname The path of the file to open.
57  * @return A pointer to a LALFILE structure or NULL on failure.
58  */
59 LALFILE *XLALSimReadDataFileOpen(const char *fname)
60 {
61  LALFILE *fp = NULL;
62  char *path = XLAL_FILE_RESOLVE_PATH(fname);
63  if (!path) /* could not find file */
64  XLAL_ERROR_FAIL(XLAL_EIO, "Could not find data file %s\n", fname);
66  if (!fp) /* open failure */
67  XLAL_ERROR_FAIL(XLAL_EIO, "Could not open data file %s\n", path);
68 XLAL_FAIL:
69  XLALFree(path);
70  return fp;
71 }
72 
73 
74 /**
75  * @brief Read a two-column data file.
76  * @details Read a data file containing two whitespace separated columns
77  * of data and create two arrays containing the data in each column.
78  * If any line begins with the character '#' then it is ignored.
79  * @param[out] xdat The x-data stored in the first column.
80  * @param[out] ydat The y-data stored in the second column.
81  * @param fp Pointer to a LALFILE structure opened for input.
82  * @return The number of data points read or <0 if an error occurs.
83  */
84 size_t XLALSimReadDataFile2Col(double **xdat, double **ydat, LALFILE * fp)
85 {
86  char line[LINE_MAX];
87  size_t size = PAGESIZE;
88  size_t lnum = 0;
89  size_t npts;
90  *xdat = XLALMalloc(size * sizeof(**xdat));
91  *ydat = XLALMalloc(size * sizeof(**ydat));
92  npts = 0;
93  while (XLALFileGets(line, sizeof(line), fp)) {
94  ++lnum;
95  if (strchr(line, '\n') == NULL) { /* line too long */
96  XLALFree(*xdat);
97  XLALFree(*ydat);
98  XLAL_ERROR(XLAL_EIO, "Line %zd too long\n", lnum);
99  }
100  if (*line == '#') /* ignore lines beginning with a '#' */
101  continue;
102  if (sscanf(line, "%lf %lf", *xdat + npts, *ydat + npts) != 2) {
103  XLALFree(*xdat);
104  XLALFree(*ydat);
105  XLAL_ERROR(XLAL_EIO, "Line %zd malformed\n", lnum);
106  }
107  if (++npts == size) {
108  size += PAGESIZE;
109  *xdat = XLALRealloc(*xdat, size * sizeof(**xdat));
110  *ydat = XLALRealloc(*ydat, size * sizeof(**ydat));
111  }
112  }
113  *xdat = XLALRealloc(*xdat, npts * sizeof(**xdat));
114  *ydat = XLALRealloc(*ydat, npts * sizeof(**ydat));
115  return npts;
116 }
117 
118 
119 /**
120  * @brief Read a multi-column data file.
121  * @details Read a data file containing multiple whitespace separated columns
122  * of data and create an array containing the data.
123  * If any line begins with the character '#' then it is ignored.
124  * The data is stored in the array in row-major format so that the data
125  * sample on row @c i (beginning with zero) and column @c j (beginning with
126  * zero) is found as the element <tt>[i * ncol + j]</tt> where @c ncol is the
127  * number of columns.
128  * @param[out] data The data stored in row-major order.
129  * @param[out] ncol The number of columns in the data file.
130  * @param fp Pointer to a LALFILE structure opened for input.
131  * @return The number of rows read or (size_t)(-1) if an error occurs.
132  */
133 size_t XLALSimReadDataFileNCol(double **data, size_t *ncol, LALFILE *fp)
134 {
135  char line[LINE_MAX];
136  size_t page = PAGESIZE;
137  size_t size = 0;
138  size_t lnum = 0;
139  size_t nrow = 0;
140 
141  *data = NULL;
142  *ncol = 0;
143  while (XLALFileGets(line, sizeof(line), fp)) {
144  char *s;
145  char *endp;
146  size_t col;
147 
148  ++lnum;
149 
150  if (strchr(line, '\n') == NULL) { /* line too long */
151  XLALFree(*data);
152  XLAL_ERROR(XLAL_EIO, "Line %zd too long\n", lnum);
153  }
154 
155  if (*line == '#') /* ignore lines beginning with '#' */
156  continue;
157 
158  if (*ncol == 0) { /* count columns on first line */
159  endp = line;
160  while (1) {
161  s = endp;
162  /* work around bug in glibc < 2.16
163  * http://sourceware.org/bugzilla/show_bug.cgi?id=13970 */
164  double v = strtod(s, &endp);
165  (void)v;
166  if (s == endp || *endp == '\0')
167  break;
168  ++*ncol;
169  }
170  if (*ncol == 0) {
171  XLALFree(*data);
172  XLAL_ERROR(XLAL_EIO, "Line %zd malformed\n", lnum);
173  }
174  }
175 
176  if (nrow == size) { /* allocate more memory for data */
177  size += page;
178  *data = XLALRealloc(*data, *ncol * size * sizeof(**data));
179  }
180 
181  /* scan line for data values in each column */
182  endp = line;
183  for (col = 0; col < *ncol; ++col) {
184  s = endp;
185  (*data)[*ncol * nrow + col] = strtod(s, &endp);
186  if (s == endp || *endp == '\0') {
187  XLALFree(*data);
188  XLAL_ERROR(XLAL_EIO, "Line %zd malformed\n", lnum);
189  }
190  }
191 
192  ++nrow;
193  }
194 
195  *data = XLALRealloc(*data, *ncol * nrow * sizeof(**data));
196 
197  return nrow;
198 }
#define PAGESIZE
size_t XLALSimReadDataFile2Col(double **xdat, double **ydat, LALFILE *fp)
Read a two-column data file.
#define LINE_MAX
size_t XLALSimReadDataFileNCol(double **data, size_t *ncol, LALFILE *fp)
Read a multi-column data file.
LALFILE * XLALSimReadDataFileOpen(const char *fname)
Opens a specified data file, searching default path if necessary.
int s
Definition: bh_qnmode.c:137
sigmaKerr data[0]
char * XLALFileGets(char *s, int size, LALFILE *file)
LALFILE * XLALFileOpenRead(const char *path)
#define XLAL_FILE_RESOLVE_PATH(fname)
void * XLALMalloc(size_t n)
void * XLALRealloc(void *p, size_t n)
void XLALFree(void *p)
#define XLAL_ERROR(...)
#define XLAL_ERROR_FAIL(...)
XLAL_EIO
path
FILE * fp