package org.seqcode.viz.metaprofile; import java.io.FileWriter; import java.io.IOException; import java.util.*; /** * MetaProfile: a collection of profiles. * @author: tdanford * Date: Aug 12, 2008 */ public class MetaProfile implements Profile, ProfileListener{ protected String name; protected BinningParameters params; protected double[] values; protected Double normalization; protected Vector<Profile> profiles; protected double max, min; protected boolean stranded=false; private LinkedList<ProfileListener> listeners; public MetaProfile(String n, BinningParameters bps) { name = n; params = bps; values = new double[params.getNumBins()]; max = min = 0.0; profiles = new Vector<Profile>(); normalization = null; listeners = new LinkedList<ProfileListener>(); } public void saveToFile(String fileName){ if(profiles.size()>0){ try { FileWriter fout = new FileWriter(fileName); int start = (-1*(params.getWindowSize()/2))+params.getBinSize()/2; int step = params.getWindowSize()/params.getNumBins(); fout.write(name+"\n"); int k= start; for(int i=0; i<values.length; i++){ fout.write(k+"\t"+values[i]+"\n"); k+=step; } fout.close(); } catch (IOException e) { e.printStackTrace(); } }else{ System.err.println("Empty MetaProfile: nothing to write to file"); } } public void saveProfilesToFile(String fileName){ if(profiles.size()>0){ try { FileWriter fout = new FileWriter(fileName); for(Profile p : profiles) { for(int i = 0; i < values.length; i++) { fout.write(String.format("%.2f", p.value(i))); if(i<values.length-1) fout.write("\t"); } fout.write("\n"); } fout.close(); } catch (IOException e) { e.printStackTrace(); } }else{ System.err.println("Empty MetaProfile: nothing to write to file"); } } public synchronized void normalize() { if(profiles.size() > 0) { normalize((double)profiles.size()); } } public synchronized void normalize(double dn) { max = min = 0.0; if(dn <= 0.0) { throw new IllegalArgumentException(String.format("Can't normalize with factor %f", dn)); } double norm = normalization == null ? 1.0 / dn : normalization / dn; for(int i = 0; i < values.length; i++) { values[i] *= norm; max = Math.max(max, values[i]); min = Math.min(min, values[i]); }normalization = dn; } protected void recalculate() { max = min = 0.0; for(int i = 0; i < values.length; i++) { values[i] = 0.0; } for(Profile p : profiles) { for(int i = 0; i < values.length; i++) { values[i] += p.value(i); } } if(isNormalized()) { for(int i = 0; i < values.length; i++) { values[i] /= normalization; max = Math.max(max, values[i]); min = Math.min(min, values[i]); } } } public synchronized void clear() { normalization = null; profiles.clear(); min = max = 0.0; for(int i = 0; i < values.length; i++ ){ values[i] = 0.0; } } public int size() { return profiles.size(); } public int length() { return values.length; } public double value(int i) { return values[i]; } public double max() { return max; } public double min() { return min; } public void setStranded(boolean s){stranded = s;} public boolean isStranded(){return stranded;} public String getName() { return name; } public BinningParameters getBinningParameters() { return params; } public Profile profile(int i) { return profiles.get(i); } public boolean isNormalized() { return normalization != null; } public synchronized void addProfile(Profile p) { if(p.isStranded()){ stranded=true; } if(p.length() != params.getNumBins()) { throw new IllegalArgumentException(String.format("Profile length %d doesn't" + " match bin-length %d", p.length(), params.getNumBins())); } if(isNormalized()) { throw new IllegalArgumentException("Can't add profile to a normalized MetaProfile"); } if(profiles.contains(p)) { /*throw new IllegalArgumentException(String.format( "Can't add same profile %s to MetaProfile", p.getName()));*/ }else{ profiles.add(p); for(int i = 0; i< values.length ;i++) { values[i] += p.value(i); max = Math.max(max, values[i]); min = Math.min(min, values[i]); } dispatchChange(new ProfileEvent(this, p)); } } public String toString() { return name; } public int hashCode() { return name.hashCode(); } public boolean equals(Object o) { if(!(o instanceof MetaProfile)) { return false; } MetaProfile mp = (MetaProfile)o; if(!mp.name.equals(name)) { return false; } return true; } public int getNumProfiles() { return profiles.size(); } public void addProfileListener(ProfileListener pl) { listeners.add(pl); } public void removeProfileListener(ProfileListener pl) { listeners.remove(pl); } protected void dispatchChange(ProfileEvent e) { for(ProfileListener pl : listeners) { pl.profileChanged(e); } } public synchronized void profileChanged(ProfileEvent p) { recalculate(); } }