/*******************************************************************************
* 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.multiGenome.operation.fileScanner;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import edu.yu.einstein.genplay.core.manager.project.ProjectManager;
import edu.yu.einstein.genplay.core.multiGenome.VCF.BGZIPReader;
import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFLine;
import edu.yu.einstein.genplay.core.multiGenome.VCF.VCFFile.VCFFile;
import edu.yu.einstein.genplay.core.multiGenome.operation.UpdateEngine;
/**
* @author Nicolas Fourel
* @version 0.1
*/
public class UpdateFileScanner implements FileScannerInterface {
private final UpdateEngine engine; // The export update engine.
private final ManualVCFReader src; // The reader for the file to use as a model.
private final BGZIPReader dest; // The reader for the file to update
/**
* Constructor of {@link UpdateFileScanner}
* @param engine the phasing engine
* @param src the VCF file to use as reference for phasing
* @param dest the VCF file to apply the phasing
* @throws Exception
*/
public UpdateFileScanner (UpdateEngine engine, VCFFile src, VCFFile dest) throws Exception {
this.engine = engine;
this.src = new ManualVCFReader(src, engine.getGenomeList(), engine.getVariationMap(), engine.getFilterList(), engine.isIncludeReferences(), engine.isIncludeNoCall());
this.dest = new BGZIPReader(dest);
}
/**
* Compares positions of two lines according to:
* - CHROM
* - POS
* @param line01 the first line
* @param line02 the second line
* @return -1 if the first line is located before the second line, 0 if they are at the same location, 1 if the first line is after the second one
*/
private int compareLines (VCFLine line01, VCFLine line02) {
int chromIndex01 = ProjectManager.getInstance().getProjectChromosomes().getIndex(line01.getCHROM());
int chromIndex02 = ProjectManager.getInstance().getProjectChromosomes().getIndex(line02.getCHROM());
if (chromIndex01 == chromIndex02) {
int position01 = line01.getReferencePosition();
int position02 = line02.getReferencePosition();
if (position01 == position02) {
return 0;
} else if (position01 < position02) {
return -1;
} else { // position01 > position02
return 1;
}
} else if ((chromIndex01 == 0) && line02.getCHROM().equals("chrM")) {
return 1;
} else if ((chromIndex02 == 0) && line01.getCHROM().equals("chrM")) {
return -1;
} else if (chromIndex01 < chromIndex02) {
return -1;
} else { // chromIndex01 > chromIndex02
return 1;
}
}
@Override
public void compute() throws Exception {
boolean valid = true;
//while ((lineNumber < lineLimit) && valid) {
while (valid) {
List<VCFLine> currentDestinationLines = getCurrentListOfDestinationLine();
if (currentDestinationLines.size() > 0) {
List<VCFLine> currentSourceLines = getCurrentListOfSourceLines(currentDestinationLines.get(0));
if (currentSourceLines.size() > 0) {
List<VCFLine> validCouplesLines = getValidCouplesLines(currentSourceLines, currentDestinationLines);
int index = 0;
while (index < validCouplesLines.size()) {
engine.processLine(validCouplesLines.get(index), validCouplesLines.get(index + 1));
index += 2;
}
}
} else {
valid = false;
}
}
}
private boolean defineSameVariation (VCFLine line01, VCFLine line02) {
boolean result = false;
if (line01.getREF().equals(line02.getREF())) {
String[] alternatives01 = line01.getAlternatives();
String[] alternatives02 = line02.getAlternatives();
for (String currentAlternative: alternatives01) {
if (hasAlternative(alternatives02, currentAlternative)) {
result = true;
break;
}
}
}
return result;
}
@Override
public VCFLine getCurrentLine() {
return null;
}
private List<VCFLine> getCurrentListOfDestinationLine () throws IOException {
List<VCFLine> result = new ArrayList<VCFLine>();
if (!dest.getCurrentLine().isLastLine()) {
VCFLine firstLine = dest.getCurrentLine();
firstLine.processForAnalyse();
result.add(firstLine);
boolean valid = true;
while (valid) {
dest.goNextLine();
VCFLine currentLine = dest.getCurrentLine();
if (!currentLine.isLastLine() && (compareLines(firstLine, currentLine) == 0)) {
result.add(currentLine);
currentLine.processForAnalyse();
} else {
valid = false;
}
}
}
return result;
}
private List<VCFLine> getCurrentListOfSourceLines (VCFLine line) throws IOException {
List<VCFLine> result = new ArrayList<VCFLine>();
boolean valid = true;
while (valid) {
VCFLine currentSrcLine = src.getCurrentValidLine();
if (currentSrcLine.isLastLine()) {
valid = false;
} else {
//int compare = compareLines(line, currentSrcLine);
int compare = compareLines(currentSrcLine, line);
if (compare == 0) {
if (currentSrcLine.hasData()) {
result.add(currentSrcLine);
currentSrcLine.processForAnalyse();
}
src.goNextLine();
} else if (compare < 0) {
src.goNextLine();
} else {
valid = false;
}
}
}
return result;
}
@Override
public VCFFile getCurrentVCFFile() {
return null;
}
@Override
public ManualVCFReader getCurrentVCFReader() {
return null;
}
/**
* @return the dest
*/
public BGZIPReader getDestinationReader() {
return dest;
}
@Override
public List<String> getGenomeList() {
return null;
}
/**
* @return the src
*/
public BGZIPReader getSourceReader() {
return src.getReader();
}
private List<VCFLine> getValidCouplesLines (List<VCFLine> currentSourceLines, List<VCFLine> currentDestinationLines) {
List<VCFLine> result = new ArrayList<VCFLine>();
for (VCFLine currentSourceLine: currentSourceLines) {
for (VCFLine currentDestinationLine: currentDestinationLines) {
if (defineSameVariation(currentSourceLine, currentDestinationLine)) {
result.add(currentSourceLine);
result.add(currentDestinationLine);
currentSourceLine.processForAnalyse();
currentDestinationLine.processForAnalyse();
break;
}
}
}
return result;
}
private boolean hasAlternative (String[] alternatives, String alternative) {
for (String currentAlternative: alternatives) {
if (currentAlternative.equals(alternative)) {
return true;
}
}
return false;
}
}