File: ArrayListSet.java

package info (click to toggle)
bbmap 39.20%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 26,024 kB
  • sloc: java: 312,743; sh: 18,099; python: 5,247; ansic: 2,074; perl: 96; makefile: 39; xml: 38
file content (202 lines) | stat: -rwxr-xr-x 5,703 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package stream;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;

import tax.TaxNode;
import tax.TaxTree;

/**
 * Associates reads with named lists.
 * Designed for dynamically demultiplexing reads into output streams with MultiCros.
 * This class is not thread-safe; one should be instantiated per thread.
 * @author Brian Bushnell
 * @date Apr 2, 2015
 *
 */
public class ArrayListSet {
	
	/*--------------------------------------------------------------*/
	/*----------------        Initialization        ----------------*/
	/*--------------------------------------------------------------*/

	public ArrayListSet(boolean ordered_){
		this(ordered_, null, TaxTree.stringToLevelExtended("phylum"));
	}

	/**
	 * Create an ArrayListSet with an optional TaxTree and level.
	 * The tree is to assign reads to a list based on the taxonomy of the name,
	 * rather than the name itself.
	 * @param ordered_ Whether input order should be maintained.  Unimplemented.
	 * @param tree_ A taxonomic tree.
	 * @param taxLevelE_ The minimum level in the tree to stop.
	 */
	public ArrayListSet(boolean ordered_, TaxTree tree_, int taxLevelE_){
		ordered=ordered_;
		tree=tree_;
		taxLevelE=taxLevelE_;
	}
	
	/*--------------------------------------------------------------*/
	/*----------------        Outer Methods         ----------------*/
	/*--------------------------------------------------------------*/
	
	public void add(Read r, Iterable<String> names){
		for(String s : names){add(r, s);}
	}
	
	public void add(Read r, String name){
		final Pack p=getPack(name, true);
		p.add(r);
	}
	
	public void add(Read r, int id){
		final Pack p=getPack(id, true);
		p.add(r);
	}
	
	public ArrayList<Read> getAndClear(String name){
		final Pack p=getPack(name, false);
		return p==null ? null : p.getAndClear();
	}
	
	public ArrayList<Read> getAndClear(int id){
		final Pack p=getPack(id, false);
		return p==null ? null : p.getAndClear();
	}
	
	public Collection<String> getNames(){
		return nameList;
	}
	
	public int size(){return nameList.size();}
	
	/*--------------------------------------------------------------*/
	/*----------------        TaxId Methods         ----------------*/
	/*--------------------------------------------------------------*/
	
	/** Look up the sequence name, which should start with a gi or ncbi number, and
	 * associate the read with the ancestor node at some taxonomic level.
	 * @param r
	 * @param name
	 */
	public void addByTaxid(Read r, String name){
		addByTaxid(r, nameToTaxid(name));
	}
	
	public void addByTaxid(Read r, int taxid){
		String key=Integer.toString(taxid);
		final Pack p=getPack(key, true);
		p.add(r);
	}
	
	public void addByTaxid(Read r, ArrayList<String> names){
		if(names.size()==0){return;}
		else if(names.size()==1){addByTaxid(r, names.get(0));}
		else{addByTaxid(r, (Iterable<String>)names);}
	}
	
	public void addByTaxid(Read r, Iterable<String> names){
		HashSet<Integer> idset=tls.get();
		if(idset==null){
			idset=new HashSet<Integer>();
			tls.set(idset);
		}
		assert(idset.isEmpty());
		for(String s : names){
			idset.add(nameToTaxid(s));
		}
		for(Integer i : idset){
			addByTaxid(r, i);
		}
		idset.clear();
	}
	
	private int nameToTaxid(String name){
		TaxNode tn=tree.getNode(name, taxLevelE);
		return (tn==null ? -1 :tn.id);
	}
	
	/*--------------------------------------------------------------*/
	/*----------------        Inner Methods         ----------------*/
	/*--------------------------------------------------------------*/
	
	private Pack getPack(String name, boolean add){
		Pack p=stringMap.get(name);
		if(p==null && add){p=new Pack(name);}
		return p;
	}
	
	private Pack getPack(int id, boolean add){
		Pack p=packList.size()>id ? packList.get(id) : null;
		if(p==null && add){p=new Pack(id);}
		return p;
	}
	
	@Override
	public String toString(){
		return nameList.toString();
	}
	
	/*--------------------------------------------------------------*/
	/*----------------        Nested Classes        ----------------*/
	/*--------------------------------------------------------------*/
	
	private class Pack {
		
		Pack(String s){
			assert(s==null || !stringMap.containsKey(s));
			name=s;
			id=packList.size();
			nameList.add(s);
			packList.add(this);
			if(s!=null){stringMap.put(s, this);}
		}
		
		Pack(int x){
			name=null;
			id=x;
			while(packList.size()<=x){packList.add(null);}
			assert(packList.get(x)==null);
			packList.set(x, this);
		}
		
		public void add(Read r){
			if(list==null){list=new ArrayList<Read>();}
			list.add(r);
		}
		
		public ArrayList<Read> getAndClear(){
			ArrayList<Read> temp=list;
			list=null;
			return temp;
		}
		
		@Override
		public String toString(){
			return "Pack "+name;
		}
		
		final String name;
		@SuppressWarnings("unused")
		final int id;
		private ArrayList<Read> list;
	}
	
	/*--------------------------------------------------------------*/
	/*----------------            Fields            ----------------*/
	/*--------------------------------------------------------------*/
	
	private final boolean ordered;
	private final ArrayList<String> nameList=new ArrayList<String>();
	private final ArrayList<Pack> packList=new ArrayList<Pack>();
	private final LinkedHashMap<String, Pack> stringMap=new LinkedHashMap<String, Pack>();
	private final int taxLevelE;
	private final TaxTree tree;
	private final ThreadLocal<HashSet<Integer>> tls=new ThreadLocal<HashSet<Integer>>();
	
	
}