package com.algobase.share1.ant; import java.io.File; import java.io.FileWriter; import java.io.IOException; public class RRVector { public void writeLog(String txt) {} public void handleArtefact(int index, int rr, float avg, float filter) {} int bin_width = 6; int max_duration = 2400; // 25 bpm int min_duration = 200; // 300 bpm int artefact_avg_interval = 5; int[] rr_vector; int rr_num; // use ring buffer for raw values (no artefact filtering) int[] raw_vector; int raw_num; double rr_sum; double rr_avg; int rr_min; int rr_max; int[] table; // histogramm int table_sz; int table_min_i; int table_max_i; double sdnn; double pnn50; double rmssd; double lnrmssd; double score; // pointcare double pc_sd1; double pc_sd2; float artefact_filter; int artefacts; public RRVector(int sz, int min_d, int max_d, int b_width) { rr_vector = new int[sz]; raw_vector = new int[sz]; min_duration = min_d; max_duration = max_d; bin_width = b_width; table_sz = max_duration/bin_width + 1; table = new int[table_sz]; clear(); writeLog("RRVector"); writeLog("vector_size = " + sz); writeLog("min_duration = " + min_duration); writeLog("max_duration = " + max_duration); writeLog("bin_width = " + bin_width); writeLog("table_sz = " + table_sz); } public void clear() { rr_num = 0; rr_min = 0; rr_max = 0; rr_sum = 0; raw_num = 0; for(int i=0; i 50) nn50++; sqr_sum2 += d*d; } pnn50 = 100*nn50/(rr_num-1); rmssd = Math.sqrt(sqr_sum2/(rr_num-1)); lnrmssd = (rmssd > 0) ? Math.log(rmssd) : 0; double ln_min = 1.5f; double ln_max = 5.5f; score = 100*(lnrmssd-ln_min)/(ln_max-ln_min); if (score < 0) score = 0; if (score > 100) score = 100; } public boolean add(int rr) { if (rr < min_duration || rr > max_duration) { // ignore illegal rr values return false; } raw_vector[raw_num % raw_vector.length] = rr; raw_num++; if (artefact_filter > 0.01 && rr_num >= artefact_avg_interval) { // artefact elimination: // ignore intervals which differ by at least x percent from the average // of the last artefact_avg_interval values (x = 100*artefact_filter) float avg = (float)slidingAvg(artefact_avg_interval); if (Math.abs((rr-avg)/avg) > artefact_filter) { handleArtefact(++artefacts,rr,avg,artefact_filter); return false; } } if (rr_num >= rr_vector.length-1) { writeLog("ERROR: RRVector overflow"); return false; } rr_vector[rr_num++] = rr; if (rr > rr_max) rr_max = rr; if (rr < rr_min || rr_min == 0) rr_min = rr; rr_sum += rr; update_statistics(); // update table int j = rr/bin_width; if (j < 0 || j >= table.length) { writeLog("RRVector: illegal table index " + j); return false; } table[j]++; if (j < table_min_i) table_min_i = j; if (j > table_max_i) table_max_i = j; return true; } public int get(int i) { if (i < 0 || i >= rr_vector.length) { writeLog("rr_vector.get: i = " + i); return 0; } return rr_vector[i]; } public int getTable(int i) { if (i < 0 || i >= table.length) { writeLog("rr_vector.getTable: i = " + i); return 0; } return table[i]; } public int getMin() { return rr_min; } public int getMax() { return rr_max; } public int getArtefacts() { return artefacts; } public double getSum() { return rr_sum; } public float getAvg() { return (float)(rr_sum/rr_num); } public float getScore() { return (float)score; } public float getSDNN() { return (float)sdnn; } public float getPNN50() { return (float)pnn50; } public float getRMSSD() { return (float)rmssd; } public float getLNRMSSD() { return (float)lnrmssd; } public float getSD1() { return (float)pc_sd1; } public float getSD2() { return (float)pc_sd2; } public int getTableMinIndex() { return table_min_i; } public int getTableMaxIndex() { return table_max_i; } public int findTableMaxValue() { int max_val = 0; int max_i = 0; for(int i = table_min_i; i <= table_max_i; i++) { if (table[i] > max_val) { max_i = i; max_val = table[i]; } } return max_i; } public double slidingAvg(int n) { if (n > rr_num) n = rr_num; double rr_sum = 0; for(int i = 1; i <= n; i++) rr_sum += rr_vector[rr_num-i]; return rr_sum/n; } public int size() { return rr_num; } public int max_size() { return rr_vector.length; } public int shift() { int x = rr_vector[0]; rr_sum -= x; rr_num -= 1; for(int i=0; i rr_max) rr_max = rr_vector[i]; } } table[x/bin_width]--; while (table_min_i < table.length && table[table_min_i] == 0) table_min_i++; while (table_max_i >= 0 && table[table_max_i] == 0) table_max_i--; update_statistics(); return x; } public float getStressIndex() { if (rr_num < 3) return 0; int sum = 0; int max_num_i = 0; int max_num = 0; for(int i=table_min_i; i<=table_max_i; i++) { sum += table[i]; if (table[i] > max_num) { max_num_i = i; max_num = table[i]; } } if (sum == 0) return 0; double AMo = (100.0*max_num)/sum; double Mo = (max_num_i * bin_width)/1000.0; double MxDMn = (table_max_i-table_min_i)*bin_width/1000.0; double si = AMo/(2*Mo*MxDMn); return (float)si; } public void write(File file) { try { FileWriter writer = new FileWriter(file); for(int i=0; i