// (C)2007 Attila Kovacs <attila@submm.caltech.edu>

import java.io.*;
import java.text.*;
import java.util.*;

public class Responsivity {

    int channels = -1;
    

    public static void main(String[] args) {
	System.err.println();
	System.err.println("  ASCIISpectrum -- Calculate spectra for Labview time-series.");
	System.err.println("                   2006 Attila Kovacs <attila@submm.caltech.edu> <akovacs@mpifr-bonn.mpg.de>");	
	System.err.println();

	if(args.length == 0) usage();

	try { 
	    Responsivity responsivity = new Responsivity(args);
	}
	catch(IOException e) { e.printStackTrace(); }
    }

    public Responsivity(String[] names) throws IOException {
	double[][] span = new double[names.length][];

	for(int i=0; i<names.length; i++) {
	    span[i] = getSpan(readData(names[i]));
	}

	for(int c=0; c<channels; c++) {
	    System.out.print((c+1));
	    for(int i=0; i<names.length; i++) 
		System.out.print("\t" + span[i][c]);
	    System.out.println();
	}
	
    }


    public double[] getSpan(Vector data) {
	double[] min = new double[channels];
	double[] max = new double[channels];
	
	Arrays.fill(min, Double.NaN);
	Arrays.fill(max, Double.NaN);

	for(int t=0; t<data.size(); t++) {
	    double[] entry = (double[]) data.get(t);
	    for(int c=0; c<channels; c++) {
		if(entry[c] < min[c] || Double.isNaN(min[c])) min[c] = entry[c];
		else if(entry[c] > max[c] || Double.isNaN(max[c])) max[c] = entry[c];
	    }
	}

	for(int c=0; c<channels; c++) max[c] -= min[c];

	return max;
    }


    public double[] getRMS(Vector data) {
	double[] var = new double[channels];

	double sum = 0.0;
	double norm = 0.0;

	for(int t=0; t<data.size(); t++) {
	    double[] entry = (double[]) data.get(t);
	    for(int c=0; c<channels; c++) {
		double di = (t - data.size());
		sum += entry[c] * di;
		norm += di*di;
	    }
	}
	double slope = sum / norm;
	
	
	for(int t=0; t<data.size(); t++) {
	    double[] entry = (double[]) data.get(t);
	    for(int c=0; c<channels; c++) {
		double value = entry[c] - slope*(t-data.size());
		var[c] += value*value;
	    }
	}
	
       	for(int c=0; c<channels; c++) var[c] = Math.sqrt(var[c]/data.size());

	
	
	return var;
    }
    


    public Vector readData(String fileName) throws IOException {
	Vector buffer = new Vector();	
	
	BufferedReader in = new BufferedReader(new FileReader(fileName));
	double dt = 1.0 / Double.parseDouble(in.readLine());
	String line;
	
	int entries = -1;
	double[] offset = null;
	
	System.err.println("  Reading data.");
	while((line = in.readLine()) != null) {
	    StringTokenizer tokens = new StringTokenizer(line);
	    if(entries <= 0) {
		entries = tokens.countTokens();
		channels = entries;
		offset = new double[channels];
	    }
	    else if(channels == tokens.countTokens()) {
		double[] entry = new double[channels];
		for(int i=0; i<entry.length; i++) {
		    entry[i] = Double.parseDouble(tokens.nextToken());
		    offset[i] += entry[i];
		}
		buffer.add(entry);
	    }
	}
	
	for(int c=0; c<channels; c++) offset[c] /= buffer.size();
	
	// Zeroing...
	for(int t=0; t<buffer.size(); t++) {
	    double[] entry = (double[]) buffer.get(t);
	    for(int c=0; c<channels; c++) entry[c] -= offset[c];	    
	}

	return buffer;
    }

    public static void usage() {
	
	System.out.println("  Usage: responsivity <hot/cold> [...]");
	System.out.println();
	System.out.println("       <hot/cold>    The Labview-style ASCII hot/cold data.");
	
	System.out.println();
	System.exit(0);
    }
}
