Add plots to ao-postflight using the plplot library
[fw/altos] / ao-tools / lib / cc-analyse.c
1 /*
2  * Copyright © 2009 Keith Packard <keithp@keithp.com>
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; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include "cc.h"
19 #include <math.h>
20
21 int
22 cc_timedata_min(struct cc_timedata *d, double min_time, double max_time)
23 {
24         int     i;
25         int     set = 0;
26         int     min_i = -1;
27         double  min;
28
29         if (d->num == 0)
30                 return -1;
31         for (i = 0; i < d->num; i++)
32                 if (min_time <= d->data[i].time && d->data[i].time <= max_time)
33                         if (!set || d->data[i].value < min) {
34                                 min_i = i;
35                                 min = d->data[i].value;
36                                 set = 1;
37                         }
38         return min_i;
39 }
40
41 int
42 cc_timedata_min_mag(struct cc_timedata *d, double min_time, double max_time)
43 {
44         int     i;
45         int     set = 0;
46         int     min_i = -1;
47         double  min;
48
49         if (d->num == 0)
50                 return -1;
51         for (i = 0; i < d->num; i++)
52                 if (min_time <= d->data[i].time && d->data[i].time <= max_time)
53                         if (!set || fabs(d->data[i].value) < min) {
54                                 min_i = i;
55                                 min = fabs(d->data[i].value);
56                                 set = 1;
57                         }
58         return min_i;
59 }
60
61 int
62 cc_timedata_max(struct cc_timedata *d, double min_time, double max_time)
63 {
64         int     i;
65         double  max;
66         int     max_i = -1;
67         int     set = 0;
68
69         if (d->num == 0)
70                 return -1;
71         for (i = 0; i < d->num; i++)
72                 if (min_time <= d->data[i].time && d->data[i].time <= max_time)
73                         if (!set || d->data[i].value > max) {
74                                 max_i = i;
75                                 max = d->data[i].value;
76                                 set = 1;
77                         }
78         return max_i;
79 }
80
81 int
82 cc_timedata_max_mag(struct cc_timedata *d, double min_time, double max_time)
83 {
84         int     i;
85         double  max;
86         int     max_i = -1;
87         int     set = 0;
88
89         if (d->num == 0)
90                 return -1;
91         for (i = 0; i < d->num; i++)
92                 if (min_time <= d->data[i].time && d->data[i].time <= max_time)
93                         if (!set || fabs(d->data[i].value) > max) {
94                                 max_i = i;
95                                 max = fabs(d->data[i].value);
96                                 set = 1;
97                         }
98         return max_i;
99 }
100
101 double
102 cc_timedata_average(struct cc_timedata *td, double start_time, double stop_time)
103 {
104         int                     i;
105         double                  prev_time;
106         double                  next_time;
107         double                  interval;
108         double                  sum = 0.0;
109         double                  period = 0.0;
110
111         prev_time = start_time;
112         for (i = 0; i < td->num; i++) {
113                 if (start_time <= td->data[i].time && td->data[i].time <= stop_time) {
114                         if (i < td->num - 1 && td->data[i+1].time < stop_time)
115                                 next_time = (td->data[i].time + td->data[i+1].time) / 2.0;
116                         else
117                                 next_time = stop_time;
118                         interval = next_time - prev_time;
119                         sum += td->data[i].value * interval;
120                         period += interval;
121                         prev_time = next_time;
122                 }
123         }
124         return sum / period;
125 }
126
127 int
128 cc_perioddata_limits(struct cc_perioddata *d, double min_time, double max_time, int *start, int *stop)
129 {
130         double  start_d, stop_d;
131
132         if (d->num == 0)
133                 return 0;
134         start_d = ceil((min_time - d->start) / d->step);
135         if (start_d < 0)
136                 start_d = 0;
137         stop_d = floor((max_time - d->start) / d->step);
138         if (stop_d >= d->num)
139                 stop_d = d->num - 1;
140         if (stop_d < start_d)
141                 return 0;
142         *start = (int) start_d;
143         *stop = (int) stop_d;
144         return 1;
145 }
146
147 int
148 cc_perioddata_min(struct cc_perioddata *d, double min_time, double max_time)
149 {
150         int     i;
151         double  min;
152         int     min_i;
153         int     start, stop;
154
155         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
156                 return -1;
157         min = d->data[start];
158         min_i = start;
159         for (i = start + 1; i <= stop; i++)
160                 if (d->data[i] < min) {
161                         min = d->data[i];
162                         min_i = i;
163                 }
164         return min_i;
165 }
166
167 int
168 cc_perioddata_min_mag(struct cc_perioddata *d, double min_time, double max_time)
169 {
170         int     start, stop;
171         int     i;
172         double  min;
173         int     min_i;
174
175         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
176                 return -1;
177         min = d->data[start];
178         min_i = start;
179         for (i = start + 1; i <= stop; i++)
180                 if (fabs(d->data[i]) < min) {
181                         min = fabs(d->data[i]);
182                         min_i = i;
183                 }
184         return min_i;
185 }
186
187 int
188 cc_perioddata_max(struct cc_perioddata *d, double min_time, double max_time)
189 {
190         int     start, stop;
191         int     i;
192         double  max;
193         int     max_i;
194
195         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
196                 return -1;
197         max = d->data[start];
198         max_i = start;
199         for (i = start + 1; i <= stop; i++)
200                 if (d->data[i] > max) {
201                         max = d->data[i];
202                         max_i = i;
203                 }
204         return max_i;
205 }
206
207 int
208 cc_perioddata_max_mag(struct cc_perioddata *d, double min_time, double max_time)
209 {
210         int     start, stop;
211         int     i;
212         double  max;
213         int     max_i;
214
215         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
216                 return -1;
217         max = d->data[start];
218         max_i = start;
219         for (i = start + 1; i <= stop; i++)
220                 if (fabs(d->data[i]) > max) {
221                         max = fabs(d->data[i]);
222                         max_i = i;
223                 }
224         return max_i;
225 }
226
227 double
228 cc_perioddata_average(struct cc_perioddata *d, double min_time, double max_time)
229 {
230         int     start, stop;
231         int     i;
232         double  sum = 0.0;
233
234         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
235                 return 0.0;
236         for (i = start; i <= stop; i++)
237                 sum += d->data[i];
238         return sum / (stop - start + 1);
239 }
240
241 double
242 cc_perioddata_average_mag(struct cc_perioddata *d, double min_time, double max_time)
243 {
244         int     start, stop;
245         int     i;
246         double  sum = 0.0;
247
248         if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
249                 return 0.0;
250         for (i = start; i <= stop; i++)
251                 sum += fabs(d->data[i]);
252         return sum / (stop - start + 1);
253 }