diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2c1dd2f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "milib"] + path = milib + url = https://github.com/milaboratory/milib.git diff --git a/CHANGELOG b/CHANGELOG index 84d4ba5..d666e57 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,11 @@ +MiTools 1.4 (14 Jul 2016) +======================== + +-- added new action: `mitools cut` to cut sequences to a fixed or random length (see help `mitools + cut -h`) + + MiTools 1.3 ( 1 Feb 2016) ======================== diff --git a/milib b/milib new file mode 160000 index 0000000..f551baa --- /dev/null +++ b/milib @@ -0,0 +1 @@ +Subproject commit f551baa70fb383bdb182f0679822c1be1fb18dec diff --git a/mitools b/mitools new file mode 100755 index 0000000..8970a6a --- /dev/null +++ b/mitools @@ -0,0 +1,146 @@ +#!/bin/bash + +java="java" + +sedString="s/.*1\.\(.*\)\..*/\1/" +jVersion=$($java -version 2>&1 | grep version | awk '{ print $3 }' | sed $sedString) +if [[ $jVersion -lt 7 ]]; +then + echo "Wrong version of java. Please use Java 7 or higher." + exit 1 +fi + +# Linux readlink -f alternative for Mac OS X +function readlinkUniversal() { + targetFile=$1 + + cd `dirname $targetFile` + targetFile=`basename $targetFile` + + # iterate down a (possible) chain of symlinks + while [ -L "$targetFile" ] + do + targetFile=`readlink $targetFile` + cd `dirname $targetFile` + targetFile=`basename $targetFile` + done + + # compute the canonicalized name by finding the physical path + # for the directory we're in and appending the target file. + phys_dir=`pwd -P` + result=$phys_dir/$targetFile + echo $result +} + +os=`uname` +delta=100 + +dir="" + +case $os in + Darwin) + freeBlocks=$(vm_stat | grep free | awk '{ print $3 }' | sed 's/\.//') + inactiveBlocks=$(vm_stat | grep inactive | awk '{ print $3 }' | sed 's/\.//') + speculativeBlocks=$(vm_stat | grep speculative | awk '{ print $3 }' | sed 's/\.//') + freeMb=$((($freeBlocks+$speculativeBlocks)*4096/1048576)) + inactiveMb=$(($inactiveBlocks*4096/1048576)) + maxMb=$((($freeMb+$inactiveMb-$delta))) + dir=$(dirname "$(readlinkUniversal "$0")") + ;; + Linux) + rFreeMb=$(free -m | head -n 3 | tail -n 1 | awk '{ print $4 }') + maxMb=$(($rFreeMb-$delta)) + dir="$(dirname "$(readlink -f "$0")")" + ;; + *) + echo "Unknown OS." + exit 1 + ;; +esac + +bin=${dir}/$0 + +jarBase="mitools" + +appArgs=() +javaArgs=() + +needXmxXms=true +otherJar="" + +while [[ $# > 0 ]] +do + key="$1" + shift + case $key in + -D*|-X*|-ea|-agentlib*) + javaArgs+=(${key}) + + case $key in + -Xmx*|-Xms*) + needXmxXms=false + ;; + esac + + ;; + -jar|-V) + otherJar="$1" + shift + ;; + *) + appArgs+=("${key}") + ;; + esac +done + +if [[ ${needXmxXms} == true ]] +then + targetXmx=3000 + + if [[ $targetXmx -gt $maxMb ]]; + then + targetXmx=$maxMb + fi + + javaArgs+=("-Xmx${targetXmx}m") + + targetXms=$((${targetXmx}*2/3)) + + if [[ $targetXms -lt 2000 ]]; + then + targetXms=$targetXmx + fi + + javaArgs+=("-Xms${targetXms}m") +fi + +jar="" + +if [[ -z "$otherJar" ]]; +then + for j in "$dir/../jar/${jarBase}.jar" "$dir/${jarBase}.jar" $(ls -d -1 $dir/target/* 2> /dev/null | grep distribution.jar) + do + if [[ -e "$j" ]]; + then + jar=$j + break + fi + done +else + for j in $(ls -1 ${dir}/* | grep "${jarBase}" | grep ".jar" | grep ${otherJar}); + do + if [[ -e "$j" ]]; + then + jar=$j + break + fi + done +fi + +if [[ "$jar" == "" ]]; +then + echo "No jar." + exit 1 +fi + +$java -Dapp.path=$dir -Dapp.command=mixcr -XX:+AggressiveOpts "${javaArgs[@]}" -jar $jar "${appArgs[@]}" diff --git a/pom.xml b/pom.xml index 7e363d5..0416e14 100644 --- a/pom.xml +++ b/pom.xml @@ -19,10 +19,10 @@ com.milaboratory mitools - 1.3 + 1.4 jar MiTools - http://milaboratory.com/ + https://github.com/milaboratory/mitools org.sonatype.oss @@ -94,7 +94,13 @@ com.milaboratory milib - ${project.version} + 1.5-SNAPSHOT + + + com.beust + jcommander + 1.48 + true com.milaboratory @@ -115,16 +121,6 @@ 1.9.5 test - - com.beust - jcommander - 1.30 - - - cc.redberry - pipe - 0.9.4 - @@ -135,11 +131,6 @@ scm:git:https://github.com/milaboratory/mitools.git - - YouTrack - http://youtrack.milaboratory.com/ - - release diff --git a/src/main/java/com/milaboratory/core/PairedEndReadsLayout.java b/src/main/java/com/milaboratory/core/PairedEndReadsLayout.java deleted file mode 100644 index c7bc411..0000000 --- a/src/main/java/com/milaboratory/core/PairedEndReadsLayout.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.core; - -import com.milaboratory.core.io.sequence.PairedRead; - -public enum PairedEndReadsLayout implements java.io.Serializable { - Opposite(new PairedTargetProvider() { - @Override - public PairedTarget[] createTargets(PairedRead read) { - return new PairedTarget[]{ - new PairedTarget( - read.getRead(0).getData(), - read.getRead(1).getData().getReverseComplement()), - new PairedTarget( - read.getRead(1).getData(), - read.getRead(0).getData().getReverseComplement())}; - } - }, true - ), - Collinear(new PairedTargetProvider() { - @Override - public PairedTarget[] createTargets(PairedRead read) { - return new PairedTarget[]{ - new PairedTarget( - read.getRead(0).getData(), - read.getRead(1).getData()), - new PairedTarget( - read.getRead(1).getData().getReverseComplement(), - read.getRead(0).getData().getReverseComplement())}; - } - }, false - ), - Unknown(new PairedTargetProvider() { - @Override - public PairedTarget[] createTargets(PairedRead read) { - return new PairedTarget[]{ - new PairedTarget( - read.getRead(0).getData(), - read.getRead(1).getData()), - new PairedTarget( - read.getRead(0).getData(), - read.getRead(1).getData().getReverseComplement()), - new PairedTarget( - read.getRead(1).getData(), - read.getRead(0).getData().getReverseComplement()), - new PairedTarget( - read.getRead(1).getData().getReverseComplement(), - read.getRead(0).getData().getReverseComplement())}; - } - }, false, true - ); - private final PairedTargetProvider provider; - private final boolean[] possibleRelativeStrands; - - PairedEndReadsLayout(PairedTargetProvider provider, boolean... possibleRelativeStrands) { - this.provider = provider; - this.possibleRelativeStrands = possibleRelativeStrands; - } - - public PairedTarget[] createTargets(PairedRead read) { - return provider.createTargets(read); - } - - public boolean[] getPossibleRelativeStrands() { - return possibleRelativeStrands; - } - - private interface PairedTargetProvider { - PairedTarget[] createTargets(PairedRead read); - } -} diff --git a/src/main/java/com/milaboratory/core/PairedTarget.java b/src/main/java/com/milaboratory/core/PairedTarget.java deleted file mode 100644 index c77bbe6..0000000 --- a/src/main/java/com/milaboratory/core/PairedTarget.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.core; - -import com.milaboratory.core.sequence.NSequenceWithQuality; - -/** - * Created by dbolotin on 24/07/14. - */ -public final class PairedTarget { - public final NSequenceWithQuality[] targets; - - PairedTarget(NSequenceWithQuality... targets) { - this.targets = targets; - } -} diff --git a/src/main/java/com/milaboratory/mitools/cli/Action.java b/src/main/java/com/milaboratory/mitools/cli/Action.java deleted file mode 100644 index 69e7111..0000000 --- a/src/main/java/com/milaboratory/mitools/cli/Action.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.cli; - -/** - * Created by dbolotin on 20/08/14. - */ -public interface Action { - void go(ActionHelper helper) throws Exception; - - String command(); - - ActionParameters params(); -} diff --git a/src/main/java/com/milaboratory/mitools/cli/ActionHelper.java b/src/main/java/com/milaboratory/mitools/cli/ActionHelper.java deleted file mode 100644 index 0b03786..0000000 --- a/src/main/java/com/milaboratory/mitools/cli/ActionHelper.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.cli; - -import java.io.PrintStream; - -public interface ActionHelper { - PrintStream getDefaultPrintStream(); - - String getCommandLineArguments(); -} diff --git a/src/main/java/com/milaboratory/mitools/cli/ActionParameters.java b/src/main/java/com/milaboratory/mitools/cli/ActionParameters.java deleted file mode 100644 index 1227a81..0000000 --- a/src/main/java/com/milaboratory/mitools/cli/ActionParameters.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.cli; - -import com.beust.jcommander.Parameter; - -public abstract class ActionParameters { - @Parameter(names = {"-h", "--help"}, help = true, description = "Displays help for this command.") - public Boolean help = false; - - public boolean help() { - return help != null && help; - } - - public void validate() { - } -} diff --git a/src/main/java/com/milaboratory/mitools/cli/CheckAction.java b/src/main/java/com/milaboratory/mitools/cli/CheckAction.java index 84345e7..18d41df 100644 --- a/src/main/java/com/milaboratory/mitools/cli/CheckAction.java +++ b/src/main/java/com/milaboratory/mitools/cli/CheckAction.java @@ -18,6 +18,9 @@ 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.core.io.sequence.PairedRead; import com.milaboratory.core.io.sequence.SingleRead; import com.milaboratory.core.io.sequence.fastq.FastqRecordsReader; diff --git a/src/main/java/com/milaboratory/mitools/cli/CutAction.java b/src/main/java/com/milaboratory/mitools/cli/CutAction.java new file mode 100644 index 0000000..bf39b42 --- /dev/null +++ b/src/main/java/com/milaboratory/mitools/cli/CutAction.java @@ -0,0 +1,131 @@ +/* + * Copyright 2016 MiLaboratory.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.milaboratory.mitools.cli; + +import cc.redberry.pipe.CUtils; +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.core.io.sequence.SingleRead; +import com.milaboratory.core.io.sequence.SingleSequenceWriter; +import com.milaboratory.core.io.sequence.fastq.SingleFastqReader; +import com.milaboratory.mitools.processors.CutSide; +import com.milaboratory.mitools.processors.RandomCutter; +import com.milaboratory.util.SmartProgressReporter; + +import java.util.ArrayList; +import java.util.List; + +import static cc.redberry.pipe.CUtils.wrap; + +public class CutAction implements Action { + final AParams actionParameters = new AParams(); + + @Override + public void go(ActionHelper helper) throws Exception { + try (SingleFastqReader reader = MiCLIUtil.createSingleReader(actionParameters.getInput(), false); + SingleSequenceWriter writer = MiCLIUtil.createSingleWriter(actionParameters.getOutput())) { + SmartProgressReporter.startProgressReport("Processing", reader, System.err); + + RandomCutter cutter = new RandomCutter(actionParameters.getPosition(), actionParameters.getMinLengt(), + actionParameters.getMaxLengt(), actionParameters.getSeed()); + + for (SingleRead read : CUtils.it(wrap(reader, cutter))) + writer.write(read); + } + } + + @Override + public String command() { + return "cut"; + } + + @Override + public ActionParameters params() { + return actionParameters; + } + + @Parameters(commandDescription = "Cut sequences.", optionPrefixes = "-") + public static final class AParams extends ActionParameters { + @Parameter(description = "[ input_file_R1.fastq[.gz] [ output_file.fastq[.gz] ] ]", variableArity = true) + public List parameters = new ArrayList<>(); + + @Parameter(description = "Length.", + names = {"-l", "--length"}) + Integer length; + + @Parameter(description = "Minimal length; inclusive (random value will be selected for each sequence; use with " + + "--max-length; don't use with --length option).", + names = {"-al", "--min-length"}) + Integer minLength; + + @Parameter(description = "Maximal length; inclusive (random value will be selected for each sequence; use with " + + "--min-length; don't use with --length option).", + names = {"-bl", "--max-length"}) + Integer maxLength; + + @Parameter(description = "Position to cut from. (possible values 'Left', 'Right', 'Random')", + names = {"-p", "--position"}) + String position = "Left"; + + @Parameter(description = "Seed for random generator.", + names = {"-s", "--seed"}) + Integer seed; + + public String getInput() { + return parameters.size() == 0 ? "-" : parameters.get(0); + } + + public String getOutput() { + return parameters.size() < 2 ? "-" : parameters.get(1); + } + + public int getSeed() { + return seed == null ? 0 : seed; + } + + public int getMinLengt() { + if (length != null) + return length; + return minLength; + } + + public int getMaxLengt() { + if (length != null) + return length; + return maxLength; + } + + public CutSide getPosition() { + return CutSide.valueOf(position); + } + + @Override + public void validate() { + if (parameters.size() > 2) + throw new ParameterException("Wrong number of parameters."); + if (length == null && minLength == null && maxLength == null) + throw new ParameterException("Please specify the length to cut: --length or --max-length and --min-length."); + if (length != null && (minLength != null || maxLength != null)) + throw new ParameterException("--length option is not compatible with --max-length and --min-length"); + if ((minLength == null) != (maxLength == null)) + throw new ParameterException("Please specify both options --max-length and --min-length."); + } + } +} diff --git a/src/main/java/com/milaboratory/mitools/cli/HiddenAction.java b/src/main/java/com/milaboratory/mitools/cli/HiddenAction.java deleted file mode 100644 index b348539..0000000 --- a/src/main/java/com/milaboratory/mitools/cli/HiddenAction.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.cli; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Created by dbolotin on 03/09/14. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface HiddenAction { -} diff --git a/src/main/java/com/milaboratory/mitools/cli/JCommanderBasedMain.java b/src/main/java/com/milaboratory/mitools/cli/JCommanderBasedMain.java deleted file mode 100644 index eb75c35..0000000 --- a/src/main/java/com/milaboratory/mitools/cli/JCommanderBasedMain.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.cli; - -import com.beust.jcommander.JCommander; -import com.beust.jcommander.Parameter; -import com.beust.jcommander.ParameterException; - -import java.io.PrintStream; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.Map; - -public class JCommanderBasedMain implements ActionHelper { - // LinkedHashMap to preserve order of actions - protected final Map actions = new LinkedHashMap<>(); - protected final String command; - protected boolean printHelpOnError = false; - protected boolean printStackTrace = false; - protected Runnable versionInfoCallback = null; - protected PrintStream outputStream = System.err; - protected String[] arguments; - - public JCommanderBasedMain(String command, Action... actions) { - this.command = command; - for (Action action : actions) - reg(action); - } - - public void setOutputStream(PrintStream outputStream) { - this.outputStream = outputStream; - } - - @Override - public PrintStream getDefaultPrintStream() { - return outputStream; - } - - @Override - public String getCommandLineArguments() { - StringBuilder builder = new StringBuilder(); - for (String arg : arguments) { - if (builder.length() != 0) - builder.append(" "); - builder.append(arg); - } - return builder.toString(); - } - - public boolean isPrintStackTrace() { - return printStackTrace; - } - - public void setPrintStackTrace(boolean printStackTrace) { - this.printStackTrace = printStackTrace; - } - - protected void reg(Action a) { - actions.put(a.command(), a); - } - - public void main(String... args) throws Exception { - // Saving current arguments - this.arguments = args; - - if (args.length == 0) { - printGlobalHelp(); - return; - } - - // Setting up JCommander - MainParameters mainParameters = getMainParameters(); - JCommander commander = new JCommander(mainParameters); - commander.setProgramName(command); - for (Action a : actions.values()) - commander.addCommand(a.command(), a.params()); - - // Getting command name - String commandName = args[0]; - - // Getting corresponding action - Action action = actions.get(commandName); - - try { - if (action != null && (action instanceof ActionParametersParser)) { - ((ActionParametersParser) action).parseParameters(Arrays.copyOfRange(args, 1, args.length)); - } else { - commander.parse(args); - - // Print Version information if requested and exit. - if (mainParameters instanceof MainParametersWithVersion && - ((MainParametersWithVersion) mainParameters).version()) { - versionInfoCallback.run(); - return; - } - - // Print complete help if requested - if (mainParameters.help()) { - // Creating new instance of jCommander to add only non-hidden actions - JCommander tmpCommander = new JCommander(mainParameters); - tmpCommander.setProgramName(command); - for (Action a : actions.values()) - if (!a.getClass().isAnnotationPresent(HiddenAction.class)) - tmpCommander.addCommand(a.command(), a.params()); - StringBuilder builder = new StringBuilder(); - tmpCommander.usage(builder); - outputStream.print(builder); - return; - } - - // Getting parsed command - // assert parsedCommand.equals(commandName) - final String parsedCommand = commander.getParsedCommand(); - - // Processing potential errors - if (parsedCommand == null || !actions.containsKey(parsedCommand)) { - if (parsedCommand == null) - outputStream.println("No command specified."); - else - outputStream.println("Command " + parsedCommand + " not supported."); - outputStream.println("Use -h option to get a list of supported commands."); - return; - } - - action = actions.get(parsedCommand); - } - - if (action.params().help()) { - printActionHelp(commander, action); - } else { - action.params().validate(); - action.go(this); - } - } catch (ParameterException pe) { - printException(pe, commander, action); - } - } - - private MainParameters getMainParameters() { - return versionInfoCallback != null ? - new MainParametersWithVersion() : - new MainParameters(); - } - - protected void printGlobalHelp() { - // Creating new instance of jCommander to add only non-hidden actions - JCommander tmpCommander = new JCommander(getMainParameters()); - tmpCommander.setProgramName(command); - for (Action a : actions.values()) - if (!a.getClass().isAnnotationPresent(HiddenAction.class)) - tmpCommander.addCommand(a.command(), a.params()); - StringBuilder builder = new StringBuilder(); - tmpCommander.usage(builder); - outputStream.print(builder); - } - - protected void printActionHelp(JCommander commander, Action action) { - StringBuilder builder = new StringBuilder(); - if (action instanceof ActionHelpProvider) - ((ActionHelpProvider) action).printHelp(builder); - else - commander.usage(action.command(), builder); - outputStream.print(builder); - } - - protected void printException(ParameterException e, - JCommander commander, Action action) { - outputStream.println("Error: " + e.getMessage()); - if (printStackTrace) - e.printStackTrace(new PrintStream(outputStream)); - if (printHelpOnError) - printActionHelp(commander, action); - } - - /** - * Enables -v / --version parameter. - * - * Sets callback that will be invoked if this option is specified by user. - * - * {@literal null} disables -v parameter. - * - * @param versionInfoCallback callback to be will be invoked if user specified -v option. {@literal null} disables - * -v parameter. - */ - public void setVersionInfoCallback(Runnable versionInfoCallback) { - this.versionInfoCallback = versionInfoCallback; - } - - public static class MainParameters { - @Parameter(names = {"-h", "--help"}, help = true, description = "Displays this help message.") - public Boolean help; - - public boolean help() { - return help != null && help; - } - } - - public static class MainParametersWithVersion extends MainParameters { - @Parameter(names = {"-v", "--version"}, help = true, description = "Output version information.") - public Boolean version; - - public boolean version() { - return version != null && version; - } - } -} diff --git a/src/main/java/com/milaboratory/mitools/cli/Main.java b/src/main/java/com/milaboratory/mitools/cli/Main.java index 49bc6fb..8dcc063 100644 --- a/src/main/java/com/milaboratory/mitools/cli/Main.java +++ b/src/main/java/com/milaboratory/mitools/cli/Main.java @@ -15,15 +15,58 @@ */ package com.milaboratory.mitools.cli; +import com.milaboratory.cli.JCommanderBasedMain; +import com.milaboratory.util.VersionInfo; +import sun.misc.Signal; +import sun.misc.SignalHandler; + public class Main { public static void main(String[] args) throws Exception { + Signal.handle(new Signal("PIPE"), new SignalHandler() { + @Override + public void handle(Signal signal) { + System.exit(0); + } + }); + JCommanderBasedMain main = new JCommanderBasedMain("mitools", new MergeAction(), new TrimAction(), new RCAction(), new RenameAction(), new SplitAction(), - new CheckAction()); + new CheckAction(), + new CutAction()); + + main.setVersionInfoCallback(new Runnable() { + @Override + public void run() { + VersionInfo milib = VersionInfo.getVersionInfoForArtifact("milib"); + VersionInfo mitools = VersionInfo.getVersionInfoForArtifact("mitools"); + + StringBuilder builder = new StringBuilder(); + + builder.append("MiTools v") + .append(mitools.getVersion()) + .append(" (built ") + .append(mitools.getTimestamp()) + .append("; rev=") + .append(mitools.getRevision()) + .append("; branch=") + .append(mitools.getBranch()) + .append(")") + .append("\n"); + + builder.append("MiLib v") + .append(milib.getVersion()) + .append(" (rev=").append(milib.getRevision()) + .append("; branch=").append(milib.getBranch()) + .append(")"); + + System.out.println(builder.toString()); + } + }); + main.main(args); } } diff --git a/src/main/java/com/milaboratory/mitools/cli/MergeAction.java b/src/main/java/com/milaboratory/mitools/cli/MergeAction.java index ab78bec..206d344 100644 --- a/src/main/java/com/milaboratory/mitools/cli/MergeAction.java +++ b/src/main/java/com/milaboratory/mitools/cli/MergeAction.java @@ -23,15 +23,18 @@ import com.beust.jcommander.ParameterException; import com.beust.jcommander.Parameters; import com.beust.jcommander.validators.PositiveInteger; +import com.milaboratory.cli.Action; +import com.milaboratory.cli.ActionHelper; +import com.milaboratory.cli.ActionParameters; import com.milaboratory.core.PairedEndReadsLayout; import com.milaboratory.core.io.sequence.PairedRead; import com.milaboratory.core.io.sequence.SingleReadImpl; import com.milaboratory.core.io.sequence.fastq.PairedFastqReader; import com.milaboratory.core.io.sequence.fastq.SingleFastqWriter; -import com.milaboratory.mitools.merger.MergerParameters; -import com.milaboratory.mitools.merger.MismatchOnlyPairedReadMerger; -import com.milaboratory.mitools.merger.PairedReadMergingResult; -import com.milaboratory.mitools.merger.QualityMergingAlgorithm; +import com.milaboratory.core.merger.MergerParameters; +import com.milaboratory.core.merger.MismatchOnlyPairedReadMerger; +import com.milaboratory.core.merger.PairedReadMergingResult; +import com.milaboratory.core.merger.QualityMergingAlgorithm; import com.milaboratory.util.SmartProgressReporter; import java.io.File; @@ -144,12 +147,6 @@ public static final class MergingParameters extends ActionParameters { names = {"-r", "--report"}) String report; - //@Parameter(description = "Output FASTQ file or \"-\" for STDOUT to put non-overlapped " + - // "reverse reads (supported formats: *.fastq and *.fastq.gz).", - // names = {"-o", "--out"}, - // required = true) - //String output; - @Parameter(description = "Include both paired-end reads for pairs where no overlap was found.", names = {"-i", "--include-non-overlapped"}) boolean includeNonOverlapped; @@ -162,10 +159,11 @@ public static final class MergingParameters extends ActionParameters { names = {"-ss", "--same-strand"}) boolean sameStrand; - @Parameter(description = "Possible values: 'max' - take maximal score value in letter conflicts, 'sub' - " + - "subtract minimal quality from maximal", + @Parameter(description = "Possible values: SumMax, SumSubtraction, MaxSubtraction, MaxMax. " + + "First word (match behaviour): Sum = sum quality values (result is limited by value of -m option); Max = maximal quality. " + + "Second word (mismatch behaviour): Max = take maximal score value, Subtraction = subtract minimal quality from maximal.", names = {"-q", "--quality-merging-algorithm"}) - String qualityMergingAlgorithm = QualityMergingAlgorithm.SumSubtraction.cliName; + String qualityMergingAlgorithm = QualityMergingAlgorithm.MaxSubtraction.name(); @Parameter(description = "Minimal overlap.", names = {"-p", "--overlap"}, validateWith = PositiveInteger.class) @@ -192,7 +190,7 @@ public String getR2() { } public String getOutput() { - return parameters.size() == 2 ? "-" : parameters.get(2); + return parameters.size() == 2 ? "." : parameters.get(2); } public QualityMergingAlgorithm getQualityMergingAlgorithm() { diff --git a/src/main/java/com/milaboratory/mitools/cli/MiCLIUtil.java b/src/main/java/com/milaboratory/mitools/cli/MiCLIUtil.java index 23bdde5..faccbdf 100644 --- a/src/main/java/com/milaboratory/mitools/cli/MiCLIUtil.java +++ b/src/main/java/com/milaboratory/mitools/cli/MiCLIUtil.java @@ -28,13 +28,13 @@ public class MiCLIUtil { public static SingleFastqWriter createSingleWriter(String fileName) throws IOException { - if (fileName.equals("-")) + if (fileName.equals("-") || fileName.equals(".")) return new SingleFastqWriter(System.out); return new SingleFastqWriter(fileName); } public static SingleFastqReader createSingleReader(String fileName, boolean replaceWildcards) throws IOException { - if (fileName.equals("-")) + if (fileName.equals("-") || fileName.equals(".")) return new SingleFastqReader(System.in, replaceWildcards); return new SingleFastqReader(fileName, replaceWildcards); } diff --git a/src/main/java/com/milaboratory/mitools/cli/RCAction.java b/src/main/java/com/milaboratory/mitools/cli/RCAction.java index 9ae9400..b6123b1 100644 --- a/src/main/java/com/milaboratory/mitools/cli/RCAction.java +++ b/src/main/java/com/milaboratory/mitools/cli/RCAction.java @@ -19,6 +19,10 @@ 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.AllowNoArguments; import com.milaboratory.core.io.sequence.SingleRead; import com.milaboratory.core.io.sequence.SingleReadImpl; import com.milaboratory.core.io.sequence.SingleSequenceWriter; @@ -28,6 +32,7 @@ import java.util.ArrayList; import java.util.List; +@AllowNoArguments public class RCAction implements Action { final RCParameters actionParameters = new RCParameters(); @@ -53,17 +58,17 @@ public ActionParameters params() { return actionParameters; } - @Parameters(commandDescription = "Reverse complement.", optionPrefixes = "-") + @Parameters(commandDescription = "Reverse complement.") public static final class RCParameters extends ActionParameters { @Parameter(description = "[ input_file_R1.fastq[.gz] [ output_file.fastq[.gz] ] ]", variableArity = true) public List parameters = new ArrayList<>(); public String getInput() { - return parameters.size() == 0 ? "-" : parameters.get(0); + return parameters.size() == 0 ? "." : parameters.get(0); } public String getOutput() { - return parameters.size() < 2 ? "-" : parameters.get(1); + return parameters.size() < 2 ? "." : parameters.get(1); } @Override diff --git a/src/main/java/com/milaboratory/mitools/cli/RenameAction.java b/src/main/java/com/milaboratory/mitools/cli/RenameAction.java index 88ec675..c1a400b 100644 --- a/src/main/java/com/milaboratory/mitools/cli/RenameAction.java +++ b/src/main/java/com/milaboratory/mitools/cli/RenameAction.java @@ -19,6 +19,9 @@ 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.core.io.sequence.SingleRead; import com.milaboratory.core.io.sequence.SingleReadImpl; import com.milaboratory.core.io.sequence.SingleSequenceWriter; @@ -27,19 +30,38 @@ import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class RenameAction implements Action { final RenameParameters actionParameters = new RenameParameters(); @Override public void go(ActionHelper helper) throws Exception { - final String pattern = actionParameters.pattern; + final String newName = actionParameters.name; + + Pattern pattern = actionParameters.pattern == null ? + null : + Pattern.compile(actionParameters.pattern); + + Matcher matcher; + try (SingleFastqReader reader = MiCLIUtil.createSingleReader(actionParameters.getInput(), false); SingleSequenceWriter writer = MiCLIUtil.createSingleWriter(actionParameters.getOutput())) { SmartProgressReporter.startProgressReport("Processing", reader, System.err); for (SingleRead read : CUtils.it(reader)) { - String description = pattern.replace("%n", Long.toString(read.getId())); + // Replacing index + String description = newName.replace("%n", Long.toString(read.getId())); + + // Replacing old description description = description.replace("%o", read.getDescription()); + + // Replacing caption groups + if (pattern != null) + if ((matcher = pattern.matcher(read.getDescription())).find()) + for (int i = 1; i <= matcher.groupCount(); i++) + description = description.replace("%g" + i, matcher.group(i)); + SingleRead rc = new SingleReadImpl(read.getId(), read.getData(), description); writer.write(rc); } @@ -56,21 +78,26 @@ public ActionParameters params() { return actionParameters; } - @Parameters(commandDescription = "Relabel sequences.", optionPrefixes = "-") + @Parameters(commandDescription = "Relabel sequences (change sequence headers).") public static final class RenameParameters extends ActionParameters { @Parameter(description = "[ input_file_R1.fastq[.gz] [ output_file.fastq[.gz] ] ]", variableArity = true) public List parameters = new ArrayList<>(); - @Parameter(description = "Pattern (%n - for index; %o - for old description)", + @Parameter(description = "New header (%n - for index; %o - for old description; %g1, %g2, ... - for old description)", names = {"-p", "--pattern"}) String pattern; + @Parameter(description = "New name (%n - for index; %o - for old description; " + + "%g1, %g2, ... - extracted regexp groups, if -p option used), example: -n \"R%n %o\" to add read index to header", + names = {"-n", "--name"}) + String name; + public String getInput() { - return parameters.size() == 0 ? "-" : parameters.get(0); + return parameters.size() == 0 ? "." : parameters.get(0); } public String getOutput() { - return parameters.size() < 2 ? "-" : parameters.get(1); + return parameters.size() < 2 ? "." : parameters.get(1); } @Override diff --git a/src/main/java/com/milaboratory/mitools/cli/SplitAction.java b/src/main/java/com/milaboratory/mitools/cli/SplitAction.java index b5c1d9e..fba7c18 100644 --- a/src/main/java/com/milaboratory/mitools/cli/SplitAction.java +++ b/src/main/java/com/milaboratory/mitools/cli/SplitAction.java @@ -18,6 +18,9 @@ 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.core.io.sequence.SequenceRead; import com.milaboratory.core.io.sequence.SequenceReaderCloseable; import com.milaboratory.core.io.sequence.SequenceWriter; @@ -111,8 +114,8 @@ public SequenceReaderCloseable getSequenceReader() throws IOException { } @Parameters(commandDescription = "Splits input fastq file(s) into several parts. \"{P}\" in output file name " + - "will be substituted with sequential part index, \n\"{R}\" will be substituted with read index (in case " + - "of one input file will always be substituted with \"1\").", optionPrefixes = "-") + "will be substituted with sequential part index, \"{R}\" will be substituted with read index (in case " + + "of one input file will always be substituted with \"1\").") public static final class AParameters extends ActionParameters { @Parameter(description = "input_file_R1.fastq[.gz] [ input_file_R2.fastq[.gz] ] output_file_part{P}_R{R}.fastq[.gz]", variableArity = true) diff --git a/src/main/java/com/milaboratory/mitools/cli/TrimAction.java b/src/main/java/com/milaboratory/mitools/cli/TrimAction.java index fda457a..910775d 100644 --- a/src/main/java/com/milaboratory/mitools/cli/TrimAction.java +++ b/src/main/java/com/milaboratory/mitools/cli/TrimAction.java @@ -22,6 +22,9 @@ import com.beust.jcommander.ParameterException; import com.beust.jcommander.Parameters; import com.beust.jcommander.validators.PositiveInteger; +import com.milaboratory.cli.Action; +import com.milaboratory.cli.ActionHelper; +import com.milaboratory.cli.ActionParameters; import com.milaboratory.core.io.sequence.SingleRead; import com.milaboratory.core.io.sequence.fastq.SingleFastqReader; import com.milaboratory.core.io.sequence.fastq.SingleFastqWriter; @@ -51,8 +54,8 @@ public void go(ActionHelper helper) throws Exception { final Merger buffered = buffered(stats, 256); - final SequenceTrimmer trimmer = new SequenceTrimmer(actionParameters.qualutyThreshold, - actionParameters.trimmLeft(), actionParameters.trimmRight()); + final SequenceTrimmer trimmer = new SequenceTrimmer(actionParameters.qualityThreshold, + actionParameters.trimLeft(), actionParameters.trimRight()); ParallelProcessor processor = new ParallelProcessor<>(buffered, trimmer, 1024, actionParameters.threads); @@ -91,20 +94,20 @@ public ActionParameters params() { return actionParameters; } - @Parameters(commandDescription = "Trim low quality ends of reads.", optionPrefixes = "-") + @Parameters(commandDescription = "Trim low quality ends of reads.") private final static class TrimParameters extends ActionParameters { @Parameter(description = "input_file.fastq[.gz] -|output_file.fastq[.gz]", variableArity = true) public List parameters = new ArrayList<>(); - @Parameter(description = "Trim left", names = {"-tl", "--left"}) + @Parameter(description = "Trim from left side", names = {"-tl", "--left"}) public Boolean left; - @Parameter(description = "Trim right", names = {"-tr", "--right"}) + @Parameter(description = "Trim from right side", names = {"-tr", "--right"}) public Boolean right; @Parameter(description = "Quality threshold", names = {"-q", "--quality"}, validateWith = PositiveInteger.class) - public int qualutyThreshold = 15; + public int qualityThreshold = 15; @Parameter(description = "Length threshold", names = {"-l", "--length"}) public int length = 10; @@ -125,11 +128,11 @@ public String getOutput() { return parameters.get(1); } - public boolean trimmLeft() { + public boolean trimLeft() { return left == null ? false : left; } - public boolean trimmRight() { + public boolean trimRight() { return right == null ? false : right; } diff --git a/src/main/java/com/milaboratory/mitools/merger/MergerParameters.java b/src/main/java/com/milaboratory/mitools/merger/MergerParameters.java deleted file mode 100644 index 10046fa..0000000 --- a/src/main/java/com/milaboratory/mitools/merger/MergerParameters.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.merger; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.milaboratory.core.PairedEndReadsLayout; -import com.milaboratory.primitivio.annotations.Serializable; - -/** - * @author Dmitry Bolotin - * @author Stanislav Poslavsky - */ -@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, isGetterVisibility = JsonAutoDetect.Visibility.NONE, - getterVisibility = JsonAutoDetect.Visibility.NONE) -@Serializable(asJson = true) -public final class MergerParameters implements java.io.Serializable { - public static final int DEFAULT_MAX_QUALITY_VALUE = 50; - - final QualityMergingAlgorithm qualityMergingAlgorithm; - final PairedEndReadsLayout partsLayout; - final int minimalOverlap, maxQuality; - final double minimalIdentity; - - @JsonCreator - public MergerParameters( - @JsonProperty("qualityMergingAlgorithm") QualityMergingAlgorithm qualityMergingAlgorithm, - @JsonProperty("partsLayout") PairedEndReadsLayout partsLayout, - @JsonProperty("minimalOverlap") int minimalOverlap, - @JsonProperty("maxQuality") Integer maxQuality, - @JsonProperty("minimalIdentity") double minimalIdentity) { - this.qualityMergingAlgorithm = qualityMergingAlgorithm; - this.partsLayout = partsLayout; - this.minimalOverlap = minimalOverlap; - this.minimalIdentity = minimalIdentity; - this.maxQuality = maxQuality == null ? DEFAULT_MAX_QUALITY_VALUE : maxQuality; - } - - public int getMinimalOverlap() { - return minimalOverlap; - } - - public double getMinimalIdentity() { - return minimalIdentity; - } - - public int getMaxQuality() { - return maxQuality; - } - - public QualityMergingAlgorithm getQualityMergingAlgorithm() { - return qualityMergingAlgorithm; - } - - public PairedEndReadsLayout getPartsLayout() { - return partsLayout; - } - - public MergerParameters overrideReadsLayout(PairedEndReadsLayout partsLayout) { - return new MergerParameters(qualityMergingAlgorithm, partsLayout, minimalOverlap, maxQuality, minimalIdentity); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MergerParameters that = (MergerParameters) o; - - if (minimalOverlap != that.minimalOverlap) return false; - if (maxQuality != that.maxQuality) return false; - if (Double.compare(that.minimalIdentity, minimalIdentity) != 0) return false; - if (qualityMergingAlgorithm != that.qualityMergingAlgorithm) return false; - return partsLayout == that.partsLayout; - - } - - @Override - public int hashCode() { - int result; - long temp; - result = qualityMergingAlgorithm != null ? qualityMergingAlgorithm.hashCode() : 0; - result = 31 * result + (partsLayout != null ? partsLayout.hashCode() : 0); - result = 31 * result + minimalOverlap; - result = 31 * result + maxQuality; - temp = Double.doubleToLongBits(minimalIdentity); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - return result; - } -} diff --git a/src/main/java/com/milaboratory/mitools/merger/MismatchOnlyPairedReadMerger.java b/src/main/java/com/milaboratory/mitools/merger/MismatchOnlyPairedReadMerger.java deleted file mode 100644 index edc18c1..0000000 --- a/src/main/java/com/milaboratory/mitools/merger/MismatchOnlyPairedReadMerger.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.merger; - -import cc.redberry.pipe.Processor; -import com.milaboratory.core.PairedEndReadsLayout; -import com.milaboratory.core.io.sequence.PairedRead; -import com.milaboratory.core.motif.BitapMatcher; -import com.milaboratory.core.motif.BitapPattern; -import com.milaboratory.core.motif.Motif; -import com.milaboratory.core.motif.MotifUtils; -import com.milaboratory.core.sequence.NSequenceWithQuality; -import com.milaboratory.core.sequence.NucleotideSequence; -import com.milaboratory.core.sequence.SequenceBuilder; -import com.milaboratory.core.sequence.SequenceQualityBuilder; - -import static com.milaboratory.core.sequence.SequencesUtils.mismatchCount; -import static java.lang.Math.*; - -public final class MismatchOnlyPairedReadMerger implements Processor, - java.io.Serializable { - public static final int MIN_SCORE_VALUE = 3; // 50-50 - final int minOverlap; - final double maxMismatchesPart; - final int maxScoreValue; - // opposite reads direction or collinear - final boolean[] strands; - final int motifLength; - final int maxMismatchesInMotif; - final QualityMergingAlgorithm qualityMergingAlgorithm; - final PairedEndReadsLayout pairedEndReadsLayout; - - /** - * Creates paired-end reads merger for Illumina (or other opposite reads) data. - * - * @param parameters merger parameters - */ - public MismatchOnlyPairedReadMerger(MergerParameters parameters) { - this(parameters.getMinimalOverlap(), parameters.getMinimalIdentity(), parameters.getMaxQuality(), - parameters.qualityMergingAlgorithm, parameters.getPartsLayout()); - } - - /** - * Creates paired-end reads merger. - * - * @param minOverlap minimal number of nucleotide in overlap region - * @param minimalIdentity maximal allowed percent of mismatches in overlap region - * @param maxScoreValue maximal output quality score value - * @param qualityMergingAlgorithm algorithm to infer quality of merged reads from it's pairs - * @param pairedEndReadsLayout orientation of read pairs - */ - public MismatchOnlyPairedReadMerger(int minOverlap, double minimalIdentity, int maxScoreValue, - QualityMergingAlgorithm qualityMergingAlgorithm, - PairedEndReadsLayout pairedEndReadsLayout) { - if (qualityMergingAlgorithm == null || pairedEndReadsLayout == null) - throw new NullPointerException(); - this.qualityMergingAlgorithm = qualityMergingAlgorithm; - this.pairedEndReadsLayout = pairedEndReadsLayout; - this.minOverlap = minOverlap; - this.maxMismatchesPart = 1.0 - minimalIdentity; - this.strands = pairedEndReadsLayout.getPossibleRelativeStrands(); - this.maxScoreValue = maxScoreValue; - - // Calculating length fo motif to be used in Bitap search. - this.motifLength = min(minOverlap, 62); - this.maxMismatchesInMotif = (int) round(motifLength * maxMismatchesPart); - } - - @Override - public PairedReadMergingResult process(PairedRead pairedRead) { - NSequenceWithQuality read1p = pairedRead.getR1().getData(); - NSequenceWithQuality read2p = pairedRead.getR2().getData(); - - // If there is no sufficient letters in one of read overlapping is impossible - if (read1p.size() < minOverlap || read2p.size() < minOverlap) - // Return failed result - return new PairedReadMergingResult(pairedRead); - - PairedReadMergingResult ret = null; - - for (boolean strand : strands) { - NSequenceWithQuality read1 = read1p; - - // Making reverse complement from second read to bring reads to the same strand - // (if reads configuration is opposite) - NSequenceWithQuality read2 = strand ? read2p.getReverseComplement() : read2p; - - // read2 always smaller then read1 - if (read2.size() > read1.size()) { - NSequenceWithQuality tmp = read1; - read1 = read2; - read2 = tmp; - } - - // Searching - - // Creating bitap pattern for beginning and ending of read2 - Motif motif = MotifUtils.twoSequenceMotif( - read2.getSequence(), 0, - read2.getSequence(), read2.size() - motifLength, - motifLength - ); - BitapPattern bitapPattern = motif.getBitapPattern(); - BitapMatcher bitapMatcher = bitapPattern.substitutionOnlyMatcherFirst(maxMismatchesInMotif, read1.getSequence()); - - int matchPosition, mismatches, overlap; - - PairedReadMergingResult tmp = null; - while ((matchPosition = bitapMatcher.findNext()) != -1) { - - // Case: beginning of r2 matched - - // Finally checking current hit position - overlap = min(read1.size() - matchPosition, read2.size()); - if ((mismatches = mismatchCount( - read1.getSequence(), matchPosition, - read2.getSequence(), 0, - overlap)) <= overlap * maxMismatchesPart) { - tmp = new PairedReadMergingResult(pairedRead, overlap(read1, read2, matchPosition), - overlap, mismatches); - break; - } - - // Case: ending of r2 matched - matchPosition += motifLength; // Calculating position of right overlap boundary - overlap = min(matchPosition, read2.size()); - if ((mismatches = mismatchCount( - read1.getSequence(), matchPosition - overlap, - read2.getSequence(), max(0, read2.size() - overlap), - overlap)) <= overlap * maxMismatchesPart) { - tmp = new PairedReadMergingResult(pairedRead, overlap(read1, read2, min(matchPosition - read2.size(), 0)), - overlap, mismatches); - break; - } - } - if (tmp != null && (ret == null || ret.score() < tmp.score())) - ret = tmp; - } - - if (ret == null) - return new PairedReadMergingResult(pairedRead); - else - return ret; - } - - /** - * @param seq1 sequence 1 - * @param seq2 sequence 2 - * @param offset position of first nucleotide of seq2 in seq1 - * @return overlapped sequence - */ - private NSequenceWithQuality overlap(NSequenceWithQuality seq1, NSequenceWithQuality seq2, int offset) { - // Calculating length of resulting sequence - int length = abs(offset) + - (offset >= 0 ? - max(seq1.size() - offset, seq2.size()) : - max(seq1.size(), seq2.size() + offset) // offset is negative here - ); - - SequenceBuilder seqBuilder = NucleotideSequence.ALPHABET.getBuilder() - .ensureCapacity(length); - SequenceQualityBuilder qualBuilder = new SequenceQualityBuilder().ensureCapacity(length); - - byte quality, letter, l, q; - int from = min(0, offset); - int position, to = length + from; - for (int i = from; i < to; ++i) { - quality = 0; - letter = -1; - - // Checking read 1 - if (i >= 0 && i < seq1.size()) { - quality = seq1.getQuality().value(i); - letter = seq1.getSequence().codeAt(i); - } - - // Checking read 2 - position = i - offset; - if (position >= 0 && position < seq2.size()) { - l = seq2.getSequence().codeAt(position); - q = seq2.getQuality().value(position); - if (letter == -1) { - letter = l; - quality = q; - } else if (letter == l) - quality = (byte) min(maxScoreValue, quality + q); - else - switch (qualityMergingAlgorithm) { - case SumSubtraction: - if (q > quality) { - letter = l; - quality = (byte) max(MIN_SCORE_VALUE, q - quality); - } else - quality = (byte) max(MIN_SCORE_VALUE, quality - q); - break; - case SumMax: - if (q > quality) { - letter = l; - quality = q; - } - break; - } - } - - assert letter != -1; - - seqBuilder.append(letter); - qualBuilder.append(quality); - } - - return new NSequenceWithQuality(seqBuilder.createAndDestroy(), qualBuilder.createAndDestroy()); - } -} diff --git a/src/main/java/com/milaboratory/mitools/merger/PairedReadMergingResult.java b/src/main/java/com/milaboratory/mitools/merger/PairedReadMergingResult.java deleted file mode 100644 index c262d63..0000000 --- a/src/main/java/com/milaboratory/mitools/merger/PairedReadMergingResult.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.merger; - -import com.milaboratory.core.io.sequence.PairedRead; -import com.milaboratory.core.sequence.NSequenceWithQuality; - -public class PairedReadMergingResult implements java.io.Serializable { - private static final int MATCH_SCORE = 2; - private static final int MISMATCH_SCORE = -5; - - final PairedRead originalRead; - final NSequenceWithQuality overlappedSequence; - final int overlap; - final int errors; - - /** - * Constructor for failed merging result. - * - * @param originalRead original read - */ - public PairedReadMergingResult(PairedRead originalRead) { - this.originalRead = originalRead; - this.overlappedSequence = null; - this.overlap = 0; - this.errors = -1; - } - - /** - * Constructor for successful merging result. - * - * @param originalRead original read - * @param overlappedSequence reconstructed (overlapped) sequence from paired-end reads - * @param overlap number of overlapped nucleotides - * @param errors number of mismatches/insertions/deletions found in overlapping region - */ - public PairedReadMergingResult(PairedRead originalRead, NSequenceWithQuality overlappedSequence, - int overlap, int errors) { - this.originalRead = originalRead; - this.overlappedSequence = overlappedSequence; - this.overlap = overlap; - this.errors = errors; - } - - public boolean isSuccessful() { - return overlappedSequence != null; - } - - public PairedRead getOriginalRead() { - return originalRead; - } - - public NSequenceWithQuality getOverlappedSequence() { - return overlappedSequence; - } - - public int getOverlap() { - return overlap; - } - - public int getErrors() { - return errors; - } - - int score() { - return (overlap - errors) * MATCH_SCORE + errors * MISMATCH_SCORE; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - PairedReadMergingResult that = (PairedReadMergingResult) o; - - if (overlap != that.overlap) return false; - if (errors != that.errors) return false; - if (!originalRead.equals(that.originalRead)) return false; - return overlappedSequence.equals(that.overlappedSequence); - - } - - @Override - public int hashCode() { - int result = originalRead.hashCode(); - result = 31 * result + overlappedSequence.hashCode(); - result = 31 * result + overlap; - result = 31 * result + errors; - return result; - } - - @Override - public String toString() { - return "PairedReadMergingResult{" + - "originalRead=" + originalRead + - ", overlappedSequence=" + overlappedSequence + - ", overlap=" + overlap + - ", errors=" + errors + - '}'; - } -} diff --git a/src/main/java/com/milaboratory/mitools/merger/QualityMergingAlgorithm.java b/src/main/java/com/milaboratory/mitools/merger/QualityMergingAlgorithm.java deleted file mode 100644 index e20f629..0000000 --- a/src/main/java/com/milaboratory/mitools/merger/QualityMergingAlgorithm.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.merger; - -public enum QualityMergingAlgorithm { - SumMax("max"), SumSubtraction("sub"); - public final String cliName; - - QualityMergingAlgorithm(String cliName) { - this.cliName = cliName; - } - - public static QualityMergingAlgorithm getFromCLIName(String cliName) { - for (QualityMergingAlgorithm qma : values()) - if (qma.cliName.equals(cliName)) - return qma; - return null; - } -} diff --git a/src/main/java/com/milaboratory/mitools/cli/ActionParametersParser.java b/src/main/java/com/milaboratory/mitools/processors/CutSide.java similarity index 78% rename from src/main/java/com/milaboratory/mitools/cli/ActionParametersParser.java rename to src/main/java/com/milaboratory/mitools/processors/CutSide.java index e52b270..3e5a8d9 100644 --- a/src/main/java/com/milaboratory/mitools/cli/ActionParametersParser.java +++ b/src/main/java/com/milaboratory/mitools/processors/CutSide.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 MiLaboratory.com + * Copyright 2016 MiLaboratory.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.milaboratory.mitools.cli; +package com.milaboratory.mitools.processors; -public interface ActionParametersParser { - void parseParameters(String[] args); +public enum CutSide { + Left, Random, Right } diff --git a/src/main/java/com/milaboratory/mitools/processors/RandomCutter.java b/src/main/java/com/milaboratory/mitools/processors/RandomCutter.java new file mode 100644 index 0000000..421c2cd --- /dev/null +++ b/src/main/java/com/milaboratory/mitools/processors/RandomCutter.java @@ -0,0 +1,80 @@ +/* + * Copyright 2016 MiLaboratory.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.milaboratory.mitools.processors; + +import cc.redberry.pipe.Processor; +import com.milaboratory.core.io.sequence.SingleRead; +import com.milaboratory.core.io.sequence.SingleReadImpl; +import com.milaboratory.util.RandomUtil; +import org.apache.commons.math3.random.RandomGenerator; +import org.apache.commons.math3.random.Well44497b; + +public final class RandomCutter implements Processor { + private final CutSide side; + private final int minLength, maxLength; + private final long seed; + + public RandomCutter(CutSide side, int minLength, int maxLength) { + this(side, minLength, maxLength, 0); + } + + public RandomCutter(CutSide side, int minLength, int maxLength, long seed) { + if (side == null) + throw new NullPointerException(); + this.side = side; + this.minLength = minLength; + this.maxLength = maxLength; + this.seed = seed; + } + + @Override + public SingleRead process(SingleRead input) { + RandomGenerator rnd; + if (seed == 0) + rnd = RandomUtil.getThreadLocalRandom(); + else { + Well44497b w = new Well44497b(seed); + w.setSeed(5147 * w.nextLong() + 7549 * input.getId()); + rnd = w; + } + int length; + if (minLength == maxLength) + length = minLength; + else + length = minLength + rnd.nextInt(maxLength - minLength + 1); + if (length > input.getData().size()) + length = input.getData().size(); + + int startPosition; + + switch (side) { + case Left: + startPosition = 0; + break; + case Right: + startPosition = input.getData().size() - length; + break; + case Random: + startPosition = length == input.getData().size() ? 0 : rnd.nextInt(input.getData().size() - length + 1); + break; + default: + // Will never be thrown + throw new IllegalArgumentException(); + } + + return new SingleReadImpl(input.getId(), input.getData().getRange(startPosition, startPosition + length), input.getDescription()); + } +} diff --git a/src/main/java/com/milaboratory/mitools/cli/ActionHelpProvider.java b/src/main/java/com/milaboratory/mitools/util/VersionInfoUtils.java similarity index 75% rename from src/main/java/com/milaboratory/mitools/cli/ActionHelpProvider.java rename to src/main/java/com/milaboratory/mitools/util/VersionInfoUtils.java index 26e475c..2d47bd7 100644 --- a/src/main/java/com/milaboratory/mitools/cli/ActionHelpProvider.java +++ b/src/main/java/com/milaboratory/mitools/util/VersionInfoUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 MiLaboratory.com + * Copyright 2016 MiLaboratory.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.milaboratory.mitools.cli; +package com.milaboratory.mitools.util; /** - * Created by dbolotin on 28/08/14. + * Created by dbolotin on 12/07/16. */ -public interface ActionHelpProvider { - void printHelp(StringBuilder builder); +public class VersionInfoUtils { } diff --git a/src/test/java/com/milaboratory/mitools/merger/MergerParametersTest.java b/src/test/java/com/milaboratory/mitools/merger/MergerParametersTest.java deleted file mode 100644 index a2749b4..0000000 --- a/src/test/java/com/milaboratory/mitools/merger/MergerParametersTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.merger; - -import com.milaboratory.core.PairedEndReadsLayout; -import com.milaboratory.test.TestUtil; -import com.milaboratory.util.GlobalObjectMappers; -import org.junit.Assert; -import org.junit.Test; - -public class MergerParametersTest { - @Test - public void test1() throws Exception { - MergerParameters parameters = new MergerParameters(QualityMergingAlgorithm.SumMax, null, 15, 50, 0.8); - TestUtil.assertJson(parameters); - } - - @Test - public void test2() throws Exception { - MergerParameters parameters = new MergerParameters(QualityMergingAlgorithm.SumSubtraction, - PairedEndReadsLayout.Collinear, 15, 50, 0.8); - TestUtil.assertJson(parameters, true); - } - - @Test - public void test3() throws Exception { - MergerParameters parameters = new MergerParameters(QualityMergingAlgorithm.SumSubtraction, - PairedEndReadsLayout.Collinear, 15, 50, 0.8); - String value = "{\n" + - " \"qualityMergingAlgorithm\" : \"SumSubtraction\",\n" + - " \"partsLayout\" : \"Collinear\",\n" + - " \"minimalOverlap\" : 15,\n" + - " \"minimalIdentity\" : 0.8\n" + - "}"; - MergerParameters deserialized = GlobalObjectMappers.PRETTY.readValue(value, MergerParameters.class); - Assert.assertEquals(parameters, deserialized); - } - -} \ No newline at end of file diff --git a/src/test/java/com/milaboratory/mitools/merger/MismatchOnlyPairedReadMergerTest.java b/src/test/java/com/milaboratory/mitools/merger/MismatchOnlyPairedReadMergerTest.java deleted file mode 100644 index 37ed68e..0000000 --- a/src/test/java/com/milaboratory/mitools/merger/MismatchOnlyPairedReadMergerTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2015 MiLaboratory.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.milaboratory.mitools.merger; - -import com.milaboratory.core.PairedEndReadsLayout; -import com.milaboratory.core.io.sequence.PairedRead; -import com.milaboratory.core.io.sequence.SingleReadImpl; -import com.milaboratory.core.sequence.NSequenceWithQuality; -import org.junit.Assert; -import org.junit.Test; - -import java.util.Arrays; - -public class MismatchOnlyPairedReadMergerTest { - @Test - public void test1() throws Exception { - //CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG - //CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCC - // CGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG - //AAAAAAAAAAAAAAAAAAAAAAAAAAAAbbbbbbbbbbbbbbbbbbbbBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB - mAssert("CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCC", - "CGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - 0, 10, - "CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAXXXXXXXXXXXXXXXXXXXXBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); - } - - @Test - public void test2() throws Exception { - //CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG - // TGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTT - //AAAAAAAAAAbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - mAssert("CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - "TGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTT", - 0, 10, - "CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - "AAAAAAAAAAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); - } - - @Test - public void test3() throws Exception { - //CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG - //CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATC - // TCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG - //AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbbbbbbbbbbbbbbbbbbbbbbBBBBBBBBBBBBBBBBBBBBBBBBBBBB - mAssert("CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATC", - "TCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - 0, 10, - "CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXXXXXXXXXXXXXXXXXXXXXXBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); - } - - @Test - public void test1mm() throws Exception { - //CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG - //CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGACGACCGGCC - // CGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG - //AAAAAAAAAAAAAAAAAAAAAAAAAAAAbbbbbbbbbbbBbbbbbbbbBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB - mAssert("CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGACGACCGGCC", - "CGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - 1, 10, - "CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAXXXXXXXXXXX$XXXXXXXXBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); - mAssert("CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGACGACCGGCC", - "CGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - 0, 10, null, null); - } - - @Test - public void test2mm() throws Exception { - //CGCACAGTGTTGTCAAAGACAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG - // TGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTT - //AAAAAAAAAAbbbbbbbbbBbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - mAssert("CGCACAGTGTTGTCAAAGACAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - "TGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTT", - 1, 10, - "CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - "AAAAAAAAAAXXXXXXXXX$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); - mAssert("CGCACAGTGTTGTCAAAGACAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - "TGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTT", - 0, 10, null, null); - } - - @Test - public void test3mm() throws Exception { - //CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG - //CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTACTCCTTTGACATGATTGGATC - // TCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG - //AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABbbbbbbbbbbbbbbbbbbbbbBBBBBBBBBBBBBBBBBBBBBBBBBBBB - mAssert("CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTACTCCTTTGACATGATTGGATC", - "TCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - 1, 10, - "CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTTCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA$XXXXXXXXXXXXXXXXXXXXXBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); - mAssert("CGCACAGTGTTGTCAAAGAAAACGCGTACGACATTGAGAAGACCGGCCGTACTCCTTTGACATGATTGGATC", - "TCTCCTTTGACATGATTGGATCGGTTGCTGCCGGCCCAGAATCCTAGCAG", - 0, 10, null, null); - } - - public static void mAssert(String seq1, String seq2, int maxMuts, int overlap, - String expectedSequence, String expectedQuality) { - MismatchOnlyPairedReadMerger merger = new MismatchOnlyPairedReadMerger(overlap, 1.0 - 1.0 * maxMuts / overlap, 55, - QualityMergingAlgorithm.SumSubtraction, - PairedEndReadsLayout.Collinear); - PairedReadMergingResult processed = merger.process(new PairedRead( - new SingleReadImpl(0, new NSequenceWithQuality(seq1, lets('A', seq1.length())), "A"), - new SingleReadImpl(0, new NSequenceWithQuality(seq2, lets('B', seq2.length())), "B"))); - if (expectedSequence == null) - Assert.assertFalse(processed.isSuccessful()); - else { - Assert.assertTrue(processed.isSuccessful()); - Assert.assertEquals(expectedSequence, processed.getOverlappedSequence().getSequence().toString()); - Assert.assertEquals(expectedQuality, processed.getOverlappedSequence().getQuality().toString()); - } - - merger = new MismatchOnlyPairedReadMerger(overlap, 1.0 - 1.0 * maxMuts / overlap, 55, - QualityMergingAlgorithm.SumSubtraction, - PairedEndReadsLayout.Unknown); - processed = merger.process(new PairedRead( - new SingleReadImpl(0, new NSequenceWithQuality(seq1, lets('A', seq1.length())), "A"), - new SingleReadImpl(0, new NSequenceWithQuality(seq2, lets('B', seq2.length())).getReverseComplement(), "B"))); - if (expectedSequence == null) - Assert.assertFalse(processed.isSuccessful()); - else { - Assert.assertTrue(processed.isSuccessful()); - Assert.assertEquals(expectedSequence, processed.getOverlappedSequence().getSequence().toString()); - Assert.assertEquals(expectedQuality, processed.getOverlappedSequence().getQuality().toString()); - } - } - - public static String lets(char letter, int count) { - char[] chars = new char[count]; - Arrays.fill(chars, letter); - return new String(chars); - } -} \ No newline at end of file diff --git a/src/test/java/com/milaboratory/mitools/merger/PairedReadMergingResultTest.java b/src/test/java/com/milaboratory/mitools/merger/PairedReadMergingResultTest.java deleted file mode 100644 index a26104c..0000000 --- a/src/test/java/com/milaboratory/mitools/merger/PairedReadMergingResultTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.milaboratory.mitools.merger; - -import com.milaboratory.core.io.sequence.PairedRead; -import com.milaboratory.core.io.sequence.SingleReadImpl; -import com.milaboratory.core.io.util.TestUtil; -import com.milaboratory.core.sequence.NSequenceWithQuality; -import com.milaboratory.core.sequence.NucleotideSequence; -import com.milaboratory.core.sequence.SequenceQuality; -import org.junit.Test; - -/** - * Created by poslavsky on 15/04/15. - */ -public class PairedReadMergingResultTest { - @Test - public void test1() throws Exception { - PairedReadMergingResult se = new PairedReadMergingResult(new PairedRead( - new SingleReadImpl(12, new NSequenceWithQuality(new NucleotideSequence("atgc"), new SequenceQuality("++++")), "x"), - new SingleReadImpl(12, new NSequenceWithQuality(new NucleotideSequence("atgc"), new SequenceQuality("++++")), "x")), - new NSequenceWithQuality(new NucleotideSequence("atgc"), new SequenceQuality("++++")), 12, 3); - TestUtil.assertJavaSerialization(se); - } -} \ No newline at end of file diff --git a/src/test/java/com/milaboratory/mitools/processors/RandomCutterTest.java b/src/test/java/com/milaboratory/mitools/processors/RandomCutterTest.java new file mode 100644 index 0000000..c3e395a --- /dev/null +++ b/src/test/java/com/milaboratory/mitools/processors/RandomCutterTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2016 MiLaboratory.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.milaboratory.mitools.processors; + +import com.milaboratory.core.io.sequence.SingleRead; +import com.milaboratory.core.io.sequence.SingleReadImpl; +import com.milaboratory.core.sequence.NSequenceWithQuality; +import gnu.trove.set.hash.TIntHashSet; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by dbolotin on 10/03/16. + */ +public class RandomCutterTest { + @Test + public void test1() throws Exception { + RandomCutter cutter = new RandomCutter(CutSide.Random, 10, 20); + SingleReadImpl read = new SingleReadImpl(1, new NSequenceWithQuality("ATTAGACA"), "Hi!"); + SingleRead processed = cutter.process(read); + Assert.assertEquals(processed, read); + + TIntHashSet vals = new TIntHashSet(); + + for (int i = 0; i < 1000; i++) { + read = new SingleReadImpl(1, new NSequenceWithQuality("ATTAGACAATTAGACAATTAGACAATTAGACA"), "Hi!"); + processed = cutter.process(read); + Assert.assertTrue(processed.getData().size() >= 10 && processed.getData().size() <= 20); + vals.add(processed.getData().size()); + } + Assert.assertTrue(vals.contains(20)); + Assert.assertTrue(vals.contains(10)); + + cutter = new RandomCutter(CutSide.Left, 10, 20); + vals = new TIntHashSet(); + for (int i = 0; i < 1000; i++) { + read = new SingleReadImpl(1, new NSequenceWithQuality("ATTAGACAATTAGACAATTAGACAATTAGACA"), "Hi!"); + processed = cutter.process(read); + Assert.assertTrue(processed.getData().size() >= 10 && processed.getData().size() <= 20); + Assert.assertTrue(read.getData().getSequence().toString().startsWith(processed.getData().getSequence().toString())); + vals.add(processed.getData().size()); + + } + Assert.assertTrue(vals.contains(20)); + Assert.assertTrue(vals.contains(10)); + + cutter = new RandomCutter(CutSide.Right, 10, 20); + vals = new TIntHashSet(); + for (int i = 0; i < 1000; i++) { + read = new SingleReadImpl(1, new NSequenceWithQuality("ATTAGACAATTAGACAATTAGACAATTAGACA"), "Hi!"); + processed = cutter.process(read); + Assert.assertTrue(processed.getData().size() >= 10 && processed.getData().size() <= 20); + Assert.assertTrue(read.getData().getSequence().toString().endsWith(processed.getData().getSequence().toString())); + vals.add(processed.getData().size()); + } + Assert.assertTrue(vals.contains(20)); + Assert.assertTrue(vals.contains(10)); + } +} \ No newline at end of file