/*******************************************************************************
* GenPlay, Einstein Genome Analyzer
* Copyright (C) 2009, 2014 Albert Einstein College of Medicine
*
* This program 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.
*
* This program 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/>.
* Authors: Julien Lajugie <julien.lajugie@einstein.yu.edu>
* Nicolas Fourel <nicolas.fourel@einstein.yu.edu>
* Eric Bouhassira <eric.bouhassira@einstein.yu.edu>
*
* Website: <http://genplay.einstein.yu.edu>
******************************************************************************/
package edu.yu.einstein.genplay.core.manager.project;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import edu.yu.einstein.genplay.dataStructure.chromosome.Chromosome;
import edu.yu.einstein.genplay.dataStructure.chromosome.SimpleChromosome;
import edu.yu.einstein.genplay.dataStructure.list.listView.AbstractListView;
import edu.yu.einstein.genplay.dataStructure.list.listView.ListView;
import edu.yu.einstein.genplay.exception.exceptions.InvalidChromosomeException;
/**
* The {@link ProjectChromosomes} class provides tools to load and access and list of {@link Chromosome}.
* This class follows the design pattern <i>Singleton</i>
* @author Julien Lajugie
* @author Nicolas Fourel
*/
public final class ProjectChromosomes extends AbstractListView<Chromosome> implements Serializable, Iterable<Chromosome>, ListView<Chromosome> {
/** Defines the value of the chromosome first base (likely to be 0 or 1) */
public static final int FIRST_BASE_POSITION = 1;
private static final long serialVersionUID = 8781043776370540275L; // generated ID
private static final int SAVED_FORMAT_VERSION_NUMBER = 0; // saved format version
private Map<String, Integer> chromosomeHash; // Hashtable indexed by chromosome name
private List<Chromosome> chromosomeList; // List of chromosome
private long genomeLength; // Total length of the genome
/**
* Creates the chromosome hash.
* Replaces the existing one.
*/
private void createChromosomeHash () {
// Creates the chromosome names list
List<String> chromosomeNames = new ArrayList<String>();
for (Chromosome chromosome: chromosomeList) {
chromosomeNames.add(chromosome.getName().toLowerCase());
}
// Creates the chromosome/index mapping
chromosomeHash = new HashMap<String, Integer>();
int cpt = 0;
for (String s: chromosomeNames) {
chromosomeHash.put(s, cpt);
cpt++;
}
}
/**
* Compute the size of the genome.
*/
private void genomeLengthCalculation () {
genomeLength = 0;
for (Chromosome chromosome: chromosomeList) {
genomeLength += chromosome.getLength();
}
}
/**
* @param index index of a {@link Chromosome}
* @return the first chromosome with the specified index
* @throws InvalidChromosomeException
*/
@Override
public Chromosome get(int index) {
if (index < chromosomeList.size()) {
return chromosomeList.get(index);
}
// throw an exception if nothing found
throw new InvalidChromosomeException();
}
/**
* @param chromosomeName name of a {@link Chromosome}
* @return the first chromosome having the specified name
* @throws InvalidChromosomeException
*/
public Chromosome get(String chromosomeName) throws InvalidChromosomeException {
// we put the chromosome name in lower case to avoid problems related to case sensitivity
chromosomeName = chromosomeName.toLowerCase();
// we get the index of associated to the chromosome name
Integer index = chromosomeHash.get(chromosomeName);
// if the index (thus the chromosome) exists, we can return the chromosome
if (index != null) {
return chromosomeList.get(index);
}
// throw an exception if nothing found
throw new InvalidChromosomeException();
}
/**
* @return the chromosomeList
*/
public List<Chromosome> getChromosomeList() {
return chromosomeList;
}
/**
* @return the length of the genome in bp
*/
public long getGenomeLength() {
return genomeLength;
}
/**
* @param chromosome a {@link Chromosome}
* @return the index of the specified chromosome
* @throws InvalidChromosomeException
*/
public int getIndex(Chromosome chromosome) throws InvalidChromosomeException {
return getIndex(chromosome.getName());
}
/**
* @param chromosomeName name of a chromosome.
* @return the index of the first chromosome having the specified name
* @throws InvalidChromosomeException
*/
public int getIndex(String chromosomeName) throws InvalidChromosomeException {
// we put the chromosome name in lower case to avoid problems related to case sensitivity
chromosomeName = chromosomeName.toLowerCase();
// we get the index of associated to the chromosome name
Integer index = chromosomeHash.get(chromosomeName);
// throw an exception if nothing found
if (index == null) {
throw new InvalidChromosomeException();
} else {
return index.intValue(); // the index is returned
}
}
/**
* Method used for unserialization
* @param in
* @throws IOException
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.readInt();
chromosomeHash = (Map<String, Integer>) in.readObject();
chromosomeList = (List<Chromosome>) in.readObject();
genomeLength = in.readLong();
}
/**
* @param chromosomeList the chromosomeList to set
*/
public void setChromosomeList(List<Chromosome> chromosomeList) {
this.chromosomeList = chromosomeList;
createChromosomeHash();
genomeLengthCalculation();
}
/**
* Set the current {@link ProjectChromosomes} using another instance of {@link ProjectChromosomes}
* Used for the unserialization.
* @param project the instance of {@link ProjectChromosomes} to use
*/
protected void setProjectChromosomes(ProjectChromosomes project) {
setChromosomeList(project.getChromosomeList());
}
/**
* @return the size of the list of chromosome (ie: the number of chromosomes)
*/
@Override
public int size() {
return chromosomeList.size();
}
/**
* @return an array containing all the chromosomes of the manager
*/
public Chromosome[] toArray() {
// Initializes the chromosome array
Chromosome[] returnArray = new Chromosome[chromosomeList.size()];
// Fills the chromosome array
returnArray = chromosomeList.toArray(returnArray);
// Returns the array
return returnArray;
}
/**
* @param lengthList the list of new chromosome lengths in the same order as the chromosome list
*/
public void updateChromosomeLengths(List<Integer> lengthList) {
for (int i = 0; i < chromosomeList.size(); i++) {
Chromosome newChromosome = new SimpleChromosome(chromosomeList.get(i).getName(), lengthList.get(i));
chromosomeList.set(i, newChromosome);
}
genomeLengthCalculation();
}
/**
* Method used for serialization
* @param out
* @throws IOException
*/
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeInt(SAVED_FORMAT_VERSION_NUMBER);
out.writeObject(chromosomeHash);
out.writeObject(chromosomeList);
out.writeLong(genomeLength);
}
}