analyzer.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. voltlogger_analyzer
  3. Copyright (C) 2015 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
  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 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "configuration.h"
  16. #include "macros.h"
  17. #include <stdio.h> /* FILE */
  18. #include <stdlib.h> /* size_t */
  19. #include <stdint.h> /* uint64_t */
  20. #include <string.h> /* memset() */
  21. #include <math.h> /* fabs() */
  22. #include <assert.h> /* assert() */
  23. //#include <errno.h> /* errno */
  24. #include "error.h"
  25. #include "malloc.h"
  26. #include "analyzer.h"
  27. #include "binary.h"
  28. #define MAX_HISTORY (1 << 20)
  29. typedef int (*vl_checkfunct_t)(history_item_t *value_history, int channelId, uint64_t *value_history_filled_p, char *checkpointfile, int concurrency, void *arg, double error_threshold, char realtime);
  30. typedef int (*vl_interpolatefunct_t)(FILE *o_f, history_item_t *value_history, int channelsNum, int channelId, int addperiods, uint64_t *value_history_filled_p, char *checkpointfile, int concurrency, void *arg, char realtime);
  31. #define SIN_PHASE_PARTS 3
  32. int vl_realcheck_sin(history_item_t *value_history, int channelId, uint64_t value_history_filled, char *checkpointfile, int concurrency, float frequency_p, double error_threshold, char realtime) {
  33. history_item_t *p, *e;
  34. p = value_history;
  35. e = &value_history[value_history_filled-1];
  36. uint64_t sensorTS_start = p->row.sensorTS;
  37. uint64_t sensorTSDiff_total = e->row.sensorTS - sensorTS_start;
  38. double y_sum = 0;
  39. while (p <= e) {
  40. y_sum += p->row.value[channelId];
  41. p++;
  42. }
  43. double y_avg = (double)y_sum / (double)value_history_filled;
  44. double y_int = 0;
  45. history_item_t *p_old = p = value_history;
  46. while (++p <= e) {
  47. double y_diff = p->row.value[channelId] - y_avg;
  48. y_int += y_diff*y_diff * (p->row.sensorTS - p_old->row.sensorTS);
  49. p_old = p;
  50. }
  51. y_int *= 2*M_PI / sensorTSDiff_total;
  52. double lambda = (double)2*M_PI / sensorTSDiff_total;
  53. double amp = sqrt(y_int / M_PI);
  54. double lambda_expected = 2*M_PI / 20000;
  55. if (lambda < lambda_expected*0.95) {
  56. p = value_history;
  57. while (p <= e) {
  58. printf("Z\t%lu\t%lu\t%u\t%lf\t%lf\t%lf\t%lf\t%lf\n", p->row.unixTSNano, p->row.sensorTS, p->row.value[channelId], (double)-1, amp, lambda, NAN, y_avg);
  59. p++;
  60. }
  61. return 0;
  62. }
  63. // f(x) = amp * sin(lambda*x + phase) + avg
  64. double phase;
  65. p_old = p = value_history;
  66. phase = 0;
  67. /* //TODO: Complete this method of phase calculation (instead of iteration method below)
  68. while (++p <= e) {
  69. if ((p_old->value - y_avg) * (p->value - y_avg) < 0) {
  70. double avg_value = (p->value + p_old->value) / 2;
  71. if (p_old->value < y_avg)
  72. phase = -lambda * avg_value;
  73. else
  74. phase = lambda * avg_value;
  75. break;
  76. }
  77. p_old = p;
  78. }
  79. */
  80. double sqdeviation_min = 1E100;
  81. double phase_add_best = M_PI;
  82. double scan_interval = 2*M_PI;
  83. while (scan_interval > 1E-3) {
  84. double phase_add = -scan_interval;
  85. double phase_add_best_add = 0;
  86. //fprintf(stderr, "scanning: %le -> %le\n", phase_add_best + phase_add, phase_add_best + scan_interval);
  87. while (phase_add_best + phase_add < phase_add_best + scan_interval) {
  88. double sqdeviation = 0;
  89. p = value_history;
  90. while (p <= e) {
  91. double y_calc = amp*sin(lambda*p->row.sensorTS + phase_add_best + phase + phase_add) + y_avg;
  92. double y_diff = y_calc - (double)p->row.value[channelId];
  93. //fprintf(stderr, "Y: %li %i %lf %le\n", p->sensorTS, p->value, y_calc, y_diff);
  94. sqdeviation += y_diff*y_diff;
  95. p++;
  96. }
  97. //fprintf(stderr, "try: %le: %le\n", phase_add_best + phase_add, sqdeviation);
  98. if (sqdeviation < sqdeviation_min) {
  99. sqdeviation_min = sqdeviation;
  100. phase_add_best_add = phase_add;
  101. }
  102. phase_add += scan_interval/SIN_PHASE_PARTS;
  103. }
  104. phase_add_best += phase_add_best_add;
  105. scan_interval /= SIN_PHASE_PARTS;
  106. //fprintf(stderr, "phase_add_best == %le (%le). sqdeviation_min == %le. scan_interval == %le\n", phase_add_best, phase_add_best_add, sqdeviation_min, scan_interval);
  107. }
  108. double err = sqdeviation_min/value_history_filled;///(value_history_filled-1);
  109. if (err > error_threshold) {
  110. p = value_history;
  111. while (p <= e) {
  112. printf("Z\t%lu\t%lu\t%u\t%lf\t%lf\t%lf\t%lf\t%lf\n", p->row.unixTSNano, p->row.sensorTS, p->row.value[channelId], err, amp, lambda, phase, y_avg);
  113. p++;
  114. }
  115. }
  116. return 0;
  117. }
  118. int vl_check_sin(history_item_t *value_history, int channelId, uint64_t *value_history_filled_p, char *checkpointfile, int concurrency, void *_frequency_p, double error_threshold, char realtime) {
  119. float frequency = *(float *)_frequency_p;
  120. //history_item_t *cur = &value_history[*value_history_filled_p - 1];
  121. uint64_t expectedEndOffset = (uint64_t)(1E9 /* nanosecs in sec */ / frequency);
  122. uint64_t currentOffset = *value_history_filled_p * 50000;
  123. int rc = 0;
  124. if ( currentOffset >= expectedEndOffset ) {
  125. rc = vl_realcheck_sin(value_history, channelId, *value_history_filled_p, checkpointfile, concurrency, frequency, error_threshold, realtime);
  126. *value_history_filled_p = 0;
  127. }
  128. return rc;
  129. }
  130. static inline void vl_analyze(FILE *i_f, FILE *o_f, int channelsNum, int channelId, char *checkpointfile, int concurrency, void *arg, vl_checkfunct_t checkfunct, double error_threshold, char realtime) {
  131. history_item_t *value_history, *history_item_ptr;
  132. uint64_t value_history_filled = 0;
  133. static uint64_t unixTSNano_prev = 0;
  134. value_history = xcalloc(MAX_HISTORY, sizeof(*value_history));
  135. while (!feof(i_f)) {
  136. assert (value_history_filled < MAX_HISTORY); // overflow
  137. history_item_ptr = &value_history[ value_history_filled++ ];
  138. while(1) {
  139. long pos = ftell(i_f);
  140. history_item_ptr->row.unixTSNano = get_uint64(i_f, realtime);
  141. if (unixTSNano_prev != 0 && llabs((int64_t)history_item_ptr->row.unixTSNano - (int64_t)unixTSNano_prev) > 1E9*1E8) {
  142. fprintf(stderr, "Wrong unixTSNano\n");
  143. fseek(i_f, pos+1, SEEK_SET);
  144. continue;
  145. }
  146. unixTSNano_prev = history_item_ptr->row.unixTSNano;
  147. break;
  148. }
  149. history_item_ptr->row.sensorTS = get_uint64(i_f, realtime);
  150. int i = 0;
  151. while (i < channelsNum) {
  152. uint32_t value = get_uint32(i_f, realtime);
  153. if (i == channelId)
  154. history_item_ptr->row.value[channelId] = value;
  155. i++;
  156. }
  157. if (checkfunct(value_history, 0, &value_history_filled, checkpointfile, concurrency, arg, error_threshold, realtime)) {
  158. printf("Problem\n");
  159. }
  160. }
  161. free(value_history);
  162. return;
  163. }
  164. void vl_analyze_sin(FILE *i_f, FILE *o_f, int channelsNum, int channelId, char *checkpointfile, int concurrency, float frequency, double error_threshold, char realtime)
  165. {
  166. float *frequency_p = xmalloc(sizeof(float));
  167. *frequency_p = frequency;
  168. vl_analyze(i_f, o_f, channelsNum, channelId, checkpointfile, concurrency, frequency_p, vl_check_sin, error_threshold, realtime);
  169. free(frequency_p);
  170. return;
  171. }
  172. static inline void out_row(FILE *o_f, history_item_t *history_item_ptr, int channelsNum) {
  173. out_uint64(o_f, history_item_ptr->row.unixTSNano);
  174. out_uint64(o_f, history_item_ptr->row.sensorTS);
  175. int i = 0;
  176. while (i < channelsNum) {
  177. out_uint32(o_f, history_item_ptr->row.value[i++]);
  178. }
  179. return;
  180. }
  181. static int vl_interpolatefunct_repeat(FILE *o_f, history_item_t *value_history, int channelsNum, int channelId, int addperiods, uint64_t *value_history_filled_p, char *checkpointfile, int concurrency, void *arg, char realtime) {
  182. float *freq_p = arg;
  183. assert (*value_history_filled_p > 2);
  184. assert (*freq_p != 0);
  185. float period = 1 / *freq_p;
  186. fprintf(stderr, "Interpolating (freq: %e; period: %e; value_history_filled: %lu)\n", *freq_p, period, *value_history_filled_p);
  187. history_item_t *value_history_last = &value_history[*value_history_filled_p - 1];
  188. history_item_t *value_history_period_end = &value_history_last[-1];
  189. history_item_t *value_history_period_start;
  190. // Getting the value of value_history_period_start
  191. {
  192. value_history_period_start = value_history;
  193. uint64_t end_unixTSNano = value_history_period_end->row.unixTSNano;
  194. while (end_unixTSNano - value_history_period_start->row.unixTSNano > period) {
  195. value_history_period_start++;
  196. assert(value_history_period_start < value_history_period_end);
  197. }
  198. value_history_period_start--;
  199. assert (value_history_period_start >= value_history);
  200. }
  201. // Interpolating
  202. {
  203. uint64_t last_unixTSNano = value_history_last->row.unixTSNano;
  204. uint64_t unixTSNano_cur = value_history_period_end->row.unixTSNano;
  205. uint64_t sensorTS_cur = value_history_period_end->row.sensorTS;
  206. history_item_t *value_history_prev = value_history_period_start;
  207. history_item_t *value_history_cur = &value_history_period_start[1];
  208. while(1) {
  209. if (value_history_cur == value_history_period_end) {
  210. value_history_prev = value_history_period_start;
  211. value_history_cur = &value_history_period_start[1];
  212. }
  213. unixTSNano_cur += value_history_cur->row.unixTSNano - value_history_prev->row.unixTSNano;
  214. sensorTS_cur += value_history_cur->row.sensorTS - value_history_prev->row.sensorTS;
  215. fprintf(stderr, "Interpolating… value_history_period_start: %lu (%lu < %lu); %lu %p %p\n", sensorTS_cur, unixTSNano_cur, last_unixTSNano, value_history_cur->row.sensorTS, value_history_cur, value_history_period_end);
  216. if (unixTSNano_cur >= last_unixTSNano)
  217. break;
  218. uint64_t unixTSNano_orig = value_history_cur->row.unixTSNano;
  219. uint64_t sensorTS_orig = value_history_cur->row.sensorTS;
  220. value_history_cur->row.unixTSNano = unixTSNano_cur;
  221. value_history_cur->row.sensorTS = sensorTS_cur;
  222. out_row(o_f, value_history_cur, channelsNum);
  223. value_history_cur->row.unixTSNano = unixTSNano_orig;
  224. value_history_cur->row.sensorTS = sensorTS_orig;
  225. value_history_prev = value_history_cur;
  226. value_history_cur++;
  227. }
  228. }
  229. return 0;
  230. }
  231. static inline void vl_interpolate(FILE *i_f, FILE *o_f, int channelsNum, int channelId, int addperiods, char *checkpointfile, int concurrency, void *arg, vl_interpolatefunct_t interpolatefunct, char realtime) {
  232. history_item_t *value_history, *history_item_ptr;
  233. uint64_t value_history_filled = 0;
  234. static uint64_t unixTSNano_prev = (1E9*1E8)/2;
  235. static uint64_t unixTSNano_diff_prev = ((uint64_t)~0)/2;
  236. static uint64_t unixTSNano_diff = ((uint64_t)~0)/2;
  237. value_history = xcalloc(MAX_HISTORY, sizeof(*value_history));
  238. while (!feof(i_f)) {
  239. assert (value_history_filled < MAX_HISTORY); // overflow
  240. history_item_ptr = &value_history[ value_history_filled++ ];
  241. while(1) {
  242. long pos = ftell(i_f);
  243. history_item_ptr->row.unixTSNano = get_uint64(i_f, realtime);
  244. if (unixTSNano_prev != 0 && llabs((int64_t)history_item_ptr->row.unixTSNano - (int64_t)unixTSNano_prev) > 1E9*1E8) {
  245. fprintf(stderr, "Wrong unixTSNano\n");
  246. fseek(i_f, pos+1, SEEK_SET);
  247. continue;
  248. }
  249. unixTSNano_diff_prev = unixTSNano_diff;
  250. unixTSNano_diff = history_item_ptr->row.unixTSNano - unixTSNano_prev;
  251. unixTSNano_prev = history_item_ptr->row.unixTSNano;
  252. break;
  253. }
  254. history_item_ptr->row.sensorTS = get_uint64(i_f, realtime);
  255. {
  256. int i = 0;
  257. while (i < channelsNum)
  258. history_item_ptr->row.value[i++] = get_uint32(i_f, realtime);
  259. }
  260. if ((unixTSNano_diff+1) / (unixTSNano_diff_prev+1) > 10)
  261. if (interpolatefunct(o_f, value_history, channelsNum, channelId, addperiods, &value_history_filled, checkpointfile, concurrency, arg, realtime)) {
  262. fprintf(stderr, "Problem\n");
  263. }
  264. out_row(o_f, history_item_ptr, channelsNum);
  265. }
  266. free(value_history);
  267. return;
  268. }
  269. void vl_interpolate_repeat(FILE *i_f, FILE *o_f, int channelsNum, int channelId, int addperiods, char *checkpointfile, int concurrency, float frequency, char realtime)
  270. {
  271. float *frequency_p = xmalloc(sizeof(float));
  272. *frequency_p = frequency;
  273. vl_interpolate(i_f, o_f, channelsNum, channelId, addperiods, checkpointfile, concurrency, frequency_p, vl_interpolatefunct_repeat, realtime);
  274. free(frequency_p);
  275. return;
  276. }