package evoker;
import java.util.Hashtable;
import java.util.Vector;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
/**
* Holds all the data about a set of SNPs, usually for one chromosome.
*
*/
public class MarkerData {
//Hashtable<String,Integer> snpIndexTable;
//Hashtable<String,String> snpAlleleATable;
//Hashtable<String,String> snpAlleleBTable;
//while this seems ridiculous, it is a considerable memory savings which is now not exposed anywhere
//outside this class. Instead of having a hash keyed on strings of chroms, taking up something like
//20 bytes per key, even though there are only a few possibilities. we do this dance to simultaneously
//avoid the memory overhead for millions of entries while allowing "chrom" to be anything, rather than
//just numbers 1..22 etc.
HashMap<String,Byte> chromosomeLookup; // chromosome -> id
HashMap<Byte,String> chromosomeBackLookup;// id -> chromosome
HashMap<String,Marker> markerTable; // SNP_Name -> Marker
HashMap<String,Integer> collectionIndices;// Collection -> ID (from collectionIndices after first chromosome file)
HashMap<String,Integer> snpsPerCollection;// Collection -> Number of SNPs
private int numCollections; // Number of Collections
private int runningCount; // Number of BimFiles so far
//HashMap<String, HashMap<String, Vector<String>>> snpDB = new HashMap<String, HashMap<String, Vector<String>>>();
public MarkerData(int numCollections){
this.numCollections = numCollections;
markerTable = new HashMap<String,Marker>();
collectionIndices = new HashMap<String,Integer>();
snpsPerCollection = new HashMap<String,Integer>();
chromosomeLookup = new HashMap<String,Byte>();
chromosomeBackLookup = new HashMap<Byte,String>();
runningCount = -1;
}
public int getSampleCollectionIndex(String collection){
return collectionIndices.get(collection);
}
/**
* Returns a Random SNP ID from markerTable (all IDs as key)
* @return SNP ID
*/
public String getRandomSNP(){
Vector v = new Vector(markerTable.keySet());
return (String)v.get((int)(Math.random()*markerTable.keySet().size()));
}
/**
* Adds information of a bim file
* @param bimFile
* @param collection
* @param chromosome
* @param isOx
* @throws IOException
*/
public void addFile(String bimFile, String collection, String chromosome,
boolean isOx) throws IOException {
if (collectionIndices.get(collection) == null){
runningCount++;
collectionIndices.put(collection,runningCount);
}
byte chrom = chromosomeLookup.get(chromosome);
String currentLine;
BufferedReader bimReader = new BufferedReader(new FileReader(bimFile));
//read through bim file to record marker order so we can quickly index
//into binary files
int index = 0;
String[] bits;
boolean missingAlleles = false;
while ((currentLine = bimReader.readLine()) != null){
bits = currentLine.split("\\s");
StringBuffer snpid = null;
char a = 'A',b = 'B';
// check the size of the bits array
if(bits.length >= 5) {
snpid = new StringBuffer(bits[1]);
if (isOx){
a = bits[3].toCharArray()[0];
b = bits[4].toCharArray()[0];
}else{
a = bits[4].toCharArray()[0];
b = bits[5].toCharArray()[0];
}
} else if (bits.length == 1){
// if there is just 1 column assume the file contains only a SNP id
missingAlleles = true;
snpid = new StringBuffer(bits[0]);
}
// not sure if these files exist
// else if(bits.length == 3) {
// // if there are 3 columns assume the file contains name, id and position
// missingAlleles = true;
// snpid = new StringBuffer(bits[1]);
// }
if (markerTable.get(snpid.toString()) == null){
markerTable.put(snpid.toString(), new Marker(numCollections,a,b,chrom));
}
//TP: only the first two args are used in addSampleCollection
markerTable.get(snpid.toString()).addSampleCollection(runningCount,index++,a,b,snpid.toString());
// if(! snpDB.containsKey(collection)) snpDB.put(collection, new HashMap<String, Vector<String>>());
// if(! snpDB.get(collection).containsKey(chromosome)) snpDB.get(collection).put(chromosome, new Vector<String>());
// snpDB.get(collection).get(chromosome).add(snpid.toString());
}
//TP CHANGED THIS
int snpsSoFar = 0;
if (snpsPerCollection.containsKey(collection))
snpsSoFar = snpsPerCollection.get(collection);
snpsPerCollection.put(collection,index + snpsSoFar);
snpsPerCollection.put(collection+chromosome,index);
if (missingAlleles) {
Genoplot.ld.log("WARNING: SNP file does not contain allele information");
}
}
// public HashMap<String, Vector<String>> getSnpInfo(String collection){
// return snpDB.get(collection);
// }
public char[] getAlleles(String snp){
return markerTable.get(snp).getAlleles();
}
public String getChrom(String name){
if (markerTable.get(name) != null){
return chromosomeBackLookup.get(markerTable.get(name).getChrom());
}else{
return null;
}
}
public HashMap<String, Marker> getMarkerTable(){
return markerTable;
}
/**
* Returns the number of SNPs contained by a Collection
* @param collectionName
* @return SNP number
*/
public int getNumSNPs(String collection) {
return snpsPerCollection.get(collection);
}
public Integer getIndex(String markerName, int sampleIndex){
if (markerTable.get(markerName) != null){
return markerTable.get(markerName).getIndex(sampleIndex);
}else{
return -1;
}
}
public void addChromToLookup(String chrom, byte counter) {
chromosomeLookup.put(chrom,counter);
chromosomeBackLookup.put(counter,chrom);
}
}