#ifndef __FILTER_H__ #define __FILTER_H__ #include #include #include #include namespace alevin{ namespace filter{ std::vector savgolFilterCoeff({0.00706405, 0.00626649, 0.00550441, 0.00477709, 0.00408383, 0.00342395, 0.00279676, 0.00220158, 0.00163774, 0.00110456, 0.00060138, 0.00012754, -0.0003176 , -0.00073469, -0.00112438, -0.00148729, -0.00182407, -0.00213532, -0.00242168, -0.00268374, -0.00292213, -0.00313743, -0.00333024, -0.00350115, -0.00365075, -0.00377962, -0.00388832, -0.00397742, -0.00404748, -0.00409906, -0.00413271, -0.00414897, -0.00414838, -0.00413147, -0.00409877, -0.00405079, -0.00398806, -0.00391109, -0.00382037, -0.0037164 , -0.00359969, -0.00347071, -0.00332994, -0.00317787, -0.00301496, -0.00284167, -0.00265847, -0.0024658 , -0.00226411, -0.00205385, -0.00183545, -0.00160933, -0.00137593, -0.00113566, -0.00088894, -0.00063617, -0.00037775, -0.00011408, 0.00015445, 0.00042746, 0.00070457, 0.0009854 , 0.00126959, 0.00155678, 0.00184661, 0.00213873, 0.00243279, 0.00272846, 0.00302541, 0.00332331, 0.00362183, 0.00392066, 0.00421949, 0.00451802, 0.00481594, 0.00511296, 0.0054088 , 0.00570317, 0.0059958 , 0.00628642, 0.00657475, 0.00686055, 0.00714357, 0.00742354, 0.00770023, 0.00797341, 0.00824284, 0.0085083 , 0.00876957, 0.00902643, 0.00927868, 0.00952612, 0.00976855, 0.01000577, 0.01023761, 0.01046388, 0.01068442, 0.01089905, 0.0111076 , 0.01130993, 0.01150589, 0.01169532, 0.01187809, 0.01205407, 0.01222312, 0.01238512, 0.01253997, 0.01268754, 0.01282773, 0.01296044, 0.01308558, 0.01320306, 0.01331279, 0.01341471, 0.01350873, 0.0135948 , 0.01367285, 0.01374283, 0.01380469, 0.01385839, 0.01390389, 0.01394116, 0.01397017, 0.01399091, 0.01400336, 0.01400751, 0.01400336, 0.01399091, 0.01397017, 0.01394116, 0.01390389, 0.01385839, 0.01380469, 0.01374283, 0.01367285, 0.0135948 , 0.01350873, 0.01341471, 0.01331279, 0.01320306, 0.01308558, 0.01296044, 0.01282773, 0.01268754, 0.01253997, 0.01238512, 0.01222312, 0.01205407, 0.01187809, 0.01169532, 0.01150589, 0.01130993, 0.0111076 , 0.01089905, 0.01068442, 0.01046388, 0.01023761, 0.01000577, 0.00976855, 0.00952612, 0.00927868, 0.00902643, 0.00876957, 0.0085083 , 0.00824284, 0.00797341, 0.00770023, 0.00742354, 0.00714357, 0.00686055, 0.00657475, 0.00628642, 0.0059958 , 0.00570317, 0.0054088 , 0.00511296, 0.00481594, 0.00451802, 0.00421949, 0.00392066, 0.00362183, 0.00332331, 0.00302541, 0.00272846, 0.00243279, 0.00213873, 0.00184661, 0.00155678, 0.00126959, 0.0009854 , 0.00070457, 0.00042746, 0.00015445, -0.00011408, -0.00037775, -0.00063617, -0.00088894, -0.00113566, -0.00137593, -0.00160933, -0.00183545, -0.00205385, -0.00226411, -0.0024658 , -0.00265847, -0.00284167, -0.00301496, -0.00317787, -0.00332994, -0.00347071, -0.00359969, -0.0037164 , -0.00382037, -0.00391109, -0.00398806, -0.00405079, -0.00409877, -0.00413147, -0.00414838, -0.00414897, -0.00413271, -0.00409906, -0.00404748, -0.00397742, -0.00388832, -0.00377962, -0.00365075, -0.00350115, -0.00333024, -0.00313743, -0.00292213, -0.00268374, -0.00242168, -0.00213532, -0.00182407, -0.00148729, -0.00112438, -0.00073469, -0.0003176 , 0.00012754, 0.00060138, 0.00110456, 0.00163774, 0.00220158, 0.00279676, 0.00342395, 0.00408383, 0.00477709, 0.00550441, 0.00626649, 0.00706405}); /* Calculate linear regression line fit and return its slope. taken from https://stackoverflow.com/questions/18939869/ \how-to-get-the-slope-of-a-linear-regression-line-using-c */ double fitLine(const std::vector& x, const std::vector& y) { const size_t n = x.size(); double s_x = std::accumulate(x.begin(), x.end(), 0.0); double s_y = std::accumulate(y.begin(), y.end(), 0.0); double s_xx = std::inner_product(x.begin(), x.end(), x.begin(), 0.0); double s_xy = std::inner_product(x.begin(), x.end(), y.begin(), 0.0); double slope = (n * s_xy - s_x * s_y) / (n * s_xx - s_x * s_x); return slope; } /* function to perform savgol filtering; Interesting Observations: 1. Numpy and Scipy(Sircel) gives difference results with convolution. 2. Ignoring edge cases to avoid conflicts and be inline with Sircel's implementation --- which is unique (in a way) . */ void sgSmooth(const std::vector& slopes, uint32_t SAVGOL_FRAME_SIZE, uint32_t SAVGOL_DIM, std::vector& filter){ uint32_t length = slopes.size() - SAVGOL_FRAME_SIZE; for(size_t i=0; i < length; i++) { //skipping left edge cases extract the window of specified length std::vector slope( slopes.begin()+i, slopes.begin()+i+SAVGOL_FRAME_SIZE); //push the convolution of the slopes with coefficient filter.push_back( std::inner_product(slope.begin(), slope.end(), savgolFilterCoeff.begin(), 0.0)); } } } } #endif