1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ubic.basecode.math;
16
17 import java.util.LinkedList;
18 import java.util.Map;
19 import java.util.Queue;
20 import java.util.TreeMap;
21
22 import cern.colt.list.DoubleArrayList;
23 import cern.colt.matrix.DoubleMatrix1D;
24 import cern.colt.matrix.DoubleMatrix2D;
25 import cern.colt.matrix.impl.DenseDoubleMatrix2D;
26 import cern.jet.stat.Descriptive;
27 import org.apache.commons.lang3.ArrayUtils;
28 import org.apache.commons.math3.analysis.interpolation.LinearInterpolator;
29 import org.apache.commons.math3.analysis.interpolation.LoessInterpolator;
30 import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction;
31 import org.apache.commons.math3.exception.OutOfRangeException;
32 import ubic.basecode.math.linearmodels.MeanVarianceEstimator;
33
34
35
36
37
38
39
40 public class Smooth {
41
42
43
44
45
46
47
48
49 public static DoubleMatrix1D movingAverage(DoubleMatrix1D m, int windowSize) {
50
51 Queue<Double> window = new LinkedList<>();
52
53 double sum = 0.0;
54
55 assert windowSize > 0;
56
57 DoubleMatrix1D result = m.like();
58 for (int i = 0; i < m.size(); i++) {
59
60 double num = m.get(i);
61 sum += num;
62 window.add(num);
63 if (window.size() > windowSize) {
64
65 sum -= window.remove();
66 }
67
68 if (!window.isEmpty()) {
69
70 result.set(i, sum / window.size());
71 } else {
72 result.set(i, Double.NaN);
73 }
74 }
75
76 return result;
77
78 }
79
80
81
82
83 static final double BANDWIDTH = 0.5;
84
85
86
87
88 static final int ROBUSTNESS_ITERS = 3;
89
90
91
92
93
94 public static DoubleMatrix2D loessFit(DoubleMatrix2D xy) {
95 return loessFit(xy, BANDWIDTH);
96 }
97
98
99
100
101
102
103
104
105 public static DoubleMatrix2D loessFit(DoubleMatrix2D xy, double bandwidth) {
106 assert xy != null;
107
108 DoubleMatrix1D sx = xy.viewColumn(0);
109 DoubleMatrix1D sy = xy.viewColumn(1);
110 Map<Double, Double> map = new TreeMap<>();
111 for (int i = 0; i < sx.size(); i++) {
112 if (Double.isNaN(sx.get(i)) || Double.isInfinite(sx.get(i)) || Double.isNaN(sy.get(i))
113 || Double.isInfinite(sy.get(i))) {
114 continue;
115 }
116 map.put(sx.get(i), sy.get(i));
117 }
118 DoubleMatrix2D xyChecked = new DenseDoubleMatrix2D(map.size(), 2);
119 xyChecked.viewColumn(0).assign(ArrayUtils.toPrimitive(map.keySet().toArray(new Double[0])));
120 xyChecked.viewColumn(1).assign(ArrayUtils.toPrimitive(map.values().toArray(new Double[0])));
121
122
123
124
125 DoubleMatrix2D loessFit = new DenseDoubleMatrix2D(xyChecked.rows(), xyChecked.columns());
126
127
128 LoessInterpolator loessInterpolator = new LoessInterpolator(bandwidth,
129 ROBUSTNESS_ITERS);
130
131 double[] loessY = loessInterpolator.smooth(xyChecked.viewColumn(0).toArray(),
132 xyChecked.viewColumn(1).toArray());
133
134 loessFit.viewColumn(0).assign(xyChecked.viewColumn(0));
135 loessFit.viewColumn(1).assign(loessY);
136
137 return loessFit;
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 public static double[] interpolate( double[] x, double[] y, double[] xInterpolate ) {
154
155 assert x != null;
156 assert y != null;
157 assert xInterpolate != null;
158 assert x.length == y.length;
159
160 double[] yInterpolate = new double[xInterpolate.length];
161 LinearInterpolator linearInterpolator = new LinearInterpolator();
162
163
164 DoubleMatrix2D matrix = new DenseDoubleMatrix2D( x.length, 2 );
165 matrix.viewColumn( 0 ).assign( x );
166 matrix.viewColumn( 1 ).assign( y );
167 matrix = matrix.viewSorted( 0 );
168 double[] sortedX = matrix.viewColumn( 0 ).toArray();
169 double[] sortedY = matrix.viewColumn( 1 ).toArray();
170
171
172 DoubleArrayList xList = new DoubleArrayList( sortedX );
173 double x3ListMin = Descriptive.min( xList );
174 double x3ListMax = Descriptive.max( xList );
175 PolynomialSplineFunction fun = linearInterpolator.interpolate( sortedX, sortedY );
176 for ( int i = 0; i < xInterpolate.length; i++ ) {
177 try {
178
179 if ( xInterpolate[i] > x3ListMax ) {
180 yInterpolate[i] = fun.value( x3ListMax );
181 } else if ( xInterpolate[i] < x3ListMin ) {
182 yInterpolate[i] = fun.value( x3ListMin );
183 } else {
184 yInterpolate[i] = fun.value( xInterpolate[i] );
185 }
186 } catch ( OutOfRangeException e ) {
187
188 yInterpolate[i] = Double.NaN;
189 }
190 }
191
192 return yInterpolate;
193 }
194
195
196
197 }