import java.util.*;

public class NormalizeFeatureRanges {
	
	Map<String, Ranges> hmap = new HashMap<String, Ranges>();
	
	public class Ranges {
		public double oMin;
		public double oMax;
		
		Ranges() {
			;
		}
		
		Ranges(double min, double max){
			oMin = min;
			oMax = max;
		}
		
		public void setRanges(double min, double max) {
			oMin = min;
			oMax = max;
		}
	
	};
	
	public NormalizeFeatureRanges() { 
		initFeatureRanges(); 
	};
	
	public void initFeatureRanges() {
		// common features for residues
		hmap.put("resASA",      new Ranges(0, 300.0));  //  280.400
		hmap.put("fracASA",     new Ranges(0, 2.0));    //  1.600
		hmap.put("fracVol", 	new Ranges(0, 2.50));
		hmap.put("sideASA", 	new Ranges(0, 100.0));  // 99.901 
		hmap.put("sideFracASA", new Ranges(0, 2.00));   // 1.80
		hmap.put("SFE", 	new Ranges(-5.00, 1.00));     // -4.40,0.90;
		hmap.put("phi", 	new Ranges(-180.00, 180.00)); // -179.798, 179.912
		hmap.put("psi", 	new Ranges(-180.00, 180.00)); // -179.954, 179.996
		hmap.put("omega", 	new Ranges(-180.00, 180.00));
		hmap.put("chi", 	new Ranges(-180.00, 180.00));
		hmap.put("chi2", 	new Ranges(-180.00, 180.00));
		hmap.put("chi3", 	new Ranges(-180.00, 180.00));
		hmap.put("phi_p", 	new Ranges(-180.00, 180.00));
		hmap.put("psi_p", 	new Ranges(-180.00, 180.00));
		hmap.put("omega_p", 	new Ranges(-180.00, 180.00));
		hmap.put("chi_p", 	new Ranges(-180.00, 180.00));
		hmap.put("phi_n", 	new Ranges(-180.00, 180.00));
		hmap.put("psi_n", 	new Ranges(-180.00, 180.00));
		hmap.put("omega_n", 	new Ranges(-180.00, 180.00));
		hmap.put("chi_n", 	new Ranges(-180.00, 180.00));
		hmap.put("phi_p2", 	new Ranges(-180.00, 180.00));
		hmap.put("psi_p2", 	new Ranges(-180.00, 180.00));
		hmap.put("omega_p2", 	new Ranges(-180.00, 180.00));
		hmap.put("chi_p2", 	new Ranges(-180.00, 180.00));
		hmap.put("phi_n2", 	new Ranges(-180.00, 180.00));
		hmap.put("psi_n2", 	new Ranges(-180.00, 180.00));
		hmap.put("omega_n2", 	new Ranges(-180.00, 180.00));
		hmap.put("chi_n2", 	new Ranges(-180.00, 180.00));
		
		hmap.put("nn_chi", 	new Ranges(0, 360.00));
		hmap.put("nn_chi2", 	new Ranges(0, 360.00));
		hmap.put("nn_chi3", 	new Ranges(0, 360.00));		
		hmap.put("nn_chi_p", 	new Ranges(0, 360.00));		
		hmap.put("nn_chi_n", 	new Ranges(0, 360.00));
		hmap.put("nn_chi_p2", 	new Ranges(0, 360.00));
		hmap.put("nn_chi_n2", 	new Ranges(0, 360.00));
		
		hmap.put("theta_donor",      new Ranges(0, 180.00));		
		hmap.put("theta_acceptor",   new Ranges(0, 180.00));
		hmap.put("kappa_donor",      new Ranges(0, 90.00));
		hmap.put("kappa_acceptor",   new Ranges(0, 90.00));
		
		hmap.put("ha1dist", 	new Ranges(0,3.00)); // 2.7721
		hmap.put("ha2dist", 	new Ranges(0,3.00)); // 2.7677
		hmap.put("hndist", 	new Ranges(0,3.50)); // 3.4914
		hmap.put("ordist", 	new Ranges(0,3.50)); // 3.3443
		
		hmap.put("ha1dist_p", 	new Ranges(0,3.00)); // 2.7721
		hmap.put("ha2dist_p", 	new Ranges(0,3.00)); // 2.7677
		hmap.put("hndist_p", 	new Ranges(0,3.50)); // 3.4914
		hmap.put("ordist_p", 	new Ranges(0,3.50)); // 3.3443

		hmap.put("ha1dist_n", 	new Ranges(0,3.00)); // 2.7721
		hmap.put("ha2dist_n", 	new Ranges(0,3.00)); // 2.7677
		hmap.put("hndist_n", 	new Ranges(0,3.50)); // 3.4914
		hmap.put("ordist_n", 	new Ranges(0,3.50)); // 3.3443

		hmap.put("hydro", 	new Ranges(-4.00, 4.00)); // -3.950, 3.575
		hmap.put("ph", 		new Ranges(0, 9.0));  // 0, 8.5
		hmap.put("temperature", new Ranges(0, 400));  // 0, 380K		
				
		// features for each atom
		// Backbone Atoms ************************************************************
		// N, CA,CB,C,HN,HA

		// Side Chain Atoms ************************************************************
		// HB, HB2, HB3, HD1, HD2, HD21, HD22, HD3, HE, HE1, HE2, HE3, HE21, HE22, HE3,
		// HG, HG1, HG12, HG13, HG2, HG3, HH2, HZ, HZ2, HZ3, CD, CD1, CD2, CG, CG1, CG2
		
        // ASA - one max measure
        // or each atom

		hmap.put("asa",         new Ranges(0, 100.0));  // 0 ~ (31.867 ~ 90.469)
		hmap.put("rcoil",       new Ranges(0, 185.0));
		hmap.put("rcurr",       new Ranges(-4.0, 2.0));
		hmap.put("electrostat", new Ranges(-1.0, 1.0));
		hmap.put("hbondeffect", new Ranges(-1.0, 3.5));
		
		hmap.put("rcoil-C",     new Ranges(170.0, 180.0));  
                hmap.put("rcoil-CALL",  new Ranges(10.0,  185.0));   
                hmap.put("rcoil-HALL",  new Ranges(0.0,   12.0));
                hmap.put("rcoil-N",     new Ranges(105.0, 130.0));

		hmap.put("hbondeffect-H",  new Ranges(-1.0, 3.5));   
                hmap.put("hbondeffect-HA", new Ranges(0.0, 1.0));
	
	}
	
    public double getNormalizeFeature(String feature, double oValue) {
    	double scaledValue = 0.0;  	
    	double lower = 0.0, upper = 1.0;
    	Ranges fr = new Ranges();   
    	
    	// get min & max of features
    	fr = hmap.get(feature);
         
    	if (oValue < fr.oMin) scaledValue = lower;
        else if (oValue > fr.oMax) scaledValue = upper;
        else { 
    	     scaledValue = lower + (upper-lower) * ( (oValue - fr.oMin) / ( fr.oMax - fr.oMin ) );
        } 
    	
    	// scaledValue = scaledValue <= upper ? scaledValue : upper;
    	// scaledValue = scaledValue >= lower ? scaledValue : lower;
    	
    	if ((Double)scaledValue == null) System.err.println("Error: scaled Value is null");  
    	
    	return scaledValue;
    }

}
