/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
package gov.nasa.arc.mct.fastplot.bridge;
import java.text.NumberFormat;
/**For calculating a simple linear regression.
* Adapted from http://www-stat.stanford.edu/~naras/java/course/lec2/
* Balasubramanian Narasimhan, Stanford
* */
public class LinearRegression {
/**An example.*/
public static void main(String[] args) {
double[] x = {95, 85, 80, 70, 60};
double[] y = {85, 95, 70, 65, 70};
LinearRegression lr = new LinearRegression(x, y);
System.out.println(lr.getRoundedModel());
// System.out.println("calculate y given an x of 38 "+lr.calculateY(38));
// System.out.println("calculate x given a y of 41 "+lr.calculateX(41));
}
//fields
private double[] x;
private double[] y;
private double meanX;
private double meanY;
private double slope;
private double intercept;
private double stndDevX;
private double stndDevY;
//constructor
public LinearRegression(double[] x, double[] y) {
this.x = x;
this.y = y;
compute();
}
//methods
/**Performs linear regression*/
private void compute() {
double n = x.length;
double sumy = 0.0,
sumx = 0.0,
sumx2 = 0.0,
sumy2 = 0.0,
sumxy = 0.0;
for (int i = 0; i < n; i++) {
sumx += x[i];
sumx2 += x[i] * x[i];
sumy += y[i];
sumy2 += y[i] * y[i];
sumxy += x[i] * y[i];
}
meanX = sumx / n;
meanY = sumy / n;
slope = (sumxy - sumx * meanY) / (sumx2 - sumx * meanX);
intercept = meanY - slope * meanX;
stndDevX = Math.sqrt((sumx2 - sumx * meanX) / (n - 1));
stndDevY = Math.sqrt((sumy2 - sumy * meanY) / (n - 1));
}
/**Return approximated Y value, good for a single interpolation, multiple calls are inefficient!*/
public static double interpolateY(double x1, double y1, double x2, double y2, double fixedX ){
double[] x = {x1, x2};
double[] y = {y1, y2};
LinearRegression lr = new LinearRegression(x,y);
return lr.calculateY(fixedX);
}
/**Return approximated X value, good for a single interpolation, multiple calls are inefficient!*/
public static double interpolateX(double x1, double y1, double x2, double y2, double fixedY ){
double[] x = {x1, x2};
double[] y = {y1, y2};
LinearRegression lr = new LinearRegression(x,y);
return lr.calculateX(fixedY);
}
//getters
public double getSlope() {
return slope;
}
public double getIntercept() {
return intercept;
}
public double getRSquared() {
double r = slope * stndDevX / stndDevY;
return r * r;
}
public double[] getX() {
return x;
}
/**Returns Y=mX+b with full precision, no rounding of numbers.*/
public String getModel(){
return "Y= "+slope+"X + "+intercept+" RSqrd="+getRSquared();
}
/**Returns Y=mX+b */
public String getRoundedModel(){
return "Y= "+formatNumber(slope,3)+"X + "+formatNumber(intercept,3)+" RSqrd="+ formatNumber(getRSquared(),3);
}
/**Calculate Y given X.*/
public double calculateY (double x){
return slope*x+intercept;
}
/**Calculate X given Y.*/
public double calculateX (double y){
return (y-intercept)/slope;
}
/**Nulls the x and y arrays. Good to call before saving.*/
public void nullArrays(){
x = null;
y = null;
}
/**Converts a double ddd.dddddddd to a user determined number of decimal places right of the . */
public static String formatNumber(double num, int numberOfDecimalPlaces){
NumberFormat f = NumberFormat.getNumberInstance();
f.setMaximumFractionDigits(numberOfDecimalPlaces);
f.setMinimumFractionDigits(numberOfDecimalPlaces);
return f.format(num);
}
}