1 package hiseq;
2 
3 import java.util.Arrays;
4 
5 import dna.AminoAcid;
6 import shared.Tools;
7 import stream.Read;
8 
9 /**
10  * Tracks base and quality composition per cycle.
11  *
12  * @author Brian Bushnell
13  * @date August 16, 2018
14  *
15  */
16 public class CycleTracker {
17 
add(Read r)18 	public void add(Read r){
19 		if(r==null || r.length()<1){return;}
20 		addBases(r.bases);
21 		addQuality(r.quality);
22 	}
23 
add(CycleTracker ct)24 	public void add(CycleTracker ct){
25 //		assert(false) : length+", "+ct.length;
26 		final long[][] matrix=ct.acgtnq;
27 		if(matrix[0]==null){return;}
28 		if(acgtnq[0]==null || ct.length>length){
29 			resize(ct.length);
30 		}
31 		for(int i=0; i<matrix.length; i++){
32 			for(int j=0; j<matrix[i].length; j++){
33 				acgtnq[i][j]+=matrix[i][j];
34 			}
35 		}
36 	}
37 
38 	//Do this before using results
process()39 	public void process(){
40 //		System.err.println("Processing); length="+length);
41 		if(length<1){return;}
42 		long[] cycleSum=new long[length];
43 		for(int i=0; i<5; i++){
44 			long[] array=acgtnq[i];
45 			for(int j=0; j<array.length; j++){
46 				cycleSum[j]+=array[j];
47 			}
48 		}
49 		maxes=new float[6];
50 		averages=new float[6];
51 		for(int i=0; i<6; i++){
52 			cycleAverages[i]=new float[length];
53 			long[] array=acgtnq[i];
54 			for(int j=0; j<length; j++){
55 				float f=array[j]/(float)cycleSum[j];
56 				cycleAverages[i][j]=f;
57 				maxes[i]=Tools.max(f, maxes[i]);
58 			}
59 		}
60 
61 		long[] sum=new long[6];
62 		long sumsum=0;
63 		for(int i=0; i<5; i++){
64 			long x=Tools.sum(acgtnq[i]);
65 			sum[i]=x;
66 			sumsum+=x;
67 		}
68 		sum[5]=Tools.sum(acgtnq[5]);
69 		for(int i=0; i<6; i++){
70 			averages[i]=sum[i]/(float)sumsum;
71 		}
72 	}
73 
74 	/*--------------------------------------------------------------*/
75 
addBases(byte[] bases)76 	private void addBases(byte[] bases){
77 		if(length<bases.length){resize(bases.length);}
78 		for(int i=0; i<bases.length; i++){
79 			byte b=bases[i];
80 			int x=AminoAcid.baseToNumberACGTN[b];
81 			assert(x>=0) : "This program does not support degenerate base codes: "+new String(bases);
82 			acgtnq[x][i]++;
83 		}
84 	}
85 
addQuality(byte[] quals)86 	private void addQuality(byte[] quals){
87 		if(quals==null){return;}
88 		if(length<quals.length){resize(quals.length);}
89 		final long[] sum=acgtnq[5];
90 		for(int i=0; i<quals.length; i++){
91 			byte q=quals[i];
92 			sum[i]+=q;
93 		}
94 	}
95 
resize(int newLen)96 	private void resize(int newLen){
97 		assert(newLen>length);
98 		length=newLen;
99 		if(acgtnq[0]==null){
100 			for(int i=0; i<acgtnq.length; i++){
101 				acgtnq[i]=new long[newLen];
102 			}
103 		}else{
104 			for(int i=0; i<acgtnq.length; i++){
105 				acgtnq[i]=Arrays.copyOf(acgtnq[i], newLen);
106 			}
107 		}
108 	}
109 
max(byte base)110 	public float max(byte base) {
111 		final int x=AminoAcid.baseToNumberACGTN[base];
112 		return(maxes[x]);
113 	}
114 
max(char base)115 	public float max(char base) {
116 		final int x=AminoAcid.baseToNumberACGTN[base];
117 		return(maxes[x]);
118 	}
119 
avg(byte base)120 	public float avg(byte base) {
121 		final int x=AminoAcid.baseToNumberACGTN[base];
122 		return(averages[x]);
123 	}
124 
avg(char base)125 	public float avg(char base) {
126 		final int x=AminoAcid.baseToNumberACGTN[base];
127 		return(averages[x]);
128 	}
129 
130 	/*--------------------------------------------------------------*/
131 
132 	public long[][] acgtnq=new long[6][];
133 	public float[][] cycleAverages=new float[6][];
134 	public float[] maxes;
135 	public float[] averages;
136 	public int length=0;
137 
138 }
139