-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinit.c
303 lines (274 loc) · 9.65 KB
/
init.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
/*
* Metaann
*
* Copyright (C) 1990-2013 George B. Moody
* Copyright (C) 2014 Benjamin Moody
*
* Based on 'init.c' from the WAVE package (revised 18 November 2013);
* modified by Benjamin Moody, 22 August 2014.
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "wave.h"
#include "gtkwave.h"
static WFDB_Siginfo *df;
static int maxnsig;
void memerr()
{
g_warning("Insufficient memory");
}
void alloc_sigdata(ns)
int ns;
{
int i;
if ((df = realloc(df, ns * sizeof(WFDB_Siginfo))) == NULL ||
(signame = realloc(signame, ns * sizeof(char *))) == NULL ||
(sigunits = realloc(sigunits, ns * sizeof(char *))) == NULL ||
(calibrated = realloc(calibrated, ns * sizeof(char))) == NULL ||
(scope_v = realloc(scope_v, ns * sizeof(WFDB_Sample))) == NULL ||
(vref = realloc(vref, ns * sizeof(WFDB_Sample))) == NULL ||
(level_v = realloc(level_v, ns * sizeof(WFDB_Sample))) == NULL ||
(v = realloc(v, ns * sizeof(WFDB_Sample))) == NULL ||
(v0 = realloc(v0, ns * sizeof(WFDB_Sample))) == NULL ||
(vmax = realloc(vmax, ns * sizeof(WFDB_Sample))) == NULL ||
(vmin = realloc(vmin, ns * sizeof(WFDB_Sample))) == NULL ||
(vvalid = realloc(vvalid, ns * sizeof(int))) == NULL ||
(level_name_string =
realloc(level_name_string, ns * sizeof(char **))) == NULL ||
(level_value_string =
realloc(level_value_string, ns * sizeof(char **))) == NULL ||
(level_units_string =
realloc(level_units_string, ns * sizeof(char **))) == NULL ||
(vscale = realloc(vscale, ns * sizeof(double))) == NULL ||
(vmag = realloc(vmag, ns * sizeof(double))) == NULL ||
(dc_coupled = realloc(dc_coupled, ns * sizeof(int))) == NULL ||
(sigbase = realloc(sigbase, ns * sizeof(int))) == NULL ||
(blabel = realloc(blabel, ns * sizeof(char *))) == NULL /*||
(level_name =
realloc(level_name, ns * sizeof(Panel_item))) == NULL ||
(level_value =
realloc(level_value, ns * sizeof(Panel_item))) == NULL ||
(level_units =
realloc(level_units, ns * sizeof(Panel_item))) == NULL*/) {
memerr();
}
for (i = maxnsig; i < ns; i++) {
signame[i] = sigunits[i] = blabel[i] = NULL;
/*level_name[i] = level_value[i] = level_units[i] = (Panel_item)NULL;*/
dc_coupled[i] = scope_v[i] = vref[i] = level_v[i] = v[i] = v0[i] =
vmax[i] = vmin[i] = 0;
vscale[i] = vmag[i] = 1.0;
if ((level_name_string[i] = calloc(1, 12)) == NULL ||
(level_value_string[i] = calloc(1, 12)) == NULL ||
(level_units_string[i] = calloc(1, 12)) == NULL) {
memerr();
}
}
maxnsig = ns;
}
/* Open up a new ECG record. */
int record_init(s)
char *s;
{
char ts[RNLMAX+30];
int i, rebuild_list, tl;
/* Suppress error messages from the WFDB library. */
wfdbquiet();
/* Do nothing if the current annotation list has been edited and the
changes can't be saved. */
if (0 /*post_changes() == 0*/)
return (0);
/* Check to see if the signal list must be rebuilt. Normally, this is
done whenever the signal list is empty or if the record name has
changed, but accept_remote_command (see xvwave.c) can force record_init
not to rebuild the signal list by setting freeze_siglist. */
if (freeze_siglist)
freeze_siglist = rebuild_list = 0;
else
rebuild_list = (siglistlen == 0) | strcmp(record, s);
/* Save the name of the new record in local storage. */
g_strlcpy(record, s, RNLMAX);
/* Reset the frame title. */
set_frame_title();
/* Open as many signals as possible. */
nsig = isigopen(record, NULL, 0);
if (nsig > maxnsig)
alloc_sigdata(nsig);
nsig = isigopen(record, df, nsig);
/* Get time resolution for annotations in sample intervals. Except in
WFDB_HIGHRES mode (selected using the -H option), the resolution is
1 sample interval. In WFDB_HIGHRES mode, when editing a multi-frequency
record, the resolution for annotation times is 1 frame interval (i.e.,
getspf() sample intervals). */
atimeres = getspf();
/* By convention, a zero or negative sampling frequency is interpreted as
if the value were WFDB_DEFFREQ (from wfdb.h); the units are samples per
second per signal. */
if (nsig < 0 || (freq = sampfreq(NULL)) <= 0.) freq = WFDB_DEFFREQ;
setifreq(freq);
/* Inhibit the output of the 'time resolution' comment annotation unless
we are operating in high-resolution mode. */
if ((getgvmode() & WFDB_HIGHRES) == 0) setafreq(0.);
/* Quit if isigopen failed. */
if (nsig < 0)
sprintf(ts, "Record %s is unavailable\n", record);
if (nsig < 0) {
/*
#ifdef NOTICE
Xv_notice notice = xv_create((Frame)frame, NOTICE,
XV_SHOW, TRUE,
#else
(void)notice_prompt((Frame)frame, (Event *)NULL,
#endif
NOTICE_MESSAGE_STRINGS,
ts, 0,
NOTICE_BUTTON_YES, "Continue", 0);
#ifdef NOTICE
xv_destroy_safe(notice);
#endif
*/
g_warning("%s", ts);
return (0);
}
/* If the record has a low sampling rate, use coarse time scale and grid
mode. */
if (freq <= 10.0) {
tsa_index = coarse_tsa_index;
grid_mode = coarse_grid_mode;
/*mode_undo();*/
/*set_modes();*/
}
else {
tsa_index = fine_tsa_index;
grid_mode = fine_grid_mode;
/*mode_undo();*/
/*set_modes();*/
}
/* Set signal name pointers. Shorten the conventional "record x, signal n"
to "signal n". */
sprintf(ts, "record %s, ", record);
tl = strlen(ts);
for (i = 0; i < nsig; i++) {
if (strncmp(df[i].desc, ts, tl) == 0)
signame[i] = df[i].desc + tl;
else
signame[i] = df[i].desc;
if (df[i].units == NULL || *df[i].units == '\0')
sigunits[i] = "mV";
else
sigunits[i] = df[i].units;
/* Replace any unspecified signal gains with the default gain from
wfdb.h; the units of gain are ADC units per physical unit. */
if (df[i].gain == 0) {
calibrated[i] = 0;
df[i].gain = WFDB_DEFGAIN;
}
else
calibrated[i] = 1;
}
/* Set range for signal selection on analyze panel. */
/*reset_maxsig();*/
/* Initialize the signal list unless the new record name matches the
old one. */
if (rebuild_list) {
if (nsig > maxsiglistlen) {
siglist = realloc(siglist, nsig * sizeof(int));
base = realloc(base, nsig * sizeof(int));
level = realloc(level, nsig * sizeof(GdkSegment));
maxsiglistlen = nsig;
}
for (i = 0; i < nsig; i++)
siglist[i] = i;
siglistlen = nsig;
/*reset_siglist();*/
}
/* Calculate the base levels (in display units) for each signal, and for
annotation display. */
set_baselines();
tmag = 1.0;
vscale[0] = 0.; /* force clear_cache() -- see calibrate() */
calibrate();
/* Rebuild the level window (see edit.c) */
/*recreate_level_popup();*/
return (1);
}
/* Set_baselines() determines the ordinates for the signal baselines and for
annotation display. Note that the signals are drawn centered about the
calculated baselines (i.e., the baselines bear no fixed relationship to
the sample values). */
void set_baselines()
{
int i;
if (sig_mode == 0)
for (i = 0; i < nsig; i++)
base[i] = canvas_height*(2*i+1.)/(2.*nsig);
else
for (i = 0; i < siglistlen; i++)
base[i] = canvas_height*(2*i+1.)/(2.*siglistlen);
if (i > 1)
abase = (base[i/2] + base[i/2-1])/2;
else if (nsig > 0)
abase = canvas_height*4/5;
else
abase = canvas_height/2;
}
/* Calibrate() sets scales for the display. Ordinate (amplitude) scaling
is determined for each signal from the gain recorded in the header file,
and from the display scales in the calibration specification file, but
calibrate() scales the abscissa (time) for all signals based on the
sampling frequency for signal 0. */
void calibrate()
{
int i;
extern char *getenv();
struct WFDB_calinfo ci;
/* vscale is a multiplicative scale factor that converts sample values to
window ordinates. Since window ordinates are inverted, vscale includes
a factor of -1. */
if (vscale[0] == 0.0) {
clear_cache();
/* If specified, read the calibration file to get standard scales. */
if ((cfname == (char *)NULL) && (cfname = getenv("WFDBCAL")))
calopen(cfname);
for (i = 0; i < nsig; i++) {
vscale[i] = - vmag[i] * millivolts(1) / df[i].gain;
dc_coupled[i] = 0;
if (getcal(df[i].desc, df[i].units, &ci) == 0 && ci.scale != 0.0) {
vscale[i] /= ci.scale;
if (ci.caltype & 1) {
dc_coupled[i] = 1;
sigbase[i] = df[i].baseline;
if (blabel[i] = (char *)malloc(strlen(ci.units) +
strlen(df[i].desc) + 6))
sprintf(blabel[i], "0 %s (%s)", ci.units, df[i].desc);
}
}
}
}
/* vscalea is used in the same way as vscale, but only when displaying
the annotation 'num' fields as a signal. */
vscalea = - millivolts(1);
if (af.name && getcal(af.name, "units", &ci) == 0 && ci.scale != 0)
vscalea /= ci.scale;
else if (getcal("ann", "units", &ci) == 0 && ci.scale != 0)
vscalea /= ci.scale;
else
vscalea /= WFDB_DEFGAIN;
/* tscale is a multiplicative scale factor that converts sample intervals
to window abscissas. */
if (freq == 0.0) freq = WFDB_DEFFREQ;
if (tmag <= 0.0) tmag = 1.0;
nsamp = canvas_width_sec * freq / tmag;
tscale = tmag * seconds(1) / freq;
}