Skip to content
Commits on Source (6)
/*
* Copyright 2014 Brian L. Browning
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package beagleutil;
/**
* <p>Class {@code BasicIntInterval} represents an interval of
* consecutive integers.
* </p>
* Instances of class {@code BasicIntInterval} are immutable.
*
* @author Brian L. Browning {@code <browning@uw.edu>}
} */
public final class BasicIntInterval implements IntInterval,
Comparable<BasicIntInterval> {
private final int start;
private final int end;
/**
* Constructs an {@code SimpleIntInterval} instance.
* @param start the starting integer (inclusive).
* @param end the ending integer (inclusive).
* @throws IllegalArgumentException if {@code start>end}.
*/
public BasicIntInterval(int start, int end) {
if (start > end) {
String s = "start=" + start + " end=" + end;
throw new IllegalArgumentException(s);
}
this.start = start;
this.end = end;
}
@Override
public int start() {
return start;
}
@Override
public int end() {
return end;
}
/**
* <p>Returns a hash code value for the object.
* </p>
* <p>The hash code is defined by the following calculation:
* </p>
* <pre>
int hash = 3;
hash += 59 * hash + this.start();
hash += 59 * hash + this.end();
* </pre>
* @return a hash code value for the object.
*/
@Override
public int hashCode() {
int hash = 3;
hash = 59 * hash + this.start;
hash = 59 * hash + this.end;
return hash;
}
/**
* Returns {@code true} if the specified object is an
* {@code BasicIntInterval} instance and
* {@code this.start() == ((BasicIntInterval) obj).start()}, and
* {@code this.end() == ((BasicIntInterval) obj).end()},
* and returns {@code false} otherwise.
*
* @param obj the object to be compared with {@code this} for equality.
* @return {@code true} if the specified object is equal to
* {@code this}, and returns false otherwise.
*/
@Override
public boolean equals(Object obj) {
if (this==obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final BasicIntInterval other = (BasicIntInterval) obj;
if (this.start != other.start) {
return false;
}
return this.end==other.end;
}
/**
* Compares the specified {@code BasicIntInterval} with this for order,
* and returns a negative integer, zero, or a positive integer as
* {@code this} is less than, equal to, or greater than the specified
* {@code BasicIntInterval} object.
* {@code BasicIntInterval} objects are
* ordered by their start and their end values in that order.
*
* @param o the {@code BasicIntInterval} to be compared with this.
*
* @return a negative integer, zero, or a positive integer as this
* object is less than, equal to, or greater than the specified object.
*/
@Override
public int compareTo(BasicIntInterval o) {
if (this.start != o.start) {
return this.start < o.start ? -1 : 1;
}
else if (this.end != o.end) {
return this.end < o.end ? -1 : 1;
}
return 0;
}
/**
* Returns a string representation of {@code this}. The exact
* details of the representation are unspecified and subject to change.
*
* @return a string representation of {@code this}. The exact
* details of the representation are unspecified and subject to change.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
sb.append(start);
sb.append(", ");
sb.append(end);
sb.append(']');
return sb.toString();
}
}
package beagleutil;
import blbutil.Const;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* <p>Class {@code CenteredIntIntervalTree} implements a centered
* interval tree that stores {@code IntInterval} objects.
* </p>
* Instances of class {@code CenteredIntIntervalTree} are not thread-safe.
* @param <E> the objects stored by {@code this}.
*
* @author Brian L. Browning {@code <browning@uw.edu>}
*/
public class CenteredIntIntervalTree<E extends IntInterval & Comparable<E>>
implements IntIntervalTree<E> {
private final int start;
private final int end;
private int size;
private Node<E> root;
/**
* Creates a new {@code CenteredIntIntervalTree} instance for the
* specified range.
* @param start the minimum start value (inclusive) for intervals stored in
* this interval tree
* @param end the maximum end value (inclusive) for intervals stored
* in this interval tree
*
* @throws IllegalArgumentException if {@code end < start}
*/
public CenteredIntIntervalTree(int start, int end) {
if (end < start) {
String s = "end= " + end + " start=" + start;
throw new IllegalArgumentException(s);
}
int length = (end - start + 1);
int center = start + (length/2);
this.start = start;
this.end = end;
this.size = 0;
this.root = new Node<>(center);
}
@Override
public int start() {
return start;
}
@Override
public int end() {
return end;
}
@Override
public void clear() {
clear(root);
size = 0;
}
private void clear(Node<E> tree) {
if (tree==null) {
return;
}
tree.clear();
clear(tree.leftChild);
clear(tree.rightChild);
}
@Override
public boolean add(E element) {
if (element.start() < start || element.end() > end) {
String s = "element out of range [" + start + ", " + end + ") : "
+ element;
throw new IllegalArgumentException(s);
}
boolean added = add(root, element);
if (added) {
++size;
}
return added;
}
private boolean add(Node<E> tree, E element) {
if (element.end() < tree.center) {
if (tree.leftChild==null) {
int nextOffset = nextOffset(tree);
tree.leftChild = new Node<>(tree.center - nextOffset);
tree.leftChild.parent = tree;
}
return add(tree.leftChild, element);
}
else if (element.start() > tree.center) {
if (tree.rightChild==null) {
int nextOffset = nextOffset(tree);
tree.rightChild = new Node<>(tree.center + nextOffset);
tree.rightChild.parent = tree;
}
return add(tree.rightChild, element);
}
else {
return tree.add(element);
}
}
private int nextOffset(Node<E> node) {
int lastOffset;
if (node.parent==null) {
lastOffset = (end - start + 1)/2;
}
else {
lastOffset = Math.abs(node.center - node.parent.center);
}
assert lastOffset > 0;
int offset = (lastOffset+1)/2;
return offset;
}
@Override
public boolean contains(E element) {
return contains(root, element);
}
private boolean contains(Node<E> tree, E element) {
if (tree==null) {
return false;
}
else if (element.end() < tree.center) {
return contains(tree.leftChild, element);
}
else if (element.start() > tree.center) {
return contains(tree.rightChild, element);
}
else {
return tree.contains(element);
}
}
@Override
public boolean remove(E element) {
boolean removed = remove(root, element);
if (removed) {
--size;
}
return removed;
}
private boolean remove(Node<E> tree, E element) {
if (tree==null) {
return false;
}
else if (element.end() < tree.center) {
return remove(tree.leftChild, element);
}
else if (element.start() > tree.center) {
return remove(tree.rightChild, element);
}
else {
return tree.remove(element);
}
}
@Override
public void intersect(final int point, Collection<E> collection) {
intersect(root, point, collection);
}
private void intersect(Node<E> tree, int point, Collection<E> collection) {
if (tree==null) {
return;
}
tree.intersect(point, collection);
if (point < tree.center) {
intersect(tree.leftChild, point, collection);
}
else if (point > tree.center) {
intersect(tree.rightChild, point, collection);
}
}
@Override
public void intersectPart(int start, int end, Collection<E> collection) {
intersectPart(root, start, end, collection);
}
private void intersectPart(Node<E> tree, int start, int end,
Collection<E> collection) {
if (tree==null) {
return;
}
tree.intersectPart(start, end, collection);
if (start < tree.center) {
intersectPart(tree.leftChild, start, end, collection);
}
if (end > tree.center) {
intersectPart(tree.rightChild, start, end, collection);
}
}
@Override
public void intersectAll(int start, int end, Collection<E> collection) {
intersectAll(root, start, end, collection);
}
private void intersectAll(Node<E> tree, int start, int end,
Collection<E> collection) {
if (tree==null) {
return;
}
tree.intersectAll(start, end, collection);
if (end < tree.center) {
intersectAll(tree.leftChild, start, end, collection);
}
if (start > tree.center) {
intersectAll(tree.rightChild, start, end, collection);
}
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public int size() {
return size;
}
@Override
public E[] toArray() {
List<E> list = new ArrayList<>(size);
toArray(root, list);
return (E[]) list.toArray();
}
private void toArray(Node<E> tree, List<E> list) {
if (tree==null) {
return;
}
toArray(tree.leftChild, list);
list.addAll(tree.sortedStart);
toArray(tree.rightChild, list);
}
/**
* Returns a string representation of {@code this}. The
* exact details of the representation are unspecified and
* subject to change.
* @return a string representation of {@code this}
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[ CenteredIntIntervalTree: ");
sb.append(Const.nl);
sb.append("start=");
sb.append(start);
sb.append(" end=");
sb.append(end);
sb.append(" size=");
sb.append(size);
sb.append(Const.nl);
toString(root, sb);
sb.append(']');
return sb.toString();
}
private void toString(Node<E> tree, StringBuilder sb) {
if (tree==null) {
return;
}
toString(tree.leftChild, sb);
sb.append(tree);
toString(tree.rightChild, sb);
}
private static final class Node<E extends IntInterval & Comparable<E>> {
private final int center;
private final SortedSet<E> sortedStart;
private final SortedSet<E> sortedEnd;
private Node<E> parent;
private Node<E> leftChild;
private Node<E> rightChild;
/**
* Returns a {@code Comparator} that is consistent with equals and
* orders elements in order of increasing start values.
* @return a {@code Comparator} that is consistent with equals and
* orders elements in order of increasing start values
*/
private static <E extends IntInterval & Comparable<E>> Comparator<E> startComparator() {
return (E e1, E e2) -> {
int start1 = e1.start();
int start2 = e2.start();
if (start1 == start2) {
return e1.compareTo(e2);
}
else {
return (start1 < start2) ? -1 : 1;
}
} ;
}
/**
* Returns a {@code Comparator} that is consistent with equals and
* orders elements in order of decreasing end values.
* @return a {@code Comparator} that is consistent with equals and
* orders elements in order of decreasing end values
*/
private static <E extends IntInterval & Comparable<E>> Comparator<E> endComparator() {
return (E e1, E e2) -> {
int end1 = e1.end();
int end2 = e2.end();
if (end1 == end2) {
return e1.compareTo(e2);
}
else {
return (end1 > end2) ? -1 : 1;
}
} ;
}
Node(int center) {
this.center = center;
Comparator<E> startComparator = startComparator();
Comparator<E> endComparator = endComparator();
this.sortedStart = new TreeSet<>(startComparator);
this.sortedEnd = new TreeSet<>(endComparator);
this.leftChild = null;
this.rightChild = null;
}
boolean add(E element) {
if (element.start() > center || element.end() < center) {
String s = "element does not overlap center=" + center + ": "
+ element;
throw new IllegalArgumentException(s);
}
boolean addedStart = sortedStart.add(element);
boolean addedEnd = sortedEnd.add(element);
assert addedStart == addedEnd;
return addedStart;
}
boolean contains(E element) {
boolean startContains = sortedStart.contains(element);
assert startContains == sortedEnd.contains(element);
return startContains;
}
boolean remove(E element) {
boolean removedStart = sortedStart.remove(element);
boolean removedEnd = sortedEnd.remove(element);
assert removedStart == removedEnd;
return removedStart;
}
void intersect(int point, Collection<E> collection) {
if (point <= center) {
boolean finished = false;
Iterator<E> it = sortedStart.iterator();
while (it.hasNext() && finished==false) {
E e = it.next();
if (e.start() <= point) {
collection.add(e);
}
else {
finished = true;
}
}
}
else {
boolean finished = false;
Iterator<E> it = sortedEnd.iterator();
while (it.hasNext() && finished==false) {
E e = it.next();
if (e.end() >= point) {
collection.add(e);
}
else {
finished = true;
}
}
}
}
void intersectPart(int start, int end, Collection<E> collection) {
if (end < center) {
boolean finished = false;
Iterator<E> it = sortedStart.iterator();
while (it.hasNext() && finished==false) {
E e = it.next();
if (e.start() <= end) {
collection.add(e);
}
else {
finished = true;
}
}
}
else if (start > center) {
boolean finished = false;
Iterator<E> it = sortedEnd.iterator();
while (it.hasNext() && finished==false) {
E e = it.next();
if (start <= e.end()) {
collection.add(e);
}
else {
finished = true;
}
}
}
else {
collection.addAll(sortedStart);
}
}
void intersectAll(int start, int end, Collection<E> collection) {
boolean finished = false;
Iterator<E> it = sortedStart.iterator();
while (it.hasNext() && finished==false) {
E e = it.next();
if (e.start() <= start) {
if (e.end() >= end) {
collection.add(e);
}
}
else {
finished = true;
}
}
}
void clear() {
sortedStart.clear();
sortedEnd.clear();
}
/**
* Returns a string representation of {@code this}. The
* exact details of the representation are unspecified and
* subject to change.
* @return a string representation of {@code this}
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(Const.nl);
sb.append("[ CenteredIntIntervalTree.Node:");
sb.append(Const.nl);
sb.append("center=");
sb.append(center);
sb.append(" parent.center=");
sb.append(parent!=null ? parent.center : null);
sb.append(" leftchild.center=");
sb.append(leftChild!=null ? leftChild.center : null);
sb.append(" rightchild.center=");
sb.append(rightChild!=null ? rightChild.center : null);
sb.append(Const.nl);
sb.append("sortedStart: ");
sb.append(sortedStart);
sb.append(Const.nl);
sb.append("sortedEnd: ");
sb.append(sortedEnd);
sb.append(Const.nl);
sb.append(']');
return sb.toString();
}
}
//<editor-fold defaultstate="collapsed" desc="code for testing class">
/*
* The main() method if for testing the CenteredIntIntervalTree class
*/
// public static void main(String[] args) {
// main1(args);
// main2(args);
// }
private static void main1(String[] args) {
int length=16;
IntIntervalTree<BasicIntInterval> tree = new CenteredIntIntervalTree<>(0,length);
assert tree.start()==0;
assert tree.end()==length;
assert tree.isEmpty();
assert tree.isEmpty();
for (int j=0; j<length; ++j) {
BasicIntInterval i = new BasicIntInterval(j, j+1);
assert tree.contains(i)==false;
boolean added = tree.add(i);
assert added == true;
assert tree.contains(i)==true;
added = tree.add(i);
assert added == false;
}
assert tree.size()==length;
System.out.println("Initial Tree: " + java.util.Arrays.toString(tree.toArray()));
for (int j=0; j<length; j+=2) {
BasicIntInterval i = new BasicIntInterval(j, j+1);
assert tree.contains(i)==true;
boolean removed = tree.remove(i);
assert removed == true;
assert tree.contains(i)==false;
removed = tree.remove(i);
assert removed==false;
}
assert tree.size()==(length/2);
System.out.println("Pruned Tree: " + java.util.Arrays.toString(tree.toArray()));
List<BasicIntInterval> list = new ArrayList<>(length);
for (int j=0; j<length; ++j) {
tree.intersect(j, list);
System.out.println("point=" + j + ": " + list);
list.clear();
}
int intSize = 3;
for (int j=0; j<length; ++j) {
tree.intersectPart(j, j+intSize, list);
System.out.println("start=" + j + " end=" + (j+intSize) + ": " + list);
list.clear();
}
for (int j=0; j<length; ++j) {
tree.intersectAll(j, j, list);
System.out.println("start=" + j + " end=" + j + ": " + list);
list.clear();
}
tree.clear();
assert tree.isEmpty()==true;
System.out.println("Empty Tree: " + java.util.Arrays.toString(tree.toArray()));
}
private static void main2(String[] args) {
int length=16;
int nOverlaps = 4;
IntIntervalTree<BasicIntInterval> tree = new CenteredIntIntervalTree<>(-length,length);
assert tree.start()==-length;
assert tree.end()==length;
assert tree.isEmpty();
assert tree.isEmpty();
for (int j=1; j<=nOverlaps; ++j) {
BasicIntInterval i = new BasicIntInterval(-j - length/2, -j);
assert tree.contains(i)==false;
boolean added = tree.add(i);
assert added == true;
assert tree.contains(i)==true;
added = tree.add(i);
assert added == false;
}
assert tree.size()==nOverlaps;
for (int j=1; j<=nOverlaps; ++j) {
BasicIntInterval i = new BasicIntInterval(j, j + length/2);
assert tree.contains(i)==false;
boolean added = tree.add(i);
assert added == true;
assert tree.contains(i)==true;
added = tree.add(i);
assert added == false;
}
assert tree.size()==2*nOverlaps;
System.out.println(java.util.Arrays.toString(tree.toArray()));
System.out.println(tree);
for (int j=1; j<=nOverlaps; j+=2) {
BasicIntInterval i = new BasicIntInterval(-j - length/2, -j);
assert tree.contains(i)==true;
boolean removed = tree.remove(i);
assert removed == true;
assert tree.contains(i)==false;
removed = tree.remove(i);
assert removed==false;
}
for (int j=1; j<=nOverlaps; j+=2) {
BasicIntInterval i = new BasicIntInterval(j, j + length/2);
assert tree.contains(i)==true;
boolean removed = tree.remove(i);
assert removed == true;
assert tree.contains(i)==false;
removed = tree.remove(i);
assert removed==false;
}
assert tree.size()==nOverlaps;
System.out.println(java.util.Arrays.toString(tree.toArray()));
List<BasicIntInterval> list = new ArrayList<>(length);
for (int j=-length; j<length; ++j) {
tree.intersect(j, list);
System.out.println("point=" + j + ": " + list);
list.clear();
}
int intSize = 3;
for (int j=-length; j<length; ++j) {
tree.intersectPart(j, j+intSize, list);
System.out.println("start=" + j + " end=" + (j+intSize) + ": " + list);
list.clear();
}
tree.clear();
assert tree.isEmpty()==true;
System.out.println(java.util.Arrays.toString(tree.toArray()));
}
//</editor-fold>
}
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......@@ -19,6 +19,9 @@
package beagleutil;
import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* <p>Class {@code ChromIds} is a singleton class that represents a
......@@ -32,12 +35,18 @@ public final class ChromIds {
private static final ChromIds chromIds = new ChromIds();
private final ThreadSafeIndexer<String> instance;
private final ThreadSafeIndexer<String> indexer;
private final ConcurrentMap<String, Integer> map;
private volatile CopyOnWriteArrayList<String> ids;
private ChromIds() {
// private constructor to restrict instantiation.
int initCapacity = 4;
this.instance = new ThreadSafeIndexer<>(initCapacity);
this.indexer = new ThreadSafeIndexer<>(initCapacity);
this.map = new ConcurrentHashMap<>(initCapacity);
this.ids = new CopyOnWriteArrayList<>(new String[0]);
}
/**
......@@ -62,7 +71,37 @@ public final class ChromIds {
if (id.isEmpty()) {
throw new IllegalArgumentException("id.isEmpty()");
}
return instance.getIndex(id);
Integer index = map.get(id);
if (index!=null) {
return index;
}
else {
int i = indexer.getIndex(id);
map.putIfAbsent(id, i);
return i;
}
}
/**
* Returns an array of chromosome identifier indices corresponding to the
* specified array of chromosome identifiers. If a sample identifier is
* not yet indexed, the sample identifier will be indexed. Sample
* identifier indices are assigned in increasing order starting with 0.
* @param ids an array of sample identifiers
* @return an array of sample identifier indices
* @throws IllegalArgumentException if there is a {@code j} satisfying
* {@code (0 <= j && j < ids.length) && ids[j].isEmpty()}
* @throws NullPointerException if {@code ids == null}
* @throws NullPointerException if there is a {@code j} satisfying
* {@code (0 <= j && j < ids.length) && (ids[j] == null)}
*/
public int[] getIndices(String[] ids) {
for (String id : ids) {
if (id.isEmpty()) {
throw new IllegalArgumentException("id.isEmpty()");
}
}
return indexer.getIndices(ids);
}
/**
......@@ -80,7 +119,17 @@ public final class ChromIds {
if (id.isEmpty()) {
throw new IllegalArgumentException("id.isEmpty()");
}
return instance.getIndexIfIndexed(id);
Integer index = map.get(id);
if (index!=null) {
return index;
}
else {
int i = indexer.getIndexIfIndexed(id);
if (i>=0) {
map.putIfAbsent(id, i);
}
return i;
}
}
/**
......@@ -88,7 +137,7 @@ public final class ChromIds {
* @return the number of indexed chromosomes identifiers
*/
public int size() {
return instance.size();
return indexer.size();
}
/**
......@@ -99,7 +148,12 @@ public final class ChromIds {
* {@code index < 0 || index >= this.size()}
*/
public String id(int index) {
return instance.item(index);
if (index >= ids.size()) {
for (int j=ids.size(), n=indexer.size(); j<n; ++j) {
ids.add(indexer.item(j));
}
}
return ids.get(index);
}
/**
......@@ -111,7 +165,7 @@ public final class ChromIds {
* @return an array of chromosome identifiers
*/
public String[] ids() {
return instance.items().toArray(new String[0]);
return indexer.items().toArray(new String[0]);
}
/**
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......@@ -306,6 +306,19 @@ public final class ChromInterval implements IntInterval,
return sb.toString();
}
/**
* Returns {@code true} if the specified marker is in this chromosome
* interval and returns {@code false} otherwise.
* @param marker a marker
* @return {@code true} if the specified marker is in this chromosome
* interval
* @throws NullPointerException if {@code marker == null}
*/
public boolean contains(Marker marker) {
int pos = marker.pos();
return marker.chromIndex()==chromIndex && start <= pos && pos <= end;
}
/**
* Returns {@code true} if the specified chromosome intervals
* have non-empty intersection and returns {@code false} otherwise.
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......@@ -18,6 +18,8 @@
*/
package beagleutil;
import java.util.Comparator;
/**
* <p>Interface {@code IntInterval} represents an interval of
* consecutive integers.
......@@ -39,4 +41,44 @@ public interface IntInterval {
* @return the end of the interval (inclusive).
*/
public int end();
/**
* Returns a {@code Comparator<IntInterval>} which orders
* {@code IntInterval} objects in order of increasing {@code this.start()}
* value and orders {@code IntInterval} objects with the same
* {@code this.start()} value in order of increasing {@code this.end()}
* value.
* @return a {@code Comparator<IntInterval>} object
*/
public static Comparator<IntInterval> incEndComp() {
return (IntInterval t1, IntInterval t2) -> {
if (t1.start() != t2.start()) {
return (t1.start() < t2.start()) ? -1 : 1;
}
else if (t1.end() != t2.end()) {
return (t1.end() < t2.end()) ? -1 : 1;
}
return 0;
} ;
}
/**
* Returns a {@code Comparator<IntInterval>} which orders
* {@code IntInterval} objects in order of increasing {@code this.start()}
* value and orders {@code IntInterval} objects with the same
* {@code this.start()} value in order of decreasing {@code this.end()}
* value.
* @return a {@code Comparator<IntInterval>} object
*/
public static Comparator<IntInterval> decEndComp() {
return (IntInterval t1, IntInterval t2) -> {
if (t1.start() != t2.start()) {
return (t1.start() < t2.start()) ? -1 : 1;
}
else if (t1.end() != t2.end()) {
return (t1.end() > t2.end()) ? -1 : 1;
}
return 0;
} ;
}
}
/*
* Copyright 2014 Brian L. Browning
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package beagleutil;
import java.util.Collection;
/**
* Interface {@code IntIntervalTree} represents an interval
* tree whose elements are {@code IntInterval} objects.
*
* @param <E> the type of objected stored in {@code this}
*
* @author Brian L. Browning {@code <browning@uw.edu>}
*/
public interface IntIntervalTree<E extends IntInterval> {
/**
* Returns the minimum start (inclusive) of an interval
* that can be stored in this interval tree.
* @return the minimum start (inclusive) of an interval
* that can be stored in this interval tree
*/
public int start();
/**
* Returns the maximum end (inclusive) of an interval
* that can be stored in this interval tree.
* @return the maximum end (inclusive) of an interval
* that can be stored in this interval tree
*/
public int end();
/**
* Removes all of the elements from this interval tree.
*/
public void clear();
/**
* Adds the specified element to this interval tree, and returns
* {@code true} if the interval tree is changed as a result of
* the call. The method returns {@code false} if
* {@code this.contains(E) == true} when the method is invoked.
*
* @param element the element to be added
* @return {@code true} if the interval tree changed as
* a result of the call
*
* @throws IllegalArgumentException if
* {@code element.start() < this.start() || element.end() > this.end()}
* @throws NullPointerException if {@code element == null}
*/
public boolean add(E element);
/**
* Returns {@code true} if the interval tree contains the specified
* element, and returns {@code false} otherwise.
* @param element the element whose presence in the interval tree
* is to be tested
* @return {@code true} if the interval tree contains the specified
* element
* @throws NullPointerException if {@code element == null}
*/
public boolean contains(E element);
/**
* Removes the specified element from this interval tree if the
* specified element is found in the interval tree.
* @param element the element to be removed from this interval tree
* @return {@code true} if the interval tree is changed as
* a result of the call
* @throws NullPointerException if {@code element == null}
*/
public boolean remove(E element);
/**
* Adds the elements in this interval tree that intersect the specified
* point to the specified collection.
*
* @param point a point
* @param collection a collection to which will be added the elements of
* this interval tree that intersect the specified point
*
* @throws NullPointerException if {@code collection == null}
*/
public void intersect(int point, Collection<E> collection);
/**
* Adds the elements in this interval tree that intersect any part of
* the specified interval to the specified collection.
*
* @param start the start (inclusive) of the specified interval
* @param end the end (inclusive) of the specified interval
* @param collection a collection to which will be added the elements of
* this interval tree that intersect any part of the specified interval
*
* @throws NullPointerException if {@code collection == null}.
*/
public void intersectPart(int start, int end, Collection<E> collection);
/**
* Adds the elements in this interval tree that contain
* the specified interval to the specified collection.
*
* @param start the start (inclusive) of the specified interval
* @param end the end (inclusive) of the specified interval
* @param collection a collection to which will be added the elements
* of this interval tree that contain the specified interval
*
* @throws NullPointerException if {@code collection == null}
*/
public void intersectAll(int start, int end, Collection<E> collection);
/**
* Returns {@code true} if this interval tree contains no elements.
* @return {@code true} if this interval tree contains no elements
*/
public boolean isEmpty();
/**
* Returns the number of elements in this interval tree.
*
* @return the number of elements in this interval tree
*/
public int size();
/**
* Returns an array containing all of the elements of this interval tree.
* @return an array containing all of the elements of this interval tree
*/
public E[] toArray();
}
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......@@ -32,12 +32,12 @@ public final class SampleIds {
private static final SampleIds sampleIds = new SampleIds();
private final ThreadSafeIndexer<String> instance;
private final ThreadSafeIndexer<String> indexer;
private SampleIds() {
// private constructor to restrict instantiation.
int initCapacity = 5000;
this.instance = new ThreadSafeIndexer<>(initCapacity);
this.indexer = new ThreadSafeIndexer<>(initCapacity);
}
/**
......@@ -62,7 +62,29 @@ public final class SampleIds {
if (id.isEmpty()) {
throw new IllegalArgumentException("id.isEmpty()");
}
return instance.getIndex(id);
return indexer.getIndex(id);
}
/**
* Returns an array of sample identifier indices corresponding to the
* specified array of sample identifiers. If a sample identifier is
* not yet indexed, the sample identifier will be indexed. Sample
* identifier indices are assigned in increasing order starting with 0.
* @param ids an array of sample identifiers
* @return an array of sample identifier indices
* @throws IllegalArgumentException if there is a {@code j} satisfying
* {@code (0 <= j && j < ids.length) && ids[j].isEmpty()}
* @throws NullPointerException if {@code ids == null}
* @throws NullPointerException if there is a {@code j} satisfying
* {@code (0 <= j && j < ids.length) && (ids[j] == null)}
*/
public int[] getIndices(String[] ids) {
for (String id : ids) {
if (id.isEmpty()) {
throw new IllegalArgumentException("id.isEmpty()");
}
}
return indexer.getIndices(ids);
}
/**
......@@ -80,7 +102,7 @@ public final class SampleIds {
if (id.isEmpty()) {
throw new IllegalArgumentException("id.isEmpty()");
}
return instance.getIndexIfIndexed(id);
return indexer.getIndexIfIndexed(id);
}
/**
......@@ -88,7 +110,7 @@ public final class SampleIds {
* @return the number of indexed samples identifiers
*/
public int size() {
return instance.size();
return indexer.size();
}
/**
......@@ -99,7 +121,19 @@ public final class SampleIds {
* {@code index < 0 || index >= this.size()}
*/
public String id(int index) {
return instance.item(index);
return indexer.item(index);
}
/**
* Returns a list of sample identifiers with the specified indices.
* @param indices an array of sample identifiers indices
* @return a list of sample identifiers with the specified indices
* @throws IndexOutOfBoundsException if there exists a {@code j} satisfying
* {@code (0 <= j && j < indices.length)
* && (indices[j] < 0 || indices[j] >= this.size())}
*/
public String[] ids(int[] indices) {
return indexer.items(indices).toArray(new String[0]);
}
/**
......@@ -112,7 +146,7 @@ public final class SampleIds {
* @return an array of sample identifiers
*/
public String[] ids() {
return instance.items().toArray(new String[0]);
return indexer.items().toArray(new String[0]);
}
/**
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......@@ -80,11 +80,7 @@ public final class Samples {
* @throws NullPointerException if {@code ids == null}
*/
public static Samples fromIds(String[] ids) {
int[] indices = new int[ids.length];
for (int j=0; j<ids.length; ++j) {
indices[j] = sampleIds.getIndex(ids[j]);
}
return new Samples(indices);
return new Samples(sampleIds.getIndices(ids));
}
/**
......@@ -206,11 +202,7 @@ public final class Samples {
* @return this list of samples as an array of sample identifiers
*/
public String[] ids() {
String[] ids = new String[indexToIdIndex.length];
for (int j=0; j<ids.length; ++j) {
ids[j] = sampleIds.id(indexToIdIndex[j]);
}
return ids;
return sampleIds.ids(indexToIdIndex);
}
/**
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......@@ -89,6 +89,38 @@ public final class ThreadSafeIndexer<T> {
}
}
/**
* Returns an array of object indices corresponding to the specified
* object array. If an object is not yet indexed, the object will be
* indexed. Object indices are assigned in increasing order starting with 0.
* @param objects an array of objects
* @return an array of object identifier indices
* @throws IllegalArgumentException if there is a {@code j} satisfying
* {@code (0 <= j && j < objects.length) && objects[j].isEmpty()}
* @throws NullPointerException if {@code objects == null}
* @throws NullPointerException if there is a {@code j} satisfying
* {@code (0 <= j && j < objects.length) && (objects[j] == null)}
*/
public synchronized int[] getIndices(T[] objects) {
int[] indices = new int[objects.length];
for (int j=0; j<indices.length; ++j) {
T object = objects[j];
if (object==null) {
throw new NullPointerException();
}
if (map.keySet().contains(object)) {
indices[j] = map.get(object);
}
else {
int idIndex = list.size();
list.add(object);
map.put(object, idIndex);
indices[j] = idIndex;
}
}
return indices;
}
/**
* Returns the index of the specified object, or returns
* {@code -1} if the specified object is not indexed.
......@@ -131,7 +163,23 @@ public final class ThreadSafeIndexer<T> {
}
/**
* Returns an listed of indexed objects. The returned list will
* Returns a list of objects with the specified indices.
* @param indices an array of object indices
* @return a list of objects with the specified indices
* @throws IndexOutOfBoundsException if there exists a {@code j} satisfying
* {@code (0 <= j && j < indices.length)
* && (indices[j] < 0 || indices[j] >= this.size())}
*/
public synchronized List<T> items(int[] indices) {
List<T> items = new ArrayList<>(indices.length);
for (int index : indices) {
items.add(list.get(index));
}
return items;
}
/**
* Returns an listed of all indexed objects. The returned list will
* have size {@code this.size()}, and it will satisfy
* {@code this.items().get(k).equals(this.item(k))==true}
* for {@code 0 <= k && k < this.size()}
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......@@ -19,52 +19,95 @@
package blbutil;
/**
* <p>Class {@code ByteIndexArray} represents an immutable
* {@code int[]} array that is stored as a {@code byte[]} array.
* <p>Class {@code ByteArray} represents an immutable array of integer
* values between -128 and 127 that is stored as a {@code byte[]} array.
* </p>
* Instances of {@code ByteIndexArray} are immutable.
* Instances of {@code ByteArray} are immutable.
*
* @author Brian L. Browning {@code <browning@uw.edu>}
*/
public class ByteIndexArray implements IntArray {
public final class ByteArray implements IntArray {
private final byte[] ba;
/**
* Constructs a new {@code ByteIndexArray} instance.
* @param ia an array of integers
* Constructs a new {@code ByteArray} instance from
* the specified data.
* @param ba an array of integer values between -128 and 127 inclusive
* @throws NullPointerException if {@code ba == null}
*/
public ByteArray(byte[] ba) {
this.ba = ba.clone();
}
/**
* Constructs a new {@code ByteArray} instance from the specified data.
* @param ia an array of integer values between -128 and 127 inclusive
* @throws IllegalArgumentException if
* {@code ia[j] < 0 || ia[j] > 127} for any index {@code j}
* satisfying {@code j >= 0 && j < ia.length}
* {@code (ia[j] < -128 || ia[j] > 127)} for any index {@code j}
* satisfying {@code (j >= 0 && j < ia.length)}
* @throws NullPointerException if {@code ia == null}
*/
public ByteIndexArray(int[] ia) {
public ByteArray(int[] ia) {
this(ia, 0, ia.length);
}
/**
* Constructs a new {@code ByteIndexArray} instance from the
* specified subarray.
* @param ia an array of integers
* @param start the first element to be included (inclusive)
* @param end the last element to be included (exclusive)
* Constructs a new {@code ByteArray} instance from the specified data.
* @param il an list of integer values between -128 and 127 inclusive
* @throws IllegalArgumentException if
* {@code ia[j] < 0 || ia[j] > 127} for any index {@code j}
* satisfying {@code j >= start && j < end}
* @throws IndexOutOfBoundsException if {@code start < 0 or end > ia.length}
* @throws IllegalArgumentException if {@code end > start}
* @throws NullPointerException if {@code ia == null}
* {@code (il.get(j) < -128 || il.get(j) > 127)} for any index {@code j}
* satisfying {@code (j >= 0 && j < il.size())}
* @throws NullPointerException if {@code il == null}
*/
public ByteIndexArray(int[] ia, int start, int end) {
if (start > end) {
throw new IllegalArgumentException("start > end");
public ByteArray(IntList il) {
this(il, 0, il.size());
}
this.ba = new byte[end - start];
for (int j=start; j<end; ++j) {
if (ia[j] < 0 || ia[j] > 127) {
/**
* Constructs a new {@code ByteArray} instance from the
* specified data.
* @param ia an array of integer values between -128 and 127 inclusive
* @param from the first element to be included (inclusive)
* @param to the last element to be included (exclusive)
* @throws IllegalArgumentException if
* {@code (ia[j] < -128 || ia[j] > 127)} for any index {@code j}
* satisfying {@code (j >= from && j < to)}
* @throws IndexOutOfBoundsException if {@code from < 0 || to > ia.length}
* @throws NegativeArraySizeException if {@code to > from}
* @throws NullPointerException if {@code ia == null}
*/
public ByteArray(int[] ia, int from, int to) {
this.ba = new byte[to - from];
for (int j=from; j<to; ++j) {
if (ia[j] < -128 || ia[j] > 127) {
throw new IllegalArgumentException(String.valueOf(ia[j]));
}
ba[j - start] = (byte) ia[j];
ba[j - from] = (byte) ia[j];
}
}
/**
* Constructs a new {@code ByteArray} instance from the
* specified data.
* @param il an list of integer values between -128 and 127 inclusive
* @param from the first element to be included (inclusive)
* @param to the last element to be included (exclusive)
* @throws IllegalArgumentException if
* {@code (il.get(j) < -128 || il.get(j) > 127)} for any index {@code j}
* satisfying {@code (j >= from && j < to)}
* @throws IndexOutOfBoundsException if {@code from < 0 || to > il.length}
* @throws NegativeArraySizeException if {@code to > from}
* @throws NullPointerException if {@code il == null}
*/
public ByteArray(IntList il, int from, int to) {
this.ba = new byte[to - from];
for (int j=from; j<to; ++j) {
int value = il.get(j);
if (value < -128 || value > 127) {
throw new IllegalArgumentException(String.valueOf(value));
}
ba[j - from] = (byte) value;
}
}
......
/*
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
* Beagle is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Beagle is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package blbutil;
/**
/**
* <p>Class {@code UnsignedByteArray} represents an immutable
* array of integer values between 0 and 65,535 inclusive that is stored
* as a {@code char[]} array.
* </p>
* Instances of {@code CharArray} are immutable.
*
* @author Brian L. Browning {@code <browning@uw.edu>}
*/
public final class CharArray implements IntArray {
private final char[] ca;
/**
* Constructs a new {@code CharArray} instance from the specified data.
* The array of bytes is interpreted as a stream of characters with
* the high byte preceding the low byte.
* @param ba an array of char values expressed as pairs of bytes.
* @throws IllegalArgumentException if {@code (ba.length % 1) != 0}
* @throws NullPointerException if {@code ca == null}
*/
public CharArray(byte[] ba) {
if ((ba.length % 1)!=0) {
throw new IllegalArgumentException(String.valueOf(ba.length));
}
this.ca = new char[ba.length/2];
for (int j=0; j<ba.length; j+=2) {
int b1 = ba[j] & 0xff;
int b2 = ba[j+1] & 0xff;
ca[j/2] = (char) ((b1 << 8) + b2);
}
}
/**
* Constructs a new {@code CharArray} instance from
* the specified data.
* @param ca an array of integer values between 0 and Character.MAX_VALUE
* inclusive
* @throws NullPointerException if {@code ca == null}
*/
public CharArray(char[] ca) {
this.ca = ca.clone();
}
/**
* Constructs a new {@code CharArray} instance from the specified data.
* @param ia an array of integers
* @throws IllegalArgumentException if
* {@code (ia[j] < 0 || ia[j] > Character.MAX_VALUE)} for any index
* {@code j} satisfying {@code (j >= from && j < to)}
* @throws NullPointerException if {@code ia == null}
*/
public CharArray(int[] ia) {
this(ia, 0, ia.length);
}
/**
* Constructs a new {@code UnsignedByteArray} instance from the specified data.
* @param il an list of integer values between 0 and
* {@code Character.MAX_VALUE} inclusive
* @throws IllegalArgumentException if
* {@code (il.get(j) < 0 || il.get(j) > Character.MAX_VALUE)} for any index
* {@code j} satisfying {@code (j >= 0 && j < il.size())}
* @throws NullPointerException if {@code il == null}
*/
public CharArray(IntList il) {
this(il, 0, il.size());
}
/**
* Constructs a new {@code CharArray} instance from the
* specified data.
* @param ia an array of integer values between 0 and
* {@code Character.MAX_VALUE} inclusive
* @param to the first element to be included (inclusive)
* @param from the last element to be included (exclusive)
* @throws IllegalArgumentException if
* {@code (ia[j] < 0 || ia[j] > Character.MAX_VALUE)} for any index
* {@code j} satisfying {@code (j >= from && j < to)}
* @throws IndexOutOfBoundsException if {@code (from < 0 || to > ia.length)}
* @throws NegativeArraySizeException if {@code to > from}
* @throws NullPointerException if {@code ia == null}
*/
public CharArray(int[] ia, int to, int from) {
this.ca = new char[from - to];
for (int j=to; j<from; ++j) {
if (ia[j] < 0 || ia[j] > Character.MAX_VALUE) {
throw new IllegalArgumentException(String.valueOf(ia[j]));
}
ca[j - to] = (char) ia[j];
}
}
/**
* Constructs a new {@code CharArray} instance from the specified data.
* @param il an list of integer values between 0 and
* {@code Character.MAX_VALUE} inclusive
* @param from the first element to be included (inclusive)
* @param to the last element to be included (exclusive)
* @throws IllegalArgumentException if
* {@code (il.get(j) < 0 || il.get(j) > Character.MAX_VALUE)} for any index {@code j}
* satisfying {@code (j >= from && j < to)}
* @throws IndexOutOfBoundsException if {@code from < 0 || to > il.length}
* @throws NegativeArraySizeException if {@code to > from}
* @throws NullPointerException if {@code il == null}
*/
public CharArray(IntList il, int from, int to) {
this.ca = new char[to - from];
for (int j=from; j<to; ++j) {
int value = il.get(j);
if (value < 0 || value > Character.MAX_VALUE) {
throw new IllegalArgumentException(String.valueOf(value));
}
ca[j - from] = (char) value;
}
}
@Override
public int size() {
return ca.length;
}
@Override
public int get(int index) {
return ca[index];
}
@Override
public String toString() {
return this.asString();
}
}
/*
* Copyright (C) 2014 Brian L. Browning
*
* This file is part of Beagle
*
* Beagle is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Beagle is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package blbutil;
/**
* <p>Class {@code CharIndexArray} represents an immutable
* {@code int[]} array that is stored as a {@code char[]} array.
* </p>
* Instances of {@code CharIndexArray} are immutable.
*
* @author Brian L. Browning {@code <browning@uw.edu>}
*/
public class CharIndexArray implements IntArray {
private final char[] ca;
/**
* Constructs a new {@code CharIndexArray} instance.
* @param ia an array of integers
* @throws IllegalArgumentException if
* {@code ia[j] < 0 || ia[j] > 65535} for any index {@code j}
* satisfying {@code j >= 0 && j < ia.length}
* @throws NullPointerException if {@code ia == null}
*/
public CharIndexArray(int[] ia) {
this(ia, 0, ia.length);
}
/**
* Constructs a new {@code CharIndexArray} instance from the
* specified subarray.
* @param ia an array of integers
* @param start the first element to be included (inclusive)
* @param end the last element to be included (exclusive)
* @throws IllegalArgumentException if
* {@code ia[j] < 0 || ia[j] > 65535} for any index {@code j}
* satisfying {@code j >= start && j < end}
* @throws IndexOutOfBoundsException if {@code start < 0 or end > ia.length}
* @throws IllegalArgumentException if {@code end > start}
* @throws NullPointerException if {@code ia == null}
*/
public CharIndexArray(int[] ia, int start, int end) {
if (start > end) {
throw new IllegalArgumentException("start > end");
}
this.ca = new char[end - start];
for (int j=start; j<end; ++j) {
if (ia[j] < 0 || ia[j] > 65535) {
throw new IllegalArgumentException(String.valueOf(ia[j]));
}
ca[j - start] = (char) ia[j];
}
}
@Override
public int size() {
return ca.length;
}
@Override
public int get(int index) {
return ca[index];
}
@Override
public String toString() {
return this.asString();
}
}
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......@@ -53,7 +53,7 @@ public interface FileIt<E> extends java.util.Iterator<E>, Closeable {
/**
* Terminates the iteration and releases any system resources that
* are held by this object. After invoking {@code close}, further
* are held by this object. After invoking {@code close()}, further
* invocations of {@code close()} have no effect.
*/
@Override
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......@@ -18,6 +18,7 @@
*/
package blbutil;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
......@@ -26,7 +27,10 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.util.zip.GZIPOutputStream;
/**
......@@ -41,65 +45,117 @@ public class FileUtil {
}
/**
* Returns an unbuffered {@code java.io.FileInputStream} reading from the
* specified file. If the input stream cannot be opened, an error message
* will be printed and the java interpreter will exit.
* Creates and returns a new empty temporary file in the specified
* directory. The temporary file will be deleted when the JVM terminates
* if the JVM terminates normally.
* @param prefix a prefix of at least 3 characters for the temporary
* filename
* @param directory the directory in which the temporary file is to
* be created.
* @return a new empty temporary file in the specified directory.
* @throws NullPointerException if
* {@code prefix == null || directory == null}
*/
public static File tempFile(String prefix, File directory) {
if (prefix==null) {
throw new NullPointerException(String.class.toString());
}
if (directory==null) {
throw new NullPointerException(File.class.toString());
}
File tmpFile = null;
try {
tmpFile = File.createTempFile(prefix, null, directory);
tmpFile.deleteOnExit();
}
catch (IOException ex) {
Utilities.exit("Error opening file", ex);
}
return tmpFile;
}
/**
* Returns a {@code java.io.RandomAccessFile} to read from or optionally
* to write to the specified file. If the input stream cannot
* be opened, an error message will be printed and the java interpreter
* will exit.
* @param file a file
* @param mode the access mode as described in the documentation for the
* {@code java.io.RandomAccessFile} constructors
* @return a {@code java.io.RandomAccessFile}
* @throws NullPointerException if {@code file == null || mode == null}
*/
public static RandomAccessFile randomAccessFile(File file, String mode) {
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(file, mode);
} catch (FileNotFoundException ex) {
Utilities.exit("Error: file not found [" + file + "]", ex);
}
return raf;
}
/**
* Returns an buffered {@code java.io.InputStream} with default buffer
* size reading from the specified file. If the input stream cannot
* be opened, an error message will be printed and the java interpreter
* will exit.
* @param file a file
* @return an unbuffered {@code java.io.FileInputStream}
* @return an buffered {@code java.io.InputStream}
* @throws NullPointerException if {@code file == null}
*/
public static FileInputStream fileInputStream(File file) {
FileInputStream fis = null;
public static InputStream bufferedInputStream(File file) {
InputStream is = null;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
Utilities.exit("Error opening " + file, e);
is = new BufferedInputStream(new FileInputStream(file));
} catch (FileNotFoundException ex) {
Utilities.exit("Error: file not found [" + file + "]", ex);
}
return fis;
return is;
}
/**
* Returns an unbuffered {@code java.io.FileOutputStream}. If the file
* cannot be opened for writing, an error message will be printed and the
* Java Virtual Machine will exit. If the specified file exists, bytes
* written by the returned {@code FileOutputSream} will overwrite the
* previously existing file.
* Returns an buffered {@code java.io.OutputStream} with default
* buffer size writing to the specified file. If the file cannot
* be opened for writing, an error message will be printed and the
* Java Virtual Machine will exit.
*
* @param file a file
* @return an unbuffered {@code java.io.PrintWriter}
* @return a buffered {@code java.io.OutputStream}
* @throws NullPointerException if {@code file == null}
*/
public static FileOutputStream fileOutputStream(File file) {
FileOutputStream fos = null;
public static OutputStream bufferedOutputStream(File file) {
OutputStream os = null;
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
Utilities.exit("Error opening " + file, e);
os = new BufferedOutputStream(new FileOutputStream(file));
} catch (FileNotFoundException ex) {
Utilities.exit("Error: file not found [" + file + "]", ex);
}
return fos;
return os;
}
/**
* Returns an unbuffered {@code java.io.FileOutputStream}. If the file
* cannot be opened for writing, an error message will be printed and the
* Returns an buffered {@code java.io.OutputStream} with default
* buffer size writing to the specified file. If the file cannot
* be opened for writing, an error message will be printed and the
* Java Virtual Machine will exit. If the specified file exists and
* {@code append} is {@code false}, bytes written by the returned
* {@code PrintWriter} will overwrite the previously existing file.
* {@code java.io.OutputStream} will overwrite the previously existing file.
*
* @param file a file
* @param append {@code true} if bytes will be appended to the end of
* the file
* @return an unbuffered {@code java.io.PrintWriter}
* @return an buffered {@code java.io.OutputStream}
* @throws NullPointerException if {@code file == null}
*/
public static FileOutputStream fileOutputStream(File file, boolean append) {
FileOutputStream fos = null;
public static OutputStream bufferedOutputStream(File file, boolean append) {
OutputStream os = null;
try {
fos = new FileOutputStream(file, append);
} catch (FileNotFoundException e) {
Utilities.exit("Error opening " + file, e);
os = new BufferedOutputStream(new FileOutputStream(file, append));
} catch (FileNotFoundException ex) {
Utilities.exit("Error: file not found [" + file + "]", ex);
}
return fos;
return os;
}
/**
......@@ -138,6 +194,33 @@ public class FileUtil {
return out;
}
/**
* Returns a buffered {@code java.io.PrintWriter} writing to
* the specified file. The resulting file will be compressed using
* the GZIP compression algorithm. If the file cannot be opened, an
* error message will be printed and the java interpreter will exit.
* If the specified file exists and {@code append} is {@code false}, bytes
* written by the returned {@code PrintWriter} will overwrite the
* previously existing file.
* @param file a file
* @param append {@code true} if bytes will be appended to the end of
* the file
* @return a {@code java.io.PrintWriter} writing to the specified file
* @throws NullPointerException if {@code file == null}
*/
public static PrintWriter gzipPrintWriter(File file, boolean append) {
PrintWriter out = null;
try {
FileOutputStream fos = new FileOutputStream(file, append);
BufferedOutputStream bos = new BufferedOutputStream(fos);
GZIPOutputStream gzos = new GZIPOutputStream(bos);
out = new PrintWriter(gzos);
} catch (IOException e) {
Utilities.exit("Error opening " + file, e);
}
return out;
}
/**
* Returns a buffered {@code java.io.PrintWriter} that compresses
* data using the BGZIP algorithm and writes the compressed data
......@@ -154,8 +237,7 @@ public class FileUtil {
*/
public static PrintWriter bgzipPrintWriter(File file) {
boolean writeBuffer = true;
FileOutputStream fos = fileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
OutputStream bos = FileUtil.bufferedOutputStream(file);
return new PrintWriter(new BGZIPOutputStream(bos, writeBuffer));
}
......@@ -178,8 +260,7 @@ public class FileUtil {
*/
public static PrintWriter bgzipPrintWriter(File file, boolean append) {
boolean writeBuffer = true;
FileOutputStream fos = fileOutputStream(file, append);
BufferedOutputStream bos = new BufferedOutputStream(fos);
OutputStream bos = bufferedOutputStream(file, append);
return new PrintWriter(new BGZIPOutputStream(bos, writeBuffer));
}
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......
/*
* Copyright (C) 2014 Brian L. Browning
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
......@@ -16,67 +16,77 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package vcf;
package blbutil;
import java.util.Arrays;
/**
* <p>Interface {@code HapsMarker} represents marker alleles for a
* list of haplotype pairs.
* </p>
* All instances of {@code HapsMarkers} are required to be
* immutable.
* Class {@code FloatArray} represents an immutable list of float floating
* point values.
*
* @author Brian L. Browning {@code <browning@uw.edu>}
*/
public interface HapsMarker extends MarkerContainer {
public class FloatArray {
private final float[] values;
/**
* Returns the allele on the specified haplotype.
* @param haplotype a haplotype index
* @return the allele on the specified haplotype
*
* @throws IndexOutOfBoundsException if
* {@code haplotype < 0 || haplotype >= this.nHaps()}
* Constructs an {@code FloatArray} object with the specified
* values.
* @param values the list of floating point values
* @throws NullPointerException if {@code values == null}
*/
int allele(int haplotype);
public FloatArray(float[] values) {
this.values = values.clone();
}
/**
* Returns the first allele for the specified haplotype pair.
* @param hapPair a haplotype pair index
* @return the first allele for the specified haplotype pair
*
* Returns the float at the specified position in this list.
* @param index the index of the returned float
* @return the float at the specified position in this list
* @throws IndexOutOfBoundsException if
* {@code hapPair < 0 || hapPair >= this.nHapPairs()}
* {@code index < 0 || index >= size}
*/
int allele1(int hapPair);
public float get(int index) {
return values[index];
}
/**
* Returns the second allele for the specified haplotype pair.
* @param hapPair a haplotype pair index
* @return the second allele for the specified haplotype pair
*
* @throws IndexOutOfBoundsException if
* {@code hapPair < 0 || hapPair >= this.nHapPairs()}
* Returns the number of elements in this list.
* @return the number of elements in this list
*/
int allele2(int hapPair);
public int size() {
return values.length;
}
/**
* Returns the marker.
* @return the marker
* Returns {@code true} if this list has no elements, and returns
* {@code false} otherwise.
* @return {@code true} if this list has no elements, and returns
* {@code false} otherwise
*/
@Override
Marker marker();
public boolean isEmpty() {
return values.length==0;
}
/**
* Returns the number of haplotypes. The returned value is equal to
* {@code 2*this.nHapPairs()}.
* @return the number of haplotypes
* Returns an integer array containing the sequence of elements in this
* list.
* @return an integer array containing the sequence of elements in this
* list
*/
int nHaps();
public float[] toArray() {
return values.clone();
}
/**
* Returns the number of haplotype pairs. The returned value is
* equal to {@code this.nHaps()/2}.
* @return the number of haplotype pairs
* Returns a string representation of this list that is
* obtained by calling {@code java.util.Arrays.toString(this.toArray())}.
*
* @return a string representation of this list
*/
int nHapPairs();
@Override
public String toString() {
return Arrays.toString(values);
}
}
/*
* Copyright (C) 2014-2016 Brian L. Browning
*
* This file is part of Beagle
*
* Beagle is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Beagle is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package blbutil;
import java.util.Arrays;
/**
* Class {@code FloatList} represents a list of floats.
* Class {@code FloatList} supports a {@code clear()} method, but does not
* support a {@code remove()} method.
*
* @author Brian L. Browning {@code <browning@uw.edu>}
*/
public class FloatList {
/**
* The default initial capacity of an {@code FloatList}, which is 10.
*/
public static final int DEFAULT_INIT_CAPACITY = 10;
private int size;
private float[] values;
/**
* Constructs an {@code FloatList} object with the default
* initial capacity.
*
* @see #DEFAULT_INIT_CAPACITY
*/
public FloatList() {
this(DEFAULT_INIT_CAPACITY);
}
/**
* Constructs an {@code FloatList} object with the specified
* initial capacity.
*
* @param initCapacity the initial capacity of this list
* @throws IllegalArgumentException if {@code initCapacity<0}.
*/
public FloatList(int initCapacity) {
if (initCapacity < 0) {
throw new IllegalArgumentException(String.valueOf(initCapacity));
}
this.size = 0;
this.values = new float[initCapacity];
}
/**
* Adds the specified integer to the end of this list.
*
* @param element the value to be added to the end of this list.
*/
public void add(float element) {
if (size==values.length) {
int newCapacity = (values.length * 3)/2 + 1;
this.values = Arrays.copyOf(this.values, newCapacity);
}
this.values[size++] = element;
}
/**
* Adds the specified value to the specified element.
*
* @param index the index of the element to which the specified value
* will be added
* @param value the to be added
* @throws IndexOutOfBoundsException if
* {@code index < 0 || index >= this.size()}
*/
public void addToElement(int index, float value) {
if (index >= size) {
throw new IndexOutOfBoundsException(String.valueOf(index));
}
this.values[index] += value;
}
/**
* Returns the float at the specified position in this list.
* @param index the index of the returned float.
* @return the float at the specified position in this list.
* @throws IndexOutOfBoundsException if
* {@code index < 0 || index >= this.size()}
*/
public float get(int index) {
if (index >= size) {
throw new IndexOutOfBoundsException(String.valueOf(index));
}
return values[index];
}
/**
* Replaces the element at the specified position in this list with the
* specified element.
* @param index the index of the element to be replaced
* @param value the value to be stored at the specified position
* in this list
* @return the previous value at the specified position in this list
* @throws IndexOutOfBoundsException if
* {@code index < 0 || index >= this.size()}
*/
public float set(int index, float value) {
if (index >= size) {
throw new IndexOutOfBoundsException(String.valueOf(index));
}
float oldValue = values[index];
values[index] = value;
return oldValue;
}
/**
* Returns the number of elements in this list.
* @return the number of elements in this list.
*/
public int size() {
return size;
}
/**
* Returns {@code true} if this list has no elements, and returns
* {@code false} otherwise.
* @return {@code true} if this list has no elements, and returns
* {@code false} otherwise.
*/
public boolean isEmpty() {
return size==0;
}
/**
* Returns an integer array containing the sequence of elements in this
* list.
* @return an integer array containing the sequence of elements in this
* list.
*/
public float[] toArray() {
return Arrays.copyOf(values, size);
}
/**
* Removes all elements from this list.
*/
public void clear() {
this.size = 0;
}
/**
* Returns a string representation of this list. The
* exact details of the representation are unspecified and
* subject to change.
*
* @return a string representation of this list.
*/
@Override
public String toString() {
return Arrays.toString(Arrays.copyOf(values, size));
}
}