From 0a6a68e9bd9e23e7989039a0ae5d8d5d64b30839 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Mon, 6 Feb 2017 19:56:29 +0300 Subject: [PATCH 01/35] Next development cycle v2.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 74f9cff29..b7f387522 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ com.milaboratory mixcr - 2.1 + 2.2-SNAPSHOT jar MiXCR From d651620ed38347b66280212875749d609e1e06e6 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Sun, 12 Feb 2017 11:05:46 +0100 Subject: [PATCH 02/35] Typo. --- .../com/milaboratory/mixcr/assembler/CloneAssembler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/milaboratory/mixcr/assembler/CloneAssembler.java b/src/main/java/com/milaboratory/mixcr/assembler/CloneAssembler.java index 1d25bc944..f7708ee5d 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/CloneAssembler.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/CloneAssembler.java @@ -165,13 +165,13 @@ public void setListener(CloneAssemblerListener listener) { private ClonalSequence extractClonalSequence(VDJCAlignments alignments) { final NSequenceWithQuality[] targets = new NSequenceWithQuality[parameters.assemblingFeatures.length]; - int totalLengt = 0; + int totalLength = 0; for (int i = 0; i < targets.length; ++i) if ((targets[i] = alignments.getFeature(parameters.assemblingFeatures[i])) == null) return null; else - totalLengt += targets[i].size(); - if (totalLengt < parameters.minimalClonalSequenceLength) + totalLength += targets[i].size(); + if (totalLength < parameters.minimalClonalSequenceLength) return null; return new ClonalSequence(targets); } From 4c7e80f1a589ee38b994e6d2db3043e9e8f54c00 Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Mon, 20 Feb 2017 17:26:35 +0300 Subject: [PATCH 03/35] This fixes #212 --- CHANGELOG_CURRENT | 1 + .../milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java | 2 +- .../java/com/milaboratory/mixcr/cli/ActionFilterAlignments.java | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG_CURRENT b/CHANGELOG_CURRENT index e69de29bb..3b258ac92 100644 --- a/CHANGELOG_CURRENT +++ b/CHANGELOG_CURRENT @@ -0,0 +1 @@ +minor: multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or ‘-i 123,456’ etc. \ No newline at end of file diff --git a/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java b/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java index 85f661421..203f787aa 100644 --- a/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java +++ b/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java @@ -287,7 +287,7 @@ public static final class AParameters extends ActionParameters { public Boolean descr = null; @Parameter(description = "List of read ids to export", - names = {"-i", "--reads-ids"}, variableArity = true) + names = {"-i", "--reads-ids"}) public List ids = new ArrayList<>(); TLongHashSet getReadIds() { diff --git a/src/main/java/com/milaboratory/mixcr/cli/ActionFilterAlignments.java b/src/main/java/com/milaboratory/mixcr/cli/ActionFilterAlignments.java index 3eac7dd61..8087b6848 100644 --- a/src/main/java/com/milaboratory/mixcr/cli/ActionFilterAlignments.java +++ b/src/main/java/com/milaboratory/mixcr/cli/ActionFilterAlignments.java @@ -142,7 +142,7 @@ public static final class FilterAlignmentsFilterParameters extends ActionParamet public long limit = 0; @Parameter(description = "List of read ids to export", - names = {"-i", "--readsIds"}, variableArity = true) + names = {"-i", "--readsIds"}) public List ids = new ArrayList<>(); TLongHashSet getReadIds() { From fe83de94ae0b6f8a9b7ab675141dbba116470932 Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Mon, 20 Feb 2017 18:01:35 +0300 Subject: [PATCH 04/35] minor to prev --- .../cli/ActionExportAlignmentsPretty.java | 18 +++++++++--------- .../mixcr/util/PositiveLongValidator.java | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/milaboratory/mixcr/util/PositiveLongValidator.java diff --git a/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java b/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java index 203f787aa..28953ca2f 100644 --- a/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java +++ b/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java @@ -33,6 +33,7 @@ import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; import com.beust.jcommander.Parameters; +import com.beust.jcommander.converters.LongConverter; import com.milaboratory.cli.Action; import com.milaboratory.cli.ActionHelper; import com.milaboratory.cli.ActionParameters; @@ -69,9 +70,9 @@ public class ActionExportAlignmentsPretty implements Action { public void go(ActionHelper helper) throws Exception { Filter filter = actionParameters.getFilter(); long total = 0, filtered = 0; - try (VDJCAlignmentsReader reader = new VDJCAlignmentsReader(actionParameters.getInputFileName()); - PrintStream output = actionParameters.getOutputFileName().equals("-") ? System.out : - new PrintStream(new BufferedOutputStream(new FileOutputStream(actionParameters.getOutputFileName()), 32768)) + try(VDJCAlignmentsReader reader = new VDJCAlignmentsReader(actionParameters.getInputFileName()); + PrintStream output = actionParameters.getOutputFileName().equals("-") ? System.out : + new PrintStream(new BufferedOutputStream(new FileOutputStream(actionParameters.getOutputFileName()), 32768)) ) { long countBefore = actionParameters.limitBefore == null ? Long.MAX_VALUE : actionParameters.limitBefore; long countAfter = actionParameters.limitAfter == null ? Long.MAX_VALUE : actionParameters.limitAfter; @@ -287,22 +288,21 @@ public static final class AParameters extends ActionParameters { public Boolean descr = null; @Parameter(description = "List of read ids to export", - names = {"-i", "--reads-ids"}) - public List ids = new ArrayList<>(); + names = {"-i", "--reads-ids"}, + converter = LongConverter.class) + public List ids = new ArrayList<>(); TLongHashSet getReadIds() { if (ids.isEmpty()) return null; - TLongHashSet r = new TLongHashSet(ids.size()); - for (String id : ids) - r.add(Long.parseLong(id)); - return r; + return new TLongHashSet(ids); } public Chains getChain() { return Util.parseLoci(chain); } + @SuppressWarnings("unchecked") public Filter getFilter() { final Chains chains = getChain(); diff --git a/src/main/java/com/milaboratory/mixcr/util/PositiveLongValidator.java b/src/main/java/com/milaboratory/mixcr/util/PositiveLongValidator.java new file mode 100644 index 000000000..291540d13 --- /dev/null +++ b/src/main/java/com/milaboratory/mixcr/util/PositiveLongValidator.java @@ -0,0 +1,15 @@ +package com.milaboratory.mixcr.util; + +import com.beust.jcommander.IValueValidator; +import com.beust.jcommander.ParameterException; + +/** + * Created by poslavsky on 20/02/2017. + */ +public final class PositiveLongValidator implements IValueValidator { + @Override + public void validate(String name, Long value) throws ParameterException { + if (value < 0) + throw new ParameterException(name + ": positive input required (found " + value + ")"); + } +} From 5bad9a599ed24435c7ce30f0c5407a743cef2890 Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Mon, 20 Feb 2017 18:06:19 +0300 Subject: [PATCH 05/35] minor to prev --- CHANGELOG_CURRENT | 3 ++- .../mixcr/cli/ActionExportAlignmentsPretty.java | 2 +- .../milaboratory/mixcr/cli/ActionFilterAlignments.java | 10 ++++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/CHANGELOG_CURRENT b/CHANGELOG_CURRENT index 3b258ac92..85e354eb0 100644 --- a/CHANGELOG_CURRENT +++ b/CHANGELOG_CURRENT @@ -1 +1,2 @@ -minor: multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or ‘-i 123,456’ etc. \ No newline at end of file +minor: multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or `-i 123,456` etc. +minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both renamed to `--read-ids` \ No newline at end of file diff --git a/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java b/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java index 28953ca2f..6211ea72e 100644 --- a/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java +++ b/src/main/java/com/milaboratory/mixcr/cli/ActionExportAlignmentsPretty.java @@ -288,7 +288,7 @@ public static final class AParameters extends ActionParameters { public Boolean descr = null; @Parameter(description = "List of read ids to export", - names = {"-i", "--reads-ids"}, + names = {"-i", "--read-ids"}, converter = LongConverter.class) public List ids = new ArrayList<>(); diff --git a/src/main/java/com/milaboratory/mixcr/cli/ActionFilterAlignments.java b/src/main/java/com/milaboratory/mixcr/cli/ActionFilterAlignments.java index 8087b6848..5becf8c08 100644 --- a/src/main/java/com/milaboratory/mixcr/cli/ActionFilterAlignments.java +++ b/src/main/java/com/milaboratory/mixcr/cli/ActionFilterAlignments.java @@ -4,6 +4,7 @@ import cc.redberry.primitives.Filter; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; +import com.beust.jcommander.converters.LongConverter; import com.beust.jcommander.validators.PositiveInteger; import com.milaboratory.cli.Action; import com.milaboratory.cli.ActionHelper; @@ -142,16 +143,13 @@ public static final class FilterAlignmentsFilterParameters extends ActionParamet public long limit = 0; @Parameter(description = "List of read ids to export", - names = {"-i", "--readsIds"}) - public List ids = new ArrayList<>(); + names = {"-i", "--read-ids"}, converter = LongConverter.class) + public List ids = new ArrayList<>(); TLongHashSet getReadIds() { if (ids.isEmpty()) return null; - TLongHashSet r = new TLongHashSet(ids.size()); - for (String id : ids) - r.add(Long.parseLong(id)); - return r; + return new TLongHashSet(ids); } @Override From 3e9e5b60aae4f6ece74ede98f3caa9df7a905aec Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Mon, 20 Feb 2017 20:25:56 +0300 Subject: [PATCH 06/35] This fixes #164 --- .../partialassembler/PartialAlignmentsAssembler.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java b/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java index 07009e662..f474e327e 100644 --- a/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java +++ b/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java @@ -302,6 +302,12 @@ private OverlapSearchResult searchOverlaps(final VDJCAlignments rightAl, if (!allowChimeras && !leftAl.getAllChains(GeneType.Variable).intersects(jChains)) continue; + // Check for the same V + if (leftAl.getBestHit(GeneType.Variable) != null + && rightAl.getBestHit(GeneType.Variable) != null + && !leftAl.hasCommonGenes(GeneType.Variable, rightAl)) + continue; + final NucleotideSequence leftSeq = leftAl.getPartitionedTarget(getLeftPartitionedSequence(leftAl)) .getSequence().getSequence(); int lFrom = match.get(i).kMerPositionFrom; @@ -523,7 +529,7 @@ private static long kMer(NucleotideSequence seq, int from, int length) { byte c = seq.codeAt(j); if (NucleotideSequence.ALPHABET.isWildcard(c)) return -1; - kmer = (kmer << 2 | c); + kmer = (kmer << 2|c); } return kmer; } From 91f1682d5ac5323da425faad8857ee8d164a709d Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Mon, 20 Feb 2017 20:26:35 +0300 Subject: [PATCH 07/35] Make VDJCObject#getFeature strict --- .../mixcr/basictypes/VDJCObject.java | 134 ++++++++++-------- 1 file changed, 76 insertions(+), 58 deletions(-) diff --git a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCObject.java b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCObject.java index a71dc4cf0..3c0cea15b 100644 --- a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCObject.java +++ b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCObject.java @@ -36,10 +36,9 @@ import io.repseq.core.Chains; import io.repseq.core.GeneFeature; import io.repseq.core.GeneType; +import io.repseq.core.VDJCGeneId; -import java.util.Arrays; -import java.util.EnumMap; -import java.util.Map; +import java.util.*; public class VDJCObject { protected final NSequenceWithQuality[] targets; @@ -76,6 +75,25 @@ protected static EnumMap createHits(VDJCHit[] vHits, VDJCHi return hits; } + @SuppressWarnings("unchecked") + private Set getGenes(GeneType gt) { + VDJCHit[] hits = getHits(gt); + if (hits == null) + return Collections.EMPTY_SET; + Set genes = new HashSet<>(); + for (VDJCHit hit : hits) + genes.add(hit.getGene().getId()); + return genes; + } + + public final boolean hasCommonGenes(GeneType gt, VDJCObject other) { + Set thisGenes = this.getGenes(gt); + for (VDJCGeneId gene : other.getGenes(gt)) + if (thisGenes.contains(gene)) + return true; + return false; + } + public final VDJCHit[] getHits(GeneType type) { VDJCHit[] hits = this.hits.get(type); return hits == null ? new VDJCHit[0] : hits; @@ -149,7 +167,7 @@ public final NSequenceWithQuality getTarget(int target) { return targets[target]; } - public final NSequenceWithQuality[] getTargets(){ + public final NSequenceWithQuality[] getTargets() { return targets.clone(); } @@ -200,60 +218,60 @@ public NSequenceWithQuality getFeature(GeneFeature geneFeature) { if (tmp != null && (feature == null || feature.getQuality().minValue() < tmp.getQuality().minValue())) feature = tmp; } - if (feature == null && targets.length == 2) { - VDJCHit bestVHit = getBestHit(GeneType.Variable); - if (bestVHit == null) - return null; - - //TODO check for V feature compatibility - Alignment - lAlignment = bestVHit.getAlignment(0), - rAlignment = bestVHit.getAlignment(1); - - if (lAlignment == null || rAlignment == null) - return null; - - int lTargetIndex = 0; - - int lFrom, rTo, f, t; - if ((f = getPartitionedTarget(1).getPartitioning().getPosition(geneFeature.getFirstPoint())) >= 0 && - (t = getPartitionedTarget(0).getPartitioning().getPosition(geneFeature.getLastPoint())) >= 0) { - lAlignment = bestVHit.getAlignment(1); - rAlignment = bestVHit.getAlignment(0); - lFrom = f; - rTo = t; - lTargetIndex = 1; - } else if ((f = getPartitionedTarget(0).getPartitioning().getPosition(geneFeature.getFirstPoint())) < 0 || - (t = getPartitionedTarget(1).getPartitioning().getPosition(geneFeature.getLastPoint())) < 0) - return null; - else { - lFrom = f; - rTo = t; - } - - Range intersection = lAlignment.getSequence1Range().intersection(rAlignment.getSequence1Range()); - if (intersection == null) - return null; - - NSequenceWithQuality intersectionSequence = Merger.merge(intersection, - new Alignment[]{bestVHit.getAlignment(0), bestVHit.getAlignment(1)}, - targets); - - Range lRange = new Range( - lFrom, - aabs(lAlignment.convertToSeq2Position(intersection.getFrom()))); - Range rRange = new Range( - aabs(rAlignment.convertToSeq2Position(intersection.getTo())), - rTo); - - feature = - new NSequenceWithQualityBuilder() - .ensureCapacity(lRange.length() + rRange.length() + intersectionSequence.size()) - .append(targets[lTargetIndex].getRange(lRange)) - .append(intersectionSequence) - .append(targets[1 - lTargetIndex].getRange(rRange)) - .createAndDestroy(); - } +// if (feature == null && targets.length == 2) { +// VDJCHit bestVHit = getBestHit(GeneType.Variable); +// if (bestVHit == null) +// return null; +// +// //TODO check for V feature compatibility +// Alignment +// lAlignment = bestVHit.getAlignment(0), +// rAlignment = bestVHit.getAlignment(1); +// +// if (lAlignment == null || rAlignment == null) +// return null; +// +// int lTargetIndex = 0; +// +// int lFrom, rTo, f, t; +// if ((f = getPartitionedTarget(1).getPartitioning().getPosition(geneFeature.getFirstPoint())) >= 0 && +// (t = getPartitionedTarget(0).getPartitioning().getPosition(geneFeature.getLastPoint())) >= 0) { +// lAlignment = bestVHit.getAlignment(1); +// rAlignment = bestVHit.getAlignment(0); +// lFrom = f; +// rTo = t; +// lTargetIndex = 1; +// } else if ((f = getPartitionedTarget(0).getPartitioning().getPosition(geneFeature.getFirstPoint())) < 0 || +// (t = getPartitionedTarget(1).getPartitioning().getPosition(geneFeature.getLastPoint())) < 0) +// return null; +// else { +// lFrom = f; +// rTo = t; +// } +// +// Range intersection = lAlignment.getSequence1Range().intersection(rAlignment.getSequence1Range()); +// if (intersection == null) +// return null; +// +// NSequenceWithQuality intersectionSequence = Merger.merge(intersection, +// new Alignment[]{bestVHit.getAlignment(0), bestVHit.getAlignment(1)}, +// targets); +// +// Range lRange = new Range( +// lFrom, +// aabs(lAlignment.convertToSeq2Position(intersection.getFrom()))); +// Range rRange = new Range( +// aabs(rAlignment.convertToSeq2Position(intersection.getTo())), +// rTo); +// +// feature = +// new NSequenceWithQualityBuilder() +// .ensureCapacity(lRange.length() + rRange.length() + intersectionSequence.size()) +// .append(targets[lTargetIndex].getRange(lRange)) +// .append(intersectionSequence) +// .append(targets[1 - lTargetIndex].getRange(rRange)) +// .createAndDestroy(); +// } return feature; } From a54f642ebf2c1c85ede1c88acfc94c129b2a362c Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Tue, 21 Feb 2017 14:28:53 +0300 Subject: [PATCH 08/35] #200 work in progress --- .../mixcr/basictypes/VDJCAlignments.java | 22 +- .../PartialAlignmentsAssembler.java | 301 ++++++++++-------- .../mixcr/partialassembler/TargetMerger.java | 138 ++++---- .../mixcr/vdjaligners/VDJCAlignerPVFirst.java | 14 +- 4 files changed, 264 insertions(+), 211 deletions(-) diff --git a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignments.java b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignments.java index a9c71cf97..d48877a9b 100644 --- a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignments.java +++ b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignments.java @@ -28,11 +28,13 @@ */ package com.milaboratory.mixcr.basictypes; +import com.milaboratory.core.alignment.Alignment; import com.milaboratory.core.sequence.NSequenceWithQuality; +import com.milaboratory.core.sequence.NucleotideSequence; import com.milaboratory.primitivio.annotations.Serializable; -import io.repseq.core.Chains; import io.repseq.core.GeneType; +import java.util.Arrays; import java.util.EnumMap; @Serializable(by = IO.VDJCAlignmentsSerializer.class) @@ -67,6 +69,22 @@ public VDJCAlignments(long readId, VDJCHit[] vHits, VDJCHit[] dHits, VDJCHit[] j this.readId = readId; } + public VDJCAlignments removeBestHitAlignment(GeneType geneType, int targetId) { + if (getBestHit(geneType) == null) + return this; + EnumMap hits = new EnumMap<>(this.hits); + VDJCHit[] gHits = hits.get(geneType).clone(); + Alignment[] als = gHits[0].getAlignments().clone(); + als[targetId] = null; + gHits[0] = new VDJCHit(gHits[0].getGene(), als, gHits[0].getAlignedFeature()); + Arrays.sort(gHits); + hits.put(geneType, gHits); + + VDJCAlignments result = new VDJCAlignments(readId, hits, targets); + result.alignmentsIndex = alignmentsIndex; + return result; + } + public long getReadId() { return readId; } @@ -186,7 +204,7 @@ public boolean equals(Object o) { @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + (int) (readId ^ (readId >>> 32)); + result = 31 * result + (int) (readId^(readId >>> 32)); return result; } } diff --git a/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java b/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java index f474e327e..aff05669d 100644 --- a/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java +++ b/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java @@ -278,162 +278,181 @@ private OverlapSearchResult searchOverlaps(final VDJCAlignments rightAl, stop -= kOffset; - int maxOverlap = -1, maxDelta = -1, - maxOverlapIndexInList = -1, - maxBegin = -1, maxEnd = -1; - List maxOverlapList = null; - boolean isMaxOverOverlapped = false; - for (int rFrom = 0; rFrom < stop && rFrom + kValue < rightSeqQ.size(); rFrom++) { - long kMer = kMer(rightSeqQ.getSequence(), rFrom, kValue); - List match = kToIndexLeft.get(kMer); - if (match == null) - continue; - - out: - for (int i = 0; i < match.size(); i++) { - boolean isOverOverlapped = false; - final VDJCAlignments leftAl = match.get(i).getAlignments(); - - if (leftAl.getAlignmentsIndex() == rightAl.getAlignmentsIndex() || // You shall not merge with yourself - alreadyMergedIds.contains(leftAl.getAlignmentsIndex())) - continue; - - // Checking chains compatibility - if (!allowChimeras && !leftAl.getAllChains(GeneType.Variable).intersects(jChains)) + // black list of left parts failed due to inconsistent overlapped alignments (failed AMerge) + TLongHashSet blackList = new TLongHashSet(); + SEARCH_LEFT_PARTS: + while (true) { + int maxOverlap = -1, maxDelta = -1, + maxOverlapIndexInList = -1, + maxBegin = -1, maxEnd = -1; + List maxOverlapList = null; + boolean isMaxOverOverlapped = false; + for (int rFrom = 0; rFrom < stop && rFrom + kValue < rightSeqQ.size(); rFrom++) { + long kMer = kMer(rightSeqQ.getSequence(), rFrom, kValue); + List match = kToIndexLeft.get(kMer); + if (match == null) continue; - // Check for the same V - if (leftAl.getBestHit(GeneType.Variable) != null - && rightAl.getBestHit(GeneType.Variable) != null - && !leftAl.hasCommonGenes(GeneType.Variable, rightAl)) - continue; - - final NucleotideSequence leftSeq = leftAl.getPartitionedTarget(getLeftPartitionedSequence(leftAl)) - .getSequence().getSequence(); - int lFrom = match.get(i).kMerPositionFrom; - - int delta, begin = delta = lFrom - rFrom; - if (begin < 0) { - begin = 0; - isOverOverlapped = true; - } - int end = leftSeq.size(); - if (end - delta >= rightSeq.size()) { - end = rightSeq.size() + delta; - isOverOverlapped = true; - } - - for (int j = begin; j < end; j++) - if (leftSeq.codeAt(j) != rightSeq.codeAt(j - delta)) - continue out; - - int overlap = end - begin; - if (maxOverlap < overlap) { - maxOverlap = overlap; - maxOverlapList = match; - maxOverlapIndexInList = i; - maxDelta = delta; - maxBegin = begin; - maxEnd = end; - isMaxOverOverlapped = isOverOverlapped; - } - } - } - - if (maxOverlapList == null) - return null; - - if (maxOverlap < minimalAssembleOverlap) - return null; + out: + for (int i = 0; i < match.size(); i++) { + boolean isOverOverlapped = false; + final VDJCAlignments leftAl = match.get(i).getAlignments(); - if (isMaxOverOverlapped) - overoverlapped.incrementAndGet(); + if (blackList.contains(leftAl.getReadId())) + continue; - final KMerInfo left = maxOverlapList.remove(maxOverlapIndexInList); - VDJCAlignments leftAl = left.alignments; + if (leftAl.getAlignmentsIndex() == rightAl.getAlignmentsIndex() || // You shall not merge with yourself + alreadyMergedIds.contains(leftAl.getAlignmentsIndex())) + continue; - final long readId = rightAl.getReadId(); + // Checking chains compatibility + if (!allowChimeras && !leftAl.getAllChains(GeneType.Variable).intersects(jChains)) + continue; - ArrayList leftTargets = extractAlignedTargets(leftAl, true); - ArrayList rightTargets = extractAlignedTargets(rightAl, false); + // Check for the same V + if (leftAl.getBestHit(GeneType.Variable) != null + && rightAl.getBestHit(GeneType.Variable) != null + && !leftAl.hasCommonGenes(GeneType.Variable, rightAl)) + continue; - AlignedTarget leftCentral = leftTargets.get(left.targetId); - AlignedTarget rightCentral = rightTargets.get(rightTargetId); + final NucleotideSequence leftSeq = leftAl.getPartitionedTarget(getLeftPartitionedSequence(leftAl)) + .getSequence().getSequence(); + int lFrom = match.get(i).kMerPositionFrom; - AlignedTarget central = targetMerger.merge(readId, leftCentral, rightCentral, maxDelta) - .overrideDescription("VJOverlap(" + maxOverlap + ") = " + leftCentral.getDescription() + " + " + rightCentral.getDescription()); - - // Setting overlap position - central = AlignedTarget.setOverlapRange(central, maxBegin, maxEnd); - - final List leftDescriptors = new ArrayList<>(2), - rightDescriptors = new ArrayList<>(2); - - for (int i = 0; i < left.targetId; ++i) - leftDescriptors.add(leftTargets.get(i)); - for (int i = left.targetId + 1; i < leftAl.numberOfTargets(); ++i) - rightDescriptors.add(leftTargets.get(i)); - for (int i = 0; i < rightTargetId; ++i) - leftDescriptors.add(rightTargets.get(i)); - for (int i = rightTargetId + 1; i < rightAl.numberOfTargets(); ++i) - rightDescriptors.add(rightTargets.get(i)); - - - // Merging to VJ junction - List[] allDescriptors = new List[]{leftDescriptors, rightDescriptors}; - TargetMerger.TargetMergingResult bestResult = null; - int bestI; + int delta, begin = delta = lFrom - rFrom; + if (begin < 0) { + begin = 0; + isOverOverlapped = true; + } + int end = leftSeq.size(); + if (end - delta >= rightSeq.size()) { + end = rightSeq.size() + delta; + isOverOverlapped = true; + } - // Trying to merge left and right reads to central one - for (List descriptors : allDescriptors) - do { - bestI = -1; - for (int i = 0; i < descriptors.size(); i++) { - TargetMerger.TargetMergingResult result = targetMerger.merge(readId, descriptors.get(i), central); - if (result != null && (bestResult == null || bestResult.score < result.score)) { - bestResult = result; - bestI = i; + for (int j = begin; j < end; j++) + if (leftSeq.codeAt(j) != rightSeq.codeAt(j - delta)) + continue out; + + int overlap = end - begin; + if (maxOverlap < overlap) { + maxOverlap = overlap; + maxOverlapList = match; + maxOverlapIndexInList = i; + maxDelta = delta; + maxBegin = begin; + maxEnd = end; + isMaxOverOverlapped = isOverOverlapped; } } + } - if (bestI != -1) { - central = bestResult.result.overrideDescription( - central.getDescription() + " / " + mergeTypePrefix(bestResult.usingAlignments) + "MergedFrom" + - (descriptors == leftDescriptors ? "Left" : "Right") + - "(" + getMMDescr(bestResult.matched, bestResult.mismatched) + ") = " + - descriptors.get(bestI).getDescription()); - descriptors.remove(bestI); - } - } while (bestI != -1); - - - // Merging left+left / right+right - outer: - for (int d = 0; d < allDescriptors.length; d++) { - List descriptors = allDescriptors[d]; - for (int i = 0; i < descriptors.size(); i++) - for (int j = i + 1; j < descriptors.size(); j++) { - TargetMerger.TargetMergingResult result = targetMerger.merge(readId, descriptors.get(i), descriptors.get(j)); - if (result != null) { - descriptors.set(i, result.result.overrideDescription( - mergeTypePrefix(result.usingAlignments) + - "Merged(" + getMMDescr(result.matched, result.mismatched) + ") = " + descriptors.get(i).getDescription() + - " + " + descriptors.get(j).getDescription())); - descriptors.remove(j); - --d; - continue outer; + if (maxOverlapList == null) + return null; + + if (maxOverlap < minimalAssembleOverlap) + return null; + + final KMerInfo left = maxOverlapList.remove(maxOverlapIndexInList); + VDJCAlignments leftAl = left.alignments; + + final long readId = rightAl.getReadId(); + + ArrayList leftTargets = extractAlignedTargets(leftAl, true); + ArrayList rightTargets = extractAlignedTargets(rightAl, false); + + AlignedTarget leftCentral = leftTargets.get(left.targetId); + AlignedTarget rightCentral = rightTargets.get(rightTargetId); + + AlignedTarget central = targetMerger.merge(readId, leftCentral, rightCentral, maxDelta) + .overrideDescription("VJOverlap(" + maxOverlap + ") = " + leftCentral.getDescription() + " + " + rightCentral.getDescription()); + + // Setting overlap position + central = AlignedTarget.setOverlapRange(central, maxBegin, maxEnd); + + final List leftDescriptors = new ArrayList<>(2), + rightDescriptors = new ArrayList<>(2); + + for (int i = 0; i < left.targetId; ++i) + leftDescriptors.add(leftTargets.get(i)); + for (int i = left.targetId + 1; i < leftAl.numberOfTargets(); ++i) + rightDescriptors.add(leftTargets.get(i)); + for (int i = 0; i < rightTargetId; ++i) + leftDescriptors.add(rightTargets.get(i)); + for (int i = rightTargetId + 1; i < rightAl.numberOfTargets(); ++i) + rightDescriptors.add(rightTargets.get(i)); + + + // Merging to VJ junction + List[] allDescriptors = new List[]{leftDescriptors, rightDescriptors}; + TargetMerger.TargetMergingResult bestResult = TargetMerger.FAILED_RESULT; + int bestI; + + // Trying to merge left and right reads to central one + for (List descriptors : allDescriptors) + do { + bestI = -1; + for (int i = 0; i < descriptors.size(); i++) { + TargetMerger.TargetMergingResult result = targetMerger.merge(readId, descriptors.get(i), central); + if (result.failedDueInconsistentAlignments()) { + // Inconsistent alignments -> retry + blackList.add(leftAl.getReadId()); + continue SEARCH_LEFT_PARTS; + } + if (bestResult.getScore() < result.getScore()) { + bestResult = result; + bestI = i; + } } - } - } - // Creating pre-list of resulting targets - List result = new ArrayList<>(); - result.addAll(leftDescriptors); - result.add(central); - result.addAll(rightDescriptors); + if (bestI != -1) { + assert bestResult != TargetMerger.FAILED_RESULT; + central = bestResult.getResult().overrideDescription( + central.getDescription() + " / " + mergeTypePrefix(bestResult.isUsingAlignments()) + "MergedFrom" + + (descriptors == leftDescriptors ? "Left" : "Right") + + "(" + getMMDescr(bestResult.getMatched(), bestResult.getMismatched()) + ") = " + + descriptors.get(bestI).getDescription()); + descriptors.remove(bestI); + } + } while (bestI != -1); + + + // Merging left+left / right+right + outer: + for (int d = 0; d < allDescriptors.length; d++) { + List descriptors = allDescriptors[d]; + for (int i = 0; i < descriptors.size(); i++) + for (int j = i + 1; j < descriptors.size(); j++) { + TargetMerger.TargetMergingResult result = targetMerger.merge(readId, descriptors.get(i), descriptors.get(j)); + if (result.failedDueInconsistentAlignments()) { + // Inconsistent alignments -> retry + blackList.add(leftAl.getReadId()); + continue SEARCH_LEFT_PARTS; + } + if (result.isSuccessful()) { + descriptors.set(i, result.getResult().overrideDescription( + mergeTypePrefix(result.isUsingAlignments()) + + "Merged(" + getMMDescr(result.getMatched(), result.getMismatched()) + ") = " + descriptors.get(i).getDescription() + + " + " + descriptors.get(j).getDescription())); + descriptors.remove(j); + --d; + continue outer; + } + } + } + + if (isMaxOverOverlapped) + overoverlapped.incrementAndGet(); - // Ordering and filtering final targets - return new OverlapSearchResult(maxOverlapList, left, AlignedTarget.orderTargets(result)); + // Creating pre-list of resulting targets + List result = new ArrayList<>(); + result.addAll(leftDescriptors); + result.add(central); + result.addAll(rightDescriptors); + + // Ordering and filtering final targets + return new OverlapSearchResult(maxOverlapList, left, AlignedTarget.orderTargets(result)); + } } private static String mergeTypePrefix(boolean usingAlignment) { diff --git a/src/main/java/com/milaboratory/mixcr/partialassembler/TargetMerger.java b/src/main/java/com/milaboratory/mixcr/partialassembler/TargetMerger.java index 4eb1d9cdc..6a39a7df9 100644 --- a/src/main/java/com/milaboratory/mixcr/partialassembler/TargetMerger.java +++ b/src/main/java/com/milaboratory/mixcr/partialassembler/TargetMerger.java @@ -223,60 +223,6 @@ static Alignment merge(AlignmentScoring return BandedAligner.alignGlobal(scoring, left == null ? right.getSequence1() : left.getSequence1(), seq, seq1From, seq1To - seq1From, seq2From, seq2To - seq2From, bandedWidth); } -// -// static Alignment merge1(AlignmentScoring scoring, -// int bandedWidth, -// NucleotideSequence seq, int offset, -// Alignment left, -// Alignment right) { -// assert left != null || right != null; -// assert offset >= 0; -// assert left == null || right == null || left.getSequence1().equals(right.getSequence1()); -// -// int seq1From = -1, seq2From = -1, seq1To = -1, seq2To = -1; -// -// if (left != null && right != null) { -// if (left.convertPosition(right.getSequence1Range().getFrom()) != right.getSequence2Range().getFrom() + offset) { -// if (left.getScore() > right.getScore()) -// right = null; -// else -// left = null; -// } else { -// if (left.getSequence1Range().getFrom() < right.getSequence1Range().getFrom()) { -// seq1From = left.getSequence1Range().getFrom(); -// seq2From = left.getSequence2Range().getFrom(); -// } else { -// seq1From = right.getSequence1Range().getFrom(); -// seq2From = right.getSequence2Range().getFrom() + offset; -// } -// -// if (left.getSequence1Range().getTo() > right.getSequence1Range().getTo()) { -// seq1To = left.getSequence1Range().getTo(); -// seq2To = left.getSequence2Range().getTo(); -// } else { -// seq1To = right.getSequence1Range().getTo(); -// seq2To = right.getSequence2Range().getTo() + offset; -// } -// } -// } -// -// if (left == null) { -// seq1From = right.getSequence1Range().getFrom(); -// seq1To = right.getSequence1Range().getTo(); -// -// seq2From = right.getSequence2Range().getFrom() + offset; -// seq2To = right.getSequence2Range().getTo() + offset; -// } else if (right == null) { -// seq1From = left.getSequence1Range().getFrom(); -// seq1To = left.getSequence1Range().getTo(); -// -// seq2From = left.getSequence2Range().getFrom(); -// seq2To = left.getSequence2Range().getTo(); -// } -// -// return BandedAligner.alignGlobal(scoring, left == null ? right.getSequence1() : left.getSequence1(), -// seq, seq1From, seq1To - seq1From, seq2From, seq2To - seq2From, bandedWidth); -// } public TargetMergingResult merge(long readId, AlignedTarget targetLeft, AlignedTarget targetRight) { for (GeneType geneType : GeneType.VJC_REFERENCE) { @@ -319,19 +265,21 @@ public int compare(HitMappingRecord o1, HitMappingRecord o2) { overlap); if (1.0 - 1.0 * mismatches / overlap < minimalAlignmentMergeIdentity) - continue; + return new TargetMergingResult(geneType); final AlignedTarget merge = merge(readId, targetLeft, targetRight, delta); - return new TargetMergingResult(merge, + return new TargetMergingResult(true, null, merge, PairedReadMergingResult.MATCH_SCORE * (overlap - mismatches) + - PairedReadMergingResult.MISMATCH_SCORE * mismatches, true, overlap, mismatches); + PairedReadMergingResult.MISMATCH_SCORE * mismatches, overlap, mismatches); } } final PairedReadMergingResult merge = merger.merge(targetLeft.getTarget(), targetRight.getTarget()); if (!merge.isSuccessful()) - return null; - return new TargetMergingResult(merge(readId, targetLeft, targetRight, merge.getOffset()), merge.score(), false, merge.getOverlap(), merge.getErrors()); + return new TargetMergingResult(); + return new TargetMergingResult(false, null, + merge(readId, targetLeft, targetRight, merge.getOffset()), + merge.score(), merge.getOverlap(), merge.getErrors()); } private static int sumScore(Alignment[] als) { @@ -343,18 +291,78 @@ private static int sumScore(Alignment[] als) { return r; } + public static final TargetMergingResult FAILED_RESULT = new TargetMergingResult(); + public final static class TargetMergingResult { - public final AlignedTarget result; - public final int score; - public final boolean usingAlignments; - public final int matched, mismatched; + private final boolean usingAlignments; + private final GeneType failedMergedGeneType; + + private final AlignedTarget result; + private final int score; + private final int matched, mismatched; + +// public TargetMergingResult(AlignedTarget result, int score, boolean usingAlignments, int matched, int mismatched) { +// this.result = result; +// this.score = score; +// this.usingAlignments = usingAlignments; +// this.matched = matched; +// this.mismatched = mismatched; +// } + + private TargetMergingResult() { + this(false, null, null, 0, 0, 0); + } - public TargetMergingResult(AlignedTarget result, int score, boolean usingAlignments, int matched, int mismatched) { + private TargetMergingResult(GeneType failedGeneType) { + this(true, failedGeneType, null, 0, 0, 0); + } + + private TargetMergingResult(boolean usingAlignments, GeneType failedMergedGeneType, AlignedTarget result, int score, int matched, int mismatched) { + this.usingAlignments = usingAlignments; + this.failedMergedGeneType = failedMergedGeneType; this.result = result; this.score = score; - this.usingAlignments = usingAlignments; this.matched = matched; this.mismatched = mismatched; } + + public boolean isSuccessful() { + return result != null; + } + + public boolean isUsingAlignments() { + return usingAlignments; + } + + public boolean failedDueInconsistentAlignments(){ + return failedMergedGeneType != null; + } + + public GeneType getFailedMergedGeneType() { + return failedMergedGeneType; + } + + private void checkSuccessful() { + if (!isSuccessful()) + throw new IllegalStateException(); + } + + public AlignedTarget getResult() { + checkSuccessful(); + return result; + } + + public int getScore() { + return score; + } + + public int getMatched() { + return matched; + } + + public int getMismatched() { + checkSuccessful(); + return mismatched; + } } } diff --git a/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerPVFirst.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerPVFirst.java index 347ce5e8b..b44c8ad0a 100644 --- a/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerPVFirst.java +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerPVFirst.java @@ -83,6 +83,7 @@ protected VDJCAlignmentResult process0(final PairedRead input) { VDJCAlignmentResult result = parameters.getAllowPartialAlignments() ? processPartial(input, helpers) : processStrict(input, helpers); + if (result.alignment != null) { final VDJCAlignments alignment = result.alignment; final TargetMerger.TargetMergingResult mergeResult = alignmentsMerger.merge( @@ -90,14 +91,21 @@ protected VDJCAlignmentResult process0(final PairedRead input) { new AlignedTarget(alignment, 0), new AlignedTarget(alignment, 1)); - if (mergeResult != null) { - NSequenceWithQuality alignedTarget = mergeResult.result.getTarget(); + if (mergeResult.failedDueInconsistentAlignments()) { + GeneType gt = mergeResult.getFailedMergedGeneType(); + int removeId = + alignment.getBestHit(gt).getAlignment(0).getScore() + > alignment.getBestHit(gt).getAlignment(1).getScore() + ? 1 : 0; + return new VDJCAlignmentResult<>(input, alignment.removeBestHitAlignment(gt, removeId)); + } else if (mergeResult.isSuccessful()) { + NSequenceWithQuality alignedTarget = mergeResult.getResult().getTarget(); SingleRead sRead = new SingleReadImpl(input.getId(), alignedTarget, ""); VDJCAlignmentResult sResult = sAligner.process0(sRead); if (sResult.alignment == null) return result; VDJCAlignments sAlignment = sResult.alignment; - sAlignment.setTargetDescriptions(new String[]{"AOverlap(" + mergeResult.matched + ")"}); + sAlignment.setTargetDescriptions(new String[]{"AOverlap(" + mergeResult.getMatched() + ")"}); return new VDJCAlignmentResult<>(input, sAlignment); } } From 7c19118ddf9de1d9f50928514d90af64d3b051a1 Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Tue, 21 Feb 2017 18:41:17 +0300 Subject: [PATCH 09/35] This fixes #202 --- .../mixcr/partialassembler/PartialAlignmentsAssembler.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java b/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java index aff05669d..3ecf8e5bb 100644 --- a/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java +++ b/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java @@ -480,9 +480,6 @@ public void writeReport(ReportHelper helper) { } private int getLeftPartitionedSequence(VDJCAlignments alignment) { - //TODO why > 2 ? - if (alignment.numberOfTargets() > 2) - return -1; for (int i = 0; i < alignment.numberOfTargets(); i++) { if (alignment.getBestHit(GeneType.Joining) != null && alignment.getBestHit(GeneType.Joining) @@ -496,9 +493,6 @@ private int getLeftPartitionedSequence(VDJCAlignments alignment) { } private int getRightPartitionedSequence(VDJCAlignments alignment) { - //TODO why > 2 ? - if (alignment.numberOfTargets() > 2) - return -1; for (int i = 0; i < alignment.numberOfTargets(); i++) { if (alignment.getBestHit(GeneType.Variable) != null && alignment.getBestHit(GeneType.Variable) From 91925eb39c9bc7541152b84b6c0944ff84529558 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Mon, 27 Feb 2017 16:08:31 +0300 Subject: [PATCH 10/35] Fixed absent space in `AA. Seq. ...` column. This fixes #218 --- CHANGELOG_CURRENT | 3 ++- pom.xml | 2 +- .../java/com/milaboratory/mixcr/export/FieldExtractors.java | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG_CURRENT b/CHANGELOG_CURRENT index 85e354eb0..cc5f7b5bb 100644 --- a/CHANGELOG_CURRENT +++ b/CHANGELOG_CURRENT @@ -1,2 +1,3 @@ -minor: multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or `-i 123,456` etc. +Fixed absent space in `AA. Seq. ...` column name (affects `exportClones` and `exportAlignments` with `-v` option; fixes compatibility with VDJTools v1.1.3 and below). +minor: Multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or `-i 123,456` etc. minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both renamed to `--read-ids` \ No newline at end of file diff --git a/pom.xml b/pom.xml index b7f387522..cf202003c 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ com.milaboratory mixcr - 2.2-SNAPSHOT + 2.1.1-SNAPSHOT jar MiXCR diff --git a/src/main/java/com/milaboratory/mixcr/export/FieldExtractors.java b/src/main/java/com/milaboratory/mixcr/export/FieldExtractors.java index ac590f9aa..b410b30cc 100644 --- a/src/main/java/com/milaboratory/mixcr/export/FieldExtractors.java +++ b/src/main/java/com/milaboratory/mixcr/export/FieldExtractors.java @@ -280,7 +280,8 @@ public String convert(NSequenceWithQuality seq) { } }); - descriptorsList.add(new FeatureExtractors.WithHeader("-aaFeature", "Export amino acid sequence of specified gene feature", 1, new String[]{"AA. Seq."}, new String[]{"aaSeq"}) { + descriptorsList.add(new FeatureExtractors.WithHeader("-aaFeature", "Export amino acid sequence of specified gene feature", + 1, new String[]{"AA. Seq. "}, new String[]{"aaSeq"}) { @Override protected String extractValue(VDJCObject object, GeneFeature[] parameters) { GeneFeature geneFeature = parameters[parameters.length - 1]; From d6dac51cca456197242356eaf54b95976e918cd5 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Mon, 27 Feb 2017 16:20:26 +0300 Subject: [PATCH 11/35] Additional fix for #218. --- CHANGELOG_CURRENT | 2 +- .../java/com/milaboratory/mixcr/export/FeatureExtractors.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG_CURRENT b/CHANGELOG_CURRENT index cc5f7b5bb..bac248d70 100644 --- a/CHANGELOG_CURRENT +++ b/CHANGELOG_CURRENT @@ -1,3 +1,3 @@ -Fixed absent space in `AA. Seq. ...` column name (affects `exportClones` and `exportAlignments` with `-v` option; fixes compatibility with VDJTools v1.1.3 and below). +Fixed absent space in `AA. Seq. ...` column name and excessive space in the end of several column names (affects `exportClones` and `exportAlignments` with `-v` option; fixes compatibility with VDJTools v1.1.3 and below). minor: Multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or `-i 123,456` etc. minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both renamed to `--read-ids` \ No newline at end of file diff --git a/src/main/java/com/milaboratory/mixcr/export/FeatureExtractors.java b/src/main/java/com/milaboratory/mixcr/export/FeatureExtractors.java index 40a9ded14..236e009ac 100644 --- a/src/main/java/com/milaboratory/mixcr/export/FeatureExtractors.java +++ b/src/main/java/com/milaboratory/mixcr/export/FeatureExtractors.java @@ -55,7 +55,7 @@ protected GeneFeature[] getParameters(String[] strings) { @Override protected String getHeader(OutputMode outputMode, GeneFeature[] features) { - return FieldExtractors.choose(outputMode, header0(hPrefix, features) + " ", header0(sPrefix, features)); + return FieldExtractors.choose(outputMode, header0(hPrefix, features), header0(sPrefix, features)); } @Override From 5481d71030e9381ce9d2a6cb06dbc77b39842a2f Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Tue, 28 Feb 2017 13:04:24 +0300 Subject: [PATCH 12/35] This fixes #197 --- .../mixcr/partialassembler/TargetMerger.java | 16 +++++++++++++++- .../mixcr/vdjaligners/VDJCAlignerPVFirst.java | 3 ++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/milaboratory/mixcr/partialassembler/TargetMerger.java b/src/main/java/com/milaboratory/mixcr/partialassembler/TargetMerger.java index 6a39a7df9..5f7de7b72 100644 --- a/src/main/java/com/milaboratory/mixcr/partialassembler/TargetMerger.java +++ b/src/main/java/com/milaboratory/mixcr/partialassembler/TargetMerger.java @@ -225,6 +225,17 @@ static Alignment merge(AlignmentScoring } public TargetMergingResult merge(long readId, AlignedTarget targetLeft, AlignedTarget targetRight) { + return merge(readId, targetLeft, targetRight, true); + } + + /** + * @param readId read id + * @param targetLeft left sequence + * @param targetRight right sequence + * @param trySequenceMerge whether to try merging using sequence overlap (if alignment overlap failed) + */ + public TargetMergingResult merge(long readId, AlignedTarget targetLeft, AlignedTarget targetRight, + boolean trySequenceMerge) { for (GeneType geneType : GeneType.VJC_REFERENCE) { Map map = extractHitsMapping(targetLeft, targetRight, geneType); @@ -274,6 +285,9 @@ public int compare(HitMappingRecord o1, HitMappingRecord o2) { } } + if (!trySequenceMerge) + return new TargetMergingResult(); + final PairedReadMergingResult merge = merger.merge(targetLeft.getTarget(), targetRight.getTarget()); if (!merge.isSuccessful()) return new TargetMergingResult(); @@ -334,7 +348,7 @@ public boolean isUsingAlignments() { return usingAlignments; } - public boolean failedDueInconsistentAlignments(){ + public boolean failedDueInconsistentAlignments() { return failedMergedGeneType != null; } diff --git a/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerPVFirst.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerPVFirst.java index b44c8ad0a..1b691ac80 100644 --- a/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerPVFirst.java +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerPVFirst.java @@ -89,7 +89,8 @@ protected VDJCAlignmentResult process0(final PairedRead input) { final TargetMerger.TargetMergingResult mergeResult = alignmentsMerger.merge( input.getId(), new AlignedTarget(alignment, 0), - new AlignedTarget(alignment, 1)); + new AlignedTarget(alignment, 1), + false); if (mergeResult.failedDueInconsistentAlignments()) { GeneType gt = mergeResult.getFailedMergedGeneType(); From edfa425840737d7c6b150a23eb0b6ade6f498210 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Tue, 28 Feb 2017 13:28:41 +0300 Subject: [PATCH 13/35] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index da306d5ca..007ea1eef 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,12 @@ Dependancy: To build MiXCR from source: +- Clone repository + + ``` + git clone https://github.com/milaboratory/mixcr.git + ``` + - Refresh git submodules ``` From a32caae71c6fbe7aeb0eca6b35bcc2836c32c6ab Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Tue, 28 Feb 2017 17:37:15 +0300 Subject: [PATCH 14/35] =?UTF-8?q?Use=20MiLib=E2=80=99s=20TempFileManager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../AlignmentsToClonesMappingContainer.java | 6 +- .../mixcr/assembler/AssemblerEventLogger.java | 4 +- .../java/com/milaboratory/mixcr/cli/Main.java | 6 +- .../mixcr/util/TempFileManager.java | 93 ------------------- ...lignmentsToClonesMappingContainerTest.java | 12 ++- .../milaboratory/mixcr/util/RunMiXCRTest.java | 13 +-- 7 files changed, 24 insertions(+), 112 deletions(-) delete mode 100644 src/main/java/com/milaboratory/mixcr/util/TempFileManager.java diff --git a/pom.xml b/pom.xml index cf202003c..fc64c4440 100644 --- a/pom.xml +++ b/pom.xml @@ -44,7 +44,7 @@ UTF-8 - 1.7.1 + 1.7.2-SNAPSHOT diff --git a/src/main/java/com/milaboratory/mixcr/assembler/AlignmentsToClonesMappingContainer.java b/src/main/java/com/milaboratory/mixcr/assembler/AlignmentsToClonesMappingContainer.java index 76a4ecc51..c52c578cc 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/AlignmentsToClonesMappingContainer.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/AlignmentsToClonesMappingContainer.java @@ -1,7 +1,7 @@ package com.milaboratory.mixcr.assembler; import cc.redberry.pipe.OutputPort; -import com.milaboratory.mixcr.util.TempFileManager; +import com.milaboratory.util.TempFileManager; import java.io.*; import java.nio.ByteBuffer; @@ -143,7 +143,7 @@ public static void writeMapping(final OutputPort mappingPort public static void writeMapping(final OutputPort mappingPort, final int cloneCount, final File file) throws IOException { - try (DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) { + try(DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) { writeMapping(mappingPort, cloneCount, dos, DEFAULT_SORTING_CHUNK_SIZE); } } @@ -166,7 +166,7 @@ public static void writeMapping(final OutputPort mappingPort // Sorting blocks (sortingChunkSize) of records by clone id (for "by clone id" index file section) // Simultaneously writing records sorted "by alignment id" - try (final DataOutputStream tempOutput = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(tempFile), 262144))) { + try(final DataOutputStream tempOutput = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(tempFile), 262144))) { final ReadToCloneMapping[] buffer = new ReadToCloneMapping[sortingChunkSize]; ReadToCloneMapping mapping; ReadToCloneMapping previous = null; diff --git a/src/main/java/com/milaboratory/mixcr/assembler/AssemblerEventLogger.java b/src/main/java/com/milaboratory/mixcr/assembler/AssemblerEventLogger.java index 8289d5cba..d43365424 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/AssemblerEventLogger.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/AssemblerEventLogger.java @@ -31,7 +31,7 @@ import cc.redberry.pipe.CUtils; import cc.redberry.pipe.OutputPortCloseable; import com.milaboratory.core.io.util.IOUtil; -import com.milaboratory.mixcr.util.TempFileManager; +import com.milaboratory.util.TempFileManager; import java.io.*; import java.util.ArrayList; @@ -179,7 +179,7 @@ public AssemblerEvent take() { if (closed) return null; final int cloneIndex; - synchronized (this) { + synchronized ( this ){ if (closed) return null; else { diff --git a/src/main/java/com/milaboratory/mixcr/cli/Main.java b/src/main/java/com/milaboratory/mixcr/cli/Main.java index 5e117d6bd..f28f65aa1 100644 --- a/src/main/java/com/milaboratory/mixcr/cli/Main.java +++ b/src/main/java/com/milaboratory/mixcr/cli/Main.java @@ -30,15 +30,13 @@ import com.milaboratory.cli.JCommanderBasedMain; import com.milaboratory.mixcr.util.MiXCRVersionInfo; -import com.milaboratory.mixcr.util.TempFileManager; +import com.milaboratory.util.TempFileManager; import io.repseq.core.VDJCLibraryRegistry; import io.repseq.seqbase.SequenceResolvers; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.security.SecureRandom; -import java.util.Arrays; public class Main { private static volatile boolean initialized = false; @@ -48,7 +46,7 @@ public static void main(String... args) throws Exception { String command = System.getProperty("mixcr.command", "java -jar mixcr.jar"); if (!initialized) { - TempFileManager.seed(Arrays.hashCode(args) + 17 * (new SecureRandom()).nextLong()); + TempFileManager.setPrefix("mixcr_"); Path cachePath = Paths.get(System.getProperty("user.home"), ".mixcr", "cache"); //if (System.getProperty("allow.http") != null || System.getenv("MIXCR_ALLOW_HTTP") != null) diff --git a/src/main/java/com/milaboratory/mixcr/util/TempFileManager.java b/src/main/java/com/milaboratory/mixcr/util/TempFileManager.java deleted file mode 100644 index 7cd328634..000000000 --- a/src/main/java/com/milaboratory/mixcr/util/TempFileManager.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2014-2015, Bolotin Dmitry, Chudakov Dmitry, Shugay Mikhail - * (here and after addressed as Inventors) - * All Rights Reserved - * - * Permission to use, copy, modify and distribute any part of this program for - * educational, research and non-profit purposes, by non-profit institutions - * only, without fee, and without a written agreement is hereby granted, - * provided that the above copyright notice, this paragraph and the following - * three paragraphs appear in all copies. - * - * Those desiring to incorporate this work into commercial products or use for - * commercial purposes should contact the Inventors using one of the following - * email addresses: chudakovdm@mail.ru, chudakovdm@gmail.com - * - * IN NO EVENT SHALL THE INVENTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, - * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, - * ARISING OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE INVENTORS HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE SOFTWARE PROVIDED HEREIN IS ON AN "AS IS" BASIS, AND THE INVENTORS HAS - * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - * MODIFICATIONS. THE INVENTORS MAKES NO REPRESENTATIONS AND EXTENDS NO - * WARRANTIES OF ANY KIND, EITHER IMPLIED OR EXPRESS, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A - * PARTICULAR PURPOSE, OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY - * PATENT, TRADEMARK OR OTHER RIGHTS. - */ -package com.milaboratory.mixcr.util; - -import org.apache.commons.math3.random.RandomDataGenerator; -import org.apache.commons.math3.random.Well44497b; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; - -public class TempFileManager { - private static final AtomicBoolean initialized = new AtomicBoolean(false); - static final ConcurrentHashMap createdFiles = new ConcurrentHashMap<>(); - static final RandomDataGenerator randomGenerator = new RandomDataGenerator(new Well44497b()); - - public static void seed(long seed) { - synchronized (randomGenerator) { - randomGenerator.reSeed(seed); - } - } - - //static final String tmpdir = getTmpDir(); - //private static String getTmpDir() { - // String tmpdir = AccessController.doPrivileged(new GetPropertyAction("java.io.tmpdir")); - // if (!tmpdir.endsWith(File.separator)) - // tmpdir = tmpdir + File.separator; - // return tmpdir; - //} - - public static File getTempFile() { - try { - if (initialized.compareAndSet(false, true)) - // Adding delete files shutdown hook on the very firs execution of getTempFile() - Runtime.getRuntime().addShutdownHook(new Thread(new RemoveAction(), "DeleteTempFiles")); - - File file; - String name; - - do { - synchronized (randomGenerator) { - name = "mixcr_" + randomGenerator.nextHexString(40); - } - file = File.createTempFile(name, null); - } while (createdFiles.putIfAbsent(name, file) != null); - if (file.length() != 0) - throw new RuntimeException(); - return file; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private static final class RemoveAction implements Runnable { - @Override - public void run() { - for (File file : createdFiles.values()) { - if (file.exists()) - try { - file.delete(); - } catch (RuntimeException e) { - } - } - } - } -} diff --git a/src/test/java/com/milaboratory/mixcr/assembler/AlignmentsToClonesMappingContainerTest.java b/src/test/java/com/milaboratory/mixcr/assembler/AlignmentsToClonesMappingContainerTest.java index 7bdec0682..89b8e6cbd 100644 --- a/src/test/java/com/milaboratory/mixcr/assembler/AlignmentsToClonesMappingContainerTest.java +++ b/src/test/java/com/milaboratory/mixcr/assembler/AlignmentsToClonesMappingContainerTest.java @@ -55,9 +55,15 @@ public void test(int minRecords, int maxRecords, int minClones, int maxClones, i Well19937c rnd = RandomUtil.getThreadLocalRandom(); RandomDataGenerator rndD = RandomUtil.getThreadLocalRandomData(); - ReadToCloneMapping[] mappings = new ReadToCloneMapping[minRecords + rnd.nextInt(maxRecords - minRecords)]; + int readsCount, clonesCount; - TLongHashSet[] clones = new TLongHashSet[minClones + rnd.nextInt(maxClones - minClones)]; + do { + readsCount = minRecords + rnd.nextInt(maxRecords - minRecords); + clonesCount = minClones + rnd.nextInt(maxClones - minClones); + } while (readsCount <= clonesCount); + + ReadToCloneMapping[] mappings = new ReadToCloneMapping[readsCount]; + TLongHashSet[] clones = new TLongHashSet[clonesCount]; int[] initialReads = rndD.nextPermutation(mappings.length, clones.length); @@ -87,7 +93,7 @@ public void test(int minRecords, int maxRecords, int minClones, int maxClones, i } File tempFile = TempFileManager.getTempFile(); - try (DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(tempFile)))) { + try(DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(tempFile)))) { AlignmentsToClonesMappingContainer.writeMapping(CUtils.asOutputPort(mappings), clones.length, dos, sortChunk); } diff --git a/src/test/java/com/milaboratory/mixcr/util/RunMiXCRTest.java b/src/test/java/com/milaboratory/mixcr/util/RunMiXCRTest.java index 4054282c0..d156df554 100644 --- a/src/test/java/com/milaboratory/mixcr/util/RunMiXCRTest.java +++ b/src/test/java/com/milaboratory/mixcr/util/RunMiXCRTest.java @@ -6,6 +6,7 @@ import com.milaboratory.mixcr.basictypes.*; import com.milaboratory.mixcr.cli.ActionAlign; import com.milaboratory.mixcr.vdjaligners.VDJCAligner; +import com.milaboratory.util.TempFileManager; import io.repseq.core.Chains; import io.repseq.core.GeneType; import org.junit.Assert; @@ -87,7 +88,7 @@ public void test2() throws Exception { RunMiXCR.AlignResult align = RunMiXCR.align(params); List reads = new ArrayList<>(); - try (PairedFastqReader fReader = new PairedFastqReader( + try(PairedFastqReader fReader = new PairedFastqReader( RunMiXCR.class.getResource("/sequences/test_R1.fastq").getFile(), RunMiXCR.class.getResource("/sequences/test_R2.fastq").getFile())) { for (PairedRead s : CUtils.it(fReader)) @@ -95,13 +96,13 @@ public void test2() throws Exception { } File tempFile = TempFileManager.getTempFile(); - try (VDJCAlignmentsWriter writer = new VDJCAlignmentsWriter(tempFile)) { + try(VDJCAlignmentsWriter writer = new VDJCAlignmentsWriter(tempFile)) { writer.header(align.aligner); for (VDJCAlignments alignment : align.alignments) writer.write(alignment); } - try (VDJCAlignmentsReader reader = new VDJCAlignmentsReader(tempFile)) { + try(VDJCAlignmentsReader reader = new VDJCAlignmentsReader(tempFile)) { int tr = 0; for (VDJCAlignments alignment : CUtils.it(reader)) { PairedRead actual = reads.get((int) alignment.getReadId()); @@ -124,7 +125,7 @@ public void test3() throws Exception { RunMiXCR.AlignResult align = RunMiXCR.align(params); List reads = new ArrayList<>(); - try (PairedFastqReader fReader = new PairedFastqReader( + try(PairedFastqReader fReader = new PairedFastqReader( "/Users/poslavsky/Projects/milab/temp/R1_part.fastq.gz", "/Users/poslavsky/Projects/milab/temp/R2_part.fastq.gz", true)) { for (PairedRead s : CUtils.it(fReader)) @@ -132,13 +133,13 @@ public void test3() throws Exception { } File tempFile = TempFileManager.getTempFile(); - try (VDJCAlignmentsWriter writer = new VDJCAlignmentsWriter(tempFile)) { + try(VDJCAlignmentsWriter writer = new VDJCAlignmentsWriter(tempFile)) { writer.header(align.aligner); for (VDJCAlignments alignment : align.alignments) writer.write(alignment); } - try (VDJCAlignmentsReader reader = new VDJCAlignmentsReader(tempFile)) { + try(VDJCAlignmentsReader reader = new VDJCAlignmentsReader(tempFile)) { int tr = 0; for (VDJCAlignments alignment : CUtils.it(reader)) { PairedRead actual = reads.get((int) alignment.getReadId()); From cb82483746bad0f42eada4c27bfd94e5fe8f9036 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Tue, 28 Feb 2017 18:36:24 +0300 Subject: [PATCH 15/35] com.milaboratory.mixcr.basictypes.VDJCAlignmentsReader#initGeneFeatureReferencesFrom --- CHANGELOG_CURRENT | 1 + .../basictypes/VDJCAlignmentsReader.java | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/CHANGELOG_CURRENT b/CHANGELOG_CURRENT index bac248d70..2b345fb97 100644 --- a/CHANGELOG_CURRENT +++ b/CHANGELOG_CURRENT @@ -1,3 +1,4 @@ Fixed absent space in `AA. Seq. ...` column name and excessive space in the end of several column names (affects `exportClones` and `exportAlignments` with `-v` option; fixes compatibility with VDJTools v1.1.3 and below). +Added `sortAlignments` action. Sort `*.vdjca` files by read id, allows diffing alignments after `assembleParial` and other actions that shuffle records inside file. minor: Multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or `-i 123,456` etc. minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both renamed to `--read-ids` \ No newline at end of file diff --git a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java index 6da0d0267..8d161bcc6 100644 --- a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java +++ b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java @@ -42,7 +42,9 @@ import io.repseq.core.VDJCLibraryRegistry; import java.io.*; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import static com.milaboratory.mixcr.basictypes.VDJCAlignmentsWriter.*; @@ -123,6 +125,10 @@ public void setIndexer(TLongArrayList index) { } public void init() { + init(null); + } + + void init(Map geneFeatureRefs) { if (usedGenes != null) return; @@ -152,6 +158,16 @@ public void init() { GeneFeature featureDeserialized = input.readObject(GeneFeature.class); if (!Objects.equals(featureDeserialized, featureParams)) throw new RuntimeException("Wrong format."); + + // Find corresponding reference + if (geneFeatureRefs != null) { + featureParams = geneFeatureRefs.get(featureParams); + if (featureParams == null) + throw new RuntimeException("Absent record for " + featureDeserialized + " in geneFeatureRefs map."); + } + + parameters.getGeneAlignerParameters(gt).setGeneFeatureToAlign(featureParams); + if (featureDeserialized != null) input.putKnownReference(featureParams); } @@ -243,4 +259,20 @@ public synchronized VDJCAlignments take() { return alignments; } + + /** + * Produce reader that uses the same reference for geneFeatures. + * + * @param reader target reader + * @param sourceReader reader to take reference from + */ + public static void initGeneFeatureReferencesFrom(VDJCAlignmentsReader reader, VDJCAlignmentsReader sourceReader) { + Map featureRefs = new HashMap<>(); + VDJCAlignerParameters parameters = sourceReader.getParameters(); + for (GeneType gt : GeneType.VDJC_REFERENCE) { + GeneFeature f = parameters.getFeatureToAlign(gt); + featureRefs.put(f, f); + } + reader.init(featureRefs); + } } From bd3d1b11c28d5d4e423f092ca170d5cceabd4e4b Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Tue, 28 Feb 2017 18:38:26 +0300 Subject: [PATCH 16/35] toPref --- .../mixcr/basictypes/VDJCAlignmentsReader.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java index 8d161bcc6..761183713 100644 --- a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java +++ b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java @@ -263,16 +263,25 @@ public synchronized VDJCAlignments take() { /** * Produce reader that uses the same reference for geneFeatures. * - * @param reader target reader - * @param sourceReader reader to take reference from + * @param reader target reader + * @param parameters parameters to take reference from */ - public static void initGeneFeatureReferencesFrom(VDJCAlignmentsReader reader, VDJCAlignmentsReader sourceReader) { + public static void initGeneFeatureReferencesFrom(VDJCAlignmentsReader reader, VDJCAlignerParameters parameters) { Map featureRefs = new HashMap<>(); - VDJCAlignerParameters parameters = sourceReader.getParameters(); for (GeneType gt : GeneType.VDJC_REFERENCE) { GeneFeature f = parameters.getFeatureToAlign(gt); featureRefs.put(f, f); } reader.init(featureRefs); } + + /** + * Produce reader that uses the same reference for geneFeatures. + * + * @param reader target reader + * @param sourceReader reader to take reference from + */ + public static void initGeneFeatureReferencesFrom(VDJCAlignmentsReader reader, VDJCAlignmentsReader sourceReader) { + initGeneFeatureReferencesFrom(reader, sourceReader.getParameters()); + } } From d9316c99dd4e205ec1ec943bebac6f235705ed93 Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Tue, 28 Feb 2017 18:41:47 +0300 Subject: [PATCH 17/35] This fixes #215 --- pom.xml | 14 +- .../mixcr/cli/ActionSortAlignments.java | 125 ++++++++++++++++++ .../java/com/milaboratory/mixcr/cli/Main.java | 3 +- 3 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/milaboratory/mixcr/cli/ActionSortAlignments.java diff --git a/pom.xml b/pom.xml index fc64c4440..d33fc0f52 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,8 @@ ~ PARTICULAR PURPOSE, OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY ~ PATENT, TRADEMARK OR OTHER RIGHTS. --> - + 4.0.0 com.milaboratory @@ -51,7 +52,7 @@ io.repseq repseqio - 1.2.6 + 1.2.7-SNAPSHOT @@ -210,12 +211,15 @@ - + - + false - + com.milaboratory.mixcr.cli.Main diff --git a/src/main/java/com/milaboratory/mixcr/cli/ActionSortAlignments.java b/src/main/java/com/milaboratory/mixcr/cli/ActionSortAlignments.java new file mode 100644 index 000000000..d81171df7 --- /dev/null +++ b/src/main/java/com/milaboratory/mixcr/cli/ActionSortAlignments.java @@ -0,0 +1,125 @@ +package com.milaboratory.mixcr.cli; + +import cc.redberry.pipe.CUtils; +import cc.redberry.pipe.OutputPort; +import cc.redberry.pipe.OutputPortCloseable; +import cc.redberry.pipe.util.CountingOutputPort; +import com.beust.jcommander.Parameter; +import com.beust.jcommander.ParameterException; +import com.beust.jcommander.Parameters; +import com.milaboratory.cli.Action; +import com.milaboratory.cli.ActionHelper; +import com.milaboratory.cli.ActionParameters; +import com.milaboratory.cli.ActionParametersWithOutput; +import com.milaboratory.mixcr.basictypes.VDJCAlignments; +import com.milaboratory.mixcr.basictypes.VDJCAlignmentsReader; +import com.milaboratory.mixcr.basictypes.VDJCAlignmentsWriter; +import com.milaboratory.mixcr.vdjaligners.VDJCAlignerParameters; +import com.milaboratory.util.SmartProgressReporter; +import com.milaboratory.util.Sorter; +import com.milaboratory.util.TempFileManager; +import io.repseq.core.VDJCGene; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; + +/** + * Created by poslavsky on 28/02/2017. + */ +public final class ActionSortAlignments implements Action { + final AParameters parameters = new AParameters(); + + @Override + public void go(ActionHelper helper) throws Exception { + try(VDJCAlignmentsReader reader = new VDJCAlignmentsReader(parameters.getInputFile())) { + SmartProgressReporter.startProgressReport("Reading vdjca", reader); + try(OutputPortCloseable sorted = + Sorter.sort(reader, idComparator, 1024 * 512, new VDJCAlignmnetsSerializer(reader), TempFileManager.getTempFile()); + VDJCAlignmentsWriter writer = new VDJCAlignmentsWriter(parameters.getOutputFile())) { + + writer.header(reader.getParameters(), reader.getUsedGenes()); + + final long nReads = reader.getNumberOfReads(); + final CountingOutputPort counter = new CountingOutputPort<>(sorted); + SmartProgressReporter.startProgressReport("Writing sorted alignments", SmartProgressReporter.extractProgress(counter, nReads)); + for (VDJCAlignments res : CUtils.it(counter)) + writer.write(res); + writer.setNumberOfProcessedReads(nReads); + } + } + } + + @Override + public String command() { + return "sortAlignments"; + } + + @Override + public ActionParameters params() { + return parameters; + } + + private static final Comparator idComparator = new Comparator() { + @Override + public int compare(VDJCAlignments o1, VDJCAlignments o2) { + return Long.compare(o1.getReadId(), o2.getReadId()); + } + }; + + private static final class VDJCAlignmnetsSerializer implements Sorter.ObjectSerializer { + final VDJCAlignerParameters parameters; + final List usedAlleles; + + public VDJCAlignmnetsSerializer(VDJCAlignmentsReader reader) { + this.parameters = reader.getParameters(); + this.usedAlleles = reader.getUsedGenes(); + } + + @Override + public void write(Collection data, OutputStream stream) { + try(VDJCAlignmentsWriter writer = new VDJCAlignmentsWriter(stream)) { + writer.header(parameters, usedAlleles); + for (VDJCAlignments datum : data) + writer.write(datum); + } + } + + @Override + public OutputPort read(InputStream stream) { + VDJCAlignmentsReader reader = new VDJCAlignmentsReader(stream); + VDJCAlignmentsReader.initGeneFeatureReferencesFrom(reader, parameters); + return reader; + } + } + + @Parameters(commandDescription = "Sort alignments in vdjca file") + private static final class AParameters extends ActionParametersWithOutput { + @Parameter(description = "input.vdjca output.vdjca") + public List parameters; + + public String getInputFile() { + return parameters.get(0); + } + + + public String getOutputFile() { + return parameters.get(1); + } + + @Override + protected List getOutputFiles() { + return Arrays.asList(getOutputFile()); + } + + @Override + public void validate() { + if (parameters.size() != 2) + throw new ParameterException("Wrong number of parameters."); + super.validate(); + } + } +} diff --git a/src/main/java/com/milaboratory/mixcr/cli/Main.java b/src/main/java/com/milaboratory/mixcr/cli/Main.java index f28f65aa1..bfd83043a 100644 --- a/src/main/java/com/milaboratory/mixcr/cli/Main.java +++ b/src/main/java/com/milaboratory/mixcr/cli/Main.java @@ -93,7 +93,8 @@ public static void main(String... args) throws Exception { new ActionClonesDiff(), new ActionFilterAlignments(), new ActionListLibraries(), - new ActionExtendAlignments()); + new ActionExtendAlignments(), + new ActionSortAlignments()); // Adding version info callback main.setVersionInfoCallback(new Runnable() { From 89303e8b04dcc4318b93252d42b02064bda01140 Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Tue, 28 Feb 2017 19:37:51 +0300 Subject: [PATCH 18/35] Treat unmapped read from aligned read pair as right half in assemblePartial. This fixes #159. --- .../mixcr/basictypes/VDJCAlignments.java | 11 ++++++ .../PartialAlignmentsAssembler.java | 35 ++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignments.java b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignments.java index d48877a9b..bf54740ac 100644 --- a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignments.java +++ b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignments.java @@ -85,6 +85,17 @@ public VDJCAlignments removeBestHitAlignment(GeneType geneType, int targetId) { return result; } + public boolean hasNoHitsInTarget(int i) { + for (VDJCHit[] vdjcHits : hits.values()) { + if (vdjcHits == null) + continue; + for (VDJCHit hit : vdjcHits) + if (hit.getAlignment(i) != null) + return false; + } + return true; + } + public long getReadId() { return readId; } diff --git a/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java b/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java index 3ecf8e5bb..b0438c77b 100644 --- a/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java +++ b/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssembler.java @@ -274,9 +274,10 @@ private OverlapSearchResult searchOverlaps(final VDJCAlignments rightAl, NucleotideSequence rightSeq = rightSeqQ.getSequence(); int stop = rightTarget.getPartitioning().getPosition(ReferencePoint.JBeginTrimmed); - assert stop != -1; - - stop -= kOffset; + if (stop == -1) + stop = rightTarget.getSequence().size(); + else + stop -= kOffset; // black list of left parts failed due to inconsistent overlapped alignments (failed AMerge) TLongHashSet blackList = new TLongHashSet(); @@ -306,7 +307,7 @@ private OverlapSearchResult searchOverlaps(final VDJCAlignments rightAl, continue; // Checking chains compatibility - if (!allowChimeras && !leftAl.getAllChains(GeneType.Variable).intersects(jChains)) + if (!allowChimeras && jChains != null && !leftAl.getAllChains(GeneType.Variable).intersects(jChains)) continue; // Check for the same V @@ -502,9 +503,34 @@ private int getRightPartitionedSequence(VDJCAlignments alignment) { if (ps.getPartitioning().isAvailable(ReferencePoint.JBeginTrimmed)) return i; } + + if (alignment.numberOfTargets() != 2) + return -1; + + + if (getAlignmentLength(alignment, GeneType.Variable, 0) == alignment.getTarget(0).size() + && alignment.hasNoHitsInTarget(1)) + return 1; + + if (getAlignmentLength(alignment, GeneType.Constant, 1) + + getAlignmentLength(alignment, GeneType.Joining, 1) == alignment.getTarget(1).size() + && alignment.hasNoHitsInTarget(0)) + return 0; + return -1; } + private static int getAlignmentLength(VDJCAlignments alignment, GeneType gt, int id) { + VDJCHit bh = alignment.getBestHit(gt); + if (bh == null) + return 0; + Alignment al = bh.getAlignment(id); + if (al == null) + return 0; + return al.getSequence2Range().length(); + } + + private boolean addLeftToIndex(VDJCAlignments alignment) { int leftTargetId = getLeftPartitionedSequence(alignment); if (leftTargetId == -1) @@ -561,6 +587,7 @@ public KMerInfo(VDJCAlignments alignments, int kMerPositionFrom, int targetId) { public VDJCAlignments getAlignments() { return alignments; } + } private static AlignedTarget overrideDescription(AlignedTarget target, boolean isLeft) { From 99525a90e5b0f11d39becf1b769992890cb9cd96 Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Tue, 28 Feb 2017 19:38:15 +0300 Subject: [PATCH 19/35] Drop C hits in PartialAssemblerAligner due to relative score. This fixes #201. --- .../partialassembler/PartialAlignmentsAssemblerAligner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssemblerAligner.java b/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssemblerAligner.java index cf8fd6582..c19b1e0c2 100644 --- a/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssemblerAligner.java +++ b/src/main/java/com/milaboratory/mixcr/partialassembler/PartialAlignmentsAssemblerAligner.java @@ -251,7 +251,7 @@ protected VDJCAlignmentResult process0(VDJCMultiRead input) { vResult, dResult, jResult, - vdjcHits.get(GeneType.Constant), + cutRelativeScore(vdjcHits.get(GeneType.Constant), parameters.getCAlignerParameters().getRelativeMinScore(), parameters.getMaxHits()), targets ); return new VDJCAlignmentResult<>(input, alignment); From 60010bce74f4daf1c0599f6daac1a0cc63efb1c5 Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Tue, 28 Feb 2017 19:43:41 +0300 Subject: [PATCH 20/35] update repseqio --- repseqio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repseqio b/repseqio index 958e0196d..e4b9a658d 160000 --- a/repseqio +++ b/repseqio @@ -1 +1 @@ -Subproject commit 958e0196db110cf3a0dfabf905d45e2edc4d49c0 +Subproject commit e4b9a658dba058de6144aa380bd9893945121bd6 From b7f853b9f6eb6a470079e13e352fa2433d8a5d83 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Tue, 28 Feb 2017 23:26:50 +0300 Subject: [PATCH 21/35] RepSeq.io updated. Fixes problem with exportClones and mmu reference, fixes #217 --- CHANGELOG_CURRENT | 1 + repseqio | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG_CURRENT b/CHANGELOG_CURRENT index 2b345fb97..a70873cc2 100644 --- a/CHANGELOG_CURRENT +++ b/CHANGELOG_CURRENT @@ -1,4 +1,5 @@ Fixed absent space in `AA. Seq. ...` column name and excessive space in the end of several column names (affects `exportClones` and `exportAlignments` with `-v` option; fixes compatibility with VDJTools v1.1.3 and below). Added `sortAlignments` action. Sort `*.vdjca` files by read id, allows diffing alignments after `assembleParial` and other actions that shuffle records inside file. +Fixes NPE in `exportClones` in some cases with mmu reference minor: Multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or `-i 123,456` etc. minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both renamed to `--read-ids` \ No newline at end of file diff --git a/repseqio b/repseqio index e4b9a658d..39c72f9ea 160000 --- a/repseqio +++ b/repseqio @@ -1 +1 @@ -Subproject commit e4b9a658dba058de6144aa380bd9893945121bd6 +Subproject commit 39c72f9ea985fc55af8140e8d59333352c5abb77 From aec354f3c9fceccb93b1b812e1de28282c28c42b Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Tue, 28 Feb 2017 23:53:33 +0300 Subject: [PATCH 22/35] `-p`deprecated, enabled by default, added `-d` with opposite action. Docs corrected accordingly. This fixes #208 --- CHANGELOG_CURRENT | 4 ++- doc/quickstart.rst | 4 +-- doc/rnaseq.rst | 6 ++--- .../cli/ActionAssemblePartialAlignments.java | 26 ++++++++++++++----- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/CHANGELOG_CURRENT b/CHANGELOG_CURRENT index a70873cc2..489339c8b 100644 --- a/CHANGELOG_CURRENT +++ b/CHANGELOG_CURRENT @@ -1,5 +1,7 @@ Fixed absent space in `AA. Seq. ...` column name and excessive space in the end of several column names (affects `exportClones` and `exportAlignments` with `-v` option; fixes compatibility with VDJTools v1.1.3 and below). -Added `sortAlignments` action. Sort `*.vdjca` files by read id, allows diffing alignments after `assembleParial` and other actions that shuffle records inside file. Fixes NPE in `exportClones` in some cases with mmu reference +`-p` option in `assemblePartial` enabled by default; deprecated, will be removed in 2.2 +Added `-d` option in `assemblePartial` to drop non-assembled partial reads to reduce output file size +Added `sortAlignments` action. Sort `*.vdjca` files by read id, allows diffing alignments after `assembleParial` and other actions that shuffle records inside file. minor: Multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or `-i 123,456` etc. minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both renamed to `--read-ids` \ No newline at end of file diff --git a/doc/quickstart.rst b/doc/quickstart.rst index 49710342d..e460ccb58 100644 --- a/doc/quickstart.rst +++ b/doc/quickstart.rst @@ -239,9 +239,9 @@ MiXCR allows to extract TCR and BCR CDR3 repertoires from RNA-Seq data. Extracti .. code-block:: console - > mixcr assemblePartial -p alignments.vdjca alignmentsRescued_1.vdjca + > mixcr assemblePartial alignments.vdjca alignmentsRescued_1.vdjca - > mixcr assemblePartial -p alignmentsRescued_1.vdjca alignmentsRescued_2.vdjca + > mixcr assemblePartial alignmentsRescued_1.vdjca alignmentsRescued_2.vdjca 3. Extend TCR alignments with uniquely determined V and J genes and having incomplete coverage of CDR3s using germline sequences: diff --git a/doc/rnaseq.rst b/doc/rnaseq.rst index 694ddd112..a9718b315 100644 --- a/doc/rnaseq.rst +++ b/doc/rnaseq.rst @@ -75,10 +75,8 @@ Typical analysis workflow :: - mixcr assemblePartial -p alignments.vdjca alignments_rescued_1.vdjca - mixcr assemblePartial -p alignments_rescued_1.vdjca alignments_rescued_2.vdjca - - ``-p`` option tells MiXCRsquences to pass unassembled alignments to the output file. + mixcr assemblePartial alignments.vdjca alignments_rescued_1.vdjca + mixcr assemblePartial alignments_rescued_1.vdjca alignments_rescued_2.vdjca 3. (optional) Perform extension of incomplete TCR CDR3s with uniquely determined V and J genes using germline sequences. As described in the :ref:`last paragraph of introduction ` diff --git a/src/main/java/com/milaboratory/mixcr/cli/ActionAssemblePartialAlignments.java b/src/main/java/com/milaboratory/mixcr/cli/ActionAssemblePartialAlignments.java index d5e5471b1..d479ab3d2 100644 --- a/src/main/java/com/milaboratory/mixcr/cli/ActionAssemblePartialAlignments.java +++ b/src/main/java/com/milaboratory/mixcr/cli/ActionAssemblePartialAlignments.java @@ -27,12 +27,17 @@ public final class ActionAssemblePartialAlignments implements Action { @Override public void go(ActionHelper helper) throws Exception { + if (parameters.writePartial != null) + System.err.println("'-p' option is deprecated and will be removed in 2.2. " + + "Use '-d' option to drop not-overlapped partial reads."); + // Saving initial timestamp long beginTimestamp = System.currentTimeMillis(); PartialAlignmentsAssemblerParameters assemblerParameters = PartialAlignmentsAssemblerParameters.getDefault(); if (!parameters.overrides.isEmpty()) { - assemblerParameters = JsonOverrider.override(assemblerParameters, PartialAlignmentsAssemblerParameters.class, parameters.overrides); + assemblerParameters = JsonOverrider.override(assemblerParameters, + PartialAlignmentsAssemblerParameters.class, parameters.overrides); if (assemblerParameters == null) { System.err.println("Failed to override some parameter."); return; @@ -40,8 +45,9 @@ public void go(ActionHelper helper) throws Exception { } long start = System.currentTimeMillis(); - try (PartialAlignmentsAssembler assembler = new PartialAlignmentsAssembler(assemblerParameters, parameters.getOutputFileName(), - parameters.getWritePartial(), parameters.getOverlappedOnly())) { + try (PartialAlignmentsAssembler assembler = new PartialAlignmentsAssembler(assemblerParameters, + parameters.getOutputFileName(), !parameters.doDropPartial(), + parameters.getOverlappedOnly())) { try (VDJCAlignmentsReader reader = new VDJCAlignmentsReader(parameters.getInputFileName())) { SmartProgressReporter.startProgressReport("Building index", reader); assembler.buildLeftPartsIndex(reader); @@ -53,7 +59,8 @@ public void go(ActionHelper helper) throws Exception { if (parameters.report != null) Util.writeReport(parameters.getInputFileName(), parameters.getOutputFileName(), - helper.getCommandLineArguments(), parameters.report, System.currentTimeMillis() - start, assembler + helper.getCommandLineArguments(), parameters.report, + System.currentTimeMillis() - start, assembler ); long time = System.currentTimeMillis() - beginTimestamp; @@ -90,10 +97,15 @@ private static class AssemblePartialAlignmentsParameters extends ActionParameter names = {"-o", "--overlapped-only"}) public Boolean overlappedOnly; - @Parameter(description = "Write partial sequences (for recurrent overlapping).", + @Parameter(description = "[Deprecated, enabled by default] Write partial sequences (for recurrent overlapping).", names = {"-p", "--write-partial"}) public Boolean writePartial; + @Parameter(description = "Drop partial sequences which were not assembled. Can be used to reduce output file " + + "size if no additional rounds of 'assemblePartial' are required.", + names = {"-d", "--drop-partial"}) + public Boolean dropPartial; + public String getInputFileName() { return parameters.get(0); } @@ -106,8 +118,8 @@ public Boolean getOverlappedOnly() { return overlappedOnly != null && overlappedOnly; } - public Boolean getWritePartial() { - return writePartial != null && writePartial; + public Boolean doDropPartial() { + return dropPartial != null && dropPartial; } @Override From ce53dcd0bbccd37b7b8a408338600aece2182496 Mon Sep 17 00:00:00 2001 From: Stanislav Poslavsky Date: Wed, 1 Mar 2017 15:46:41 +0300 Subject: [PATCH 23/35] Aligners parameters in clone assembler now inherited from initial alignment parameters (specified at align step). This fixes #153, fixes #219 --- .../mixcr/assembler/CloneAssembler.java | 18 ++- .../assembler/CloneAssemblerParameters.java | 23 ++- .../mixcr/assembler/CloneFactory.java | 8 +- .../assembler/CloneFactoryParameters.java | 68 ++++----- .../assembler/DClonalAlignerParameters.java | 126 ++++++++++------ .../assembler/VJCClonalAlignerParameters.java | 123 +++++++++++++--- .../basictypes/ClonalUpdatableParameters.java | 12 ++ .../basictypes/VDJCAlignmentsReader.java | 2 +- .../mixcr/cli/ActionAssemble.java | 24 +-- .../com/milaboratory/mixcr/util/RunMiXCR.java | 2 +- .../ClonalGeneAlignmentParameters.java | 15 ++ .../mixcr/vdjaligners/DAlignerParameters.java | 82 ++++------- .../vdjaligners/GeneAlignmentParameters.java | 71 +-------- .../GeneAlignmentParametersAbstract.java} | 50 ++++--- .../vdjaligners/KGeneAlignmentParameters.java | 31 ++-- .../mixcr/vdjaligners/SingleDAligner.java | 8 +- .../vdjaligners/VDJCAlignerParameters.java | 7 + .../parameters/assembler_parameters.json | 137 +++--------------- .../CloneAssemblerParametersTest.java | 20 +-- .../assembler/CloneAssemblerRunnerTest.java | 15 +- .../assembler/CloneFactoryParametersTest.java | 26 ++-- .../DClonalAlignerParametersTest.java | 48 ------ .../VJCClonalAlignerParametersTest.java | 19 ++- .../mixcr/cli/JsonOverriderTest.java | 36 +++-- .../vdjaligners/DAlignerParametersTest.java | 4 +- .../VDJCAlignerParametersTest.java | 2 +- 26 files changed, 460 insertions(+), 517 deletions(-) create mode 100644 src/main/java/com/milaboratory/mixcr/basictypes/ClonalUpdatableParameters.java create mode 100644 src/main/java/com/milaboratory/mixcr/vdjaligners/ClonalGeneAlignmentParameters.java rename src/main/java/com/milaboratory/mixcr/{assembler/AbstractClonalAlignerParameters.java => vdjaligners/GeneAlignmentParametersAbstract.java} (61%) delete mode 100644 src/test/java/com/milaboratory/mixcr/assembler/DClonalAlignerParametersTest.java diff --git a/src/main/java/com/milaboratory/mixcr/assembler/CloneAssembler.java b/src/main/java/com/milaboratory/mixcr/assembler/CloneAssembler.java index f7708ee5d..0595d5d8c 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/CloneAssembler.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/CloneAssembler.java @@ -42,7 +42,7 @@ import com.milaboratory.core.tree.NeighborhoodIterator; import com.milaboratory.core.tree.SequenceTreeMap; import com.milaboratory.mixcr.basictypes.*; -import io.repseq.core.*; +import com.milaboratory.mixcr.vdjaligners.VDJCAlignerParameters; import com.milaboratory.util.CanReportProgress; import com.milaboratory.util.Factory; import com.milaboratory.util.HashFunctions; @@ -51,6 +51,8 @@ import gnu.trove.map.hash.TIntIntHashMap; import gnu.trove.map.hash.TObjectFloatHashMap; import gnu.trove.procedure.TObjectProcedure; +import io.repseq.core.GeneFeature; +import io.repseq.core.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -82,6 +84,7 @@ public final class CloneAssembler implements CanReportProgress, AutoCloseable { volatile boolean deferredExists = false; volatile boolean preClusteringDone = false; final TIntIntHashMap preClustered = new TIntIntHashMap(); + final EnumMap featuresToAlign; public static final Factory> LIST_FACTORY = new Factory>() { @Override @@ -90,8 +93,11 @@ public ArrayList create() { } }; - public CloneAssembler(CloneAssemblerParameters parameters, boolean logAssemblerEvents, Collection genes) { + public CloneAssembler(CloneAssemblerParameters parameters, boolean logAssemblerEvents, Collection genes, EnumMap featuresToAlign) { + if (!parameters.isComplete()) + throw new IllegalArgumentException("Not complete parameters"); this.parameters = parameters.clone(); + this.featuresToAlign = featuresToAlign; if (!logAssemblerEvents && !parameters.isMappingEnabled()) globalLogger = null; else @@ -100,6 +106,10 @@ public CloneAssembler(CloneAssemblerParameters parameters, boolean logAssemblerE usedGenes.put(gene.getId(), gene); } + public CloneAssembler(CloneAssemblerParameters parameters, boolean logAssemblerEvents, Collection genes, VDJCAlignerParameters alignerParameters) { + this(parameters.clone().updateFrom(alignerParameters), logAssemblerEvents, genes, alignerParameters.getFeaturesToAlignMap()); + } + /* Initial Assembly Events */ void onNewCloneCreated(CloneAccumulator accumulator) { @@ -296,7 +306,7 @@ public void close() { public CloneSet getCloneSet() { EnumMap features = new EnumMap<>(GeneType.class); for (GeneType geneType : GeneType.values()) { - GeneFeature gf = parameters.cloneFactoryParameters.getFeatureToAlign(geneType); + GeneFeature gf = featuresToAlign.get(geneType); if (gf != null) features.put(geneType, gf); } @@ -506,7 +516,7 @@ public boolean isFinished() { void buildClones() { CloneFactory cloneFactory = new CloneFactory(parameters.getCloneFactoryParameters(), - parameters.getAssemblingFeatures(), usedGenes); + parameters.getAssemblingFeatures(), usedGenes, featuresToAlign); Collection source; if (clusteredClonesAccumulators != null) source = clusteredClonesAccumulators; diff --git a/src/main/java/com/milaboratory/mixcr/assembler/CloneAssemblerParameters.java b/src/main/java/com/milaboratory/mixcr/assembler/CloneAssemblerParameters.java index 6b2d490bf..5ca39fe92 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/CloneAssemblerParameters.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/CloneAssemblerParameters.java @@ -32,8 +32,9 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import io.repseq.core.GeneFeature; import com.milaboratory.core.sequence.quality.QualityAggregationType; +import com.milaboratory.mixcr.vdjaligners.VDJCAlignerParameters; +import io.repseq.core.GeneFeature; import java.util.Arrays; import java.util.regex.Matcher; @@ -90,6 +91,18 @@ public CloneAssemblerParameters(@JsonProperty("assemblingFeatures") GeneFeature[ updateVariants(); } + public CloneAssemblerParameters updateFrom(VDJCAlignerParameters alignerParameters) { + if (cloneFactoryParameters != null) + cloneFactoryParameters.update(alignerParameters); + return this; + } + + public boolean isComplete() { + if (cloneFactoryParameters != null) + return cloneFactoryParameters.isComplete(); + return true; + } + public static final Pattern thresholdPattern = Pattern.compile("\\s*(\\d+)\\s*(of|from)\\s*(\\d+)\\s*"); private void updateVariants() { @@ -295,13 +308,13 @@ public int hashCode() { result = 31 * result + (separateByJ ? 1 : 0); result = 31 * result + (separateByC ? 1 : 0); temp = Double.doubleToLongBits(maximalPreClusteringRatio); - result = 31 * result + (int) (temp ^ (temp >>> 32)); + result = 31 * result + (int) (temp^(temp >>> 32)); result = 31 * result + (addReadsCountOnClustering ? 1 : 0); result = 31 * result + (int) badQualityThreshold; temp = Double.doubleToLongBits(maxBadPointsPercent); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - result = 31 * result + (int) (variants ^ (variants >>> 32)); - result = 31 * result + (int) (minimalQuality ^ (minimalQuality >>> 32)); + result = 31 * result + (int) (temp^(temp >>> 32)); + result = 31 * result + (int) (variants^(variants >>> 32)); + result = 31 * result + (int) (minimalQuality^(minimalQuality >>> 32)); return result; } } diff --git a/src/main/java/com/milaboratory/mixcr/assembler/CloneFactory.java b/src/main/java/com/milaboratory/mixcr/assembler/CloneFactory.java index 33ffc0025..e6f61bdf6 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/CloneFactory.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/CloneFactory.java @@ -47,17 +47,19 @@ class CloneFactory { final HashMap usedGenes; final GeneFeature[] assemblingFeatures; final int indexOfAssemblingFeatureWithD; + final EnumMap featuresToAlign; CloneFactory(CloneFactoryParameters parameters, GeneFeature[] assemblingFeatures, - HashMap usedGenes) { + HashMap usedGenes, EnumMap featuresToAlign) { this.parameters = parameters.clone(); this.assemblingFeatures = assemblingFeatures.clone(); this.usedGenes = usedGenes; + this.featuresToAlign = featuresToAlign; List dGenes = new ArrayList<>(); for (VDJCGene gene : usedGenes.values()) if (gene.getGeneType() == GeneType.Diversity) dGenes.add(gene); - this.dAligner = new SingleDAligner(parameters.getDParameters(), dGenes); + this.dAligner = new SingleDAligner(parameters.getDParameters(), featuresToAlign.get(GeneType.Diversity), dGenes); int indexOfAssemblingFeatureWithD = -1; for (int i = 0; i < assemblingFeatures.length; ++i) @@ -76,7 +78,7 @@ Clone create(int id, CloneAccumulator accumulator) { if (vjcParameters == null) continue; - GeneFeature featureToAlign = vjcParameters.getFeatureToAlign(); + GeneFeature featureToAlign = featuresToAlign.get(geneType); TObjectFloatHashMap geneScores = accumulator.geneScores.get(geneType); if (geneScores == null) diff --git a/src/main/java/com/milaboratory/mixcr/assembler/CloneFactoryParameters.java b/src/main/java/com/milaboratory/mixcr/assembler/CloneFactoryParameters.java index bd6abf1cf..f59db6f6f 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/CloneFactoryParameters.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/CloneFactoryParameters.java @@ -29,25 +29,29 @@ package com.milaboratory.mixcr.assembler; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import io.repseq.core.GeneFeature; +import com.milaboratory.mixcr.basictypes.ClonalUpdatableParameters; +import com.milaboratory.mixcr.vdjaligners.VDJCAlignerParameters; import io.repseq.core.GeneType; -import com.milaboratory.mixcr.vdjaligners.DAlignerParameters; import java.util.EnumMap; import java.util.Map; +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, + getterVisibility = JsonAutoDetect.Visibility.NONE) public final class CloneFactoryParameters implements java.io.Serializable { EnumMap vdcParameters = new EnumMap<>(GeneType.class); - DAlignerParameters dParameters; + @JsonSerialize(as = DClonalAlignerParameters.class) + DClonalAlignerParameters dParameters; @JsonCreator public CloneFactoryParameters(@JsonProperty("vParameters") VJCClonalAlignerParameters vParameters, @JsonProperty("jParameters") VJCClonalAlignerParameters jParameters, @JsonProperty("cParameters") VJCClonalAlignerParameters cParameters, - @JsonProperty("dParameters") DAlignerParameters dParameters) { + @JsonProperty("dParameters") DClonalAlignerParameters dParameters) { if (vParameters != null) vdcParameters.put(GeneType.Variable, vParameters); if (jParameters != null) @@ -57,11 +61,32 @@ public CloneFactoryParameters(@JsonProperty("vParameters") VJCClonalAlignerParam this.dParameters = dParameters; } - CloneFactoryParameters(EnumMap vdcParameters, DAlignerParameters dParameters) { + CloneFactoryParameters(EnumMap vdcParameters, DClonalAlignerParameters dParameters) { this.vdcParameters = vdcParameters; this.dParameters = dParameters; } + private ClonalUpdatableParameters uParameters(GeneType gt) { + return gt == GeneType.Diversity ? dParameters : vdcParameters.get(gt); + } + + public void update(VDJCAlignerParameters alignerParameters) { + for (GeneType gt : GeneType.VDJC_REFERENCE) { + ClonalUpdatableParameters up = uParameters(gt); + if (up != null) + up.updateFrom(alignerParameters.getGeneAlignerParameters(gt)); + } + } + + public boolean isComplete() { + for (GeneType gt : GeneType.VDJC_REFERENCE) { + ClonalUpdatableParameters up = uParameters(gt); + if (up != null && !up.isComplete()) + return false; + } + return true; + } + public VJCClonalAlignerParameters getVJCParameters(GeneType geneType) { return vdcParameters.get(geneType); } @@ -86,39 +111,10 @@ public VJCClonalAlignerParameters getCParameters() { @JsonProperty("dParameters") @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) - public DAlignerParameters getDParameters() { + public DClonalAlignerParameters getDParameters() { return dParameters; } - public GeneFeature getFeatureToAlign(GeneType geneType) { - if (geneType == GeneType.Diversity) - if (dParameters == null) - return null; - else - return dParameters.getGeneFeatureToAlign(); - VJCClonalAlignerParameters params = getVJCParameters(geneType); - if (params == null) - return null; - else - return params.getFeatureToAlign(); - } - - public CloneFactoryParameters setFeatureToAlign(GeneType geneType, GeneFeature feature) { - if (geneType == GeneType.Diversity) - if (dParameters == null) - throw new IllegalArgumentException("No D parameters."); - else - dParameters.setGeneFeatureToAlign(feature); - else { - VJCClonalAlignerParameters params = getVJCParameters(geneType); - if (params == null) - throw new IllegalArgumentException("No parameters for " + geneType + "."); - else - params.setFeatureToAlign(feature); - } - return this; - } - public CloneFactoryParameters setVJCParameters(GeneType geneType, VJCClonalAlignerParameters parameters) { if (parameters == null) vdcParameters.remove(geneType); @@ -142,7 +138,7 @@ public CloneFactoryParameters setCParameters(VJCClonalAlignerParameters paramete return this; } - public CloneFactoryParameters setDParameters(DAlignerParameters dParameters) { + public CloneFactoryParameters setDParameters(DClonalAlignerParameters dParameters) { this.dParameters = dParameters; return this; } diff --git a/src/main/java/com/milaboratory/mixcr/assembler/DClonalAlignerParameters.java b/src/main/java/com/milaboratory/mixcr/assembler/DClonalAlignerParameters.java index 18a8ca99a..5393cc446 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/DClonalAlignerParameters.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/DClonalAlignerParameters.java @@ -1,31 +1,3 @@ -/* - * Copyright (c) 2014-2015, Bolotin Dmitry, Chudakov Dmitry, Shugay Mikhail - * (here and after addressed as Inventors) - * All Rights Reserved - * - * Permission to use, copy, modify and distribute any part of this program for - * educational, research and non-profit purposes, by non-profit institutions - * only, without fee, and without a written agreement is hereby granted, - * provided that the above copyright notice, this paragraph and the following - * three paragraphs appear in all copies. - * - * Those desiring to incorporate this work into commercial products or use for - * commercial purposes should contact the Inventors using one of the following - * email addresses: chudakovdm@mail.ru, chudakovdm@gmail.com - * - * IN NO EVENT SHALL THE INVENTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, - * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, - * ARISING OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE INVENTORS HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE SOFTWARE PROVIDED HEREIN IS ON AN "AS IS" BASIS, AND THE INVENTORS HAS - * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - * MODIFICATIONS. THE INVENTORS MAKES NO REPRESENTATIONS AND EXTENDS NO - * WARRANTIES OF ANY KIND, EITHER IMPLIED OR EXPRESS, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A - * PARTICULAR PURPOSE, OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY - * PATENT, TRADEMARK OR OTHER RIGHTS. - */ package com.milaboratory.mixcr.assembler; import com.fasterxml.jackson.annotation.JsonAutoDetect; @@ -33,54 +5,120 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.milaboratory.core.alignment.AlignmentScoring; import com.milaboratory.core.sequence.NucleotideSequence; -import io.repseq.core.GeneFeature; +import com.milaboratory.mixcr.basictypes.ClonalUpdatableParameters; +import com.milaboratory.mixcr.vdjaligners.ClonalGeneAlignmentParameters; +/** + * Created by poslavsky on 01/03/2017. + */ @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE) -public final class DClonalAlignerParameters extends AbstractClonalAlignerParameters - implements java.io.Serializable { - AlignmentScoring scoring; +public class DClonalAlignerParameters> implements + ClonalUpdatableParameters, ClonalGeneAlignmentParameters, java.io.Serializable { + protected Float relativeMinScore; + protected Float absoluteMinScore; + protected Integer maxHits; + protected AlignmentScoring scoring; @JsonCreator public DClonalAlignerParameters( - @JsonProperty("relativeMinScore") float relativeMinScore, - @JsonProperty("featureToAlign") GeneFeature featureToAlign, + @JsonProperty("relativeMinScore") Float relativeMinScore, + @JsonProperty("absoluteMinScore") Float absoluteMinScore, + @JsonProperty("maxHits") Integer maxHits, @JsonProperty("scoring") AlignmentScoring scoring) { - super(featureToAlign, relativeMinScore); + this.relativeMinScore = relativeMinScore; + this.absoluteMinScore = absoluteMinScore; + this.maxHits = maxHits; this.scoring = scoring; } + @Override + public void updateFrom(ClonalGeneAlignmentParameters alignerParameters) { + if (!(alignerParameters instanceof DClonalAlignerParameters)) + throw new IllegalArgumentException(); + DClonalAlignerParameters oth = (DClonalAlignerParameters) alignerParameters; + + if (relativeMinScore == null) + relativeMinScore = oth.relativeMinScore; + if (absoluteMinScore == null) + absoluteMinScore = oth.absoluteMinScore; + if (maxHits == null) + maxHits = oth.maxHits; + if (scoring == null) + scoring = oth.scoring; + } + + @Override + public boolean isComplete() { + return relativeMinScore != null && absoluteMinScore != null && maxHits != null && scoring != null; + } + + @Override public AlignmentScoring getScoring() { return scoring; } - public DClonalAlignerParameters setScoring(AlignmentScoring scoring) { + + public T setRelativeMinScore(float relativeMinScore) { + this.relativeMinScore = relativeMinScore; + return (T) this; + } + + @Override + public float getRelativeMinScore() { + return relativeMinScore; + } + + + public T setScoring(AlignmentScoring scoring) { this.scoring = scoring; - return this; + return (T) this; + } + + public float getAbsoluteMinScore() { + return absoluteMinScore; + } + + public T setAbsoluteMinScore(float absoluteMinScore) { + this.absoluteMinScore = absoluteMinScore; + return (T) this; + } + + public int getMaxHits() { + return maxHits; + } + + public T setMaxHits(int maxHits) { + this.maxHits = maxHits; + return (T) this; } @Override public DClonalAlignerParameters clone() { - return new DClonalAlignerParameters(relativeMinScore, featureToAlign, scoring); + return new DClonalAlignerParameters(relativeMinScore, absoluteMinScore, maxHits, scoring); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; DClonalAlignerParameters that = (DClonalAlignerParameters) o; - if (!scoring.equals(that.scoring)) return false; - - return true; + if (relativeMinScore != null ? !relativeMinScore.equals(that.relativeMinScore) : that.relativeMinScore != null) + return false; + if (absoluteMinScore != null ? !absoluteMinScore.equals(that.absoluteMinScore) : that.absoluteMinScore != null) + return false; + if (maxHits != null ? !maxHits.equals(that.maxHits) : that.maxHits != null) return false; + return scoring != null ? scoring.equals(that.scoring) : that.scoring == null; } @Override public int hashCode() { - int result = super.hashCode(); - result = 31 * result + scoring.hashCode(); + int result = relativeMinScore != null ? relativeMinScore.hashCode() : 0; + result = 31 * result + (absoluteMinScore != null ? absoluteMinScore.hashCode() : 0); + result = 31 * result + (maxHits != null ? maxHits.hashCode() : 0); + result = 31 * result + (scoring != null ? scoring.hashCode() : 0); return result; } } diff --git a/src/main/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParameters.java b/src/main/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParameters.java index 80b9fcf28..2b28e7f94 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParameters.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParameters.java @@ -28,59 +28,138 @@ */ package com.milaboratory.mixcr.assembler; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.*; +import com.milaboratory.core.alignment.AffineGapAlignmentScoring; +import com.milaboratory.core.alignment.AlignmentScoring; import com.milaboratory.core.alignment.BandedAlignerParameters; import com.milaboratory.core.sequence.NucleotideSequence; -import io.repseq.core.GeneFeature; +import com.milaboratory.mixcr.basictypes.ClonalUpdatableParameters; +import com.milaboratory.mixcr.vdjaligners.ClonalGeneAlignmentParameters; @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE) -public final class VJCClonalAlignerParameters extends AbstractClonalAlignerParameters - implements java.io.Serializable { - BandedAlignerParameters alignmentParameters; +@JsonIgnoreProperties({"featureToAlign", "alignmentParameters"}) +public final class VJCClonalAlignerParameters + implements ClonalGeneAlignmentParameters, java.io.Serializable, ClonalUpdatableParameters { + Float relativeMinScore; + AlignmentScoring scoring; + @JsonIgnore + int maxAlignmentWidthLinear; + @JsonIgnore + int maxAlignmentWidthAffine; + + public VJCClonalAlignerParameters( + float relativeMinScore, + AlignmentScoring scoring, + int maxAlignmentWidth) { + this.relativeMinScore = relativeMinScore; + this.scoring = scoring; + this.maxAlignmentWidthLinear = maxAlignmentWidth; + this.maxAlignmentWidthAffine = maxAlignmentWidth; + } @JsonCreator public VJCClonalAlignerParameters( - @JsonProperty("featureToAlign") GeneFeature featureToAlign, - @JsonProperty("relativeMinScore") float relativeMinScore, - @JsonProperty("alignmentParameters") BandedAlignerParameters alignmentParameters) { - super(featureToAlign, relativeMinScore); - this.alignmentParameters = alignmentParameters; + @JsonProperty("relativeMinScore") Float relativeMinScore, + @JsonProperty("scoring") AlignmentScoring scoring, + @JsonProperty(value = "maxAlignmentWidth") Integer maxAlignmentWidth, + @JsonProperty(value = "maxAlignmentWidthLinear") Integer maxAlignmentWidthLinear, + @JsonProperty(value = "maxAlignmentWidthAffine") Integer maxAlignmentWidthAffine) { + this.relativeMinScore = relativeMinScore; + this.scoring = scoring; + if (maxAlignmentWidth == null && (maxAlignmentWidthAffine == null || maxAlignmentWidthLinear == null)) + throw new IllegalArgumentException("maxAlignmentWidth or maxAlignmentWidthAffine and maxAlignmentWidthLinear are not specified"); + + this.maxAlignmentWidthLinear = maxAlignmentWidth != null ? maxAlignmentWidth : maxAlignmentWidthLinear; + this.maxAlignmentWidthAffine = maxAlignmentWidth != null ? maxAlignmentWidth : maxAlignmentWidthAffine; } public BandedAlignerParameters getAlignmentParameters() { - return alignmentParameters; + if (!isComplete()) + throw new IllegalStateException(); + return new BandedAlignerParameters<>(scoring, getMaxAlignmentWidth(), Integer.MIN_VALUE); + } + + @Override + public void updateFrom(ClonalGeneAlignmentParameters alignerParameters) { + if (scoring == null) + scoring = alignerParameters.getScoring(); + if (relativeMinScore == null) + relativeMinScore = alignerParameters.getRelativeMinScore(); + } + + @Override + public boolean isComplete() { + return relativeMinScore != null && scoring != null; + } + + @Override + public AlignmentScoring getScoring() { + return scoring; + } + + public VJCClonalAlignerParameters setScoring(AlignmentScoring scoring) { + this.scoring = scoring; + return this; } - public VJCClonalAlignerParameters setAlignmentParameters(BandedAlignerParameters alignmentParameters) { - this.alignmentParameters = alignmentParameters; + @Override + public float getRelativeMinScore() { + return relativeMinScore; + } + + public VJCClonalAlignerParameters setRelativeMinScore(Float relativeMinScore) { + this.relativeMinScore = relativeMinScore; return this; } + public int getMaxAlignmentWidth() { + return scoring instanceof AffineGapAlignmentScoring ? maxAlignmentWidthAffine : maxAlignmentWidthLinear; + } + + @JsonProperty("maxAlignmentWidth") + @JsonInclude(JsonInclude.Include.NON_NULL) + public Integer getMaxAlignmentWidthJSON() { + return (maxAlignmentWidthAffine == maxAlignmentWidthLinear) ? maxAlignmentWidthAffine : null; + } + + @JsonProperty("maxAlignmentWidthLinear") + @JsonInclude(JsonInclude.Include.NON_NULL) + public Integer getMaxAlignmentWidthLinearJSON() { + return (maxAlignmentWidthAffine != maxAlignmentWidthLinear) ? maxAlignmentWidthLinear : null; + } + + @JsonProperty("maxAlignmentWidthAffine") + @JsonInclude(JsonInclude.Include.NON_NULL) + public Integer getMaxAlignmentWidthAffineJSON() { + return (maxAlignmentWidthAffine != maxAlignmentWidthLinear) ? maxAlignmentWidthAffine : null; + } + @Override public VJCClonalAlignerParameters clone() { - return new VJCClonalAlignerParameters(featureToAlign, relativeMinScore, alignmentParameters.clone()); + return new VJCClonalAlignerParameters(relativeMinScore, scoring, null, maxAlignmentWidthLinear, maxAlignmentWidthAffine); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; VJCClonalAlignerParameters that = (VJCClonalAlignerParameters) o; - if (!alignmentParameters.equals(that.alignmentParameters)) return false; - - return true; + if (maxAlignmentWidthLinear != that.maxAlignmentWidthLinear) return false; + if (maxAlignmentWidthAffine != that.maxAlignmentWidthAffine) return false; + if (relativeMinScore != null ? !relativeMinScore.equals(that.relativeMinScore) : that.relativeMinScore != null) + return false; + return scoring != null ? scoring.equals(that.scoring) : that.scoring == null; } @Override public int hashCode() { - int result = super.hashCode(); - result = 31 * result + alignmentParameters.hashCode(); + int result = relativeMinScore != null ? relativeMinScore.hashCode() : 0; + result = 31 * result + (scoring != null ? scoring.hashCode() : 0); + result = 31 * result + maxAlignmentWidthLinear; + result = 31 * result + maxAlignmentWidthAffine; return result; } } diff --git a/src/main/java/com/milaboratory/mixcr/basictypes/ClonalUpdatableParameters.java b/src/main/java/com/milaboratory/mixcr/basictypes/ClonalUpdatableParameters.java new file mode 100644 index 000000000..113feb33f --- /dev/null +++ b/src/main/java/com/milaboratory/mixcr/basictypes/ClonalUpdatableParameters.java @@ -0,0 +1,12 @@ +package com.milaboratory.mixcr.basictypes; + +import com.milaboratory.mixcr.vdjaligners.ClonalGeneAlignmentParameters; + +/** + * Created by poslavsky on 01/03/2017. + */ +public interface ClonalUpdatableParameters { + void updateFrom(ClonalGeneAlignmentParameters alignerParameters); + + boolean isComplete(); +} diff --git a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java index 761183713..fe072112f 100644 --- a/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java +++ b/src/main/java/com/milaboratory/mixcr/basictypes/VDJCAlignmentsReader.java @@ -166,7 +166,7 @@ void init(Map geneFeatureRefs) { throw new RuntimeException("Absent record for " + featureDeserialized + " in geneFeatureRefs map."); } - parameters.getGeneAlignerParameters(gt).setGeneFeatureToAlign(featureParams); +// parameters.getGeneAlignerParameters(gt).setGeneFeatureToAlign(featureParams); if (featureDeserialized != null) input.putKnownReference(featureParams); diff --git a/src/main/java/com/milaboratory/mixcr/cli/ActionAssemble.java b/src/main/java/com/milaboratory/mixcr/cli/ActionAssemble.java index 89a178c46..be88e1fb1 100644 --- a/src/main/java/com/milaboratory/mixcr/cli/ActionAssemble.java +++ b/src/main/java/com/milaboratory/mixcr/cli/ActionAssemble.java @@ -45,8 +45,6 @@ import com.milaboratory.mixcr.vdjaligners.VDJCAlignerParameters; import com.milaboratory.primitivio.PipeWriter; import com.milaboratory.util.SmartProgressReporter; -import io.repseq.core.GeneFeature; -import io.repseq.core.GeneType; import io.repseq.core.VDJCGene; import io.repseq.core.VDJCLibraryRegistry; @@ -67,7 +65,7 @@ public void go(ActionHelper helper) throws Exception { // Extracting V/D/J/C gene list from input vdjca file final List genes; final VDJCAlignerParameters alignerParameters; - try (VDJCAlignmentsReader reader = new VDJCAlignmentsReader(actionParameters.getInputFileName(), + try(VDJCAlignmentsReader reader = new VDJCAlignmentsReader(actionParameters.getInputFileName(), VDJCLibraryRegistry.getDefault())) { genes = reader.getUsedGenes(); // Saving aligner parameters to correct assembler parameters @@ -79,6 +77,8 @@ public void go(ActionHelper helper) throws Exception { VDJCLibraryRegistry.getDefault()); CloneAssemblerParameters assemblerParameters = actionParameters.getCloneAssemblerParameters(); + //set aligner parameters + assemblerParameters.updateFrom(alignerParameters); // Overriding JSON parameters if (!actionParameters.overrides.isEmpty()) { @@ -90,19 +90,9 @@ public void go(ActionHelper helper) throws Exception { } } - // Adjusting features to align for correct processing - for (GeneType geneType : GeneType.values()) { - GeneFeature featureAssemble = assemblerParameters.getCloneFactoryParameters().getFeatureToAlign(geneType); - GeneFeature featureAlignment = alignerParameters.getFeatureToAlign(geneType); - if (featureAssemble == null || featureAlignment == null) - continue; - GeneFeature intersection = GeneFeature.intersection(featureAlignment, featureAssemble); - assemblerParameters.getCloneFactoryParameters().setFeatureToAlign(geneType, intersection); - } - // Performing assembly - try (CloneAssembler assembler = new CloneAssembler(assemblerParameters, - actionParameters.readsToClonesMapping != null, genes)) { + try(CloneAssembler assembler = new CloneAssembler(assemblerParameters, + actionParameters.readsToClonesMapping != null, genes, alignerParameters.getFeaturesToAlignMap())) { // Creating event listener to collect run statistics CloneAssemblerReport report = new CloneAssemblerReport(); assembler.setListener(report); @@ -122,7 +112,7 @@ public void go(ActionHelper helper) throws Exception { chainsStatistics.put(clone); // Writing results - try (CloneSetIO.CloneSetWriter writer = new CloneSetIO.CloneSetWriter(cloneSet, actionParameters.getOutputFileName())) { + try(CloneSetIO.CloneSetWriter writer = new CloneSetIO.CloneSetWriter(cloneSet, actionParameters.getOutputFileName())) { SmartProgressReporter.startProgressReport(writer); writer.write(); } @@ -144,7 +134,7 @@ public void go(ActionHelper helper) throws Exception { // Writing raw events (not documented feature) if (actionParameters.events != null) - try (PipeWriter writer = new PipeWriter<>(actionParameters.events)) { + try(PipeWriter writer = new PipeWriter<>(actionParameters.events)) { CUtils.drain(assembler.getAssembledReadsPort(), writer); } diff --git a/src/main/java/com/milaboratory/mixcr/util/RunMiXCR.java b/src/main/java/com/milaboratory/mixcr/util/RunMiXCR.java index 052da3bc9..968912d6c 100644 --- a/src/main/java/com/milaboratory/mixcr/util/RunMiXCR.java +++ b/src/main/java/com/milaboratory/mixcr/util/RunMiXCR.java @@ -51,7 +51,7 @@ public final class RunMiXCR { public static AssembleResult assemble(final AlignResult align) { RunMiXCRAnalysis parameters = align.parameters; try (CloneAssembler assembler = new CloneAssembler(parameters.cloneAssemblerParameters, - false, align.usedGenes)) { + false, align.usedGenes, align.parameters.alignerParameters)) { CloneAssemblerReport report = new CloneAssemblerReport(); assembler.setListener(report); diff --git a/src/main/java/com/milaboratory/mixcr/vdjaligners/ClonalGeneAlignmentParameters.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/ClonalGeneAlignmentParameters.java new file mode 100644 index 000000000..6b0a1f221 --- /dev/null +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/ClonalGeneAlignmentParameters.java @@ -0,0 +1,15 @@ +package com.milaboratory.mixcr.vdjaligners; + +import com.milaboratory.core.alignment.AlignmentScoring; +import com.milaboratory.core.sequence.NucleotideSequence; + +/** + * Created by poslavsky on 01/03/2017. + */ +public interface ClonalGeneAlignmentParameters { + float getRelativeMinScore(); + + AlignmentScoring getScoring(); + + ClonalGeneAlignmentParameters clone(); +} diff --git a/src/main/java/com/milaboratory/mixcr/vdjaligners/DAlignerParameters.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/DAlignerParameters.java index e644a2b9a..c7384ee00 100644 --- a/src/main/java/com/milaboratory/mixcr/vdjaligners/DAlignerParameters.java +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/DAlignerParameters.java @@ -28,74 +28,58 @@ */ package com.milaboratory.mixcr.vdjaligners; -import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.milaboratory.core.alignment.AlignmentScoring; import com.milaboratory.core.sequence.NucleotideSequence; +import com.milaboratory.mixcr.assembler.DClonalAlignerParameters; import io.repseq.core.GeneFeature; +import io.repseq.core.GeneType; -@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, - getterVisibility = JsonAutoDetect.Visibility.NONE) -public final class DAlignerParameters extends GeneAlignmentParameters - implements java.io.Serializable { - private float absoluteMinScore, relativeMinScore; - private int maxHits; - private AlignmentScoring scoring; +public final class DAlignerParameters extends DClonalAlignerParameters + implements GeneAlignmentParameters, java.io.Serializable { + private GeneFeature geneFeatureToAlign; @JsonCreator public DAlignerParameters( @JsonProperty("geneFeatureToAlign") GeneFeature geneFeatureToAlign, - @JsonProperty("absoluteMinScore") float absoluteMinScore, - @JsonProperty("relativeMinScore") float relativeMinScore, - @JsonProperty("maxHits") int maxHits, - @JsonProperty("scoring") AlignmentScoring scoring) { - super(geneFeatureToAlign); - this.absoluteMinScore = absoluteMinScore; - this.relativeMinScore = relativeMinScore; - this.maxHits = maxHits; - this.scoring = scoring; + @JsonProperty("relativeMinScore") Float relativeMinScore, + @JsonProperty("absoluteMinScore") Float absoluteMinScore, + @JsonProperty("maxHits") Integer maxHits, + @JsonProperty("scoring") AlignmentScoring scoring) { + super(relativeMinScore, absoluteMinScore, maxHits, scoring); + this.geneFeatureToAlign = geneFeatureToAlign; } - public AlignmentScoring getScoring() { - return scoring; - } - - public DAlignerParameters setScoring(AlignmentScoring scoring) { - this.scoring = scoring; - return this; - } - - public float getAbsoluteMinScore() { - return absoluteMinScore; + @Override + public GeneFeature getGeneFeatureToAlign() { + return geneFeatureToAlign; } - public DAlignerParameters setAbsoluteMinScore(float absoluteMinScore) { - this.absoluteMinScore = absoluteMinScore; + public DAlignerParameters setGeneFeatureToAlign(GeneFeature geneFeatureToAlign) { + this.geneFeatureToAlign = geneFeatureToAlign; return this; } - public float getRelativeMinScore() { - return relativeMinScore; + @Override + public GeneType getGeneType() { + return GeneType.Diversity; } - public DAlignerParameters setRelativeMinScore(float relativeMinScore) { - this.relativeMinScore = relativeMinScore; - return this; + @Override + public void updateFrom(ClonalGeneAlignmentParameters alignerParameters) { + throw new IllegalStateException(); } - public int getMaxHits() { - return maxHits; + @Override + public boolean isComplete() { + throw new IllegalStateException(); } - public DAlignerParameters setMaxHits(int maxHits) { - this.maxHits = maxHits; - return this; - } @Override public DAlignerParameters clone() { - return new DAlignerParameters(geneFeatureToAlign, absoluteMinScore, relativeMinScore, maxHits, scoring); + return new DAlignerParameters(geneFeatureToAlign, relativeMinScore, absoluteMinScore, maxHits, scoring); } @Override @@ -111,26 +95,18 @@ public String toString() { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof DAlignerParameters)) return false; + if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; DAlignerParameters that = (DAlignerParameters) o; - if (Float.compare(that.absoluteMinScore, absoluteMinScore) != 0) return false; - if (maxHits != that.maxHits) return false; - if (Float.compare(that.relativeMinScore, relativeMinScore) != 0) return false; - if (!scoring.equals(that.scoring)) return false; - - return true; + return geneFeatureToAlign != null ? geneFeatureToAlign.equals(that.geneFeatureToAlign) : that.geneFeatureToAlign == null; } @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + (absoluteMinScore != +0.0f ? Float.floatToIntBits(absoluteMinScore) : 0); - result = 31 * result + (relativeMinScore != +0.0f ? Float.floatToIntBits(relativeMinScore) : 0); - result = 31 * result + maxHits; - result = 31 * result + scoring.hashCode(); + result = 31 * result + (geneFeatureToAlign != null ? geneFeatureToAlign.hashCode() : 0); return result; } } diff --git a/src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParameters.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParameters.java index 74982b956..10e9b0d90 100644 --- a/src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParameters.java +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParameters.java @@ -1,73 +1,16 @@ -/* - * Copyright (c) 2014-2015, Bolotin Dmitry, Chudakov Dmitry, Shugay Mikhail - * (here and after addressed as Inventors) - * All Rights Reserved - * - * Permission to use, copy, modify and distribute any part of this program for - * educational, research and non-profit purposes, by non-profit institutions - * only, without fee, and without a written agreement is hereby granted, - * provided that the above copyright notice, this paragraph and the following - * three paragraphs appear in all copies. - * - * Those desiring to incorporate this work into commercial products or use for - * commercial purposes should contact the Inventors using one of the following - * email addresses: chudakovdm@mail.ru, chudakovdm@gmail.com - * - * IN NO EVENT SHALL THE INVENTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, - * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, - * ARISING OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE INVENTORS HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE SOFTWARE PROVIDED HEREIN IS ON AN "AS IS" BASIS, AND THE INVENTORS HAS - * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - * MODIFICATIONS. THE INVENTORS MAKES NO REPRESENTATIONS AND EXTENDS NO - * WARRANTIES OF ANY KIND, EITHER IMPLIED OR EXPRESS, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A - * PARTICULAR PURPOSE, OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY - * PATENT, TRADEMARK OR OTHER RIGHTS. - */ package com.milaboratory.mixcr.vdjaligners; import io.repseq.core.GeneFeature; import io.repseq.core.GeneType; -public abstract class GeneAlignmentParameters> - implements java.io.Serializable { - protected GeneFeature geneFeatureToAlign; - - protected GeneAlignmentParameters(GeneFeature geneFeatureToAlign) { - this.geneFeatureToAlign = geneFeatureToAlign; - } - - public GeneFeature getGeneFeatureToAlign() { - return geneFeatureToAlign; - } - - public T setGeneFeatureToAlign(GeneFeature geneFeatureToAlign) { - this.geneFeatureToAlign = geneFeatureToAlign; - return (T) this; - } - - public GeneType getGeneType() { - return geneFeatureToAlign.getGeneType(); - } - - public abstract T clone(); - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof GeneAlignmentParameters)) return false; - - GeneAlignmentParameters that = (GeneAlignmentParameters) o; - - if (!geneFeatureToAlign.equals(that.geneFeatureToAlign)) return false; +/** + * Created by poslavsky on 01/03/2017. + */ +public interface GeneAlignmentParameters extends ClonalGeneAlignmentParameters { + GeneFeature getGeneFeatureToAlign(); - return true; - } + GeneType getGeneType(); @Override - public int hashCode() { - return geneFeatureToAlign.hashCode(); - } + GeneAlignmentParameters clone(); } diff --git a/src/main/java/com/milaboratory/mixcr/assembler/AbstractClonalAlignerParameters.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParametersAbstract.java similarity index 61% rename from src/main/java/com/milaboratory/mixcr/assembler/AbstractClonalAlignerParameters.java rename to src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParametersAbstract.java index 33eb350c7..b17a48714 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/AbstractClonalAlignerParameters.java +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParametersAbstract.java @@ -26,39 +26,45 @@ * PARTICULAR PURPOSE, OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY * PATENT, TRADEMARK OR OTHER RIGHTS. */ -package com.milaboratory.mixcr.assembler; +package com.milaboratory.mixcr.vdjaligners; +import com.milaboratory.mixcr.basictypes.ClonalUpdatableParameters; import io.repseq.core.GeneFeature; +import io.repseq.core.GeneType; -public abstract class AbstractClonalAlignerParameters> - implements java.io.Serializable { - protected float relativeMinScore; - protected GeneFeature featureToAlign; +public abstract class GeneAlignmentParametersAbstract> + implements java.io.Serializable, GeneAlignmentParameters { + protected GeneFeature geneFeatureToAlign; + protected Float relativeMinScore; - protected AbstractClonalAlignerParameters() { + protected GeneAlignmentParametersAbstract(GeneFeature geneFeatureToAlign, Float relativeMinScore) { + this.geneFeatureToAlign = geneFeatureToAlign; + this.relativeMinScore = relativeMinScore; } - protected AbstractClonalAlignerParameters(GeneFeature featureToAlign, float relativeMinScore) { + public T setRelativeMinScore(float relativeMinScore) { this.relativeMinScore = relativeMinScore; - this.featureToAlign = featureToAlign; + return (T) this; } + @Override public float getRelativeMinScore() { return relativeMinScore; } - public T setRelativeMinScore(float relativeMinScore) { - this.relativeMinScore = relativeMinScore; - return (T) this; + @Override + public GeneFeature getGeneFeatureToAlign() { + return geneFeatureToAlign; } - public GeneFeature getFeatureToAlign() { - return featureToAlign; + public T setGeneFeatureToAlign(GeneFeature geneFeatureToAlign) { + this.geneFeatureToAlign = geneFeatureToAlign; + return (T) this; } - public T setFeatureToAlign(GeneFeature featureToAlign) { - this.featureToAlign = featureToAlign; - return (T) this; + @Override + public GeneType getGeneType() { + return geneFeatureToAlign.getGeneType(); } public abstract T clone(); @@ -66,20 +72,18 @@ public T setFeatureToAlign(GeneFeature featureToAlign) { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof AbstractClonalAlignerParameters)) return false; + if (o == null || getClass() != o.getClass()) return false; - AbstractClonalAlignerParameters that = (AbstractClonalAlignerParameters) o; + GeneAlignmentParametersAbstract that = (GeneAlignmentParametersAbstract) o; if (Float.compare(that.relativeMinScore, relativeMinScore) != 0) return false; - if (!featureToAlign.equals(that.featureToAlign)) return false; - - return true; + return geneFeatureToAlign != null ? geneFeatureToAlign.equals(that.geneFeatureToAlign) : that.geneFeatureToAlign == null; } @Override public int hashCode() { - int result = (relativeMinScore != +0.0f ? Float.floatToIntBits(relativeMinScore) : 0); - result = 31 * result + featureToAlign.hashCode(); + int result = geneFeatureToAlign != null ? geneFeatureToAlign.hashCode() : 0; + result = 31 * result + (relativeMinScore != +0.0f ? Float.floatToIntBits(relativeMinScore) : 0); return result; } } diff --git a/src/main/java/com/milaboratory/mixcr/vdjaligners/KGeneAlignmentParameters.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/KGeneAlignmentParameters.java index c6156f696..52759dd15 100644 --- a/src/main/java/com/milaboratory/mixcr/vdjaligners/KGeneAlignmentParameters.java +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/KGeneAlignmentParameters.java @@ -31,18 +31,18 @@ import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import com.milaboratory.core.alignment.batch.BatchAlignerWithBaseParameters; +import com.milaboratory.core.alignment.AlignmentScoring; import com.milaboratory.core.alignment.kaligner1.AbstractKAlignerParameters; import com.milaboratory.core.alignment.kaligner1.KAlignerParameters; +import com.milaboratory.core.sequence.NucleotideSequence; import io.repseq.core.GeneFeature; @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE) -public final class KGeneAlignmentParameters extends GeneAlignmentParameters +public final class KGeneAlignmentParameters extends GeneAlignmentParametersAbstract implements java.io.Serializable { private AbstractKAlignerParameters parameters; private int minSumScore; - private float relativeMinScore; @JsonCreator public KGeneAlignmentParameters( @@ -50,22 +50,11 @@ public KGeneAlignmentParameters( @JsonProperty("minSumScore") int minSumScore, @JsonProperty("relativeMinScore") float relativeMinScore, @JsonProperty("parameters") AbstractKAlignerParameters parameters) { - super(geneFeatureToAlign); + super(geneFeatureToAlign, relativeMinScore); this.minSumScore = minSumScore; - this.relativeMinScore = relativeMinScore; this.parameters = parameters; } - - public KGeneAlignmentParameters setRelativeMinScore(float relativeMinScore) { - this.relativeMinScore = relativeMinScore; - return this; - } - - public float getRelativeMinScore() { - return relativeMinScore; - } - public int getMinSumScore() { return minSumScore; } @@ -89,6 +78,11 @@ public KGeneAlignmentParameters clone() { return new KGeneAlignmentParameters(geneFeatureToAlign, minSumScore, relativeMinScore, parameters.clone()); } + @Override + public AlignmentScoring getScoring() { + return parameters.getScoring(); + } + @Override public String toString() { return "KGeneAlignmentParameters{" + @@ -107,17 +101,14 @@ public boolean equals(Object o) { KGeneAlignmentParameters that = (KGeneAlignmentParameters) o; if (minSumScore != that.minSumScore) return false; - if (Float.compare(that.relativeMinScore, relativeMinScore) != 0) return false; - return parameters.equals(that.parameters); - + return parameters != null ? parameters.equals(that.parameters) : that.parameters == null; } @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + parameters.hashCode(); + result = 31 * result + (parameters != null ? parameters.hashCode() : 0); result = 31 * result + minSumScore; - result = 31 * result + (relativeMinScore != +0.0f ? Float.floatToIntBits(relativeMinScore) : 0); return result; } } diff --git a/src/main/java/com/milaboratory/mixcr/vdjaligners/SingleDAligner.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/SingleDAligner.java index ed7728347..21fc45f77 100644 --- a/src/main/java/com/milaboratory/mixcr/vdjaligners/SingleDAligner.java +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/SingleDAligner.java @@ -35,6 +35,7 @@ import com.milaboratory.core.alignment.Alignment; import com.milaboratory.core.alignment.AlignmentScoring; import com.milaboratory.core.sequence.NucleotideSequence; +import com.milaboratory.mixcr.assembler.DClonalAlignerParameters; import com.milaboratory.mixcr.basictypes.VDJCHit; import io.repseq.core.Chains; import io.repseq.core.GeneFeature; @@ -67,11 +68,16 @@ public List load(NucleotideSequence key) { public SingleDAligner(DAlignerParameters parameters, List genes) { + this(parameters, parameters.getGeneFeatureToAlign(), genes); + } + + public SingleDAligner(DClonalAlignerParameters parameters, GeneFeature geneFeature, + List genes) { this.scoring = parameters.getScoring(); this.absoluteMinScore = parameters.getAbsoluteMinScore(); this.relativeMinScore = parameters.getRelativeMinScore(); this.maxHits = parameters.getMaxHits(); - this.featureToAlign = parameters.getGeneFeatureToAlign(); + this.featureToAlign = geneFeature; for (VDJCGene gene : genes) sequences.add(new SequenceWithChains(gene, featureToAlign)); this.genes = new ArrayList<>(genes); diff --git a/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerParameters.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerParameters.java index c0a350821..51c6c3645 100644 --- a/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerParameters.java +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerParameters.java @@ -260,6 +260,13 @@ public GeneFeature getFeatureToAlign(GeneType type) { return params == null ? null : params.getGeneFeatureToAlign(); } + public EnumMap getFeaturesToAlignMap(){ + EnumMap res = new EnumMap<>(GeneType.class); + for (GeneType gt : GeneType.VDJC_REFERENCE) + res.put(gt,getFeatureToAlign(gt)); + return res; + } + protected EnumMap getCloneOfAlignmentParameters() { EnumMap map = new EnumMap(GeneType.class); for (Map.Entry entry : alignmentParameters.entrySet()) diff --git a/src/main/resources/parameters/assembler_parameters.json b/src/main/resources/parameters/assembler_parameters.json index c6a79a18e..d20607de8 100644 --- a/src/main/resources/parameters/assembler_parameters.json +++ b/src/main/resources/parameters/assembler_parameters.json @@ -19,130 +19,31 @@ }, "cloneFactoryParameters": { "vParameters": { - "featureToAlign": "VTranscriptWithP", - "relativeMinScore": 0.8, - "alignmentParameters": { - "scoring": { - "type": "linear", - "subsMatrix": "simple(match = 5, mismatch = -9)", - "gapPenalty": -12 - }, - "width": 5, - "stopPenalty": -1500 - } + "maxAlignmentWidth": null, + "maxAlignmentWidthLinear" : 5, + "maxAlignmentWidthAffine" : 500, + "relativeMinScore": null, + "scoring": null }, "jParameters": { - "featureToAlign": "JRegionWithP", - "relativeMinScore": 0.8, - "alignmentParameters": { - "scoring": { - "type": "linear", - "subsMatrix": "simple(match = 5, mismatch = -9)", - "gapPenalty": -12 - }, - "width": 5, - "stopPenalty": -1500 - } + "maxAlignmentWidth": null, + "maxAlignmentWidthLinear" : 5, + "maxAlignmentWidthAffine" : 500, + "relativeMinScore": null, + "scoring": null }, "dParameters": { - "geneFeatureToAlign": "DRegionWithP", - "absoluteMinScore": 25.0, - "relativeMinScore": 0.85, - "maxHits": 3, - "scoring": { - "type": "linear", - "subsMatrix": "simple(match = 5, mismatch = -9)", - "gapPenalty": -12 - } + "absoluteMinScore": null, + "relativeMinScore": null, + "maxHits": null, + "scoring": null }, "cParameters": { - "featureToAlign": "CExon1", - "relativeMinScore": 0.8, - "alignmentParameters": { - "scoring": { - "type": "linear", - "subsMatrix": "simple(match = 5, mismatch = -9)", - "gapPenalty": -12 - }, - "width": 5 - } - } - }, - "addReadsCountOnClustering": false, - "badQualityThreshold": 20, - "maxBadPointsPercent": 0.7, - "mappingThreshold": "2of5" - }, - "default_affine": { - "assemblingFeatures": ["CDR3"], - "minimalQuality" : 0, - "minimalClonalSequenceLength": 12, - "qualityAggregationType": "Max", - "separateByV": false, - "separateByJ": false, - "separateByC": false, - "maximalPreClusteringRatio": 1.0, - "cloneClusteringParameters": { - "searchDepth": 2, - "allowedMutationsInNRegions": 1, - "searchParameters": "twoMismatchesOrIndels", - "clusteringFilter": { - "type": "relativeConcentration", - "specificMutationProbability": 1E-3 - } - }, - "cloneFactoryParameters": { - "vParameters": { - "featureToAlign": "VTranscriptWithP", - "relativeMinScore": 0.8, - "alignmentParameters": { - "scoring" : { - "type" : "affine", - "subsMatrix" : "simple(match = 10, mismatch = -19)", - "gapOpenPenalty" : -40, - "gapExtensionPenalty" : -11 - }, - "width": 500, - "stopPenalty": 0 - } - }, - "jParameters": { - "featureToAlign": "JRegionWithP", - "relativeMinScore": 0.8, - "alignmentParameters": { - "scoring" : { - "type" : "affine", - "subsMatrix" : "simple(match = 10, mismatch = -19)", - "gapOpenPenalty" : -40, - "gapExtensionPenalty" : -11 - }, - "width": 500, - "stopPenalty": 0 - } - }, - "dParameters": { - "geneFeatureToAlign": "DRegionWithP", - "absoluteMinScore": 25.0, - "relativeMinScore": 0.85, - "maxHits": 3, - "scoring" : { - "type" : "affine", - "subsMatrix" : "simple(match = 10, mismatch = -30)", - "gapOpenPenalty" : -40, - "gapExtensionPenalty" : -10 - } - }, - "cParameters": { - "featureToAlign": "CExon1", - "relativeMinScore": 0.8, - "alignmentParameters": { - "scoring": { - "type": "linear", - "subsMatrix": "simple(match = 5, mismatch = -9)", - "gapPenalty": -12 - }, - "width": 5 - } + "maxAlignmentWidth": null, + "maxAlignmentWidthLinear" : 5, + "maxAlignmentWidthAffine" : 500, + "relativeMinScore": null, + "scoring": null } }, "addReadsCountOnClustering": false, diff --git a/src/test/java/com/milaboratory/mixcr/assembler/CloneAssemblerParametersTest.java b/src/test/java/com/milaboratory/mixcr/assembler/CloneAssemblerParametersTest.java index c35b73617..adc1d1c5d 100644 --- a/src/test/java/com/milaboratory/mixcr/assembler/CloneAssemblerParametersTest.java +++ b/src/test/java/com/milaboratory/mixcr/assembler/CloneAssemblerParametersTest.java @@ -45,11 +45,11 @@ public class CloneAssemblerParametersTest { @Test public void test1() throws Exception { CloneFactoryParameters factoryParameters = new CloneFactoryParameters( - new VJCClonalAlignerParameters(GeneFeature.VRegion, 0.3f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3, -50)), - new VJCClonalAlignerParameters(GeneFeature.JRegion, 0.4f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5, -40)), - null, new DAlignerParameters(GeneFeature.DRegion, 30.0f, 0.85f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) + new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3), + new VJCClonalAlignerParameters(0.4f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5), + null, new DClonalAlignerParameters(0.85f, 30.0f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) ); CloneAssemblerParameters params = new CloneAssemblerParameters(new GeneFeature[]{GeneFeature.FR1, GeneFeature.CDR3}, 12, @@ -73,11 +73,11 @@ null, new DAlignerParameters(GeneFeature.DRegion, 30.0f, 0.85f, 3, AffineGapAlig @Test public void test2() throws Exception { CloneFactoryParameters factoryParameters = new CloneFactoryParameters( - new VJCClonalAlignerParameters(GeneFeature.VRegion, 0.3f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3, -50)), - new VJCClonalAlignerParameters(GeneFeature.JRegion, 0.4f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5, -40)), - null, new DAlignerParameters(GeneFeature.DRegion, 30.0f, 0.85f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) + new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3), + new VJCClonalAlignerParameters(0.4f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5), + null, new DClonalAlignerParameters(0.85f, 30.0f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) ); CloneAssemblerParameters params = new CloneAssemblerParameters(new GeneFeature[]{GeneFeature.FR1, GeneFeature.CDR3}, 12, diff --git a/src/test/java/com/milaboratory/mixcr/assembler/CloneAssemblerRunnerTest.java b/src/test/java/com/milaboratory/mixcr/assembler/CloneAssemblerRunnerTest.java index 6a0e39d09..6b2d40304 100644 --- a/src/test/java/com/milaboratory/mixcr/assembler/CloneAssemblerRunnerTest.java +++ b/src/test/java/com/milaboratory/mixcr/assembler/CloneAssemblerRunnerTest.java @@ -30,7 +30,6 @@ import cc.redberry.pipe.CUtils; import cc.redberry.pipe.OutputPortCloseable; -import com.milaboratory.core.alignment.BandedAlignerParameters; import com.milaboratory.core.alignment.LinearGapAlignmentScoring; import com.milaboratory.core.io.sequence.SequenceRead; import com.milaboratory.core.io.sequence.SequenceReader; @@ -94,7 +93,7 @@ private static CloneSet runFullPipeline(String... fastqFiles) throws IOException //write alignments to byte array ByteArrayOutputStream alignmentsSerialized = new ByteArrayOutputStream(); - try (VDJCAlignmentsWriter writer = new VDJCAlignmentsWriter(alignmentsSerialized)) { + try(VDJCAlignmentsWriter writer = new VDJCAlignmentsWriter(alignmentsSerialized)) { writer.header(aligner); for (Object read : CUtils.it(reader)) { VDJCAlignmentResult result = (VDJCAlignmentResult) aligner.process((SequenceRead) read); @@ -109,12 +108,12 @@ private static CloneSet runFullPipeline(String... fastqFiles) throws IOException LinearGapAlignmentScoring scoring = new LinearGapAlignmentScoring<>(NucleotideSequence.ALPHABET, 5, -9, -12); CloneFactoryParameters factoryParameters = new CloneFactoryParameters( - new VJCClonalAlignerParameters(GeneFeature.VRegion, 0.8f, - new BandedAlignerParameters(scoring, 5, -150)), - new VJCClonalAlignerParameters(GeneFeature.JRegion, 0.8f, - new BandedAlignerParameters(scoring, 5, -150)), + new VJCClonalAlignerParameters(0.8f, + scoring, 5), + new VJCClonalAlignerParameters(0.8f, + scoring, 5), null, - new DAlignerParameters(GeneFeature.DRegion, 30.0f, 0.85f, 3, scoring) + new DAlignerParameters(GeneFeature.DRegion, 0.85f, 30.0f, 3, scoring) ); CloneAssemblerParameters assemblerParameters = new CloneAssemblerParameters( @@ -126,7 +125,7 @@ private static CloneSet runFullPipeline(String... fastqFiles) throws IOException System.out.println(GlobalObjectMappers.toOneLine(assemblerParameters)); CloneAssemblerRunner assemblerRunner = new CloneAssemblerRunner(alignmentsProvider, - new CloneAssembler(assemblerParameters, true, aligner.getUsedGenes()), 2); + new CloneAssembler(assemblerParameters, true, aligner.getUsedGenes(), alignerParameters), 2); SmartProgressReporter.startProgressReport(assemblerRunner); assemblerRunner.run(); diff --git a/src/test/java/com/milaboratory/mixcr/assembler/CloneFactoryParametersTest.java b/src/test/java/com/milaboratory/mixcr/assembler/CloneFactoryParametersTest.java index 8c3c21972..1eba040f6 100644 --- a/src/test/java/com/milaboratory/mixcr/assembler/CloneFactoryParametersTest.java +++ b/src/test/java/com/milaboratory/mixcr/assembler/CloneFactoryParametersTest.java @@ -31,9 +31,9 @@ import com.milaboratory.core.alignment.AffineGapAlignmentScoring; import com.milaboratory.core.alignment.BandedAlignerParameters; import com.milaboratory.core.alignment.LinearGapAlignmentScoring; -import io.repseq.core.GeneFeature; import com.milaboratory.mixcr.vdjaligners.DAlignerParameters; import com.milaboratory.util.GlobalObjectMappers; +import io.repseq.core.GeneFeature; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -43,13 +43,13 @@ public class CloneFactoryParametersTest { @Test public void test1() throws Exception { CloneFactoryParameters paramentrs = new CloneFactoryParameters( - new VJCClonalAlignerParameters(GeneFeature.VRegion, 0.3f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3, -50)), - new VJCClonalAlignerParameters(GeneFeature.JRegion, 0.4f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5, -40)), - new VJCClonalAlignerParameters(GeneFeature.CExon1, 0.2f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 9, -30)), - new DAlignerParameters(GeneFeature.DRegion, 30.0f, 0.85f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) + new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3), + new VJCClonalAlignerParameters(0.4f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5), + new VJCClonalAlignerParameters(0.2f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 9), + new DClonalAlignerParameters(0.85f, 30.0f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) ); String str = GlobalObjectMappers.PRETTY.writeValueAsString(paramentrs); //System.out.println(str); @@ -64,11 +64,11 @@ public void test1() throws Exception { @Test public void test2() throws Exception { CloneFactoryParameters paramentrs = new CloneFactoryParameters( - new VJCClonalAlignerParameters(GeneFeature.VRegion, 0.3f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3, -50)), - new VJCClonalAlignerParameters(GeneFeature.JRegion, 0.4f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5, -40)), - null, new DAlignerParameters(GeneFeature.DRegion, 30.0f, 0.85f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) + new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3), + new VJCClonalAlignerParameters(0.4f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5), + null, new DClonalAlignerParameters(0.85f, 30.0f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) ); String str = GlobalObjectMappers.PRETTY.writeValueAsString(paramentrs); //System.out.println(str); diff --git a/src/test/java/com/milaboratory/mixcr/assembler/DClonalAlignerParametersTest.java b/src/test/java/com/milaboratory/mixcr/assembler/DClonalAlignerParametersTest.java deleted file mode 100644 index 2faf499f6..000000000 --- a/src/test/java/com/milaboratory/mixcr/assembler/DClonalAlignerParametersTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2014-2015, Bolotin Dmitry, Chudakov Dmitry, Shugay Mikhail - * (here and after addressed as Inventors) - * All Rights Reserved - * - * Permission to use, copy, modify and distribute any part of this program for - * educational, research and non-profit purposes, by non-profit institutions - * only, without fee, and without a written agreement is hereby granted, - * provided that the above copyright notice, this paragraph and the following - * three paragraphs appear in all copies. - * - * Those desiring to incorporate this work into commercial products or use for - * commercial purposes should contact the Inventors using one of the following - * email addresses: chudakovdm@mail.ru, chudakovdm@gmail.com - * - * IN NO EVENT SHALL THE INVENTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, - * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, - * ARISING OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE INVENTORS HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE SOFTWARE PROVIDED HEREIN IS ON AN "AS IS" BASIS, AND THE INVENTORS HAS - * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - * MODIFICATIONS. THE INVENTORS MAKES NO REPRESENTATIONS AND EXTENDS NO - * WARRANTIES OF ANY KIND, EITHER IMPLIED OR EXPRESS, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A - * PARTICULAR PURPOSE, OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY - * PATENT, TRADEMARK OR OTHER RIGHTS. - */ -package com.milaboratory.mixcr.assembler; - -import com.milaboratory.core.alignment.LinearGapAlignmentScoring; -import io.repseq.core.GeneFeature; -import com.milaboratory.util.GlobalObjectMappers; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class DClonalAlignerParametersTest { - @Test - public void test1() throws Exception { - DClonalAlignerParameters paramentrs = new DClonalAlignerParameters(0.3f, GeneFeature.DRegion, - LinearGapAlignmentScoring.getNucleotideBLASTScoring()); - String str = GlobalObjectMappers.PRETTY.writeValueAsString(paramentrs); - DClonalAlignerParameters deser = GlobalObjectMappers.PRETTY.readValue(str, DClonalAlignerParameters.class); - assertEquals(paramentrs, deser); - assertEquals(paramentrs, deser.clone()); - } -} \ No newline at end of file diff --git a/src/test/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParametersTest.java b/src/test/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParametersTest.java index 030a3333c..9ab5998dd 100644 --- a/src/test/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParametersTest.java +++ b/src/test/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParametersTest.java @@ -28,9 +28,8 @@ */ package com.milaboratory.mixcr.assembler; -import com.milaboratory.core.alignment.BandedAlignerParameters; import com.milaboratory.core.alignment.LinearGapAlignmentScoring; -import io.repseq.core.GeneFeature; +import com.milaboratory.test.TestUtil; import com.milaboratory.util.GlobalObjectMappers; import org.junit.Test; @@ -39,11 +38,23 @@ public class VJCClonalAlignerParametersTest { @Test public void test1() throws Exception { - VJCClonalAlignerParameters paramentrs = new VJCClonalAlignerParameters(GeneFeature.VRegion, 0.3f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3, -50)); + VJCClonalAlignerParameters paramentrs = new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3); String str = GlobalObjectMappers.PRETTY.writeValueAsString(paramentrs); VJCClonalAlignerParameters deser = GlobalObjectMappers.PRETTY.readValue(str, VJCClonalAlignerParameters.class); assertEquals(paramentrs, deser); assertEquals(paramentrs, deser.clone()); } + + @Test + public void test2() throws Exception { + TestUtil.assertJson(new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3), true); + + TestUtil.assertJson(new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), null, 2, 3), true); + + TestUtil.assertJson(new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 1, 2, 3), true); + } } \ No newline at end of file diff --git a/src/test/java/com/milaboratory/mixcr/cli/JsonOverriderTest.java b/src/test/java/com/milaboratory/mixcr/cli/JsonOverriderTest.java index ccb28821e..7adc88232 100644 --- a/src/test/java/com/milaboratory/mixcr/cli/JsonOverriderTest.java +++ b/src/test/java/com/milaboratory/mixcr/cli/JsonOverriderTest.java @@ -29,17 +29,15 @@ package com.milaboratory.mixcr.cli; import com.milaboratory.core.alignment.AffineGapAlignmentScoring; -import com.milaboratory.core.alignment.BandedAlignerParameters; import com.milaboratory.core.alignment.LinearGapAlignmentScoring; import com.milaboratory.core.alignment.kaligner1.KAlignerParameters; import com.milaboratory.core.sequence.NucleotideSequence; import com.milaboratory.core.sequence.quality.QualityAggregationType; import com.milaboratory.core.tree.TreeSearchParameters; import com.milaboratory.mixcr.assembler.*; -import io.repseq.core.GeneFeature; -import com.milaboratory.mixcr.vdjaligners.DAlignerParameters; import com.milaboratory.mixcr.vdjaligners.VDJCAlignerParameters; import com.milaboratory.mixcr.vdjaligners.VDJCParametersPresets; +import io.repseq.core.GeneFeature; import org.junit.Assert; import org.junit.Test; @@ -89,11 +87,11 @@ public void test2() throws Exception { @Test public void testArray1() throws Exception { CloneFactoryParameters factoryParameters = new CloneFactoryParameters( - new VJCClonalAlignerParameters(GeneFeature.VRegion, 0.3f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3, -50)), - new VJCClonalAlignerParameters(GeneFeature.JRegion, 0.4f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5, -40)), - null, new DAlignerParameters(GeneFeature.DRegion, 30.0f, 0.85f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) + new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3), + new VJCClonalAlignerParameters(0.4f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5), + null, new DClonalAlignerParameters(0.85f, 30.0f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) ); CloneAssemblerParameters params = new CloneAssemblerParameters(new GeneFeature[]{GeneFeature.FR1, GeneFeature.CDR3}, 12, @@ -118,17 +116,17 @@ null, new DAlignerParameters(GeneFeature.DRegion, 30.0f, 0.85f, 3, AffineGapAlig @Test public void testCloneFactoryParameters2() throws Exception { CloneFactoryParameters factoryParameters = new CloneFactoryParameters( - new VJCClonalAlignerParameters(GeneFeature.VRegion, 0.3f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3, -50)), - new VJCClonalAlignerParameters(GeneFeature.JRegion, 0.4f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5, -40)), - null, new DAlignerParameters(GeneFeature.DRegion, 30.0f, 0.85f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) + new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3), + new VJCClonalAlignerParameters(0.4f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5), + null, new DClonalAlignerParameters(0.85f, 30.0f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) ); CloneAssemblerParameters params = new CloneAssemblerParameters(new GeneFeature[]{GeneFeature.FR1, GeneFeature.CDR3}, 12, QualityAggregationType.Average, new CloneClusteringParameters(2, 1, TreeSearchParameters.ONE_MISMATCH, new RelativeConcentrationFilter(1.0E-6)), - factoryParameters, true, true, false, 0.4, true, (byte) 20, .8, "2of6", (byte) 15); + factoryParameters, true, true, false, 0.4, true, (byte) 20, .8, "2of6", (byte) 15); CloneAssemblerParameters override = JsonOverrider.override( params, @@ -136,11 +134,11 @@ null, new DAlignerParameters(GeneFeature.DRegion, 30.0f, 0.85f, 3, AffineGapAlig "dParameters.absoluteMinScore=101"); CloneFactoryParameters expectedFactoryParameters = new CloneFactoryParameters( - new VJCClonalAlignerParameters(GeneFeature.VRegion, 0.3f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3, -50)), - new VJCClonalAlignerParameters(GeneFeature.JRegion, 0.4f, - new BandedAlignerParameters(LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5, -40)), - null, new DAlignerParameters(GeneFeature.DRegion, 101f, 0.85f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) + new VJCClonalAlignerParameters(0.3f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 3), + new VJCClonalAlignerParameters(0.4f, + LinearGapAlignmentScoring.getNucleotideBLASTScoring(), 5), + null, new DClonalAlignerParameters(0.85f, 101f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()) ); Assert.assertEquals(expectedFactoryParameters, override.getCloneFactoryParameters()); diff --git a/src/test/java/com/milaboratory/mixcr/vdjaligners/DAlignerParametersTest.java b/src/test/java/com/milaboratory/mixcr/vdjaligners/DAlignerParametersTest.java index 452d8c6c8..1d076d69b 100644 --- a/src/test/java/com/milaboratory/mixcr/vdjaligners/DAlignerParametersTest.java +++ b/src/test/java/com/milaboratory/mixcr/vdjaligners/DAlignerParametersTest.java @@ -40,7 +40,7 @@ public class DAlignerParametersTest { @Test public void test1() throws Exception { DAlignerParameters paramentrs = new DAlignerParameters(GeneFeature.DRegion, - 30.0f, 0.85f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()); + 0.85f, 30.0f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()); String str = GlobalObjectMappers.PRETTY.writeValueAsString(paramentrs); DAlignerParameters deser = GlobalObjectMappers.PRETTY.readValue(str, DAlignerParameters.class); assertEquals(paramentrs, deser); @@ -51,7 +51,7 @@ public void test1() throws Exception { @Test public void test2() throws Exception { DAlignerParameters se = new DAlignerParameters(GeneFeature.DRegion, - 30.0f, 0.85f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()); + 0.85f, 30.0f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()); IOTestUtil.assertJavaSerialization(se); } } \ No newline at end of file diff --git a/src/test/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerParametersTest.java b/src/test/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerParametersTest.java index 69b8522a5..6ddf8db31 100644 --- a/src/test/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerParametersTest.java +++ b/src/test/java/com/milaboratory/mixcr/vdjaligners/VDJCAlignerParametersTest.java @@ -49,7 +49,7 @@ public void test1() throws Exception { 1.5f, 0.75f, 1.0f, -0.1f, -0.3f, 4, 10, 15, 2, -10, 40.0f, 0.87f, 7, LinearGapAlignmentScoring.getNucleotideBLASTScoring())), new DAlignerParameters(GeneFeature.DRegion, - 30.0f, 0.85f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()), + 0.85f, 30.0f, 3, AffineGapAlignmentScoring.getNucleotideBLASTScoring()), new KGeneAlignmentParameters(GeneFeature.JRegion, 120, 0.87f, new KAlignerParameters(5, false, false, 1.5f, 0.75f, 1.0f, -0.1f, -0.3f, 4, 10, 15, 2, -10, 40.0f, 0.87f, 7, From 39170d1a97c82a22f4bf5fcf1f2f60945c75f0fd Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Wed, 1 Mar 2017 20:26:39 +0300 Subject: [PATCH 24/35] This fixes bug in exportAlignments and exportClones with default preset and additional columns. This fixes #222 --- .../com/milaboratory/mixcr/cli/ActionExportParameters.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/milaboratory/mixcr/cli/ActionExportParameters.java b/src/main/java/com/milaboratory/mixcr/cli/ActionExportParameters.java index ccd21938b..baf43d0f0 100644 --- a/src/main/java/com/milaboratory/mixcr/cli/ActionExportParameters.java +++ b/src/main/java/com/milaboratory/mixcr/cli/ActionExportParameters.java @@ -45,9 +45,9 @@ public class ActionExportParameters extends ActionParamete names = {"-l", "--loci"}, hidden = true) public String chains_legacy = null; - @Parameter(description = "Specify preset of export fields (full, min)", + @Parameter(description = "Specify preset of export fields (possible values: 'full', 'min'; 'full' by default)", names = {"-p", "--preset"}) - public String preset = "full"; + public String preset; @Parameter(description = "Specify preset file of export fields", names = {"-pf", "--preset-file"}) @@ -162,7 +162,7 @@ public static void parse(Class clazz, final String[] args, ActionExportParameter parameters.exporters = new ArrayList<>(); //if preset was explicitly specified - if (!parameters.preset.equals(DEFAULT_PRESET)) + if (parameters.preset != null) parameters.exporters.addAll(getPresetParameters(outputMode, clazz, parameters.preset)); if (parameters.presetFile != null) From 1042af3ebaa2e6474bff767d7c5c1bac352e010f Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Wed, 1 Mar 2017 20:46:27 +0300 Subject: [PATCH 25/35] This adds back positions like VEndTrimmed. Fixes #221. Docs fixed accordingly. --- doc/export.rst | 36 +++++++++++-------- .../mixcr/export/FieldExtractors.java | 18 +++++----- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/doc/export.rst b/doc/export.rst index 0d30f7d8e..6317ec869 100644 --- a/doc/export.rst +++ b/doc/export.rst @@ -175,34 +175,44 @@ The following table shows the correspondance between anchor point and positions +--------------------------+---------------------+--------------------+ | FR3End / CDR3Begin | 9 | 10 | +--------------------------+---------------------+--------------------+ -| VEnd / *PSegmentBegin* | 10 | 11 | -+--------------------------+---------------------+--------------------+ -| Number of 3' V deletions | 11 | 12 | +| Number of 3' V deletions | 10 | 11 | | (negative value), or | | | | length of 3' V P-segment | | | | (positive value) | | | +--------------------------+---------------------+--------------------+ -| Number of 5' D deletions | 12 | 13 | +| VEndTrimmed, next | 11 | 12 | +| position after last | | | +| aligned nucleotide of V | | | +| gene | | | ++--------------------------+---------------------+--------------------+ +| DBeginTrimmed, position | 12 | 13 | +| of first aligned | | | +| nucleotide of D gene | | | ++--------------------------+---------------------+--------------------+ +| Number of 5' D deletions | 13 | 14 | | (negative value), or | | | | length of 5' D P-segment | | | | (positive value) | | | +--------------------------+---------------------+--------------------+ -| DBegin / *PSegmentEnd* | 13 | 14 | -+--------------------------+---------------------+--------------------+ -| DEnd / *PSegmentBegin* | 14 | 15 | -+--------------------------+---------------------+--------------------+ -| Number of 3' D deletions | 15 | 16 | +| Number of 3' D deletions | 14 | 15 | | (negative value), or | | | | length of 3' D P-segment | | | | (positive value) | | | +--------------------------+---------------------+--------------------+ -| Number of 3' J deletions | 16 | 17 | +| DEndTrimmed, next | 15 | 16 | +| position after last | | | +| aligned nucleotide of V | | | +| gene | | | ++--------------------------+---------------------+--------------------+ +| JBeginTrimmed, position | 16 | 17 | +| of first aligned | | | +| nucleotide of J gene | | | ++--------------------------+---------------------+--------------------+ +| Number of 3' J deletions | 17 | 18 | | (negative value), or | | | | length of 3' J P-segment | | | | (positive value) | | | +--------------------------+---------------------+--------------------+ -| JBegin / *PSegmentEnd* | 17 | 18 | -+--------------------------+---------------------+--------------------+ | CDR3End / FR4Begin | 18 | 19 | +--------------------------+---------------------+--------------------+ | FR4End | 19 | 20 | @@ -212,8 +222,6 @@ The following table shows the correspondance between anchor point and positions | CExon1End | 21 | 22 | +--------------------------+---------------------+--------------------+ -Positions of anchor points like ``VEnd`` are printed only if corresponding P-segment was detected in the sequence, in this case e.g. P-segment of V gene can be found between positions of ``VEnd`` and ``VEndTrimmed``. - Examples -------- diff --git a/src/main/java/com/milaboratory/mixcr/export/FieldExtractors.java b/src/main/java/com/milaboratory/mixcr/export/FieldExtractors.java index b410b30cc..319273e61 100644 --- a/src/main/java/com/milaboratory/mixcr/export/FieldExtractors.java +++ b/src/main/java/com/milaboratory/mixcr/export/FieldExtractors.java @@ -706,15 +706,15 @@ protected String extract(VDJCObject object) { for (int j = 0; ; j++) { ReferencePoint refPoint = ReferencePoint.DefaultReferencePoints[j]; - // Processing special cases of trimmed points - if (refPoint.equals(ReferencePoint.VEndTrimmed)) - sb.append(trimmedPosition(bestVHit, i, refPoint, ReferencePoint.VEnd)); - else if (refPoint.equals(ReferencePoint.DBeginTrimmed)) - sb.append(trimmedPosition(bestDHit, i, refPoint, ReferencePoint.DBegin)); - else if (refPoint.equals(ReferencePoint.DEndTrimmed)) - sb.append(trimmedPosition(bestDHit, i, refPoint, ReferencePoint.DEnd)); - else if (refPoint.equals(ReferencePoint.JBeginTrimmed)) - sb.append(trimmedPosition(bestJHit, i, refPoint, ReferencePoint.JBegin)); + // Processing special cases for number of deleted / P-segment nucleotides + if (refPoint.equals(ReferencePoint.VEnd)) + sb.append(trimmedPosition(bestVHit, i, ReferencePoint.VEndTrimmed, ReferencePoint.VEnd)); + else if (refPoint.equals(ReferencePoint.DBegin)) + sb.append(trimmedPosition(bestDHit, i, ReferencePoint.DBeginTrimmed, ReferencePoint.DBegin)); + else if (refPoint.equals(ReferencePoint.DEnd)) + sb.append(trimmedPosition(bestDHit, i, ReferencePoint.DEndTrimmed, ReferencePoint.DEnd)); + else if (refPoint.equals(ReferencePoint.JBegin)) + sb.append(trimmedPosition(bestJHit, i, ReferencePoint.JBeginTrimmed, ReferencePoint.JBegin)); else { // Normal points From 019a9d9eb24adee7b45b0daa9e058953cb572c47 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Wed, 1 Mar 2017 20:53:10 +0300 Subject: [PATCH 26/35] Typo in doc for anchor point positions in export. --- doc/export.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/export.rst b/doc/export.rst index 6317ec869..e2e9eb5d1 100644 --- a/doc/export.rst +++ b/doc/export.rst @@ -201,7 +201,7 @@ The following table shows the correspondance between anchor point and positions +--------------------------+---------------------+--------------------+ | DEndTrimmed, next | 15 | 16 | | position after last | | | -| aligned nucleotide of V | | | +| aligned nucleotide of D | | | | gene | | | +--------------------------+---------------------+--------------------+ | JBeginTrimmed, position | 16 | 17 | From f4cb72310d0bf85b19e674fbaa036818891ece6b Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Wed, 1 Mar 2017 21:10:49 +0300 Subject: [PATCH 27/35] Changelog. --- CHANGELOG_CURRENT | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG_CURRENT b/CHANGELOG_CURRENT index 489339c8b..363dbe216 100644 --- a/CHANGELOG_CURRENT +++ b/CHANGELOG_CURRENT @@ -1,7 +1,9 @@ +Several anchor point positions in export points changed their meaning. Fixed absent space in `AA. Seq. ...` column name and excessive space in the end of several column names (affects `exportClones` and `exportAlignments` with `-v` option; fixes compatibility with VDJTools v1.1.3 and below). Fixes NPE in `exportClones` in some cases with mmu reference -`-p` option in `assemblePartial` enabled by default; deprecated, will be removed in 2.2 +`-p` option in `assemblePartial` enabled by default; deprecated; will be removed in 2.2 Added `-d` option in `assemblePartial` to drop non-assembled partial reads to reduce output file size Added `sortAlignments` action. Sort `*.vdjca` files by read id, allows diffing alignments after `assembleParial` and other actions that shuffle records inside file. +Fixed incorrect behaviour of `exportClones` and `exportAlignments` in cases like `mixcr exportAlignments -p full -descrR1 ...` minor: Multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or `-i 123,456` etc. minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both renamed to `--read-ids` \ No newline at end of file From 105f18226b160efc1a15df12716c7d9d5350a582 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Thu, 2 Mar 2017 04:05:36 +0300 Subject: [PATCH 28/35] Cosmetics --- .../assembler/DClonalAlignerParameters.java | 3 +++ .../assembler/VJCClonalAlignerParameters.java | 11 +++++++--- .../basictypes/ClonalUpdatableParameters.java | 8 ++++++++ .../ClonalGeneAlignmentParameters.java | 20 +++++++++++++++++++ .../vdjaligners/GeneAlignmentParameters.java | 11 ++++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/milaboratory/mixcr/assembler/DClonalAlignerParameters.java b/src/main/java/com/milaboratory/mixcr/assembler/DClonalAlignerParameters.java index 5393cc446..1d485527b 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/DClonalAlignerParameters.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/DClonalAlignerParameters.java @@ -9,6 +9,9 @@ import com.milaboratory.mixcr.vdjaligners.ClonalGeneAlignmentParameters; /** + * Some fields of this object might not be set, to indicate that their values must be taken from original alignment + * parameters (from *.vdjca file) + * * Created by poslavsky on 01/03/2017. */ @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, diff --git a/src/main/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParameters.java b/src/main/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParameters.java index 2b28e7f94..06ce576f5 100644 --- a/src/main/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParameters.java +++ b/src/main/java/com/milaboratory/mixcr/assembler/VJCClonalAlignerParameters.java @@ -36,6 +36,10 @@ import com.milaboratory.mixcr.basictypes.ClonalUpdatableParameters; import com.milaboratory.mixcr.vdjaligners.ClonalGeneAlignmentParameters; +/** + * Some fields of this object might not be set, to indicate that their values must be taken from original alignment + * parameters (from *.vdjca file) + */ @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE) @JsonIgnoreProperties({"featureToAlign", "alignmentParameters"}) @@ -62,11 +66,12 @@ public VJCClonalAlignerParameters( public VJCClonalAlignerParameters( @JsonProperty("relativeMinScore") Float relativeMinScore, @JsonProperty("scoring") AlignmentScoring scoring, - @JsonProperty(value = "maxAlignmentWidth") Integer maxAlignmentWidth, - @JsonProperty(value = "maxAlignmentWidthLinear") Integer maxAlignmentWidthLinear, - @JsonProperty(value = "maxAlignmentWidthAffine") Integer maxAlignmentWidthAffine) { + @JsonProperty("maxAlignmentWidth") Integer maxAlignmentWidth, + @JsonProperty("maxAlignmentWidthLinear") Integer maxAlignmentWidthLinear, + @JsonProperty("maxAlignmentWidthAffine") Integer maxAlignmentWidthAffine) { this.relativeMinScore = relativeMinScore; this.scoring = scoring; + if (maxAlignmentWidth == null && (maxAlignmentWidthAffine == null || maxAlignmentWidthLinear == null)) throw new IllegalArgumentException("maxAlignmentWidth or maxAlignmentWidthAffine and maxAlignmentWidthLinear are not specified"); diff --git a/src/main/java/com/milaboratory/mixcr/basictypes/ClonalUpdatableParameters.java b/src/main/java/com/milaboratory/mixcr/basictypes/ClonalUpdatableParameters.java index 113feb33f..94990d0b5 100644 --- a/src/main/java/com/milaboratory/mixcr/basictypes/ClonalUpdatableParameters.java +++ b/src/main/java/com/milaboratory/mixcr/basictypes/ClonalUpdatableParameters.java @@ -6,7 +6,15 @@ * Created by poslavsky on 01/03/2017. */ public interface ClonalUpdatableParameters { + /** + * Set absent parameters from ClonalGeneAlignmentParameters object + * + * @param alignerParameters + */ void updateFrom(ClonalGeneAlignmentParameters alignerParameters); + /** + * Returns true if all parameters are defined + */ boolean isComplete(); } diff --git a/src/main/java/com/milaboratory/mixcr/vdjaligners/ClonalGeneAlignmentParameters.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/ClonalGeneAlignmentParameters.java index 6b0a1f221..8f942df8d 100644 --- a/src/main/java/com/milaboratory/mixcr/vdjaligners/ClonalGeneAlignmentParameters.java +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/ClonalGeneAlignmentParameters.java @@ -4,12 +4,32 @@ import com.milaboratory.core.sequence.NucleotideSequence; /** + * Define common fields for alignment parameters for clones. + * + * ClonalGeneAlignmentParameters don't have some properties like target gene feature like {@link + * GeneAlignmentParameters}. + * * Created by poslavsky on 01/03/2017. */ public interface ClonalGeneAlignmentParameters { + /** + * Define score threshold for hits relative to top hit score. + * + * @return relative min score + */ float getRelativeMinScore(); + /** + * Alignment scoring + * + * @return alignment scoring + */ AlignmentScoring getScoring(); + /** + * Returns a copy of this object + * + * @return copy of this object + */ ClonalGeneAlignmentParameters clone(); } diff --git a/src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParameters.java b/src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParameters.java index 10e9b0d90..fa78deecd 100644 --- a/src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParameters.java +++ b/src/main/java/com/milaboratory/mixcr/vdjaligners/GeneAlignmentParameters.java @@ -4,13 +4,24 @@ import io.repseq.core.GeneType; /** + * Define additional properties required to align raw sequencing reads. + * * Created by poslavsky on 01/03/2017. */ public interface GeneAlignmentParameters extends ClonalGeneAlignmentParameters { + /** + * Part of gene to use as alignment subject (sequence1 in terms of MiLib) + */ GeneFeature getGeneFeatureToAlign(); + /** + * getGeneFeatureToAlign().getGeneType() + */ GeneType getGeneType(); + /** + * Return copy of this object + */ @Override GeneAlignmentParameters clone(); } From e99f8bf2c048ac7c94d1cfa08da456e790dd5d70 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Thu, 2 Mar 2017 04:06:15 +0300 Subject: [PATCH 29/35] Description of alignment parameters for assemble removed from docs. --- doc/assemble.rst | 85 +++++++++++++++--------------------------------- 1 file changed, 27 insertions(+), 58 deletions(-) diff --git a/doc/assemble.rst b/doc/assemble.rst index 0225de597..7141b66b9 100644 --- a/doc/assemble.rst +++ b/doc/assemble.rst @@ -271,72 +271,41 @@ In order to turn off clustering one should use the following parameters: mixcr assemble -OcloneClusteringParameters=null alignments.vdjca output.clns -Clone factory parameters ------------------------- +.. Clone factory parameters +.. ------------------------ -Parameters which control final alignment of clonal sequences are placed -in ``cloneFactoryParameters`` group. These parameters includes separate -groups for V, D, J and C aligners: ``vParameters``, ``dParameters``, -``jParameters`` and ``cParameters``. The D aligner is the same as used -in ``align`` and thus all its parameters and their default values are -the same as described for :ref:`D aligner in align `. One -can override these parameters in the following way: +.. Parameters which control final alignment of clonal sequences are placed in ``cloneFactoryParameters`` group. These parameters includes separate groups for V, D, J and C aligners: ``vParameters``, ``dParameters``, ``jParameters`` and ``cParameters``. The D aligner is the same as used in ``align`` and thus all its parameters and their default values are the same as described for :ref:`D aligner in align `. One can override these parameters in the following way: -:: - - mixcr assemble -OcloneFactoryParameters.dParameters.absoluteMinScore=10 alignments.vdjca output.clns - -:: - - mixcr assemble -OcloneFactoryParameters.dParameters.scoring.gapOpenPenalty=-10 alignments.vdjca output.clns - -The aligners used to build alignments with V, J and C genes are -different from those used by ``align``. +.. -V, J and C aligner parameters -''''''''''''''''''''''''''''' +.. mixcr assemble -OcloneFactoryParameters.dParameters.absoluteMinScore=10 alignments.vdjca output.clns -The following table lists parameters of V, J and C aligners: +.. +.. mixcr assemble -OcloneFactoryParameters.dParameters.scoring.gapOpenPenalty=-10 alignments.vdjca output.clns +.. The aligners used to build alignments with V, J and C genes are different from those used by ``align``. -+----------------------+-----------------+-----------------+------------------+-----------------------------------------------------------+ -| Parameter | Default V value | Default J value | Default C value |Description | -+======================+=================+=================+==================+===========================================================+ -| ``featureToAlign`` | ``VTranscript`` | ``JRegion`` | ``CExon1`` | Gene region used to build alignments. | -+----------------------+-----------------+-----------------+------------------+-----------------------------------------------------------+ -| ``relativeMinScore`` | ``0.8`` | ``0.8`` | ``0.8`` | Relative minimal score of hit: hits with score less than | -| | | | | ``relativeMinScore * maxScore`` (``maxScore`` is score of | -| | | | | best hit) will be dropped. | -+----------------------+-----------------+-----------------+------------------+-----------------------------------------------------------+ +.. The scoring parameters are placed in group ``alignmentParameters.scoring``: -One can override these parameters in the following way +.. +-------------------------+----------------------------------------+--------------------------------------------------------------------+ +.. | Parameter | Default value (same for V, J, C) | Description | +.. +=========================+========================================+====================================================================+ +.. | ``subsMatrix`` | ``simple(match = 5,`` | Substitution matrix. Available types: | +.. | | ``mismatch = -9)`` | | +.. | | | - ``simple`` --- a matrix with diagonal elements equal to | +.. | | | ``match`` and other elements equal to ``mismatch`` | +.. | | | - ``raw`` --- a complete set of 16 matrix elements should be | +.. | | | specified; for  example: | +.. | | | ``raw(5,-9,-9,-9,-9,5,-9,-9,-9,-9,5,-9,-9,-9,-9,5)`` | +.. | | |   (*equivalent to the default value*) | +.. +-------------------------+----------------------------------------+--------------------------------------------------------------------+ +.. | ``gapPenalty`` | ``-12`` | Penalty for gap. | +.. +-------------------------+----------------------------------------+--------------------------------------------------------------------+ -:: - - mixcr assemble -OcloneFactoryParameters.jParameters.featureToAlign=JRegion(-6,0) alignments.vdjca output.clns - -The scoring parameters are placed in group -``alignmentParameters.scoring``: +.. One can override these parameters in the following way -+-------------------------+----------------------------------------+--------------------------------------------------------------------+ -| Parameter | Default value (same for V, J, C) | Description | -+=========================+========================================+====================================================================+ -| ``subsMatrix`` | ``simple(match = 5,`` | Substitution matrix. Available types: | -| | ``mismatch = -9)`` | | -| | | - ``simple`` --- a matrix with diagonal elements equal to | -| | | ``match`` and other elements equal to ``mismatch`` | -| | | - ``raw`` --- a complete set of 16 matrix elements should be | -| | | specified; for  example: | -| | | ``raw(5,-9,-9,-9,-9,5,-9,-9,-9,-9,5,-9,-9,-9,-9,5)`` | -| | |   (*equivalent to the default value*) | -+-------------------------+----------------------------------------+--------------------------------------------------------------------+ -| ``gapPenalty`` | ``-12`` | Penalty for gap. | -+-------------------------+----------------------------------------+--------------------------------------------------------------------+ - -One can override these parameters in the following way - -:: +.. - mixcr assemble -OcloneFactoryParameters.vParameters.alignmentParameters.scoring.gapPenalty=-5 \ - alignments.vdjca output.clns +.. mixcr assemble -OcloneFactoryParameters.vParameters.alignmentParameters.scoring.gapPenalty=-5 \ +.. alignments.vdjca output.clns From 8042bf7e0bd8d05888760d515c2444b5d30a7f93 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Thu, 2 Mar 2017 12:11:12 +0300 Subject: [PATCH 30/35] Feature/backward compatibility tests (#223) * Backward compatibility tests. --- .../mixcr/tests/BackwardCompatibilityTests.java | 11 ++--------- .../backward_compatibility/2.1.0/test.clns.gz | Bin 0 -> 4510 bytes .../backward_compatibility/2.1.0/test.vdjca.gz | Bin 0 -> 39242 bytes 3 files changed, 2 insertions(+), 9 deletions(-) create mode 100644 src/test/resources/backward_compatibility/2.1.0/test.clns.gz create mode 100644 src/test/resources/backward_compatibility/2.1.0/test.vdjca.gz diff --git a/src/test/java/com/milaboratory/mixcr/tests/BackwardCompatibilityTests.java b/src/test/java/com/milaboratory/mixcr/tests/BackwardCompatibilityTests.java index f5197aae7..a161034d6 100644 --- a/src/test/java/com/milaboratory/mixcr/tests/BackwardCompatibilityTests.java +++ b/src/test/java/com/milaboratory/mixcr/tests/BackwardCompatibilityTests.java @@ -42,11 +42,7 @@ public class BackwardCompatibilityTests { @Test public void testAlignments() throws Exception { - //assertGoodVDJCA("/backward_compatibility/alignments_v1.6.vdjca.gz", 98); - //assertGoodVDJCA("/backward_compatibility/test_16.vdjca.gz", 76); - //assertGoodVDJCA("/backward_compatibility/test_17.vdjca.gz", 75); - //assertGoodVDJCA("/backward_compatibility/test_18.vdjca.gz", 76); - //assertGoodVDJCA("/backward_compatibility/test_183.vdjca.gz", 76); + assertGoodVDJCA("/backward_compatibility/2.1.0/test.vdjca.gz", 76); } public static void assertGoodVDJCA(String resource, int size) throws IOException { @@ -68,10 +64,7 @@ public static void assertGoodVDJCA(String resource, int size) throws IOException @Test public void testBC16Cloneset() throws Exception { - //assertGoodCLNS("/backward_compatibility/clones_v1.6.clns.gz", 24, 24); - //assertGoodCLNS("/backward_compatibility/test_16.clns.gz", 22, 17); - //assertGoodCLNS("/backward_compatibility/test_17.clns.gz", 21, 16); - //assertGoodCLNS("/backward_compatibility/test_18.clns.gz", 81, 66); + assertGoodCLNS("/backward_compatibility/2.1.0/test.clns.gz", 22, 17); } public static void assertGoodCLNS(String resource, int size, int good) throws IOException { diff --git a/src/test/resources/backward_compatibility/2.1.0/test.clns.gz b/src/test/resources/backward_compatibility/2.1.0/test.clns.gz new file mode 100644 index 0000000000000000000000000000000000000000..3ee6fe624bd96aa49bb3b84176ea4bd14efd6e27 GIT binary patch literal 4510 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 C5cw_u literal 0 HcmV?d00001 From ea3c51cedcfefbbd4e5f3be6461ade58dcc65071 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Thu, 2 Mar 2017 14:15:39 +0300 Subject: [PATCH 31/35] Test fix. --- .../mixcr/export/FieldExtractorsTest.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/java/com/milaboratory/mixcr/export/FieldExtractorsTest.java b/src/test/java/com/milaboratory/mixcr/export/FieldExtractorsTest.java index f6c764d22..f6d2eb12d 100644 --- a/src/test/java/com/milaboratory/mixcr/export/FieldExtractorsTest.java +++ b/src/test/java/com/milaboratory/mixcr/export/FieldExtractorsTest.java @@ -124,27 +124,27 @@ public Integer[][] go(String seq, int len, int offset1, int offset2, int offset3 Integer[][] r = goAssert.go("{CDR3Begin(-250):VEnd(-3)} 'CCAAA' {DBegin(0):DEnd(0)} 'AAA' {JBegin(2):FR4End} " + "{CBegin}C*100 N*100", 100, 240, 307, 450, ""); - assertExportPoint(r[0], ReferencePoint.VEndTrimmed, -3); - assertExportPoint(r[0], ReferencePoint.DBeginTrimmed, 0); - assertExportPoint(r[0], ReferencePoint.DEndTrimmed, 0); - assertExportPoint(r[0], ReferencePoint.JBeginTrimmed, -2); + assertExportPoint(r[0], ReferencePoint.VEnd, -3); + assertExportPoint(r[0], ReferencePoint.DBegin, 0); + assertExportPoint(r[0], ReferencePoint.DEnd, 0); + assertExportPoint(r[0], ReferencePoint.JBegin, -2); r = goAssert.go("{CDR3Begin(-250):VEnd(0)} 'CCAAA' {DBegin(0):DEnd(-2)} 'AAA' {JBegin:FR4End} {CBegin}C*100 N*100", 100, 240, 307, 450, ""); - assertExportPoint(r[0], ReferencePoint.VEndTrimmed, 0); - assertExportPoint(r[0], ReferencePoint.DBeginTrimmed, 0); - assertExportPoint(r[0], ReferencePoint.DEndTrimmed, -2); - assertExportPoint(r[0], ReferencePoint.JBeginTrimmed, 0); + assertExportPoint(r[0], ReferencePoint.VEnd, 0); + assertExportPoint(r[0], ReferencePoint.DBegin, 0); + assertExportPoint(r[0], ReferencePoint.DEnd, -2); + assertExportPoint(r[0], ReferencePoint.JBegin, 0); // With PSegments r = goAssert.go("{CDR3Begin(-250):VEnd(0)} {VEnd:VEnd(-3)} 'CCAAA' {DBegin(3):DBegin} {DBegin:DEnd(-2)} 'AAA' " + "{JBegin(2):JBegin} {JBegin:FR4End} {CBegin}C*100 N*100", 100, 240, 307, 450, ""); - assertExportPoint(r[0], ReferencePoint.VEndTrimmed, 3); - assertExportPoint(r[0], ReferencePoint.DBeginTrimmed, 3); - assertExportPoint(r[0], ReferencePoint.DEndTrimmed, -2); - assertExportPoint(r[0], ReferencePoint.JBeginTrimmed, 2); + assertExportPoint(r[0], ReferencePoint.VEnd, 3); + assertExportPoint(r[0], ReferencePoint.DBegin, 3); + assertExportPoint(r[0], ReferencePoint.DEnd, -2); + assertExportPoint(r[0], ReferencePoint.JBegin, 2); } static void assertExportPoint(Integer[] r, ReferencePoint rp, Integer value) { From 7069820cf613152b07ef587a064477a5638d49ea Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Thu, 2 Mar 2017 16:24:43 +0300 Subject: [PATCH 32/35] Integration test for #219. This fixes #219. Integration tests incorporated int Travic-CI pipeline. --- .travis.yml | 3 +++ itests.sh | 51 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9fbf327bf..fd174cb12 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,9 @@ before_install: - mvn clean install -DskipTests -B && cd .. - mv ./repseqio/.cache .cache +script: + - mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V && mvn test -B && ./itests.sh test + jdk: - openjdk7 diff --git a/itests.sh b/itests.sh index a203898f9..be423c082 100755 --- a/itests.sh +++ b/itests.sh @@ -1,5 +1,8 @@ #!/bin/bash +set -e +set -o pipefail + # "Integration" tests for MiXCR # Test standard analysis pipeline results @@ -46,6 +49,26 @@ case $os in ;; esac +create_standard_results=false +run_tests=false +while [[ $# > 0 ]] +do + key="$1" + shift + case $key in + std) + create_standard_results=true + ;; + test) + run_tests=true + ;; + *) + echo "Unknown option $key"; + exit 1 + ;; +esac +done + rm -rf ${dir}/test_target mkdir ${dir}/test_target @@ -60,17 +83,27 @@ which mixcr mixcr -v function go_assemble { - mixcr assemble -r $1.clns.report $1.vdjca $1.clns || exit 1 + mixcr assemble -r $1.clns.report $1.vdjca $1.clns for c in TCR IG TRB TRA TRG TRD IGH IGL IGK ALL do - mixcr exportClones -c ${c} -s $1.clns $1.clns.${c}.txt || exit 1 + mixcr exportClones -c ${c} -s $1.clns $1.clns.${c}.txt done } -for s in sample_IGH test; -do - mixcr align -r ${s}_paired.vdjca.report ${s}_R1.fastq ${s}_R2.fastq ${s}_paired.vdjca || exit 1 - go_assemble ${s}_paired - mixcr align -r ${s}_single.vdjca.report ${s}_R1.fastq ${s}_single.vdjca || exit 1 - go_assemble ${s}_single -done +if [[ $create_standard_results == true ]]; then + for s in sample_IGH test; + do + mixcr align -r ${s}_paired.vdjca.report ${s}_R1.fastq ${s}_R2.fastq ${s}_paired.vdjca + go_assemble ${s}_paired + mixcr align -r ${s}_single.vdjca.report ${s}_R1.fastq ${s}_single.vdjca + go_assemble ${s}_single + done +fi + +# UseCase 1 + +if [[ $run_tests == true ]]; then + echo "Running test case 1" + mixcr align -OvParameters.geneFeatureToAlign=VGeneWithP test_R1.fastq test_R2.fastq case1.vdjca + mixcr assemble case1.vdjca case1.clns +fi From 2549896af8ee26750a6ade50855528de0da4d807 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Thu, 2 Mar 2017 16:30:50 +0300 Subject: [PATCH 33/35] Fixes for TravisCI --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fd174cb12..9b25c4011 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,11 +15,15 @@ before_install: - mv ./repseqio/.cache .cache script: - - mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V && mvn test -B && ./itests.sh test + - mvn test -B && ./itests.sh test jdk: - openjdk7 +before_cache: + - rm -f $HOME/.m2/repository/io/repseqio/ + - rm -f $HOME/.m2/repository/com/milaboratory/ + cache: directories: - $HOME/.m2 From 9cbb23c0974a175780153a3c357f1caa8666884a Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Fri, 3 Mar 2017 01:02:53 +0300 Subject: [PATCH 34/35] Changelog + Repseq.IO upgraded to release version. --- CHANGELOG_CURRENT | 8 +++++++- pom.xml | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG_CURRENT b/CHANGELOG_CURRENT index 363dbe216..33458bc75 100644 --- a/CHANGELOG_CURRENT +++ b/CHANGELOG_CURRENT @@ -1,3 +1,8 @@ +Additional check for the same V hits in merging sequences in `assemblePartial` +Fix: list of C hits limited by `relativeMinScore` in `assemblePartial` +Not aligned mates from fully aligned opposite PE reads are now taken into `assemblePartial` procedure (case when V and J parts of the target read are shorter than 12 nt) +Additional consistency cehcks in `assemblePartial`, overlaps of non-CDR3-covering mates of PE reads are also taken into account +More sophisticated algorithm for alignment-guided merging of paired-end reads in `align` Several anchor point positions in export points changed their meaning. Fixed absent space in `AA. Seq. ...` column name and excessive space in the end of several column names (affects `exportClones` and `exportAlignments` with `-v` option; fixes compatibility with VDJTools v1.1.3 and below). Fixes NPE in `exportClones` in some cases with mmu reference @@ -6,4 +11,5 @@ Added `-d` option in `assemblePartial` to drop non-assembled partial reads to re Added `sortAlignments` action. Sort `*.vdjca` files by read id, allows diffing alignments after `assembleParial` and other actions that shuffle records inside file. Fixed incorrect behaviour of `exportClones` and `exportAlignments` in cases like `mixcr exportAlignments -p full -descrR1 ...` minor: Multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or `-i 123,456` etc. -minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both renamed to `--read-ids` \ No newline at end of file +minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both renamed to `--read-ids` +minor: infrastructure for post-build tests in Travis CI \ No newline at end of file diff --git a/pom.xml b/pom.xml index d33fc0f52..450e08d9b 100644 --- a/pom.xml +++ b/pom.xml @@ -45,14 +45,14 @@ UTF-8 - 1.7.2-SNAPSHOT + 1.7.2 io.repseq repseqio - 1.2.7-SNAPSHOT + 1.2.7 From 6b61b73a2f010cb4e646223c23ea781e89767ee0 Mon Sep 17 00:00:00 2001 From: Dmitry Bolotin Date: Fri, 3 Mar 2017 01:03:59 +0300 Subject: [PATCH 35/35] Release v2.1.1 --- CHANGELOG | 29 +++++++++++++++++++++++++++++ CHANGELOG_CURRENT | 15 --------------- pom.xml | 14 +++++--------- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 326002892..c8d3a7319 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,33 @@ +MiXCR 2.1.1 ( 3 Mar 2017) +======================== + +-- Additional check for the same V hits in merging sequences in `assemblePartial` +-- Fix: list of C hits limited by `relativeMinScore` in `assemblePartial` +-- Not aligned mates from fully aligned opposite PE reads are now taken into `assemblePartial` + procedure (case when V and J parts of the target read are shorter than 12 nt) +-- Additional consistency cehcks in `assemblePartial`, overlaps of non-CDR3-covering mates of PE + reads are also taken into account +-- More sophisticated algorithm for alignment-guided merging of paired-end reads in `align` +-- Several anchor point positions in export points changed their meaning. +-- Fixed absent space in `AA. Seq. ...` column name and excessive space in the end of several + column names (affects `exportClones` and `exportAlignments` with `-v` option; fixes compatibility + with VDJTools v1.1.3 and below). +-- Fixes NPE in `exportClones` in some cases with mmu reference +-- `-p` option in `assemblePartial` enabled by default; deprecated; will be removed in 2.2 +-- Added `-d` option in `assemblePartial` to drop non-assembled partial reads to reduce output file + size +-- Added `sortAlignments` action. Sort `*.vdjca` files by read id, allows diffing alignments after + `assembleParial` and other actions that shuffle records inside file. +-- Fixed incorrect behaviour of `exportClones` and `exportAlignments` in cases like `mixcr + exportAlignments -p full -descrR1 ...` +-- minor: Multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified + as `-i 123 -i 456` or `-i 123,456` etc. +-- minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both + renamed to `--read-ids` +-- minor: infrastructure for post-build tests in Travis CI + + MiXCR 2.1 ( 6 Feb 2017) ======================== diff --git a/CHANGELOG_CURRENT b/CHANGELOG_CURRENT index 33458bc75..e69de29bb 100644 --- a/CHANGELOG_CURRENT +++ b/CHANGELOG_CURRENT @@ -1,15 +0,0 @@ -Additional check for the same V hits in merging sequences in `assemblePartial` -Fix: list of C hits limited by `relativeMinScore` in `assemblePartial` -Not aligned mates from fully aligned opposite PE reads are now taken into `assemblePartial` procedure (case when V and J parts of the target read are shorter than 12 nt) -Additional consistency cehcks in `assemblePartial`, overlaps of non-CDR3-covering mates of PE reads are also taken into account -More sophisticated algorithm for alignment-guided merging of paired-end reads in `align` -Several anchor point positions in export points changed their meaning. -Fixed absent space in `AA. Seq. ...` column name and excessive space in the end of several column names (affects `exportClones` and `exportAlignments` with `-v` option; fixes compatibility with VDJTools v1.1.3 and below). -Fixes NPE in `exportClones` in some cases with mmu reference -`-p` option in `assemblePartial` enabled by default; deprecated; will be removed in 2.2 -Added `-d` option in `assemblePartial` to drop non-assembled partial reads to reduce output file size -Added `sortAlignments` action. Sort `*.vdjca` files by read id, allows diffing alignments after `assembleParial` and other actions that shuffle records inside file. -Fixed incorrect behaviour of `exportClones` and `exportAlignments` in cases like `mixcr exportAlignments -p full -descrR1 ...` -minor: Multiple reads in `exportAlignmentsPretty` and `filterAlignments` should be now specified as `-i 123 -i 456` or `-i 123,456` etc. -minor: `--reads-ids` in `exportAlignmentsPretty` and `--readsIds` in `filterAlignments` both renamed to `--read-ids` -minor: infrastructure for post-build tests in Travis CI \ No newline at end of file diff --git a/pom.xml b/pom.xml index 450e08d9b..bf0aec46b 100644 --- a/pom.xml +++ b/pom.xml @@ -27,13 +27,12 @@ ~ PARTICULAR PURPOSE, OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY ~ PATENT, TRADEMARK OR OTHER RIGHTS. --> - + 4.0.0 com.milaboratory mixcr - 2.1.1-SNAPSHOT + 2.1.1 jar MiXCR @@ -211,15 +210,12 @@ - + - + false - + com.milaboratory.mixcr.cli.Main