Mercurial > repos > timpalpant > java_genomics_toolkit
changeset 0:1daf3026d231
Upload alpha version
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/.classpath Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gui"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="lib" path="lib/jcommander-1.20.jar" sourcepath="/jcommander/src"/> + <classpathentry kind="lib" path="lib/jtransforms-2.4.jar"/> + <classpathentry kind="lib" path="lib/log4j-1.2.15.jar"/> + <classpathentry kind="lib" path="lib/BigWig.jar"/> + <classpathentry kind="lib" path="lib/commons-math-2.2.jar"/> + <classpathentry kind="lib" path="lib/commons-lang3-3.1.jar"/> + <classpathentry kind="lib" path="lib/sam-1.56.jar"/> + <classpathentry kind="lib" path="lib/macify-1.4.jar" sourcepath="/macify/src"/> + <classpathentry combineaccessrules="false" kind="src" path="/java-genomics-io"/> + <classpathentry kind="output" path="bin"/> +</classpath>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/.gitignore Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,6 @@ +bin +build +dist +*.class +*.log +.DS_Store
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/.project Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>java-genomics-toolkit</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/META-INF/MANIFEST.MF Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,9 @@ +Manifest-Version: 1.0 +Main-Class: edu.unc.genomics.GenomicsToolkit +Bundle-ManifestVersion: 2 +Bundle-Name: java-genomics-toolkit +Bundle-SymbolicName: java-genomics-toolkit +Bundle-Version: 1.0.0 +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-Description: This project provides tools for common genomic data processing. +Bundle-DocURL: http://github.com/timpalpant/java-genomics-toolkit \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/README.rdoc Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,43 @@ += Java Genomics Toolkit + +This is a collection of applications for genomics data processing, primarily high-throughput next-generation sequencing. There is a particular focus on processing data in Wiggle format, since many other tools already cover SAM, BAM, FastQ, etc. However, Wiggle/BigWig formats provide a compact way to store numerical data resulting from ChIP-seq and MNase-seq experiments. Common computations provided in this toolkit include adding, subtracting, dividing, multiplying, log-transforming, averaging, Z-scoring, and Gaussian smoothing Wig files. + +Tools may be run from the command-line, a simple Swing GUI, or from Galaxy (http://getgalaxy.org). + +== Loading the Tools into Galaxy + +TODO + +== Using the ToolRunner GUI + +TODO + +== Command-Line Usage + +Applications can be run on the command-line, and the toolRunner.sh script is provided for convenience. Calling any script without arguments will display the help, as well as the missing mandatory arguments: + + $ > ./toolRunner.sh wigmath.AddWig + $ Usage: <main class> [options] Input files + $ Options: + $ * -o, --output Output file + +Mandatory arguments are denoted with a (*). + +Other tools require more input: + + $ > ./toolRunner.sh ngs.Autocorrelation + $ Usage: <main class> [options] + $ Options: + $ * -i, --input Input file + $ * -l, --loci Genomic loci (Bed format) + $ -m, --max Autocorrelation limit (bp) + $ Default: 200 + $ * -o, --output Output file + +=== Log transform a Wig file with base 2 + + $ > ./toolRunner.sh wigmath.LogTransform --input input.wig --base 2 --output output.log2.wig + +== Java Genomics IO + +Those wishing to write their own scripts may be interested in https://github.com/timpalpant/java-genomics-io, the toolkit upon which these applications are built. \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/build.xml Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<project name="java-genomics-toolkit" default="jar" basedir="."> + <description> + build the toolkit + </description> + + <!-- set global properties for this build --> + <property name="version" value="1.1.0"/> + <property name="buildnumber" value="1"/> + <property name="copyright" value="Copyright © 2011 Timothy Palpant"/> + + <!-- directory variables --> + <property name="src" location="src"/> + <property name="test" location="test"/> + <property name="gui" location="gui"/> + <property name="build" location="build"/> + <property name="dist" location="dist"/> + <property name="lib" location="lib"/> + + <!-- compile all Java code --> + <target name="compile" description="compile the scripts"> + <!-- Create the build directory structure used by compile --> + <mkdir dir="${build}"/> + + <!-- Compile the java code from ${src} into ${build} --> + <javac srcdir="${src}" destdir="${build}" source="1.7" target="1.7"> + <classpath> + <path id="lib.path.ref"> + <fileset dir="lib" includes="*.jar"/> + </path> + </classpath> + </javac> + + <!-- Compile the java code from ${gui} into ${build} --> + <javac srcdir="${gui}" destdir="${build}" source="1.7" target="1.7"> + <classpath> + <path id="lib.path.ref"> + <fileset dir="lib" includes="*.jar"/> + </path> + </classpath> + </javac> + </target> + + <!-- package all Java code into a JAR file --> + <target name="jar" depends="compile" description="generate the jarfile"> + <!-- Create the distribution directory --> + <mkdir dir="${dist}"/> + + <!-- Put everything in ${build} into the jar file --> + <jar jarfile="${dist}/${ant.project.name}.jar" manifest="META-INF/MANIFEST.MF"> + <fileset dir="${build}" /> + </jar> + </target> + + <!-- Package the jar file into a Mac OS X application with jarbundler --> + <target name="package-osx" depends="jar" description="Build the application for OS X"> + <taskdef name="jarbundler" + classpath="${lib}/jarbundler-2.2.0.jar" + classname="net.sourceforge.jarbundler.JarBundler"/> + + <jarbundler dir="${dist}" verbose="false" showPlist="false" + name="Genomics Toolkit" + mainclass="edu.unc.genomics.ToolRunner" + jvmversion="1.7+" + stubfile="stubFile.sh" + version="${version}" + infostring="${ant.project.name}, ${copyright}" + build="${buildnumber}" + bundleid="edu.unc.genomics.GenomicsToolkit"> + + <jarfilelist dir="${dist}" files="${ant.project.name}.jar"/> + <jarfileset dir="${lib}"> + <include name="*.jar" /> + <exclude name="launch4j.jar" /> + <exclude name="xstream.jar" /> + <exclude name="jarbundler-2.2.0.jar" /> + </jarfileset> + + <!-- Adjust the look, feel and behavior --> + <javaproperty name="apple.laf.useScreenMenuBar" value="true"/> + <javaproperty name="apple.awt.brushMetal" value="true"/> + <javaproperty name="apple.awt.showGrowBox" value="false"/> + <javaproperty name="apple.awt.textantialiasing" value="true"/> + <javaproperty name="apple.awt.antialiasing" value="true"/> + + <!-- Associate document types with this application --> + <documenttype name="Assembly files" + extensions="len" + role="Viewer" /> + + <!-- Include resource files --> + <resourcefilelist dir="." files="README.rdoc"/> + <resourcefilelist dir="." files="toolConf.xml"/> + <resourcefileset dir="." includes="resources/assemblies/*.len"/> + <javafilelist dir="." files="log4j.properties"/> + </jarbundler> + </target> + + <!-- Package the jar file into a Windows application with launch4j --> + <target name="package-win" depends="jar" description="Build the application for Windows"> + <taskdef name="launch4j" + classname="net.sf.launch4j.ant.Launch4jTask" + classpath="${lib}/launch4j.jar:${lib}/xstream.jar" /> + + <launch4j configFile="launch4j.xml" /> + </target> + + <target name="clean" description="clean up" > + <delete dir="${build}"/> + <delete dir="${dist}"/> + </target> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/galaxy-conf/BaseAlignCounts.xml Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,21 @@ +<tool id="BaseAlignCounts" name="Map coverage" version="1.0.0"> + <description>of sequencing reads</description> + <command>galaxyToolRunner.sh -i $input -g $dbkey -x $X -p 4 -o $output</command> + <inputs> + <param name="input" type="data" format="bam,sam,bed,bedgraph" label="Sequencing reads" /> + <param name="X" type="integer" value="0" label="In silico extension (leave 0 for read length)" /> + </inputs> + <outputs> + <data name="output" format="wig" /> + </outputs> + + <help> + .. class:: warningmark + + This tool requires sequencing reads in SAM/BAM/Bed/BedGraph format. + + .. class:: warningmark + + This tool was contributed by Timothy Palpant. + </help> +</tool>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/galaxy-conf/galaxyToolRunner.sh Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +if [ $# -eq 0 ] +then + echo "USAGE: galaxyToolRunner.sh APPNAME [ARGS]"; + exit; +fi + +if [ "$1" = "list" ] +then + find src/edu/unc/genomics/**/*.java -exec basename -s .java {} \; +fi + +java -Dlog4j.configuration=log4j.properties -cp .:../build:../lib/* edu.unc.genomics."$@" \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/galaxyToolConf.xml Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,41 @@ +<!-- Add to galaxy/tool_conf.xml within the <toolbox></toolbox> section --> + <label name="Java Genomics Toolkit" /> + <section name="Converters" id="java-genomics-toolkit-converters"> + <tool file="java-genomics-toolkit/galaxy-conf/IntervalToWig.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/RomanNumeralize.xml" /> + </section> + <section name="Nucleosomes" id="java-genomics-toolkit-nucleosomes"> + <tool file="java-genomics-toolkit/galaxy-conf/FindBoundaryNucleosomes.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/GreedyCaller.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/MapDyads.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/NRLCalculator.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/Phasogram.xml" /> + </section> + <section name="NGS" id="java-genomics-toolkit-ngs"> + <tool file="java-genomics-toolkit/other-tools/Autocorrelation.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/BaseAlignCounts.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/FindAbsoluteMaxima.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/IntervalLengthDistribution.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/IntervalStats.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/PowerSpectrum.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/RollingReadLength.xml" /> + </section> + <section name="WigMath" id="java-genomics-toolkit-wigmath"> + <tool file="java-genomics-toolkit/galaxy-conf/Add.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/Average.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/Divide.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/GaussianSmooth.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/LogTransform.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/MovingAverageSmooth.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/Multiply.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/Scale.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/Subtract.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/WigSummary.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/ZScore.xml" /> + </section> + <section name="Visualization" id="java-genomics-toolkit-visualization"> + <tool file="java-genomics-toolkit/galaxy-conf/IntervalAverager.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/KMeans.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/MatrixAligner.xml" /> + <tool file="java-genomics-toolkit/galaxy-conf/StripMatrix.xml" /> + </section> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/AssemblyManager.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,83 @@ +package edu.unc.genomics; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.DataFormatException; + +import org.apache.log4j.Logger; + +/** + * Suite of static methods for managing the built-in assemblies in the resources dir + * as well as keeping track of the last used assembly + * + * @author timpalpant + * + */ +public class AssemblyManager { + + private static final Logger log = Logger.getLogger(AssemblyManager.class); + + /** + * The last used Assembly + */ + private static Assembly lastUsed; + + /** + * Returns all available assemblies in the resources directory + * @return the assemblies available in the resources directory + */ + public static List<Assembly> getAvailableAssemblies() { + List<Assembly> assemblies = new ArrayList<>(); + + try (DirectoryStream<Path> stream = Files.newDirectoryStream(ResourceManager.getAssembliesDirectory(), "*.{len}")) { + for (Path entry : stream) { + log.debug("Loading assembly: " + entry); + try { + Assembly a = new Assembly(entry); + assemblies.add(a); + } catch (IOException | DataFormatException e1) { + log.warn("Error loading assembly: " + entry); + } + } + } catch (IOException e) { + log.error("Error listing assemblies"); + e.printStackTrace(); + } + + return assemblies; + } + + public static void deleteAssembly(Assembly a) throws IOException { + Files.deleteIfExists(a.getPath()); + } + + public static Assembly loadCustomAssembly(Path assemblyFile) throws IOException, DataFormatException { + log.debug("Loading custom assembly from file: " + assemblyFile); + Assembly a = new Assembly(assemblyFile); + + // TODO: Warn if this assembly is already loaded + + // Copy the assembly file into the built-in assemblies directory + Files.copy(assemblyFile, ResourceManager.getAssembliesDirectory().resolve(assemblyFile.getFileName())); + return a; + } + + /** + * @return the lastUsed + */ + public static Assembly getLastUsed() { + return lastUsed; + } + + /** + * @param lastUsed the lastUsed to set + */ + public static void setLastUsed(Assembly lastUsed) { + AssemblyManager.lastUsed = lastUsed; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/AssemblyManagerDialog.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,135 @@ +package edu.unc.genomics; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.EmptyBorder; + +import org.apache.log4j.Logger; + +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.nio.file.Path; +import java.util.zip.DataFormatException; + +/** + * View for AssemblyManager + * + * @author timpalpant + * + */ +public class AssemblyManagerDialog extends JDialog { + + public static final int DEFAULT_WIDTH = 400; + public static final int DEFAULT_HEIGHT = 500; + + private static final long serialVersionUID = -1461628562713621064L; + private static final Logger log = Logger.getLogger(AssemblyManagerDialog.class); + + private final JPanel contentPanel = new JPanel(); + private final JFileChooser fcCustomAssembly = new JFileChooser(); + private final JTable assembliesTable = new JTable(); + + private AssemblyTableModel model; + + /** + * Create the dialog. + */ + public AssemblyManagerDialog(JFrame parent) { + super(parent, "Assembly Manager", true); + + setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); + int centeredX = parent.getX() + (parent.getWidth()-getWidth()) / 2; + int centeredY = parent.getY() + (parent.getHeight()-getHeight()) / 2; + setLocation(centeredX, centeredY); + + getContentPane().setLayout(new BorderLayout()); + contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); + getContentPane().add(contentPanel, BorderLayout.CENTER); + contentPanel.setLayout(new BorderLayout(0, 0)); + + // Initialize the assemblies list + model = new AssemblyTableModel(AssemblyManager.getAvailableAssemblies()); + assembliesTable.setModel(model); + assembliesTable.setRowSelectionAllowed(true); + JScrollPane scrollPane = new JScrollPane(assembliesTable); + assembliesTable.setFillsViewportHeight(true); + contentPanel.add(scrollPane); + + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); + getContentPane().add(buttonPane, BorderLayout.SOUTH); + + JButton removeAssemblyButton = new JButton("Remove"); + removeAssemblyButton.setActionCommand("RemoveAssembly"); + removeAssemblyButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + removeCustomAssembly(); + } + }); + buttonPane.add(removeAssemblyButton); + + JButton loadAssemblyButton = new JButton("Load Custom Assembly"); + loadAssemblyButton.setActionCommand("LoadAssembly"); + loadAssemblyButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + loadCustomAssembly(); + } + }); + buttonPane.add(loadAssemblyButton); + + JButton doneButton = new JButton("Done"); + doneButton.setActionCommand("Done"); + doneButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + closeDialog(); + } + }); + buttonPane.add(doneButton); + getRootPane().setDefaultButton(doneButton); + } + + private void removeCustomAssembly() { + for (int row : assembliesTable.getSelectedRows()) { + try { + Assembly a = model.getRow(row); + AssemblyManager.deleteAssembly(a); + model.removeRow(row); + } catch (IOException e) { + log.error("Error deleting Assembly"); + e.printStackTrace(); + JOptionPane.showMessageDialog(this, "Error deleting assembly", "Assembly Manager Error", JOptionPane.ERROR_MESSAGE); + } + } + } + + private void loadCustomAssembly() { + int returnVal = fcCustomAssembly.showOpenDialog(this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + Path assemblyFile = fcCustomAssembly.getSelectedFile().toPath(); + try { + Assembly a = AssemblyManager.loadCustomAssembly(assemblyFile); + // Add it to the assemblies list model + model.addAssembly(a); + } catch (IOException | DataFormatException e) { + log.error("Error loading custom assembly: " + assemblyFile); + e.printStackTrace(); + JOptionPane.showMessageDialog(this, "Error loading custom assembly", "Assembly Manager Error", JOptionPane.ERROR_MESSAGE); + } + } + } + + private void closeDialog() { + this.dispose(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/AssemblyTableModel.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,97 @@ +package edu.unc.genomics; + +import java.util.List; + +import javax.swing.table.AbstractTableModel; + +/** + * Model for the AssemblyManagerDialog table view + * + * @author timpalpant + * + */ +public class AssemblyTableModel extends AbstractTableModel { + + private static final long serialVersionUID = 8225453782461913732L; + + private static final String[] COLUMN_NAMES = { "Name", "# Contigs" }; + + private final List<Assembly> assemblies; + + public AssemblyTableModel(List<Assembly> assemblies) { + this.assemblies = assemblies; + } + + /* (non-Javadoc) + * @see javax.swing.table.AbstractTableModel#getColumnName(int) + */ + @Override + public String getColumnName(int col) { + return COLUMN_NAMES[col]; + } + + /* (non-Javadoc) + * @see javax.swing.table.AbstractTableModel#isCellEditable(int, int) + */ + @Override + public boolean isCellEditable(int row, int col) { + return false; + } + + /* (non-Javadoc) + * @see javax.swing.table.TableModel#getRowCount() + */ + @Override + public int getRowCount() { + return assemblies.size(); + } + + /* (non-Javadoc) + * @see javax.swing.table.TableModel#getColumnCount() + */ + @Override + public int getColumnCount() { + return 2; + } + + /* (non-Javadoc) + * @see javax.swing.table.TableModel#getValueAt(int, int) + */ + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + Assembly a = assemblies.get(rowIndex); + if (columnIndex == 0) { + return a.toString(); + } else if (columnIndex == 1) { + return a.chromosomes().size(); + } else { + return null; + } + } + + public Assembly getRow(int rowIndex) { + return assemblies.get(rowIndex); + } + + public boolean containsAssembly(Assembly a) { + String aName = a.toString(); + for (Assembly assembly : assemblies) { + if (assembly.toString().equalsIgnoreCase(aName)) { + return true; + } + } + + return false; + } + + public void addAssembly(Assembly a) { + assemblies.add(a); + fireTableRowsInserted(assemblies.size()-1, assemblies.size()-1); + } + + public void removeRow(int rowIndex) { + assemblies.remove(rowIndex); + fireTableRowsDeleted(rowIndex, rowIndex); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/ButtonLabel.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,50 @@ +package edu.unc.genomics; + +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JButton; + +/** + * Act like a button, look like a label + * + * @author timpalpant + * + */ +public class ButtonLabel extends JButton { + + private static final long serialVersionUID = -4449260534784095223L; + + public ButtonLabel() { + init(); + } + + public ButtonLabel(Icon icon) { + super(icon); + init(); + } + + public ButtonLabel(String text) { + super(text); + init(); + } + + public ButtonLabel(Action a) { + super(a); + init(); + } + + public ButtonLabel(String text, Icon icon) { + super(text, icon); + init(); + } + + private void init() { + setBorder(BorderFactory.createEmptyBorder()); + setBorderPainted(false); + setContentAreaFilled(false); + setFocusPainted(false); + setOpaque(false); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/Job.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,207 @@ +package edu.unc.genomics; + +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.log4j.PatternLayout; +import org.apache.log4j.WriterAppender; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.ParameterDescription; + +/** + * A Job represents an instance of a tool configured with specific arguments + * Attempting to run a Job with invalid arguments will throw a RuntimeException + * If tool execution fails, a RuntimeException will also be thrown + * UncheckedExceptions should be managed by setting the Job's UncheckedExceptionManager + * or providing a ThreadGroup / default UncheckedExceptionManager + * + * @author timpalpant + * + */ +public class Job implements Iterable<ParameterDescription>, Runnable { + + private static final Logger log = Logger.getLogger(Job.class); + + private final Class<? extends CommandLineTool> tool; + private final CommandLineTool app; + private final List<ParameterDescription> parameters; + private final String usageText; + private boolean isRunning = false; + private StringWriter writer = new StringWriter(); + + /** + * Arguments for running this Job + */ + private Map<ParameterDescription,String> args = new HashMap<>(); + + /** + * Creates a new Job model for the specified tool + * @param tool + * @throws IllegalAccessException + * @throws InstantiationException + */ + public Job(final Class<? extends CommandLineTool> tool) throws InstantiationException, IllegalAccessException { + this.tool = tool; + + // Attempt to instantiate the tool and extract parameter information + app = tool.newInstance(); + JCommander jc = new JCommander(app); + jc.setProgramName(tool.getSimpleName()); + parameters = jc.getParameters(); + StringBuilder sbuilder = new StringBuilder(); + jc.usage(sbuilder); + usageText = sbuilder.toString(); + + // Set default arguments + for (ParameterDescription param : parameters) { + if (param.getDefault() != null) { + setArgument(param, String.valueOf(param.getDefault())); + } + } + } + + /** + * Copy-constructor + * @param job + */ + public Job(final Job job) { + this.tool = job.tool; + this.app = job.app; + this.parameters = job.parameters; + this.args = job.args; + this.usageText = job.usageText; + } + + @Override + public void run() { + // Load the arguments for running the tool + String[] args; + try { + args = getArguments(); + } catch (JobException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new CommandLineToolException("Job arguments are not valid"); + } + + // Attempt to instantiate and run the tool + WriterAppender appender = new WriterAppender(new PatternLayout(), writer); + appender.addFilter(new ThreadFilter(Thread.currentThread().getName())); + Logger.getRootLogger().addAppender(appender); + isRunning = true; + app.toolRunnerMain(args); + isRunning = false; + Logger.getRootLogger().removeAppender(appender); + } + + /** + * Render the arguments for running an instance of this Job + * @return + * @throws JobException + */ + public String[] getArguments() throws JobException { + if (!validateArguments()) { + throw new JobException("Job Arguments are not valid"); + } + + List<String> cmdArgs = new ArrayList<>(); + for (ParameterDescription p : args.keySet()) { + cmdArgs.add(p.getLongestName()); + cmdArgs.add(args.get(p)); + } + + String[] ret = new String[cmdArgs.size()]; + return cmdArgs.toArray(ret); + } + + public String getArgument(final ParameterDescription p) { + return args.get(p); + } + + /** + * Set a value for the given parameter + * @param p + * @param value + */ + public void setArgument(final ParameterDescription p, final String value) { + if (value.length() == 0) { + args.remove(p); + } else { + args.put(p, value); + } + } + + /** + * Remove all set arguments for this Job + */ + public void resetArguments() { + args.clear(); + } + + /** + * Is this parameter set? + * @param p + * @return + */ + public boolean isSet(final ParameterDescription p) { + return args.containsKey(p); + } + + /** + * Validate that this job has all of its parameters set + * and that they are all valid + * @return + */ + public boolean validateArguments() { + // TODO: Better validation based on parameter type + boolean hasAllRequiredParams = true; + for (ParameterDescription param : parameters) { + if (param.getParameter().required() && !isSet(param)) { + log.debug("Job is missing required argument: " + param.getLongestName()); + hasAllRequiredParams = false; + } + } + + return hasAllRequiredParams; + } + + public int numParameters() { + return parameters.size(); + } + + @Override + public Iterator<ParameterDescription> iterator() { + return parameters.iterator(); + } + + public String getName() { + return tool.getSimpleName(); + } + + public boolean isRunning() { + return isRunning; + } + + /** + * @return the usageText + */ + public String getUsageText() { + return usageText; + } + + @Override + public String toString() { + return getName(); + } + + public String getOutput() { + return writer.toString(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/JobConfigPanel.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,246 @@ +package edu.unc.genomics; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FileDialog; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.lang.reflect.Field; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SpringLayout; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.layout.SpringUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; + +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; + +import com.beust.jcommander.ParameterDescription; + +import edu.unc.genomics.io.IntervalFile; +import edu.unc.genomics.io.WigFile; + +/** + * View for configuring the parameters of a Job + * Implements databinding between a Job object and the various Swing components + * for configuring each parameter + * + * @author timpalpant + * + */ +public class JobConfigPanel extends JPanel { + + private static final long serialVersionUID = 3336295203155728629L; + private static final Logger log = Logger.getLogger(JobConfigPanel.class); + + private static final ImageIcon fileIcon = new ImageIcon(ResourceManager.getImagesDirectory().resolve("folder_page.png").toString()); + + /** + * Maps parameters in the Job to GUI components (forward data-binding) + */ + private Map<ParameterDescription, JComponent> guiMap = new HashMap<>(); + + /** + * Maps GUI components to parameters in the Job (reverse data-binding) + */ + private Map<Component, ParameterDescription> jobMap = new HashMap<>(); + + /** + * The model for the Job that this panel allows you to configure + */ + private Job job; + + /** + * Initialize a new ConfigurationPanel with no Job + */ + public JobConfigPanel() { + this(null); + } + + /** + * Initialize a new ConfigurationPanel for the given Job + * @param job + */ + public JobConfigPanel(final Job job) { + setJob(job); + setLayout(new SpringLayout()); + } + + /** + * Return the Job that this ConfigurationPanel is editing + * @return + */ + public Job getJob() { + return job; + } + + /** + * Set the job for this Configuration panel and re-render + * @param job + */ + public void setJob(final Job job) { + this.job = job; + renderJob(); + } + + /** + * Highlights fields on the Panel that are not set correctly + */ + public void highlightInvalidArguments() { + for (ParameterDescription param : job) { + JComponent guiComponent = guiMap.get(param); + if (param.getParameter().required() && !job.isSet(param)) { + guiComponent.setBorder(BorderFactory.createLineBorder(Color.RED)); + } else { + guiComponent.setBorder(BorderFactory.createEmptyBorder()); + } + } + } + + /** + * Render the parameters from the Job into GUI components + * and set up one-way data binding to map changes to the GUI fields + * back into the Job object's parameters + */ + private void renderJob() { + removeAll(); + guiMap.clear(); + jobMap.clear(); + if (job == null) { + validate(); + repaint(); + return; + } + + // Iterate through the parameters in the Job + // and render them appropriately based on their type + for (ParameterDescription paramDescription : job) { + // Add the parameter name to the configuration panel + String name = paramDescription.getLongestName(); + while (name.startsWith("-")) { + name = name.substring(1); + } + name = StringUtils.capitalize(name); + JLabel label = new JLabel(name); + label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); + add(label); + + // Add a panel for configuring the parameter + JPanel fieldPanel = new JPanel(); + fieldPanel.setLayout(new BoxLayout(fieldPanel, BoxLayout.LINE_AXIS)); + add(fieldPanel); + Field field = paramDescription.getField(); + Class<?> type = field.getType(); + if (type.equals(Assembly.class)) { + List<Assembly> availableAssemblies = AssemblyManager.getAvailableAssemblies(); + Assembly[] assemblies = new Assembly[availableAssemblies.size()]; + assemblies = availableAssemblies.toArray(assemblies); + final JComboBox<Assembly> cbAssemblyChooser = new JComboBox<Assembly>(assemblies); + cbAssemblyChooser.setPreferredSize(new Dimension(0, 25)); + cbAssemblyChooser.setMaximumSize(new Dimension(Integer.MAX_VALUE, cbAssemblyChooser.getPreferredSize().height)); + cbAssemblyChooser.setSelectedItem(AssemblyManager.getLastUsed()); + cbAssemblyChooser.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + log.debug("Auto-databinding changed assembly into Job argument"); + Assembly selectedAssembly = (Assembly) cbAssemblyChooser.getSelectedItem(); + AssemblyManager.setLastUsed(selectedAssembly); + ParameterDescription param = jobMap.get(cbAssemblyChooser); + job.setArgument(param, selectedAssembly.toString()); + } + }); + fieldPanel.add(cbAssemblyChooser); + guiMap.put(paramDescription, cbAssemblyChooser); + jobMap.put(cbAssemblyChooser, paramDescription); + } else { + final JTextField textField = new JTextField(); + // Set to default parameter, if it exists + if (job.isSet(paramDescription)) { + textField.setText(job.getArgument(paramDescription)); + } + textField.setPreferredSize(new Dimension(0, 20)); + textField.setMaximumSize(new Dimension(Integer.MAX_VALUE, textField.getPreferredSize().height)); + textField.getDocument().addDocumentListener(new DocumentListener() { + public void changedUpdate(DocumentEvent e) { + pushTextToModel(e); + } + + public void removeUpdate(DocumentEvent e) { + pushTextToModel(e); + } + + public void insertUpdate(DocumentEvent e) { + pushTextToModel(e); + } + + private void pushTextToModel(DocumentEvent e) { + log.debug("Auto-databinding changed text into Job argument"); + Document doc = (Document) e.getDocument(); + ParameterDescription param = jobMap.get(textField); + try { + String text = doc.getText(0, doc.getLength()); + job.setArgument(param, text); + } catch (BadLocationException e1) { + log.error("Error pushing changed text into Job model"); + e1.printStackTrace(); + } + } + }); + fieldPanel.add(textField); + guiMap.put(paramDescription, textField); + jobMap.put(textField, paramDescription); + + // For input/output files, add a file chooser button + if (type.equals(Path.class) || type.equals(WigFile.class) || type.equals(IntervalFile.class)) { + // TODO Replace with file icon + JButton btnChooseFile = new JButton(fileIcon); + btnChooseFile.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + // AWT FileDialog uses native components, but seems to hang + //Component c = (Component) e.getSource(); + //JFrame frame = (JFrame) SwingUtilities.getRoot(c); + //FileDialog fd = new FileDialog(frame, "Choose File"); + //fd.setVisible(true); + //if (fd.getFile() != null) { + // textField.setText(fd.getDirectory()+fd.getFile()); + //} + + // Swing JFileChooser + JFileChooser fc = new JFileChooser(); + int retValue = fc.showDialog(getParent(), "OK"); + if (retValue == JFileChooser.APPROVE_OPTION) { + textField.setText(fc.getSelectedFile().toString()); + } + } + }); + fieldPanel.add(btnChooseFile); + } + } + } + + // Lay out the panel + SpringUtilities.makeCompactGrid(this, job.numParameters(), 2, 5, 5, 5, 5); + + validate(); + repaint(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/JobException.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,57 @@ +package edu.unc.genomics; + +/** + * Exception thrown if attempting to perform an invalid action with a Job + * + * @author timpalpant + * + */ +public class JobException extends Exception { + + private static final long serialVersionUID = -831504993593959450L; + + /** + * + */ + public JobException() { + // TODO Auto-generated constructor stub + } + + /** + * @param message + */ + public JobException(String message) { + super(message); + // TODO Auto-generated constructor stub + } + + /** + * @param cause + */ + public JobException(Throwable cause) { + super(cause); + // TODO Auto-generated constructor stub + } + + /** + * @param message + * @param cause + */ + public JobException(String message, Throwable cause) { + super(message, cause); + // TODO Auto-generated constructor stub + } + + /** + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace + */ + public JobException(String message, Throwable cause, + boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + // TODO Auto-generated constructor stub + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/JobQueue.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,77 @@ +package edu.unc.genomics; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.swing.ListModel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; + +import org.apache.log4j.Logger; + +/** + * Model for the queue of SubmittedJobs + * Should be managed through the JobQueueManager controller + * + * @author timpalpant + * + */ +public class JobQueue implements ListModel<SubmittedJob>, Iterable<SubmittedJob> { + + private static final Logger log = Logger.getLogger(JobQueue.class); + + private final List<SubmittedJob> submittedJobs = new ArrayList<>(); + private final List<ListDataListener> dataListeners = new ArrayList<>(); + + public void add(SubmittedJob job) { + int N = submittedJobs.size(); + submittedJobs.add(job); + ListDataEvent e = new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, N, N); + for (ListDataListener l : dataListeners) { + l.intervalAdded(e); + } + } + + public void remove(SubmittedJob job) { + submittedJobs.remove(job); + int N = submittedJobs.size(); + ListDataEvent e = new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, N, N); + for (ListDataListener l : dataListeners) { + l.intervalAdded(e); + } + } + + public void update(SubmittedJob job) { + int index = submittedJobs.indexOf(job); + ListDataEvent e = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index, index); + for (ListDataListener l : dataListeners) { + l.intervalAdded(e); + } + } + + @Override + public int getSize() { + return submittedJobs.size(); + } + + @Override + public SubmittedJob getElementAt(int index) { + return submittedJobs.get(index); + } + + @Override + public void addListDataListener(ListDataListener l) { + dataListeners.add(l); + } + + @Override + public void removeListDataListener(ListDataListener l) { + dataListeners.remove(l); + } + + @Override + public Iterator<SubmittedJob> iterator() { + return submittedJobs.iterator(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/JobQueueCellRenderer.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,125 @@ +package edu.unc.genomics; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.ListCellRenderer; +import javax.swing.SwingConstants; +import javax.swing.border.EtchedBorder; + +/** + * @author timpalpant + * + */ +public class JobQueueCellRenderer extends JPanel implements ListCellRenderer<SubmittedJob> { + + private static final long serialVersionUID = 4270263302075586018L; + + private static final ImageIcon inProgressIcon = new ImageIcon(ResourceManager.getImagesDirectory().resolve("beachball.png").toString()); + private static final ImageIcon rerunIcon = new ImageIcon(ResourceManager.getImagesDirectory().resolve("arrow-circle.png").toString()); + private static final ImageIcon infoIcon = new ImageIcon(ResourceManager.getImagesDirectory().resolve("information-white.png").toString()); + private static final ImageIcon logIcon = new ImageIcon(ResourceManager.getImagesDirectory().resolve("sticky-note-text.png").toString()); + private static final ImageIcon showFileIcon = new ImageIcon(ResourceManager.getImagesDirectory().resolve("eye_icon.png").toString()); + + private static final ImageIcon successIcon = new ImageIcon(ResourceManager.getImagesDirectory().resolve("icon_success_sml.gif").toString()); + private static final ImageIcon errorIcon = new ImageIcon(ResourceManager.getImagesDirectory().resolve("icon_error_sml.gif").toString()); + private static final ImageIcon warningIcon = new ImageIcon(ResourceManager.getImagesDirectory().resolve("icon_warning_sml.gif").toString()); + + private JLabel statusIconLabel = new JLabel(inProgressIcon); + private JLabel nameLabel = new JLabel(); + + public JobQueueCellRenderer() { + FlowLayout flowLayout = new FlowLayout(FlowLayout.LEADING, 5, 2); + setPreferredSize(new Dimension(190, 48)); + setLayout(flowLayout); + setBorder(BorderFactory.createLineBorder(Color.GRAY, 1, true)); + + JPanel statusPanel = new JPanel(); + statusPanel.setBorder(BorderFactory.createEmptyBorder(0, 3, 16, 0)); + statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.PAGE_AXIS)); + statusPanel.add(statusIconLabel); + add(statusPanel); + + JPanel mainPanel = new JPanel(); + mainPanel.setAlignmentX(LEFT_ALIGNMENT); + mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS)); + + JPanel namePanel = new JPanel(); + namePanel.setLayout(flowLayout); + nameLabel.setPreferredSize(new Dimension(145, 16)); + nameLabel.setHorizontalTextPosition(SwingConstants.LEFT); + nameLabel.setFont(nameLabel.getFont().deriveFont(Font.BOLD)); + namePanel.add(nameLabel); + mainPanel.add(namePanel); + + JPanel buttonsPanel = new JPanel(); + buttonsPanel.setLayout(flowLayout); + mainPanel.add(buttonsPanel); + + ButtonLabel rerunLabel = new ButtonLabel(rerunIcon); + rerunLabel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + //addJobToQueue(); + } + }); + buttonsPanel.add(rerunLabel); + ButtonLabel infoLabel = new ButtonLabel(infoIcon); + infoLabel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + //addJobToQueue(); + } + }); + buttonsPanel.add(infoLabel); + ButtonLabel logLabel = new ButtonLabel(logIcon); + logLabel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + //addJobToQueue(); + } + }); + buttonsPanel.add(logLabel); + ButtonLabel showFileLabel = new ButtonLabel(showFileIcon); + showFileLabel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + //addJobToQueue(); + } + }); + buttonsPanel.add(showFileLabel); + + add(mainPanel); + } + + @Override + public Component getListCellRendererComponent( + JList<? extends SubmittedJob> list, SubmittedJob value, int index, + boolean isSelected, boolean cellHasFocus) { + + nameLabel.setText(value.toString()); + if (value.isRunning()) { + statusIconLabel.setIcon(inProgressIcon); + nameLabel.setForeground(Color.BLACK); + } else if (value.succeeded()) { + statusIconLabel.setIcon(successIcon); + nameLabel.setForeground(Color.BLACK); + } else { + statusIconLabel.setIcon(errorIcon); + nameLabel.setForeground(Color.RED); + } + + return this; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/JobQueueManager.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,105 @@ +package edu.unc.genomics; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import org.apache.log4j.Logger; + +/** + * Controller for scheduling and running jobs + * Wrapper for ExcecutorService, although the implementation could change + * + * @author timpalpant + * + */ +public class JobQueueManager { + + private static final Logger log = Logger.getLogger(JobQueueManager.class); + + private final JobQueue queue; + private final ExecutorService exec; + private final Thread monitor; + + public JobQueueManager(JobQueue queue) { + this.queue = queue; + + int numProcessors = Runtime.getRuntime().availableProcessors(); + log.debug("Initializing thread pool with "+numProcessors+" processors"); + exec = Executors.newFixedThreadPool(numProcessors); + + monitor = new Thread(new JobMonitor()); + monitor.start(); + } + + public List<Runnable> shutdownNow() { + return exec.shutdownNow(); + } + + /** + * Add a Job to the queue + * @param job + * @throws JobException + */ + public SubmittedJob submitJob(Job job) throws JobException { + // Refuse to add the Job to the queue if its arguments are not valid + if (!job.validateArguments()) { + throw new JobException("Job arguments are not valid"); + } + + // Submit the job for execution into the thread pool + Future<?> future = exec.submit(job); + SubmittedJob submittedJob = new SubmittedJob(job, future); + log.info("Submitted job " + submittedJob.getId()); + + // Add the SubmittedJob to the JobQueue + queue.add(submittedJob); + return submittedJob; + } + + /** + * Are any jobs running? (not done) + * @return + */ + public boolean isRunning() { + for (SubmittedJob job : queue) { + if (!job.isDone()) { + return true; + } + } + + return false; + } + + + /** + * Background process for polling the status of submitted jobs + * @author timpalpant + * + */ + public class JobMonitor implements Runnable { + + public static final int JOB_POLL_INTERVAL = 1_000; + + public void run() { + try { + while (true) { + // Check Job statuses every 1s + Thread.sleep(JOB_POLL_INTERVAL); + + for (SubmittedJob job : queue) { + if (job.isDone()) { + queue.update(job); + } + } + } + } catch (InterruptedException e) { + log.fatal("JobMonitor crashed"); + e.printStackTrace(); + throw new RuntimeException("JobMonitor crashed"); + } + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/ResourceManager.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,33 @@ +package edu.unc.genomics; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Find resources based on platform/package + * @author timpalpant + * + */ +public class ResourceManager { + + private static final Path ASSEMBLIES_DIR = Paths.get("assemblies"); + private static final Path IMAGES_DIR = Paths.get("images"); + + public static Path getResourceDirectory() { + Path osx = Paths.get("../Resources"); + if (Files.exists(osx)) { + return osx; + } + + return Paths.get("resources"); + } + + public static Path getAssembliesDirectory() { + return getResourceDirectory().resolve(ASSEMBLIES_DIR); + } + + public static Path getImagesDirectory() { + return getResourceDirectory().resolve(IMAGES_DIR); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/SubmittedJob.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,103 @@ +package edu.unc.genomics; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +/** + * Represents a job that was submitted for processing + * + * @author timpalpant + * + */ +public class SubmittedJob { + private static int numJobs = 0; + + private final Future<?> future; + private final int id; + private final Job job; + + public SubmittedJob(Job job, Future<?> future) { + this.id = ++numJobs; + this.job = job; + this.future = future; + } + + /** + * @return the id + */ + public int getId() { + return id; + } + + /** + * @return the job + */ + public Job getJob() { + return job; + } + + /** + * If the job is currently running + * @return + */ + public boolean isRunning() { + return job.isRunning() && !isDone(); + } + + /** + * If the job is done running + * (it may have failed or succeeded) + * @return + */ + public boolean isDone() { + return future.isDone(); + } + + /** + * If this job completed without any Exceptions + * @return + */ + public boolean succeeded() { + return (future.isDone() && !failed()); + } + + /** + * If this job completed with Exceptions + * @return + */ + public boolean failed() { + if (future.isDone()) { + try { + future.get(); + return false; + } catch (InterruptedException | ExecutionException e) { + return true; + } + } + + return false; + } + + /** + * Return an Exception that occured, or null if there were none + * or the job is not yet done + * @return + */ + public Exception getException() { + if (future.isDone()) { + try { + future.get(); + return null; + } catch (InterruptedException | ExecutionException e) { + return e; + } + } + + return null; + } + + @Override + public String toString() { + return "Job "+id+": "+job.getName(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/ThreadFilter.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,35 @@ +package edu.unc.genomics; + +import org.apache.log4j.spi.Filter; +import org.apache.log4j.spi.LoggingEvent; + +/** + * A Log4j filter that filters for messages from a single thread + * @author timpalpant + * + */ +public class ThreadFilter extends Filter { + + private final String threadName; + + public ThreadFilter(String threadName) { + this.threadName = threadName; + } + + @Override + public int decide(LoggingEvent e) { + if(e.getThreadName().equalsIgnoreCase(threadName)) { + return Filter.DENY; + } + + return Filter.NEUTRAL; + } + + /** + * @return the threadName + */ + public String getThreadName() { + return threadName; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/ToolRunner.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,38 @@ +package edu.unc.genomics; + +import java.awt.EventQueue; + +import javax.swing.JFrame; + +import org.apache.log4j.Logger; + +/** + * The main application for running the genomics toolkit gui + * Could do resource checking, etc. prior to startup + * + * @author timpalpant + * + */ +public class ToolRunner { + + private static final Logger log = Logger.getLogger(ToolRunner.class); + + private JFrame frmToolRunner = new ToolRunnerFrame(); + + /** + * Launch the application. + */ + public static void main(String[] args) { + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + try { + ToolRunner window = new ToolRunner(); + window.frmToolRunner.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/ToolRunnerFrame.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,328 @@ +package edu.unc.genomics; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenuBar; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JButton; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.SwingConstants; + +import javax.swing.JProgressBar; +import javax.swing.JSplitPane; +import javax.swing.BoxLayout; +import javax.swing.JTabbedPane; +import javax.swing.JTextPane; + +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.log4j.Logger; +import org.simplericity.macify.eawt.Application; +import org.simplericity.macify.eawt.ApplicationEvent; +import org.simplericity.macify.eawt.ApplicationListener; +import org.simplericity.macify.eawt.DefaultApplication; +import org.xml.sax.SAXException; + +import com.beust.jcommander.JCommander; + +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.io.IOException; + +/** + * The main ToolRunner window + * and controller for creating, running, and managing Jobs + * + * @author timpalpant + * + */ +public class ToolRunnerFrame extends JFrame implements ApplicationListener { + + private static final long serialVersionUID = 6454774196137357898L; + private static final Logger log = Logger.getLogger(ToolRunnerFrame.class); + + private final Application application = new DefaultApplication(); + + private final JPanel contentPane = new JPanel(); + private final JSplitPane splitPane = new JSplitPane(); + private final JPanel mainPane = new JPanel(); + private final JProgressBar progressBar = new JProgressBar(); + private final JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.TOP); + private final JobConfigPanel configurationPanel = new JobConfigPanel(); + private final JTextPane helpTextPanel = new JTextPane(); + private final ToolsTree toolsTree = new ToolsTree(); + + private final JobQueue queue = new JobQueue(); + private final JobQueueManager queueManager = new JobQueueManager(queue); + private final JList<SubmittedJob> queueList = new JList<>(queue); + + /** + * Create the frame. + */ + public ToolRunnerFrame() { + //application.addPreferencesMenuItem(); + //application.setEnabledPreferencesMenu(true); + application.addApplicationListener(this); + + // set OS X-specific properties + if (application.isMac()) { + setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + //toolsTree.putClientProperty("Quaqua.Tree.style", "sourceList"); + } else { + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + setTitle("Genomics Toolkit Tool Runner"); + setBounds(100, 100, 1000, 600); + + contentPane.setBorder(BorderFactory.createEmptyBorder()); + contentPane.setLayout(new BorderLayout(0, 0)); + setContentPane(contentPane); + + initializeChildren(); + initializeMenuBar(); + } + + private void initializeChildren() { + splitPane.setBorder(BorderFactory.createEmptyBorder()); + contentPane.add(splitPane, BorderLayout.CENTER); + + initializeQueuePanel(); + initializeToolsTree(); + + mainPane.setLayout(new BorderLayout(0, 0)); + mainPane.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY)); + mainPane.add(tabbedPane, BorderLayout.CENTER); + + JPanel runPanel = new JPanel(); + runPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + runPanel.setLayout(new BoxLayout(runPanel, BoxLayout.X_AXIS)); + runPanel.add(progressBar); + JButton btnRun = new JButton("Run"); + btnRun.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + addJobToQueue(); + } + }); + runPanel.add(btnRun); + mainPane.add(runPanel, BorderLayout.SOUTH); + splitPane.setRightComponent(mainPane); + + initializeConfigurationPanel(); + initializeHelpPanel(); + } + + private void initializeMenuBar() { + JMenuBar menuBar = new JMenuBar(); + setJMenuBar(menuBar); + + JMenu mnFileMenu = new JMenu("File"); + menuBar.add(mnFileMenu); + + JMenuItem mntmAssemblyManager = new JMenuItem("Assembly manager"); + mntmAssemblyManager.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JMenuItem menuItem = (JMenuItem) e.getSource(); + JPopupMenu popupMenu = (JPopupMenu) menuItem.getParent(); + Component invoker = popupMenu.getInvoker(); //this is the JMenu (in my code) + JComponent invokerAsJComponent = (JComponent) invoker; + Container topLevel = invokerAsJComponent.getTopLevelAncestor(); + AssemblyManagerDialog dialog = new AssemblyManagerDialog((JFrame) topLevel); + //dialog.getRootPane().putClientProperty("Window.style", "small"); + dialog.setVisible(true); + } + }); + mnFileMenu.add(mntmAssemblyManager); + + JMenu mnHelpMenu = new JMenu("Help"); + menuBar.add(mnHelpMenu); + + JMenuItem mntmHelpContents = new JMenuItem("Help Contents"); + mnHelpMenu.add(mntmHelpContents); + + if (!application.isMac()) { + JMenuItem mntmAbout = new JMenuItem("About"); + mnHelpMenu.add(mntmAbout); + mnHelpMenu.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + handleAbout(null); + } + }); + } + } + + private void initializeQueuePanel() { + JPanel queuePanel = new JPanel(); + queuePanel.setLayout(new BoxLayout(queuePanel, BoxLayout.PAGE_AXIS)); + queuePanel.setBorder(BorderFactory.createEmptyBorder()); + contentPane.add(queuePanel, BorderLayout.EAST); + + JLabel queueLabel = new JLabel("Job Queue"); + queueLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + queueLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT); + queuePanel.add(queueLabel); + + queueList.setBackground(contentPane.getBackground()); + queueList.setCellRenderer(new JobQueueCellRenderer()); + JScrollPane queueListScrollPane = new JScrollPane(queueList); + queueListScrollPane.setBorder(BorderFactory.createEmptyBorder()); + queueListScrollPane.setBackground(contentPane.getBackground()); + queueListScrollPane.setPreferredSize(new Dimension(200, Integer.MAX_VALUE)); + queuePanel.add(queueListScrollPane); + } + + private void initializeConfigurationPanel() { + JScrollPane configScrollPane = new JScrollPane(configurationPanel); + configScrollPane.setBorder(BorderFactory.createEmptyBorder()); + tabbedPane.addTab("Tool Configuration", null, configScrollPane, "Configure tool"); + } + + private void initializeHelpPanel() { + JPanel helpPanel = new JPanel(); + tabbedPane.addTab("Help", null, helpPanel, null); + helpPanel.setLayout(new BorderLayout(0, 0)); + + helpTextPanel.setEditable(false); + helpTextPanel.setBackground(tabbedPane.getBackground()); + Font mono = new Font("Monospaced", helpTextPanel.getFont().getStyle(), helpTextPanel.getFont().getSize()); + helpTextPanel.setFont(mono); + JScrollPane helpScrollPane = new JScrollPane(helpTextPanel); + helpScrollPane.setBorder(BorderFactory.createEmptyBorder()); + helpPanel.add(helpScrollPane); + } + + private void initializeToolsTree() { + try { + ToolsTreeModel model = ToolsTreeModel.loadDefaultConfig(); + toolsTree.setModel(model); + } catch (ParserConfigurationException | SAXException | IOException e1) { + log.error("Error loading tool configuration file"); + e1.printStackTrace(); + System.exit(-1); + } catch (ClassNotFoundException e) { + log.error("Error loading tool: " + e.getMessage()); + e.printStackTrace(); + System.exit(-1); + } + + toolsTree.addTreeSelectionListener(new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent e) { + changeTool(); + } + }); + + JScrollPane toolsTreeScrollPane = new JScrollPane(toolsTree); + toolsTreeScrollPane.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.LIGHT_GRAY)); + splitPane.setLeftComponent(toolsTreeScrollPane); + } + + /** + * Change the configuration panel to the currently selected tool + * to configure a new Job + */ + private void changeTool() { + // Returns the last path element of the selection. + Object node = toolsTree.getLastSelectedPathComponent(); + // Nothing is selected + if (node == null) { + return; + } + + if (node instanceof ToolsTreeNode) { + ToolsTreeNode toolNode = (ToolsTreeNode) node; + try { + Class<? extends CommandLineTool> tool = toolNode.getClazz(); + + // Set up the configuration panel to configure this tool + Job job = new Job(tool); + configurationPanel.setJob(job); + // Set the help text to the usage + helpTextPanel.setText(job.getUsageText()); + } catch (InstantiationException | IllegalAccessException e) { + log.error("Error initializing Job"); + e.printStackTrace(); + JOptionPane.showMessageDialog(this, "Error initializing job", "Job Initialization Error", JOptionPane.ERROR_MESSAGE); + } + + } + } + + private void addJobToQueue() { + Job currentJob = configurationPanel.getJob(); + if (currentJob == null) return; + + // Validate the required parameters + log.info("Validating parameters for tool"); + if (!currentJob.validateArguments()) { + configurationPanel.highlightInvalidArguments(); + return; + } + + // Add the job to the queue + try { + queueManager.submitJob(currentJob); + configurationPanel.setJob(null); + } catch (JobException e) { + log.error("Error adding Job to queue"); + e.printStackTrace(); + JOptionPane.showMessageDialog(this, "Error adding job to queue", "Job Queue Error", JOptionPane.ERROR_MESSAGE); + } + } + + public void handleAbout(ApplicationEvent event) { + JOptionPane.showMessageDialog(this, "Java Genomics Toolkit v1.0"); + if (event != null) { + event.setHandled(true); + } + } + + public void handleOpenApplication(ApplicationEvent event) { + // Application was opened + } + + public void handleOpenFile(ApplicationEvent event) { + //JOptionPane.showMessageDialog(frmToolRunner, "OS X told us to open " + event.getFilename()); + } + + public void handlePreferences(ApplicationEvent event) { + //JOptionPane.showMessageDialog(frmToolRunner, "No preferences available"); + } + + public void handlePrintFile(ApplicationEvent event) { + //JOptionPane.showMessageDialog(frmToolRunner, "OS X told us to print " + event.getFilename()); + } + + public void handleQuit(ApplicationEvent event) { + boolean confirm = true; + if (queueManager.isRunning()) { + int result = JOptionPane.showConfirmDialog(this, "Jobs are currently running. Are you sure you want to quit?", "Confirm Quit", JOptionPane.OK_CANCEL_OPTION); + confirm = (result == JOptionPane.OK_OPTION); + } + + if (confirm) { + dispose(); + System.exit(0); + } + } + + public void handleReOpenApplication(ApplicationEvent event) { + //JOptionPane.showMessageDialog(frmToolRunner, "OS X told the application was reopened"); + setVisible(true); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/ToolsTree.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,38 @@ +package edu.unc.genomics; + +import java.awt.Dimension; + +import javax.swing.BorderFactory; +import javax.swing.JTree; +import javax.swing.tree.TreeSelectionModel; + +/** + * Tree view of the available tools + * + * @author timpalpant + * + */ +public class ToolsTree extends JTree { + + private static final long serialVersionUID = -2591915754191263660L; + + public ToolsTree() { + super(); + initialize(); + } + + public ToolsTree(ToolsTreeModel model) { + super(model); + initialize(); + } + + private void initialize() { + getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + + setBorder(BorderFactory.createEmptyBorder()); + setRootVisible(false); + setShowsRootHandles(true); + setPreferredSize(new Dimension(200, 0)); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/ToolsTreeModel.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,82 @@ +package edu.unc.genomics; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +/** + * Model for the ToolsTree + * Essentially just a DefaultTreeModel, but provides methods for + * loading the available tools from a configuration file + * + * @author timpalpant + * + */ +public class ToolsTreeModel extends DefaultTreeModel { + + public static final Path DEFAULT_CONFIGURATION_FILE = Paths.get("toolConf.xml"); + + private static final Logger log = Logger.getLogger(ToolsTreeModel.class); + + private static final long serialVersionUID = -6587614270922489960L; + + public ToolsTreeModel() { + super(new DefaultMutableTreeNode("Tools")); + } + + public static ToolsTreeModel loadDefaultConfig() throws ClassNotFoundException, ParserConfigurationException, SAXException, IOException { + return loadConfig(ResourceManager.getResourceDirectory().resolve(DEFAULT_CONFIGURATION_FILE)); + } + + public static ToolsTreeModel loadConfig(Path p) throws ParserConfigurationException, SAXException, IOException, ClassNotFoundException { + ToolsTreeModel model = new ToolsTreeModel(); + DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); + + // Populate the TreeModel with the tools in the default configuration file + log.debug("Loading tools from: " + DEFAULT_CONFIGURATION_FILE.toAbsolutePath()); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(p.toFile()); + + // Iterate over the sections + NodeList sections = doc.getElementsByTagName("section"); + log.debug("Found "+sections.getLength()+" sections"); + for (int i = 0; i < sections.getLength(); i++) { + Node section = sections.item(i); + String sectionName = section.getAttributes().getNamedItem("name").getNodeValue(); + log.debug("Loading section: " + sectionName); + DefaultMutableTreeNode sectionNode = new DefaultMutableTreeNode(sectionName); + root.add(sectionNode); + NodeList tools = section.getChildNodes(); + + // Iterate over the tools in each section + for (int j = 0; j < tools.getLength(); j++) { + Node tool = tools.item(j); + if (tool.getNodeType() == Node.ELEMENT_NODE && tool.getNodeName().equalsIgnoreCase("tool")) { + String toolName = tool.getAttributes().getNamedItem("name").getNodeValue(); + log.debug("Loading tool: " + toolName); + String toolClassName = tool.getAttributes().getNamedItem("class").getNodeValue(); + Class<? extends CommandLineTool> toolClass = (Class<? extends CommandLineTool>) Class.forName(toolClassName); + ToolsTreeNode toolNode = new ToolsTreeNode(toolName, toolClass); + sectionNode.add(toolNode); + } + } + } + + return model; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/edu/unc/genomics/ToolsTreeNode.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,44 @@ +package edu.unc.genomics; + +import javax.swing.tree.DefaultMutableTreeNode; + +/** + * A node in the ToolsTreeModel + * Contains a class and a name for the tool + * TODO Add help for each tool + * + * @author timpalpant + * + */ +public class ToolsTreeNode extends DefaultMutableTreeNode { + + private static final long serialVersionUID = -9067416927466519457L; + + private final String name; + private final Class<? extends CommandLineTool> clazz; + + /** + * @param userObject + */ + public ToolsTreeNode(String name, Class<? extends CommandLineTool> clazz) { + super(name, false); + + this.name = name; + this.clazz = clazz; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @return the clazz + */ + public Class<? extends CommandLineTool> getClazz() { + return clazz; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/gui/javax/swing/layout/SpringUtilities.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,225 @@ +/* + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle or the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package javax.swing.layout; + +import javax.swing.*; +import javax.swing.SpringLayout; +import java.awt.*; + +/** + * A 1.4 file that provides utility methods for + * creating form- or grid-style layouts with SpringLayout. + * These utilities are used by several programs, such as + * SpringBox and SpringCompactGrid. + */ +public class SpringUtilities { + /** + * A debugging utility that prints to stdout the component's + * minimum, preferred, and maximum sizes. + */ + public static void printSizes(Component c) { + System.out.println("minimumSize = " + c.getMinimumSize()); + System.out.println("preferredSize = " + c.getPreferredSize()); + System.out.println("maximumSize = " + c.getMaximumSize()); + } + + /** + * Aligns the first <code>rows</code> * <code>cols</code> + * components of <code>parent</code> in + * a grid. Each component is as big as the maximum + * preferred width and height of the components. + * The parent is made just big enough to fit them all. + * + * @param rows number of rows + * @param cols number of columns + * @param initialX x location to start the grid at + * @param initialY y location to start the grid at + * @param xPad x padding between cells + * @param yPad y padding between cells + */ + public static void makeGrid(Container parent, + int rows, int cols, + int initialX, int initialY, + int xPad, int yPad) { + SpringLayout layout; + try { + layout = (SpringLayout)parent.getLayout(); + } catch (ClassCastException exc) { + System.err.println("The first argument to makeGrid must use SpringLayout."); + return; + } + + Spring xPadSpring = Spring.constant(xPad); + Spring yPadSpring = Spring.constant(yPad); + Spring initialXSpring = Spring.constant(initialX); + Spring initialYSpring = Spring.constant(initialY); + int max = rows * cols; + + //Calculate Springs that are the max of the width/height so that all + //cells have the same size. + Spring maxWidthSpring = layout.getConstraints(parent.getComponent(0)). + getWidth(); + Spring maxHeightSpring = layout.getConstraints(parent.getComponent(0)). + getHeight(); + for (int i = 1; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints( + parent.getComponent(i)); + + maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth()); + maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight()); + } + + //Apply the new width/height Spring. This forces all the + //components to have the same size. + for (int i = 0; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints( + parent.getComponent(i)); + + cons.setWidth(maxWidthSpring); + cons.setHeight(maxHeightSpring); + } + + //Then adjust the x/y constraints of all the cells so that they + //are aligned in a grid. + SpringLayout.Constraints lastCons = null; + SpringLayout.Constraints lastRowCons = null; + for (int i = 0; i < max; i++) { + SpringLayout.Constraints cons = layout.getConstraints( + parent.getComponent(i)); + if (i % cols == 0) { //start of new row + lastRowCons = lastCons; + cons.setX(initialXSpring); + } else { //x position depends on previous component + cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST), + xPadSpring)); + } + + if (i / cols == 0) { //first row + cons.setY(initialYSpring); + } else { //y position depends on previous row + cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH), + yPadSpring)); + } + lastCons = cons; + } + + //Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints(parent); + pCons.setConstraint(SpringLayout.SOUTH, + Spring.sum( + Spring.constant(yPad), + lastCons.getConstraint(SpringLayout.SOUTH))); + pCons.setConstraint(SpringLayout.EAST, + Spring.sum( + Spring.constant(xPad), + lastCons.getConstraint(SpringLayout.EAST))); + } + + /* Used by makeCompactGrid. */ + private static SpringLayout.Constraints getConstraintsForCell( + int row, int col, + Container parent, + int cols) { + SpringLayout layout = (SpringLayout) parent.getLayout(); + Component c = parent.getComponent(row * cols + col); + return layout.getConstraints(c); + } + + /** + * Aligns the first <code>rows</code> * <code>cols</code> + * components of <code>parent</code> in + * a grid. Each component in a column is as wide as the maximum + * preferred width of the components in that column; + * height is similarly determined for each row. + * The parent is made just big enough to fit them all. + * + * @param rows number of rows + * @param cols number of columns + * @param initialX x location to start the grid at + * @param initialY y location to start the grid at + * @param xPad x padding between cells + * @param yPad y padding between cells + */ + public static void makeCompactGrid(Container parent, + int rows, int cols, + int initialX, int initialY, + int xPad, int yPad) { + SpringLayout layout; + try { + layout = (SpringLayout)parent.getLayout(); + } catch (ClassCastException exc) { + System.err.println("The first argument to makeCompactGrid must use SpringLayout."); + return; + } + + //Align all cells in each column and make them the same width. + Spring x = Spring.constant(initialX); + for (int c = 0; c < cols; c++) { + Spring width = Spring.constant(0); + for (int r = 0; r < rows; r++) { + width = Spring.max(width, + getConstraintsForCell(r, c, parent, cols). + getWidth()); + } + for (int r = 0; r < rows; r++) { + SpringLayout.Constraints constraints = + getConstraintsForCell(r, c, parent, cols); + constraints.setX(x); + constraints.setWidth(width); + } + x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad))); + } + + //Align all cells in each row and make them the same height. + Spring y = Spring.constant(initialY); + for (int r = 0; r < rows; r++) { + Spring height = Spring.constant(0); + for (int c = 0; c < cols; c++) { + height = Spring.max(height, + getConstraintsForCell(r, c, parent, cols). + getHeight()); + } + for (int c = 0; c < cols; c++) { + SpringLayout.Constraints constraints = + getConstraintsForCell(r, c, parent, cols); + constraints.setY(y); + constraints.setHeight(height); + } + y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad))); + } + + //Set the parent's size. + SpringLayout.Constraints pCons = layout.getConstraints(parent); + pCons.setConstraint(SpringLayout.SOUTH, y); + pCons.setConstraint(SpringLayout.EAST, x); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/launch4j.xml Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,26 @@ +<launch4jConfig> + <dontWrapJar>false</dontWrapJar> + <headerType>gui</headerType> + <jar>dist/java-genomics-toolkit.jar</jar> + <outfile>dist/Genomics Toolkit.exe</outfile> + <errTitle></errTitle> + <cmdLine></cmdLine> + <chdir></chdir> + <priority>normal</priority> + <downloadUrl>http://java.com/download</downloadUrl> + <supportUrl>http://github.com/timpalpant/java-genomics-toolkit</supportUrl> + <customProcName>false</customProcName> + <stayAlive>false</stayAlive> + <manifest>META-INF/MANIFEST.MF</manifest> + <icon></icon> + <classPath> + <mainClass>edu.unc.genomics.GenomicsToolkit</mainClass> + <cp>../lib/*</cp> + </classPath> + <jre> + <path></path> + <minVersion>1.7.0</minVersion> + <maxVersion></maxVersion> + <jdkPreference>preferJre</jdkPreference> + </jre> +</launch4jConfig> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/log4j.properties Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,10 @@ +log4j.rootLogger=debug, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout + +# Pattern to output the caller's file name and line number. +log4j.appender.stdout.layout.ConversionPattern=%5p - %m%n + +# Only output errors from the BigWig library +log4j.logger.org.broad.igv.bbfile=ERROR \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/ce2.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,7 @@ +chrI 15080483 +chrII 15279308 +chrIII 13783313 +chrIV 17493791 +chrM 13794 +chrV 20922231 +chrX 17718849
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/ce3.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,7 @@ +chrI 15080552 +chrII 15279311 +chrIII 13783317 +chrIV 17493785 +chrM 13794 +chrV 20922231 +chrX 17718850
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/ce4.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,7 @@ +chrI 15072419 +chrII 15279316 +chrIII 13783681 +chrIV 17493784 +chrM 13794 +chrV 20919398 +chrX 17718852
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/ce5.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,7 @@ +chrV 20919568 +chrX 17718851 +chrIV 17493785 +chrII 15279316 +chrI 15072421 +chrIII 13783681 +chrM 13794
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/ce6.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,7 @@ +chrV 20919568 +chrX 17718854 +chrIV 17493785 +chrII 15279323 +chrI 15072421 +chrIII 13783681 +chrM 13794
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/ce7.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,7 @@ +chrV 20924143 +chrX 17718854 +chrIV 17493784 +chrII 15279324 +chrI 15072421 +chrIII 13783682 +chrM 13794
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/ce8.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,7 @@ +chrV 20924143 +chrX 17718854 +chrIV 17493784 +chrII 15279323 +chrI 15072421 +chrIII 13783685 +chrM 13794
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/ce9.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,7 @@ +chrV 20924143 +chrX 17718854 +chrIV 17493784 +chrII 15279323 +chrI 15072421 +chrIII 13783685 +chrM 13794
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/dm1.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,11 @@ +chr4 1237870 +chrU 8248647 +chrX 21780003 +chr2L 22217931 +chr2R 20302755 +chr2h 1651714 +chr3L 23352213 +chr3R 27890790 +chr3h 1961095 +chrXh 359526 +chrYh 321294
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/dm2.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,13 @@ +chr4 1281640 +chrM 19517 +chrU 8724946 +chrX 22224390 +chr2L 22407834 +chr2R 20766785 +chr2h 1694122 +chr3L 23771897 +chr3R 27905053 +chr3h 2955737 +chr4h 88110 +chrXh 359526 +chrYh 396896
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/dm3.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,15 @@ +chr2L 23011544 +chr2LHet 368872 +chr2R 21146708 +chr2RHet 3288761 +chr3L 24543557 +chr3LHet 2555491 +chr3R 27905053 +chr3RHet 2517507 +chr4 1351857 +chrU 10049037 +chrUextra 29004656 +chrX 22422827 +chrXHet 204112 +chrYHet 347038 +chrM 19517
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/hg15.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,44 @@ +chr1 245203898 +chr2 243315028 +chr3 199411731 +chr4 191610523 +chr5 180967295 +chr6 170740541 +chr7 158431299 +chr8 145908738 +chr9 134505819 +chrM 16571 +chrX 152634166 +chrY 50961097 +chr1_random 12562665 +chr2_random 1464032 +chr3_random 423185 +chr4_random 1219494 +chr6_random 12061844 +chr7_random 1057565 +chr8_random 427716 +chr9_random 2536476 +chrX_random 4859112 +chrY_random 191708 +chr10 135480874 +chr11 134978784 +chr12 133464434 +chr13 114151656 +chr14 105311216 +chr15 100114055 +chr16 89995999 +chr17 81691216 +chr18 77753510 +chr19 63790860 +chr20 63644868 +chr21 46976537 +chr22 49476972 +chr10_random 710249 +chr11_random 150110 +chr12_random 590431 +chr13_random 414659 +chr15_random 366089 +chr16_random 24360 +chr17_random 337440 +chr19_random 301858 +chrUn_random 611077
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/hg16.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,42 @@ +chr1 246127941 +chr2 243615958 +chr3 199344050 +chr4 191731959 +chr5 181034922 +chr6 170914576 +chr7 158545518 +chr8 146308819 +chr9 136372045 +chrM 16571 +chrX 153692391 +chrY 50286555 +chr1_random 6515988 +chr2_random 1104831 +chr3_random 749256 +chr4_random 648024 +chr5_random 143687 +chr6_random 2055751 +chr7_random 632637 +chr8_random 1499381 +chr9_random 2766341 +chrX_random 3403558 +chr10 135037215 +chr11 134482954 +chr12 132078379 +chr13 113042980 +chr14 105311216 +chr15 100256656 +chr16 90041932 +chr17 81860266 +chr18 76115139 +chr19 63811651 +chr20 63741868 +chr21 46976097 +chr22 49396972 +chr10_random 1043775 +chr13_random 189598 +chr15_random 1132826 +chr17_random 2549222 +chr18_random 4262 +chr19_random 92689 +chrUn_random 3349625
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/hg17.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,46 @@ +chr10 135413628 +chr10_random 113275 +chr11 134452384 +chr12 132449811 +chr12_random 466818 +chr13 114142980 +chr13_random 186858 +chr14 106368585 +chr15 100338915 +chr15_random 784346 +chr16 88827254 +chr16_random 105485 +chr17 78774742 +chr17_random 2618010 +chr18 76117153 +chr18_random 4262 +chr19 63811651 +chr19_random 301858 +chr1 245522847 +chr1_random 3897131 +chr20 62435964 +chr21 46944323 +chr22 49554710 +chr22_random 257318 +chr2 243018229 +chr2_random 418158 +chr3 199505740 +chr3_random 970716 +chr4 191411218 +chr4_random 1030282 +chr5 180857866 +chr5_random 143687 +chr6 170975699 +chr6_random 1875562 +chr6_hla_hap1 139182 +chr6_hla_hap2 150447 +chr7 158628139 +chr7_random 778964 +chr8 146274826 +chr8_random 943810 +chr9 138429268 +chr9_random 1312665 +chrM 16571 +chrX 154824264 +chrX_random 1719168 +chrY 57701691
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/hg18.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,49 @@ +chr1 247249719 +chr1_random 1663265 +chr10 135374737 +chr10_random 113275 +chr11 134452384 +chr11_random 215294 +chr12 132349534 +chr13 114142980 +chr13_random 186858 +chr14 106368585 +chr15 100338915 +chr15_random 784346 +chr16 88827254 +chr16_random 105485 +chr17 78774742 +chr17_random 2617613 +chr18 76117153 +chr18_random 4262 +chr19 63811651 +chr19_random 301858 +chr2 242951149 +chr2_random 185571 +chr20 62435964 +chr21 46944323 +chr21_random 1679693 +chr22 49691432 +chr22_random 257318 +chr22_h2_hap1 63661 +chr3 199501827 +chr3_random 749256 +chr4 191273063 +chr4_random 842648 +chr5 180857866 +chr5_random 143687 +chr5_h2_hap1 1794870 +chr6 170899992 +chr6_random 1875562 +chr6_cox_hap1 4731698 +chr6_qbl_hap2 4565931 +chr7 158821424 +chr7_random 549659 +chr8 146274826 +chr8_random 943810 +chr9 140273252 +chr9_random 1146434 +chrM 16571 +chrX 154913754 +chrX_random 1719168 +chrY 57772954
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/hg19.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,93 @@ +chr1 249250621 +chr2 243199373 +chr3 198022430 +chr4 191154276 +chr5 180915260 +chr6 171115067 +chr7 159138663 +chrX 155270560 +chr8 146364022 +chr9 141213431 +chr10 135534747 +chr11 135006516 +chr12 133851895 +chr13 115169878 +chr14 107349540 +chr15 102531392 +chr16 90354753 +chr17 81195210 +chr18 78077248 +chr20 63025520 +chrY 59373566 +chr19 59128983 +chr22 51304566 +chr21 48129895 +chr6_ssto_hap7 4928567 +chr6_mcf_hap5 4833398 +chr6_cox_hap2 4795371 +chr6_mann_hap4 4683263 +chr6_apd_hap1 4622290 +chr6_qbl_hap6 4611984 +chr6_dbb_hap3 4610396 +chr17_ctg5_hap1 1680828 +chr4_ctg9_hap1 590426 +chr1_gl000192_random 547496 +chrUn_gl000225 211173 +chr4_gl000194_random 191469 +chr4_gl000193_random 189789 +chr9_gl000200_random 187035 +chrUn_gl000222 186861 +chrUn_gl000212 186858 +chr7_gl000195_random 182896 +chrUn_gl000223 180455 +chrUn_gl000224 179693 +chrUn_gl000219 179198 +chr17_gl000205_random 174588 +chrUn_gl000215 172545 +chrUn_gl000216 172294 +chrUn_gl000217 172149 +chr9_gl000199_random 169874 +chrUn_gl000211 166566 +chrUn_gl000213 164239 +chrUn_gl000220 161802 +chrUn_gl000218 161147 +chr19_gl000209_random 159169 +chrUn_gl000221 155397 +chrUn_gl000214 137718 +chrUn_gl000228 129120 +chrUn_gl000227 128374 +chr1_gl000191_random 106433 +chr19_gl000208_random 92689 +chr9_gl000198_random 90085 +chr17_gl000204_random 81310 +chrUn_gl000233 45941 +chrUn_gl000237 45867 +chrUn_gl000230 43691 +chrUn_gl000242 43523 +chrUn_gl000243 43341 +chrUn_gl000241 42152 +chrUn_gl000236 41934 +chrUn_gl000240 41933 +chr17_gl000206_random 41001 +chrUn_gl000232 40652 +chrUn_gl000234 40531 +chr11_gl000202_random 40103 +chrUn_gl000238 39939 +chrUn_gl000244 39929 +chrUn_gl000248 39786 +chr8_gl000196_random 38914 +chrUn_gl000249 38502 +chrUn_gl000246 38154 +chr17_gl000203_random 37498 +chr8_gl000197_random 37175 +chrUn_gl000245 36651 +chrUn_gl000247 36422 +chr9_gl000201_random 36148 +chrUn_gl000235 34474 +chrUn_gl000239 33824 +chr21_gl000210_random 27682 +chrUn_gl000231 27386 +chrUn_gl000229 19913 +chrM 16571 +chrUn_gl000226 15008 +chr18_gl000207_random 4262
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/hg19Haps.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,9 @@ +chr6_ssto_hap7 4928567 +chr6_mcf_hap5 4833398 +chr6_cox_hap2 4795371 +chr6_mann_hap4 4683263 +chr6_apd_hap1 4622290 +chr6_qbl_hap6 4611984 +chr6_dbb_hap3 4610396 +chr17_ctg5_hap1 1680828 +chr4_ctg9_hap1 590426
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/hg19Patch2.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,80 @@ +chr6_ssto_hap7 4928567 +chr6_mcf_hap5 4833398 +chr6_cox_hap2 4795371 +chr6_mann_hap4 4683263 +chr6_apd_hap1 4622290 +chr6_qbl_hap6 4611984 +chr6_dbb_hap3 4610396 +chr17_ctg5_hap1 1680828 +chr5_ctg1_gl339449 1620324 +chr4_ctg9_hap1 590426 +chr17_gl383560 534288 +chr17_gl383558 457041 +chr8_gl383535 429806 +chr17_gl383561 406963 +chr10_gl383543 392792 +chr15_ctg8_gl383555 388773 +chr19_ctg3_gl383573 385657 +chr4_ctg6_gl383528 376187 +chr1_ctg31_gl383520 366579 +chr17_gl383559 338640 +chr9_gl339450 330164 +chr10_ctg5_gl383546 309802 +chr15_ctg4_gl383554 296527 +chr18_ctg1_gl383567 289831 +chr17_ctg1_gl383563 270261 +chr17_ctg4_gl383565 223995 +chr8_gl383536 203777 +chr21_ctg1_gl383579 201198 +chr18_ctg2_gl383571 198278 +chr16_ctg3_gl383556 192462 +chr19_ctg3_gl383576 188024 +chr12_ctg5_gl383551 184319 +chr1_ctg31_gl383518 182439 +chr3_ctg2_gl383526 180671 +chr10_ctg2_gl383545 179254 +chr5_ctg5_gl383531 173459 +chr3_gl383523 171362 +chr9_ctg35_gl383541 171286 +chr19_ctg3_gl383575 170227 +chr12_ctg2_gl383550 169178 +chr18_ctg2_gl383569 167950 +chr12_gl383548 165247 +chr18_ctg1_gl383570 164789 +chr4_ctg12_gl383527 164536 +chr9_ctg1_gl383539 162988 +chr18_ctg2_gl383572 159547 +chr22_ctg1_gl383582 158507 +chr19_ctg3_gl383574 155864 +chr12_ctg2_gl383553 154881 +chr11_ctg1_gl383547 154407 +chr2_ctg1_gl383521 143390 +chr12_ctg2_gl383552 138655 +chr17_ctg4_gl383564 133151 +chr20_ctg1_gl383577 128385 +chr10_gl383544 128378 +chr6_ctg5_gl383533 124736 +chr2_ctg12_gl383522 123821 +chr4_ctg9_gl383529 121345 +chr12_ctg2_gl383549 120804 +chr7_ctg6_gl383534 119383 +chr21_ctg1_gl383581 116690 +chr1_ctg31_gl383519 110268 +chr18_ctg2_gl383568 104552 +chr5_ctg2_gl383530 101241 +chr22_ctg2_gl383583 96924 +chr17_ctg4_gl383566 90219 +chr16_ctg3_gl383557 89672 +chr5_ctg1_gl383532 82728 +chr3_gl383524 78793 +chr21_ctg1_gl383580 74652 +chr9_ctg35_gl383540 71551 +chr3_gl383525 65063 +chr21_ctg1_gl383578 63917 +chr9_gl383537 62435 +chr9_ctg35_gl383542 60032 +chr1_gl383517 49352 +chr1_gl383516 49316 +chr9_gl383538 49281 +chr17_gl383562 45551 +chrM_rCRS 16569
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/klac.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,6 @@ +1 1062590 +2 1320834 +3 1753957 +4 1715506 +5 2234072 +6 2602197
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/kwal.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,459 @@ +0 2534 +1 125497 +2 14630 +3 14849 +4 21406 +5 143962 +6 27307 +7 88161 +8 132901 +9 16396 +10 8070 +11 186703 +12 36232 +13 51137 +14 15683 +15 19814 +16 24938 +17 58820 +18 38681 +19 5673 +20 23346 +21 4497 +22 41879 +23 29929 +24 38007 +25 7906 +26 32971 +27 213938 +28 44808 +29 35672 +30 18684 +31 57206 +32 39731 +33 128244 +34 41627 +35 25640 +36 83302 +37 18219 +38 7667 +39 19053 +40 3209 +41 26587 +42 27452 +43 129376 +44 73166 +45 12013 +46 86564 +47 106408 +48 11182 +49 9044 +50 17620 +51 17937 +52 12313 +53 13758 +54 21810 +55 238839 +56 2172 +57 2068 +58 24309 +59 27367 +60 19249 +61 49414 +62 2239 +63 9166 +64 3092 +65 5670 +66 2379 +67 89261 +68 119088 +69 16610 +70 68860 +71 7266 +72 40707 +73 49099 +74 3103 +75 15753 +76 37215 +77 9752 +78 2842 +79 3547 +80 8340 +81 2898 +82 26275 +83 1877 +84 7360 +85 10758 +86 12945 +87 2482 +88 1710 +89 10942 +90 2738 +91 4243 +92 4063 +93 4079 +94 95425 +95 1533 +96 26470 +97 1680 +98 8165 +99 1842 +100 10872 +101 72566 +102 41877 +103 25474 +104 80558 +105 89805 +106 18077 +107 7530 +108 62247 +109 3586 +110 8739 +111 2464 +112 12564 +113 4895 +114 68417 +115 2717 +116 36429 +117 33291 +118 43283 +119 32251 +120 6350 +121 27512 +122 3350 +123 92481 +124 139895 +125 7256 +126 69178 +127 2478 +128 65621 +129 16657 +130 116273 +131 4418 +132 42306 +133 2406 +134 7442 +135 34971 +136 5638 +137 25742 +138 24660 +139 33008 +140 12961 +141 3891 +142 11359 +143 4509 +144 14574 +145 12379 +146 1563 +147 14893 +148 40168 +149 38705 +150 11968 +151 8479 +152 45612 +153 41502 +154 3140 +155 7073 +156 9905 +157 20593 +158 4160 +159 193906 +160 62941 +161 118475 +162 6963 +163 22133 +164 16355 +165 75530 +166 54174 +167 1343 +168 12950 +169 3447 +170 2919 +171 62747 +172 18589 +173 35297 +174 21491 +175 27381 +176 72161 +177 20372 +178 2700 +179 3322 +180 14134 +181 28845 +182 12905 +183 95360 +184 183765 +185 88813 +186 33036 +187 8378 +188 85033 +189 25272 +190 55902 +191 32868 +192 15238 +193 7566 +194 18007 +195 55872 +196 40080 +197 67181 +198 33220 +199 2793 +200 3391 +201 3701 +202 26101 +203 3511 +204 59973 +205 19265 +206 71746 +207 60023 +208 13067 +209 16995 +210 23815 +211 28487 +212 33526 +213 3586 +214 8067 +215 40367 +216 6559 +217 4358 +218 20016 +219 49821 +220 4268 +223 1302 +224 93571 +225 50086 +226 2886 +227 52355 +228 16270 +229 17925 +230 23564 +231 18755 +232 31964 +233 1570 +234 2415 +235 14560 +236 1731 +237 81585 +238 28707 +239 17167 +240 2875 +241 25088 +242 31259 +243 26745 +244 154632 +245 115160 +246 72184 +247 33539 +248 57737 +249 14547 +250 33679 +251 31357 +252 103558 +253 45320 +254 49503 +255 143040 +256 2466 +257 4108 +258 2372 +259 1928 +260 167397 +261 15852 +262 1441 +263 1554 +264 2637 +265 24142 +266 3777 +267 7711 +268 18551 +269 4004 +270 8972 +271 26934 +272 87860 +273 19114 +274 30786 +275 9656 +278 8868 +279 3258 +280 21868 +281 1988 +282 4323 +283 1223 +284 2472 +285 6576 +286 5548 +287 3198 +288 4014 +289 9582 +290 162263 +291 2221 +292 1850 +293 1652 +294 20909 +295 17606 +296 2866 +297 1704 +298 9311 +299 1009 +301 4475 +303 9229 +304 1977 +305 11008 +311 23764 +312 4784 +313 1296 +314 4092 +316 8619 +317 2626 +318 2050 +319 1424 +320 5110 +322 6341 +323 4249 +324 1824 +325 1783 +326 6231 +327 5048 +328 4865 +329 1570 +330 3539 +331 13212 +332 1641 +333 5872 +334 5842 +335 5050 +336 43798 +337 1403 +338 1507 +339 2056 +340 1548 +341 1516 +343 2948 +344 93162 +345 10302 +346 1452 +347 4043 +348 2486 +349 2696 +350 1996 +351 6210 +352 747 +353 5694 +354 4998 +355 4074 +356 4769 +357 4339 +358 36291 +359 9937 +360 2677 +361 2847 +362 1661 +363 52128 +364 3720 +365 1654 +366 2713 +367 1250 +368 3279 +369 7143 +372 8172 +373 1057 +376 113992 +377 1076 +378 2288 +379 1144 +380 4811 +381 9891 +386 4220 +387 1417 +388 41838 +389 1218 +390 2234 +391 1105 +392 871 +393 3493 +394 1983 +395 1310 +396 28400 +397 919 +398 1362 +399 3442 +400 1525 +401 1671 +402 1120 +403 799 +404 1763 +405 1818 +406 1786 +407 1123 +408 1388 +409 839 +410 2870 +411 1955 +412 2189 +413 1100 +414 2057 +415 991 +416 3094 +417 3187 +418 1185 +419 3118 +420 1230 +421 1421 +422 1603 +423 1641 +424 1882 +425 1479 +426 4008 +427 1785 +428 2536 +429 1193 +430 2549 +431 1682 +432 3994 +433 1014 +434 745 +435 1117 +436 3520 +437 1677 +438 676 +439 2979 +440 1726 +441 5119 +442 5142 +443 935 +444 1354 +446 2597 +447 2611 +448 1179 +449 5365 +450 1259 +451 5395 +452 1972 +453 3195 +454 816 +455 7081 +456 1241 +457 21922 +458 1100 +459 927 +460 1100 +461 5552 +462 5577 +463 5460 +665 2006 +666 1381 +667 1781 +668 1407 +690 4541 +691 2971 +692 1226 +693 1100 +694 1218 +695 5394 +696 4542 +697 14183 +698 5428 +699 577 +700 2530 +710 16854 +711 2634 +712 5627
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/sacCer1.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,17 @@ +chr1 230208 +chr10 745446 +chr11 666445 +chr12 1078173 +chr13 924430 +chr14 784328 +chr15 1091285 +chr16 948060 +chr2 813136 +chr3 316613 +chr4 1531914 +chr5 576869 +chr6 270148 +chr7 1090944 +chr8 562639 +chr9 439885 +chrM 85779
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/sacCer2.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,18 @@ +chrIV 1531919 +chrXV 1091289 +chrVII 1090947 +chrXII 1078175 +chrXVI 948062 +chrXIII 924429 +chrII 813178 +chrXIV 784333 +chrX 745742 +chrXI 666454 +chrV 576869 +chrVIII 562643 +chrIX 439885 +chrIII 316617 +chrVI 270148 +chrI 230208 +chrM 85779 +2micron 6318
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/assemblies/sacCer3.len Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,17 @@ +chrI 230218 +chrII 813184 +chrIII 316620 +chrIV 1531933 +chrIX 439888 +chrV 576874 +chrVI 270161 +chrVII 1090940 +chrVIII 562643 +chrX 745751 +chrXI 666816 +chrXII 1078177 +chrXIII 924431 +chrXIV 784333 +chrXV 1091291 +chrXVI 948066 +chrM 85779
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/resources/toolConf.xml Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- This is the tool configuration file for the ToolRunner GUI --> +<tools> + <section name="Converters"> + <tool name="IntervalToWig" class="edu.unc.genomics.converters.IntervalToWig" /> + <tool name="RomanNumeralize" class="edu.unc.genomics.converters.RomanNumeralize" /> + </section> + + <section name="NGS"> + <tool name="Autocorrelation" class="edu.unc.genomics.ngs.Autocorrelation" /> + <tool name="BaseAlignCounts" class="edu.unc.genomics.ngs.BaseAlignCounts" /> + <tool name="FindAbsoluteMaxima" class="edu.unc.genomics.ngs.FindAbsoluteMaxima" /> + <tool name="IntervalLengthDistribution" class="edu.unc.genomics.ngs.IntervalLengthDistribution" /> + <tool name="IntervalStats" class="edu.unc.genomics.ngs.IntervalStats" /> + <tool name="PowerSpectrum" class="edu.unc.genomics.ngs.PowerSpectrum" /> + <tool name="RollingReadLength" class="edu.unc.genomics.ngs.RollingReadLength" /> + </section> + + <section name="Nucleosomes"> + <tool name="FindBoundaryNucleosomes" class="edu.unc.genomics.nucleosomes.FindBoundaryNucleosomes" /> + <tool name="GreedyCaller" class="edu.unc.genomics.nucleosomes.GreedyCaller" /> + <tool name="MapDyads" class="edu.unc.genomics.nucleosomes.MapDyads" /> + <tool name="NRLCalculator" class="edu.unc.genomics.nucleosomes.NRLCalculator" /> + <tool name="Phasogram" class="edu.unc.genomics.nucleosomes.Phasogram" /> + </section> + + <section name="Visualization"> + <tool name="IntervalAverager" class="edu.unc.genomics.visualization.IntervalAverager" /> + <tool name="KMeans" class="edu.unc.genomics.visualization.KMeans" /> + <tool name="MatrixAligner" class="edu.unc.genomics.visualization.MatrixAligner" /> + </section> + + <section name="WigMath"> + <tool name="Add" class="edu.unc.genomics.wigmath.Add" /> + <tool name="Average" class="edu.unc.genomics.wigmath.Average" /> + <tool name="Divide" class="edu.unc.genomics.wigmath.Divide" /> + <tool name="GaussianSmooth" class="edu.unc.genomics.wigmath.GaussianSmooth" /> + <tool name="LogTransform" class="edu.unc.genomics.wigmath.LogTransform" /> + <tool name="MovingAverageSmooth" class="edu.unc.genomics.wigmath.MovingAverageSmooth" /> + <tool name="Multiply" class="edu.unc.genomics.wigmath.Multiply" /> + <tool name="Scale" class="edu.unc.genomics.wigmath.Scale" /> + <tool name="Subtract" class="edu.unc.genomics.wigmath.Subtract" /> + <tool name="WigSummary" class="edu.unc.genomics.wigmath.WigSummary" /> + <tool name="ZScore" class="edu.unc.genomics.wigmath.ZScore" /> + </section> +</tools> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/config/GalaxyConfig.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,42 @@ +package edu.unc.config; + +import java.io.IOException; +import java.nio.file.Path; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +public class GalaxyConfig { + + /** + * Parse a Galaxy configuration file + * @param p + * @return + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public static GalaxyConfig parse(Path p) throws ParserConfigurationException, SAXException, IOException { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(p.toFile()); + return parse(doc); + } + + /** + * Parse a Galaxy configuration XML + * @param doc + * @return + */ + public static GalaxyConfig parse(Document doc) { + GalaxyConfig config = new GalaxyConfig(); + + // TODO Implement parser + + return config; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/AssemblyConverter.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,43 @@ +package edu.unc.genomics; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.zip.DataFormatException; + +import com.beust.jcommander.IStringConverter; +import com.beust.jcommander.ParameterException; + +/** + * @author timpalpant + * + */ +public class AssemblyConverter implements IStringConverter<Assembly> { + + public static final Path ASSEMBLIES_DIR = Paths.get("resources", "assemblies"); + + @Override + public Assembly convert(String value) throws ParameterException { + // Look for the assembly in the resources/assemblies directory + Path p = ASSEMBLIES_DIR.resolve(value+".len"); + + // If it does not exist in the assemblies directory, check if it is a path to a file + if (!Files.isReadable(p)) { + PathConverter converter = new PathConverter(); + p = converter.convert(value); + // If it does not exist, then throw an exception that the assembly cannot be found + if (!Files.isReadable(p)) { + throw new ParameterException("Cannot find Assembly file: " + value); + } + } + + // Attempt to load the assembly from file + try { + return new Assembly(p); + } catch (IOException | DataFormatException e) { + throw new ParameterException("Error loading Assembly from file: " + p); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/AssemblyFactory.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,26 @@ +/** + * + */ +package edu.unc.genomics; + +import com.beust.jcommander.IStringConverterFactory; + +/** + * @author timpalpant + * + */ +public class AssemblyFactory implements IStringConverterFactory { + + /* (non-Javadoc) + * @see com.beust.jcommander.IStringConverterFactory#getConverter(java.lang.Class) + */ + @Override + public Class<AssemblyConverter> getConverter(Class forType) { + if (forType.equals(Assembly.class)) { + return AssemblyConverter.class; + } else { + return null; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/CommandLineTool.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,73 @@ +package edu.unc.genomics; + +import java.io.IOException; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.ParameterException; + +/** + * A command-line script + * @author timpalpant + * + */ +public abstract class CommandLineTool { + + /** + * JCommander command-line argument parser + */ + private final JCommander jc = new JCommander(this); + + public CommandLineTool() { + // Add factories for parsing Paths, Assemblies, IntervalFiles, and WigFiles + jc.addConverterFactory(new PathFactory()); + jc.addConverterFactory(new AssemblyFactory()); + jc.addConverterFactory(new IntervalFileFactory()); + jc.addConverterFactory(new WigFileFactory()); + + // Set the program name to be the class name + jc.setProgramName(this.getClass().getSimpleName()); + } + + /** + * The default bite-size to use for applications that process files in chunks + */ + public static final int DEFAULT_CHUNK_SIZE = 500_000; + + /** + * Do the main computation of this tool + * @throws IOException + */ + public abstract void run() throws IOException; + + /** + * Parse command-line arguments and run the tool + * Exit on parameter exceptions + * @param args + */ + public void instanceMain(String[] args) throws CommandLineToolException { + try { + toolRunnerMain(args); + } catch (ParameterException e) { + System.err.println(e.getMessage()); + jc.usage(); + System.exit(-1); + } + } + + /** + * Parse command-line arguments and run the tool + * @param args + * @throws ParameterException if there are invalid/missing parameters + * @throws CommandLineToolException if an exception occurs while running the tool + */ + public void toolRunnerMain(String[] args) throws ParameterException, CommandLineToolException { + jc.parse(args); + + try { + run(); + } catch (IOException e) { + e.printStackTrace(); + throw new CommandLineToolException("IO error while running tool"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/CommandLineToolException.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,58 @@ +package edu.unc.genomics; + +/** + * @author timpalpant + * + */ +public class CommandLineToolException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 4740440799806133636L; + + /** + * + */ + public CommandLineToolException() { + // TODO Auto-generated constructor stub + } + + /** + * @param message + */ + public CommandLineToolException(String message) { + super(message); + // TODO Auto-generated constructor stub + } + + /** + * @param cause + */ + public CommandLineToolException(Throwable cause) { + super(cause); + // TODO Auto-generated constructor stub + } + + /** + * @param message + * @param cause + */ + public CommandLineToolException(String message, Throwable cause) { + super(message, cause); + // TODO Auto-generated constructor stub + } + + /** + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace + */ + public CommandLineToolException(String message, Throwable cause, + boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + // TODO Auto-generated constructor stub + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/IntervalFileConverter.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,28 @@ +package edu.unc.genomics; + +import java.io.IOException; +import java.nio.file.Path; + +import com.beust.jcommander.IStringConverter; +import com.beust.jcommander.ParameterException; + +import edu.unc.genomics.io.IntervalFile; + +/** + * @author timpalpant + * + */ +public class IntervalFileConverter implements IStringConverter<IntervalFile<? extends Interval>> { + + @Override + public IntervalFile<? extends Interval> convert(String value) throws ParameterException { + PathConverter converter = new PathConverter(); + Path p = converter.convert(value); + try { + return IntervalFile.autodetect(p); + } catch (IOException e) { + throw new ParameterException("IOException while attempting to autodetect interval file type"); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/IntervalFileFactory.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,25 @@ +package edu.unc.genomics; + +import com.beust.jcommander.IStringConverterFactory; + +import edu.unc.genomics.io.IntervalFile; + +/** + * @author timpalpant + * + */ +public class IntervalFileFactory implements IStringConverterFactory { + + /* (non-Javadoc) + * @see com.beust.jcommander.IStringConverterFactory#getConverter(java.lang.Class) + */ + @Override + public Class<IntervalFileConverter> getConverter(Class forType) { + if (forType.equals(IntervalFile.class)) { + return IntervalFileConverter.class; + } else { + return null; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/PathConverter.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,19 @@ +package edu.unc.genomics; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import com.beust.jcommander.IStringConverter; + +/** + * @author timpalpant + * + */ +public class PathConverter implements IStringConverter<Path> { + + @Override + public Path convert(String value) { + return Paths.get(value); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/PathFactory.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,27 @@ +/** + * + */ +package edu.unc.genomics; + +import java.nio.file.Path; + +import com.beust.jcommander.IStringConverterFactory; + +/** + * @author timpalpant + * + */ +public class PathFactory implements IStringConverterFactory { + /* (non-Javadoc) + * @see com.beust.jcommander.IStringConverterFactory#getConverter(java.lang.Class) + */ + @Override + public Class<PathConverter> getConverter(Class forType) { + if (forType.equals(Path.class)) { + return PathConverter.class; + } else { + return null; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/PositiveIntegerValidator.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,23 @@ +package edu.unc.genomics; + +import com.beust.jcommander.IParameterValidator; +import com.beust.jcommander.ParameterException; + +/** + * @author timpalpant + * + */ +public class PositiveIntegerValidator implements IParameterValidator { + + /* (non-Javadoc) + * @see com.beust.jcommander.IParameterValidator#validate(java.lang.String, java.lang.String) + */ + @Override + public void validate(String name, String value) throws ParameterException { + int n = Integer.parseInt(value); + if (n <= 0) { + throw new ParameterException("Parameter "+name+" must be > 0 (was "+value+")"); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/ReadablePathValidator.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,30 @@ +/** + * + */ +package edu.unc.genomics; + +import java.nio.file.Files; +import java.nio.file.Path; + +import com.beust.jcommander.IParameterValidator; +import com.beust.jcommander.ParameterException; + +/** + * @author timpalpant + * + */ +public class ReadablePathValidator implements IParameterValidator { + + /* (non-Javadoc) + * @see com.beust.jcommander.IParameterValidator#validate(java.lang.String, java.lang.String) + */ + @Override + public void validate(String name, String value) throws ParameterException { + PathConverter converter = new PathConverter(); + Path p = converter.convert(value); + if (!Files.isReadable(p)) { + throw new ParameterException("Parameter " + name + " should be a readable file"); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/WigFileConverter.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,29 @@ +package edu.unc.genomics; + +import java.io.IOException; +import java.nio.file.Path; + +import com.beust.jcommander.IStringConverter; +import com.beust.jcommander.ParameterException; + +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +/** + * @author timpalpant + * + */ +public class WigFileConverter implements IStringConverter<WigFile> { + + @Override + public WigFile convert(String value) throws ParameterException { + PathConverter converter = new PathConverter(); + Path p = converter.convert(value); + try { + return WigFile.autodetect(p); + } catch (WigFileException | IOException e) { + throw new ParameterException("Error autodetecting and initializing BigWig/Wig file"); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/WigFileFactory.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,25 @@ +package edu.unc.genomics; + +import com.beust.jcommander.IStringConverterFactory; + +import edu.unc.genomics.io.WigFile; + +/** + * @author timpalpant + * + */ +public class WigFileFactory implements IStringConverterFactory { + + /* (non-Javadoc) + * @see com.beust.jcommander.IStringConverterFactory#getConverter(java.lang.Class) + */ + @Override + public Class<WigFileConverter> getConverter(Class forType) { + if (forType.equals(WigFile.class)) { + return WigFileConverter.class; + } else { + return null; + } + } + +}
Binary file java-genomics-toolkit/src/edu/unc/genomics/converters/._RomanNumeralize.java has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/converters/IntervalToWig.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,91 @@ +package edu.unc.genomics.converters; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Iterator; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.ucsc.genome.TrackHeader; +import edu.unc.genomics.Assembly; +import edu.unc.genomics.Interval; +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.ValuedInterval; +import edu.unc.genomics.io.IntervalFile; + +public class IntervalToWig extends CommandLineTool { + + private static final Logger log = Logger.getLogger(IntervalToWig.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (Bed/BedGraph)", required = true) + public IntervalFile<? extends Interval> intervalFile; + @Parameter(names = {"-a", "--assembly"}, description = "Genome assembly", required = true) + public Assembly assembly; + @Parameter(names = {"-o", "--output"}, description = "Output file (Wig)", required = true) + public Path outputFile; + + @Override + public void run() throws IOException { + log.info(intervalFile.count() + " entries in input"); + + log.debug("Initializing output file"); + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + // Write the Wiggle track header to the output file + TrackHeader header = new TrackHeader("wiggle_0"); + header.setName("Converted " + intervalFile.getPath().getFileName()); + header.setDescription("Converted " + intervalFile.getPath().getFileName()); + writer.write(header.toString()); + writer.newLine(); + + // Process each chromosome in the assembly + for (String chr : assembly) { + log.debug("Processing chromosome " + chr); + // Write the contig header to the output file + writer.write("fixedStep chrom="+chr+" start=1 step=1 span=1"); + writer.newLine(); + + int start = 1; + while (start < assembly.getChrLength(chr)) { + int stop = start + DEFAULT_CHUNK_SIZE - 1; + int length = stop - start + 1; + int[] count = new int[length]; + float[] sum = new float[length]; + + Iterator<? extends Interval> it = intervalFile.query(chr, start, stop); + while (it.hasNext()) { + ValuedInterval entry = (ValuedInterval) it.next(); + if (entry.getValue() != null) { + for (int i = entry.getStart(); i <= entry.getStop(); i++) { + sum[i-start] += entry.getValue().floatValue(); + count[i-start]++; + } + } + } + + // Write the average at each base pair to the output file + for (int i = 0; i < sum.length; i++) { + if (count[i] == 0) { + writer.write(String.valueOf(Float.NaN)); + } else { + writer.write(String.valueOf(sum[i]/count[i])); + } + writer.newLine(); + } + + // Process the next chunk + start = stop + 1; + } + } + } + } + + public static void main(String[] args) { + new IntervalToWig().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/converters/RomanNumeralize.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,61 @@ +package edu.unc.genomics.converters; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.ReadablePathValidator; +import edu.unc.utils.RomanNumeral; + +public class RomanNumeralize extends CommandLineTool { + + private static final Logger log = Logger.getLogger(RomanNumeralize.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file", required = true, validateWith = ReadablePathValidator.class) + public Path inputFile; + @Parameter(names = {"-o", "--output"}, description = "Output file", required = true) + public Path outputFile; + + /** + * Pattern for finding "chr12" tokens (will find "chr1" through "chr99") + */ + Pattern p = Pattern.compile("/chr[\\d]{1,2}/i"); + + @Override + public void run() throws IOException { + try (BufferedReader reader = Files.newBufferedReader(inputFile, Charset.defaultCharset()); + BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + log.debug("Copying input to output and replacing with Roman Numerals"); + String line; + while ((line = reader.readLine()) != null) { + Matcher m = p.matcher(line); + StringBuffer converted = new StringBuffer(line.length()); + while (m.find()) { + String chrNum = line.substring(m.start()+3, m.end()); + int arabic = Integer.parseInt(chrNum); + String roman = RomanNumeral.int2roman(arabic); + m.appendReplacement(converted, "chr"+roman); + } + m.appendTail(converted); + + writer.write(converted.toString()); + writer.newLine(); + } + } + } + + public static void main(String[] args) { + new RomanNumeralize().instanceMain(args); + } + +}
Binary file java-genomics-toolkit/src/edu/unc/genomics/ngs/._IntervalLengthDistribution.java has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/ngs/Autocorrelation.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,84 @@ +package edu.unc.genomics.ngs; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Iterator; + +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D; +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.Interval; +import edu.unc.genomics.PositiveIntegerValidator; +import edu.unc.genomics.io.IntervalFile; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class Autocorrelation extends CommandLineTool { + + private static final Logger log = Logger.getLogger(Autocorrelation.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file", required = true) + public WigFile wig; + @Parameter(names = {"-l", "--loci"}, description = "Genomic loci (Bed format)", required = true) + public IntervalFile<? extends Interval> loci; + @Parameter(names = {"-o", "--output"}, description = "Output file", required = true) + public Path outputFile; + @Parameter(names = {"-m", "--max"}, description = "Autocorrelation limit (bp)", validateWith = PositiveIntegerValidator.class) + public int limit = 200; + + private void abs2(float[] data) { + for (int i = 0; i < data.length; i+=2) { + data[i] = data[i]*data[i] + data[i+1]*data[i+1]; + data[i+1] = 0; + } + } + + @Override + public void run() throws IOException { + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + log.debug("Computing autocorrelation for each window"); + int skipped = 0; + for (Interval interval : loci) { + if (interval.length() < limit) { + log.debug("Skipping interval: " + interval.toString()); + skipped++; + continue; + } + + Iterator<WigItem> wigIter; + try { + wigIter = wig.query(interval); + } catch (IOException | WigFileException e) { + log.debug("Skipping interval: " + interval.toString()); + skipped++; + continue; + } + + float[] data = WigFile.flattenData(wigIter, interval.getStart(), interval.getStop()); + + // Compute the autocorrelation with the Wiener-Khinchin theorem + FloatFFT_1D fft = new FloatFFT_1D(data.length); + fft.realForward(data); + abs2(data); + fft.realInverse(data, true); + + writer.write(StringUtils.join(data, "\t")); + writer.newLine(); + } + + log.info("Skipped " + skipped + " intervals"); + } + } + + public static void main(String[] args) { + new Autocorrelation().instanceMain(args); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/ngs/BaseAlignCounts.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,94 @@ +package edu.unc.genomics.ngs; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Iterator; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.ucsc.genome.TrackHeader; +import edu.unc.genomics.Assembly; +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.Interval; +import edu.unc.genomics.io.IntervalFile; + +public class BaseAlignCounts extends CommandLineTool { + + private static final Logger log = Logger.getLogger(BaseAlignCounts.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (reads)", required = true) + public IntervalFile<? extends Interval> intervalFile; + @Parameter(names = {"-a", "--assembly"}, description = "Genome assembly", required = true) + public Assembly assembly; + @Parameter(names = {"-x", "--extend"}, description = "Extend reads from 5' end (default = read length)") + public Integer extend; + @Parameter(names = {"-o", "--output"}, description = "Output file (Wig)", required = true) + public Path outputFile; + + @Override + public void run() throws IOException { + log.debug("Initializing output file"); + int mapped = 0; + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + // Write the Wiggle track header to the output file + TrackHeader header = new TrackHeader("wiggle_0"); + header.setName("Converted " + intervalFile.getPath().getFileName()); + header.setDescription("Converted " + intervalFile.getPath().getFileName()); + writer.write(header.toString()); + writer.newLine(); + + // Process each chromosome in the assembly + for (String chr : assembly) { + log.debug("Processing chromosome " + chr); + // Write the contig header to the output file + writer.write("fixedStep chrom="+chr+" start=1 step=1 span=1"); + writer.newLine(); + + int start = 1; + while (start < assembly.getChrLength(chr)) { + int stop = start + DEFAULT_CHUNK_SIZE - 1; + int length = stop - start + 1; + int[] count = new int[length]; + + Iterator<? extends Interval> it = intervalFile.query(chr, start, stop); + while (it.hasNext()) { + Interval entry = it.next(); + int entryStop = entry.getStop(); + if (extend != null) { + if (entry.isWatson()) { + entryStop = entry.getStart() + extend; + } else { + entryStop = entry.getStart() - extend; + } + } + + for (int i = entry.getStart(); i <= entryStop; i++) { + count[i-start]++; + } + mapped++; + } + + // Write the count at each base pair to the output file + for (int i = 0; i < count.length; i++) { + writer.write(count[i]); + writer.newLine(); + } + + // Process the next chunk + start = stop + 1; + } + } + } + + log.info("Mapped "+mapped+" reads"); + } + + public static void main(String[] args) { + new BaseAlignCounts().instanceMain(args); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/ngs/FindAbsoluteMaxima.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,99 @@ +package edu.unc.genomics.ngs; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.Interval; +import edu.unc.genomics.io.IntervalFile; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class FindAbsoluteMaxima extends CommandLineTool { + + private static final Logger log = Logger.getLogger(FindAbsoluteMaxima.class); + + @Parameter(description = "Input files", required = true) + public List<String> inputFiles = new ArrayList<String>(); + @Parameter(names = {"-l", "--loci"}, description = "Loci file (Bed)", required = true) + public IntervalFile<? extends Interval> lociFile; + @Parameter(names = {"-o", "--output"}, description = "Output file", required = true) + public Path outputFile; + + private List<WigFile> wigs = new ArrayList<>(); + + @Override + public void run() throws IOException { + log.debug("Initializing input Wig file(s)"); + for (String inputFile : inputFiles) { + try { + WigFile wig = WigFile.autodetect(Paths.get(inputFile)); + wigs.add(wig); + } catch (WigFileException e) { + log.error("Error initializing Wig input file: " + inputFile); + e.printStackTrace(); + throw new RuntimeException("Error initializing Wig input file: " + inputFile); + } + } + + log.debug("Initializing output file"); + int count = 0, skipped = 0; + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + writer.write("#Chr\tStart\tStop\tID\tValue\tStrand"); + for (String inputFile : inputFiles) { + Path p = Paths.get(inputFile); + writer.write("\t" + p.getFileName().toString()); + } + writer.newLine(); + + log.debug("Iterating over all intervals and finding maxima"); + for (Interval interval : lociFile) { + writer.write(interval.toBed()); + for (WigFile wig : wigs) { + float maxValue = -Float.MAX_VALUE; + int maxima = -1; + try { + Iterator<WigItem> results = wig.query(interval); + while (results.hasNext()) { + WigItem item = results.next(); + if (item.getWigValue() > maxValue) { + maxValue = item.getWigValue(); + maxima = (item.getStartBase() + item.getEndBase()) / 2; + } + } + writer.write("\t" + maxima); + } catch (WigFileException e) { + writer.write("\t" + Float.NaN); + skipped++; + } + } + writer.newLine(); + count++; + } + } + + lociFile.close(); + for (WigFile wig : wigs) { + wig.close(); + } + log.info(count + " intervals processed"); + log.info(skipped + " interval skipped"); + } + + public static void main(String[] args) { + new FindAbsoluteMaxima().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/ngs/IntervalLengthDistribution.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,59 @@ +package edu.unc.genomics.ngs; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.commons.math.stat.Frequency; +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.Interval; +import edu.unc.genomics.io.IntervalFile; + +public class IntervalLengthDistribution extends CommandLineTool { + + private static final Logger log = Logger.getLogger(IntervalLengthDistribution.class); + + @Parameter(names = {"-i", "--input"}, description = "Interval file", required = true) + public IntervalFile<? extends Interval> inputFile; + @Parameter(names = {"-o", "--output"}, description = "Output file", required = true) + public Path outputFile; + + + @Override + public void run() throws IOException { + log.debug("Generating histogram of interval lengths"); + Frequency freq = new Frequency(); + int min = Integer.MAX_VALUE; + int max = -1; + for (Interval i : inputFile) { + int L = i.length(); + freq.addValue(L); + + if (L < min) { + min = L; + } + if (L > max) { + max = L; + } + } + + log.debug("Writing histogram output"); + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + for (int i = min; i <= max; i++) { + writer.write(i+"\t"+freq.getCount(i)); + writer.newLine(); + } + } + } + + public static void main(String[] args) { + new IntervalLengthDistribution().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/ngs/IntervalStats.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,102 @@ +package edu.unc.genomics.ngs; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.math.stat.descriptive.SummaryStatistics; +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.Interval; +import edu.unc.genomics.io.IntervalFile; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class IntervalStats extends CommandLineTool { + + private static final Logger log = Logger.getLogger(IntervalStats.class); + + @Parameter(description = "Input files", required = true) + public List<String> inputFiles = new ArrayList<String>(); + @Parameter(names = {"-l", "--loci"}, description = "Loci file (Bed)", required = true) + public IntervalFile<? extends Interval> lociFile; + @Parameter(names = {"-o", "--output"}, description = "Output file", required = true) + public Path outputFile; + + private List<WigFile> wigs = new ArrayList<>(); + + @Override + public void run() throws IOException { + log.debug("Initializing input Wig file(s)"); + for (String inputFile : inputFiles) { + try { + WigFile wig = WigFile.autodetect(Paths.get(inputFile)); + wigs.add(wig); + } catch (WigFileException e) { + log.error("Error initializing Wig input file: " + inputFile); + e.printStackTrace(); + throw new RuntimeException("Error initializing Wig input file: " + inputFile); + } + } + + log.debug("Initializing output file"); + int count = 0, skipped = 0; + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + writer.write("#Chr\tStart\tStop\tID\tValue\tStrand"); + for (String inputFile : inputFiles) { + Path p = Paths.get(inputFile); + writer.write("\t" + p.getFileName().toString()); + } + writer.newLine(); + + log.debug("Iterating over all intervals and computing statistics"); + SummaryStatistics stats = new SummaryStatistics(); + for (Interval interval : lociFile) { + List<Double> means = new ArrayList<>(wigs.size()); + for (WigFile wig : wigs) { + stats.clear(); + try { + Iterator<WigItem> result = wig.query(interval); + while(result.hasNext()) { + WigItem item = result.next(); + for (int i = item.getStartBase(); i <= item.getEndBase(); i++) { + stats.addValue(item.getWigValue()); + } + } + means.add(stats.getMean()); + } catch (WigFileException e) { + means.add(Double.NaN); + skipped++; + } + } + + writer.write(interval.toBed() + "\t" + StringUtils.join(means, "\t")); + writer.newLine(); + count++; + } + } + + lociFile.close(); + for (WigFile wig : wigs) { + wig.close(); + } + log.info(count + " intervals processed"); + log.info(skipped + " interval skipped"); + } + + public static void main(String[] args) { + new IntervalStats().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/ngs/PowerSpectrum.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,106 @@ +package edu.unc.genomics.ngs; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Iterator; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D; +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.Interval; +import edu.unc.genomics.io.IntervalFile; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class PowerSpectrum extends CommandLineTool { + + private static final Logger log = Logger.getLogger(PowerSpectrum.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (Wig)", required = true) + public WigFile inputFile; + @Parameter(names = {"-l", "--loci"}, description = "Genomic loci (Bed format)", required = true) + public IntervalFile<? extends Interval> loci; + @Parameter(names = {"-o", "--output"}, description = "Output file (tabular)", required = true) + public Path outputFile; + + /** + * Computes the power spectrum from FFT data + * taking into accound even/odd length arrays + * refer to JTransforms documentation for layout of the FFT data + * @param f + * @return + */ + private float[] abs2(float[] f) { + int n = f.length; + float[] ps = new float[n/2+1]; + // DC component + ps[0] = (f[0]*f[0]) / (n*n); + + // Even + if (n % 2 == 0) { + for (int k = 1; k < n/2; k++) { + ps[k] = f[2*k]*f[2*k] + f[2*k+1]*f[2*k+1]; + } + ps[n/2] = f[1]*f[1]; + // Odd + } else { + for (int k = 1; k < (n-1)/2; k++) { + ps[k] = f[2*k]*f[2*k] + f[2*k+1]*f[2*k+1]; + } + + ps[(n-1)/2] = f[n-1]*f[n-1] + f[1]*f[1]; + } + + return ps; + } + + public void run() throws IOException { + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + log.debug("Computing power spectrum for each window"); + int skipped = 0; + for (Interval interval : loci) { + Iterator<WigItem> wigIter; + try { + wigIter = inputFile.query(interval); + } catch (IOException | WigFileException e) { + log.debug("Skipping interval: " + interval.toString()); + skipped++; + continue; + } + + float[] data = WigFile.flattenData(wigIter, interval.getStart(), interval.getStop()); + // Compute the power spectrum + FloatFFT_1D fft = new FloatFFT_1D(data.length); + fft.realForward(data); + float[] ps = abs2(data); + // and normalize the power spectrum + float sum = 0; + for (int i = 1; i < ps.length; i++) { + sum += ps[i]; + } + for (int i = 1; i < ps.length; i++) { + ps[i] /= sum; + } + + writer.write(interval.toBed()); + for (int i = 1; i < Math.min(ps.length, 40); i++) { + writer.write("\t"+ps[i]); + } + writer.newLine(); + } + + log.info("Skipped " + skipped + " intervals"); + } + } + + public static void main(String[] args) { + new PowerSpectrum().instanceMain(args); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/ngs/RollingReadLength.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,89 @@ +package edu.unc.genomics.ngs; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Iterator; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.ucsc.genome.TrackHeader; +import edu.unc.genomics.Assembly; +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.Interval; +import edu.unc.genomics.io.IntervalFile; + +public class RollingReadLength extends CommandLineTool { + + private static final Logger log = Logger.getLogger(RollingReadLength.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (reads)", required = true) + public IntervalFile<? extends Interval> intervalFile; + @Parameter(names = {"-a", "--assembly"}, description = "Genome assembly", required = true) + public Assembly assembly; + @Parameter(names = {"-o", "--output"}, description = "Output file (Wig)", required = true) + public Path outputFile; + + @Override + public void run() throws IOException { + log.debug("Initializing output file"); + int mapped = 0; + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + // Write the Wiggle track header to the output file + TrackHeader header = new TrackHeader("wiggle_0"); + header.setName("Converted " + intervalFile.getPath().getFileName()); + header.setDescription("Converted " + intervalFile.getPath().getFileName()); + writer.write(header.toString()); + writer.newLine(); + + // Process each chromosome in the assembly + for (String chr : assembly) { + log.debug("Processing chromosome " + chr); + // Write the contig header to the output file + writer.write("fixedStep chrom="+chr+" start=1 step=1 span=1"); + writer.newLine(); + + int start = 1; + while (start < assembly.getChrLength(chr)) { + int stop = start + DEFAULT_CHUNK_SIZE - 1; + int length = stop - start + 1; + int[] sum = new int[length]; + int[] count = new int[length]; + + Iterator<? extends Interval> it = intervalFile.query(chr, start, stop); + while (it.hasNext()) { + Interval entry = it.next(); + for (int i = entry.getStart(); i <= entry.getStop(); i++) { + sum[i-start] += entry.length(); + count[i-start]++; + } + mapped++; + } + + // Write the average at each base pair to the output file + for (int i = 0; i < sum.length; i++) { + if (count[i] == 0) { + writer.write(String.valueOf(Float.NaN)); + } else { + writer.write(String.valueOf(sum[i]/count[i])); + } + writer.newLine(); + } + + // Process the next chunk + start = stop + 1; + } + } + } + + log.info("Mapped "+mapped+" reads"); + } + + public static void main(String[] args) { + new RollingReadLength().instanceMain(args); + } +} \ No newline at end of file
Binary file java-genomics-toolkit/src/edu/unc/genomics/nucleosomes/._FindBoundaryNucleosomes.java has changed
Binary file java-genomics-toolkit/src/edu/unc/genomics/nucleosomes/._NucleosomeCall.java has changed
Binary file java-genomics-toolkit/src/edu/unc/genomics/nucleosomes/._NucleosomeCallsFile.java has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/nucleosomes/FindBoundaryNucleosomes.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,98 @@ +package edu.unc.genomics.nucleosomes; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.Interval; +import edu.unc.genomics.ReadablePathValidator; +import edu.unc.genomics.io.IntervalFile; + +public class FindBoundaryNucleosomes extends CommandLineTool { + + private static final Logger log = Logger.getLogger(FindBoundaryNucleosomes.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (nucleosome calls)", required = true, validateWith = ReadablePathValidator.class) + public Path inputFile; + @Parameter(names = {"-l", "--loci"}, description = "Boundary loci (Bed format)", required = true) + public IntervalFile<? extends Interval> lociFile; + @Parameter(names = {"-o", "--output"}, description = "Output file", required = true) + public Path outputFile; + + private Map<String,List<NucleosomeCall>> nucs = new HashMap<>(); + + private List<NucleosomeCall> getIntervalNucleosomes(Interval i) { + List<NucleosomeCall> intervalNucs = new ArrayList<>(); + for (NucleosomeCall call : nucs.get(i.getChr())) { + if (call.getDyad() >= i.low() && call.getDyad() <= i.high()) { + intervalNucs.add(call); + } + } + + return intervalNucs; + } + + @Override + public void run() throws IOException { + log.debug("Initializing input file"); + NucleosomeCallsFile nucsFile = new NucleosomeCallsFile(inputFile); + log.debug("Loading all nucleosomes"); + for (NucleosomeCall nuc : nucsFile) { + if (nuc == null) continue; + if (!nucs.containsKey(nuc.getChr())) { + nucs.put(nuc.getChr(), new ArrayList<NucleosomeCall>()); + } + nucs.get(nuc.getChr()).add(nuc); + } + nucsFile.close(); + + log.debug("Initializing output file"); + int skipped = 0; + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + log.debug("Finding boundary nucleosomes for each interval"); + NucleosomeCall.DyadComparator comparator = new NucleosomeCall.DyadComparator(); + for (Interval interval : lociFile) { + writer.write(interval.toBed()); + + // Get all of the nucleosomes within this interval + List<NucleosomeCall> intervalNucs = getIntervalNucleosomes(interval); + + if (intervalNucs.size() > 0) { + // Sort the list by nucleosome position + Collections.sort(intervalNucs, comparator); + if (interval.isCrick()) { + Collections.reverse(intervalNucs); + } + + int fivePrime = intervalNucs.get(0).getDyad(); + int threePrime = intervalNucs.get(intervalNucs.size()-1).getDyad(); + writer.write("\t"+fivePrime+"\t"+threePrime); + } else { + skipped++; + writer.write("\tNA\tNA"); + } + + writer.newLine(); + } + } + + lociFile.close(); + log.info("Skipped "+skipped+" intervals with 0 nucleosomes"); + } + + public static void main(String[] args) { + new FindBoundaryNucleosomes().instanceMain(args); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/nucleosomes/GreedyCaller.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,120 @@ +package edu.unc.genomics.nucleosomes; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Iterator; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.CommandLineToolException; +import edu.unc.genomics.ReadablePathValidator; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; +import edu.unc.utils.SortUtils; + +public class GreedyCaller extends CommandLineTool { + + private static final Logger log = Logger.getLogger(GreedyCaller.class); + + private static final int CHUNK_SIZE = 500_000; + + @Parameter(names = {"-d", "--dyads"}, description = "Dyad counts file", required = true, validateWith = ReadablePathValidator.class) + public WigFile dyadsFile; + @Parameter(names = {"-s", "--smoothed"}, description = "Smoothed dyad counts file", required = true, validateWith = ReadablePathValidator.class) + public WigFile smoothedDyadsFile; + @Parameter(names = {"-n", "--size"}, description = "Nucleosome size (bp)") + public int nucleosomeSize = 147; + @Parameter(names = {"-o", "--output"}, description = "Output file", required = true) + public Path outputFile; + + public void run() throws IOException { + int halfNuc = nucleosomeSize / 2; + + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + for (String chr : smoothedDyadsFile.chromosomes()) { + log.debug("Processing chromosome "+chr); + int chunkStart = smoothedDyadsFile.getChrStart(chr); + int chrStop = smoothedDyadsFile.getChrStop(chr); + while (chunkStart < chrStop) { + int chunkStop = chunkStart + CHUNK_SIZE; + int paddedStart = chunkStart - nucleosomeSize; + int paddedStop = chunkStop + nucleosomeSize; + log.debug("Processing chunk "+chunkStart+"-"+chunkStop); + + log.debug("Loading data and sorting"); + Iterator<WigItem> dyadsIter; + Iterator<WigItem> smoothedIter; + try { + dyadsIter = dyadsFile.query(chr, paddedStart, paddedStop); + smoothedIter = smoothedDyadsFile.query(chr, paddedStart, paddedStop); + } catch (IOException | WigFileException e) { + e.printStackTrace(); + throw new CommandLineToolException("Error loading data from Wig file"); + } + + float[] dyads = WigFile.flattenData(dyadsIter, paddedStart, paddedStop); + float[] smoothed = WigFile.flattenData(smoothedIter, paddedStart, paddedStop); + int[] sortedIndices = SortUtils.indexSort(smoothed); + + // Proceed through the data in descending order + log.debug("Calling nucleosomes"); + for (int j = sortedIndices.length; j >= 0; j++) { + int i = sortedIndices[j]; + int dyad = paddedStart + i; + + if (smoothed[i] > 0) { + int nucStart = Math.max(1, dyad-halfNuc); + int nucStop = Math.min(dyad+halfNuc, chrStop); + NucleosomeCall call = new NucleosomeCall(chr, nucStart, nucStop); + call.setDyad(dyad); + + double occupancy = 0; + double weightedSum = 0; + double smoothedSum = 0; + double sumOfSquares = 0; + for (int bp = nucStart; bp <= nucStop; bp++) { + occupancy += dyads[bp-paddedStart]; + weightedSum += bp * dyads[bp-paddedStart]; + smoothedSum += smoothed[bp-paddedStart]; + sumOfSquares += bp * bp * dyads[bp-paddedStart]; + } + call.setOccupancy(occupancy); + + if (occupancy > 0) { + call.setDyadMean(Math.round(weightedSum/occupancy)); + call.setConditionalPosition(smoothed[i] / smoothedSum); + double variance = (sumOfSquares - weightedSum*call.getDyadMean()) / occupancy; + call.setDyadStdev(Math.sqrt(variance)); + + // Only write nucleosomes within the current chunk to disk + if (chunkStart <= dyad && dyad <= chunkStop) { + writer.write(call.toString()); + writer.newLine(); + } + + // Don't allow nucleosome calls overlapping this nucleosome + int low = Math.max(i-nucleosomeSize, 0); + int high = Math.min(i-nucleosomeSize, paddedStop-1); + for (int k = low; k <= high; k++) { + smoothed[k] = 0; + } + } + } + } + + chunkStart = chunkStop + 1; + } + } + } + } + + public static void main(String[] args) { + new GreedyCaller().instanceMain(args); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/nucleosomes/MapDyads.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,88 @@ +package edu.unc.genomics.nucleosomes; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Iterator; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.ucsc.genome.TrackHeader; +import edu.unc.genomics.Assembly; +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.Interval; +import edu.unc.genomics.PositiveIntegerValidator; +import edu.unc.genomics.io.IntervalFile; + +public class MapDyads extends CommandLineTool { + + private static final Logger log = Logger.getLogger(MapDyads.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (reads)", required = true) + public IntervalFile<? extends Interval> inputFile; + @Parameter(names = {"-s", "--size"}, description = "Mononucleosome length (default: read length)", validateWith = PositiveIntegerValidator.class) + public Integer nucleosomeSize; + @Parameter(names = {"-a", "--assembly"}, description = "Genome assembly", required = true) + public Assembly assembly; + @Parameter(names = {"-o", "--output"}, description = "Output file (Wig)", required = true) + public Path outputFile; + + @Override + public void run() throws IOException { + log.debug("Initializing output file"); + int mapped = 0; + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + // Write the Wiggle track header to the output file + TrackHeader header = new TrackHeader("wiggle_0"); + header.setName("Converted " + inputFile.getPath().getFileName()); + header.setDescription("Converted " + inputFile.getPath().getFileName()); + writer.write(header.toString()); + writer.newLine(); + + // Process each chromosome in the assembly + for (String chr : assembly) { + log.debug("Processing chromosome " + chr); + // Write the contig header to the output file + writer.write("fixedStep chrom="+chr+" start=1 step=1 span=1"); + writer.newLine(); + + int start = 1; + while (start < assembly.getChrLength(chr)) { + int stop = start + DEFAULT_CHUNK_SIZE - 1; + int length = stop - start + 1; + int[] count = new int[length]; + + Iterator<? extends Interval> it = inputFile.query(chr, start, stop); + while (it.hasNext()) { + Interval entry = it.next(); + if (nucleosomeSize == null) { + count[entry.center()-start]++; + } else { + count[entry.getStart()+nucleosomeSize-start]++; + } + mapped++; + } + + // Write the average at each base pair to the output file + for (int i = 0; i < count.length; i++) { + writer.write(count[i]); + writer.newLine(); + } + + // Process the next chunk + start = stop + 1; + } + } + } + + log.info("Mapped "+mapped+" reads"); + } + + public static void main(String[] args) { + new MapDyads().instanceMain(args); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/nucleosomes/NRLCalculator.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,93 @@ +package edu.unc.genomics.nucleosomes; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.Interval; +import edu.unc.genomics.ReadablePathValidator; +import edu.unc.genomics.io.IntervalFile; + +public class NRLCalculator extends CommandLineTool { + + private static final Logger log = Logger.getLogger(NRLCalculator.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (nucleosome calls)", required = true, validateWith = ReadablePathValidator.class) + public Path inputFile; + @Parameter(names = {"-l", "--loci"}, description = "Genomic loci (Bed format)", required = true) + public IntervalFile<? extends Interval> lociFile; + @Parameter(names = {"-o", "--output"}, description = "Output file (NRL for each gene)", required = true) + public Path outputFile; + + private Map<String,List<NucleosomeCall>> nucs = new HashMap<>(); + + private List<NucleosomeCall> getIntervalNucleosomes(Interval i) { + List<NucleosomeCall> intervalNucs = new ArrayList<>(); + for (NucleosomeCall call : nucs.get(i.getChr())) { + if (call.getDyad() >= i.low() && call.getDyad() <= i.high()) { + intervalNucs.add(call); + } + } + + return intervalNucs; + } + + @Override + public void run() throws IOException { + log.debug("Initializing input file"); + NucleosomeCallsFile nucsFile = new NucleosomeCallsFile(inputFile); + log.debug("Loading all nucleosomes"); + for (NucleosomeCall nuc : nucsFile) { + if (nuc == null) continue; + if (!nucs.containsKey(nuc.getChr())) { + nucs.put(nuc.getChr(), new ArrayList<NucleosomeCall>()); + } + nucs.get(nuc.getChr()).add(nuc); + } + nucsFile.close(); + + log.debug("Initializing output file"); + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + log.debug("Calculating nucleosome spacing for each interval"); + NucleosomeCall.DyadComparator comparator = new NucleosomeCall.DyadComparator(); + for (Interval interval : lociFile) { + writer.write(interval.toBed()); + + // Get all of the nucleosomes within this interval + List<NucleosomeCall> intervalNucs = getIntervalNucleosomes(interval); + + if (intervalNucs.size() > 1) { + // Sort the list by nucleosome position + Collections.sort(intervalNucs, comparator); + if (interval.isCrick()) { + Collections.reverse(intervalNucs); + } + + for (int i = 1; i < Math.min(intervalNucs.size(), 10); i++) { + writer.write("\t" + Math.abs(intervalNucs.get(i).getDyad()-intervalNucs.get(i-1).getDyad())); + } + } + + writer.newLine(); + } + } + + lociFile.close(); + } + + public static void main(String[] args) throws IOException { + new NRLCalculator().instanceMain(args); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/nucleosomes/NucleosomeCall.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,174 @@ +package edu.unc.genomics.nucleosomes; + +import java.util.Comparator; + +import edu.unc.genomics.ValuedInterval; +import edu.unc.genomics.io.IntervalFileFormatException; + +/** + * @author timpalpant + * + */ +public class NucleosomeCall extends ValuedInterval implements Comparable<NucleosomeCall> { + + private static final long serialVersionUID = 6522702303121259979L; + + private int dyad; + private double dyadStdev; + private double dyadMean; + private double conditionalPosition; + private int length; + private double lengthStdev; + + /** + * @param chr + * @param start + * @param stop + */ + public NucleosomeCall(String chr, int start, int stop) { + super(chr, start, stop); + } + + public static NucleosomeCall parse(String line) { + if (line.startsWith("#")) return null; + + String[] entry = line.split("\t"); + if (entry.length < 10) { + throw new IntervalFileFormatException("Invalid nucleosome call has < 10 columns"); + } + + String chr = entry[0]; + int start = Integer.parseInt(entry[1]); + int stop = Integer.parseInt(entry[2]); + + NucleosomeCall call = new NucleosomeCall(chr, start, stop); + call.setLength(Integer.parseInt(entry[3])); + call.setLengthStdev(Double.parseDouble(entry[4])); + call.setDyad(Integer.parseInt(entry[5])); + call.setDyadStdev(Double.parseDouble(entry[6])); + call.setConditionalPosition(Double.parseDouble(entry[7])); + call.setDyadMean(Double.parseDouble(entry[8])); + call.setValue(Double.parseDouble(entry[9])); + + return call; + } + + @Override + public String toString() { + return chr+"\t"+start+"\t"+stop+"\t"+length()+"\t"+lengthStdev+"\t"+dyad+"\t"+dyadStdev+"\t"+conditionalPosition+"\t"+dyadMean+"\t"+occupancy(); + } + + /** + * @return the dyad + */ + public int getDyad() { + return dyad; + } + + /** + * @param dyad the dyad to set + */ + public void setDyad(int dyad) { + this.dyad = dyad; + } + + /** + * @return the dyadStdev + */ + public double getDyadStdev() { + return dyadStdev; + } + + /** + * @param dyadStdev the dyadStdev to set + */ + public void setDyadStdev(double dyadStdev) { + this.dyadStdev = dyadStdev; + } + + /** + * @return the dyadMean + */ + public double getDyadMean() { + return dyadMean; + } + + /** + * @param dyadMean the dyadMean to set + */ + public void setDyadMean(double dyadMean) { + this.dyadMean = dyadMean; + } + + /** + * @return the conditionalPosition + */ + public double getConditionalPosition() { + return conditionalPosition; + } + + /** + * @param conditionalPosition the conditionalPosition to set + */ + public void setConditionalPosition(double conditionalPosition) { + this.conditionalPosition = conditionalPosition; + } + + /** + * @return the length + */ + public int getLength() { + return length; + } + + /** + * @param length the length to set + */ + public void setLength(int length) { + this.length = length; + } + + /** + * @return the lengthStdev + */ + public double getLengthStdev() { + return lengthStdev; + } + + /** + * @param lengthStdev the lengthStdev to set + */ + public void setLengthStdev(double lengthStdev) { + this.lengthStdev = lengthStdev; + } + + public double occupancy() { + return value; + } + + public void setOccupancy(double value) { + this.value = value; + } + + @Override + public int compareTo(NucleosomeCall o) { + DyadComparator comparator = new DyadComparator(); + return comparator.compare(this, o); + } + + public static class DyadComparator implements Comparator<NucleosomeCall> { + + @Override + public int compare(NucleosomeCall o1, NucleosomeCall o2) { + if (o1.getDyad() == o2.getDyad()) { + return 0; + } else if (o1.getDyad() < o2.getDyad()) { + return -1; + } else { + return 1; + } + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/nucleosomes/NucleosomeCallsFile.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,31 @@ +/** + * + */ +package edu.unc.genomics.nucleosomes; + +import java.io.IOException; +import java.nio.file.Path; + +import edu.unc.genomics.IntervalFactory; +import edu.unc.genomics.io.TextIntervalFile; + +/** + * @author timpalpant + * + */ +public class NucleosomeCallsFile extends TextIntervalFile<NucleosomeCall> { + + public NucleosomeCallsFile(Path p) throws IOException { + super(p, new NucleosomeCallFactory()); + } + + public static class NucleosomeCallFactory implements IntervalFactory<NucleosomeCall> { + + @Override + public NucleosomeCall parse(String line) { + return NucleosomeCall.parse(line); + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/nucleosomes/Phasogram.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,71 @@ +package edu.unc.genomics.nucleosomes; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.CommandLineToolException; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class Phasogram extends CommandLineTool { + + private static final Logger log = Logger.getLogger(Phasogram.class); + + @Parameter(names = {"-i", "--input"}, description = "Input wig file (read counts)", required = true) + public WigFile inputFile; + @Parameter(names = {"-m", "--max"}, description = "Maximum phase shift", required = true) + public int maxPhase; + @Parameter(names = {"-o", "--output"}, description = "Output file (histogram)", required = true) + public Path outputFile; + + public void run() throws IOException { + long[] phaseCounts = new long[maxPhase+1]; + + // Process each chromosome in the assembly + for (String chr : inputFile.chromosomes()) { + log.debug("Processing chromosome " + chr); + + int start = inputFile.getChrStart(chr); + while (start < inputFile.getChrStop(chr)) { + int stop = start + DEFAULT_CHUNK_SIZE - 1; + + try { + float[] data = WigFile.flattenData(inputFile.query(chr, start, stop), start, stop); + for (int i = 0; i < data.length-maxPhase; i++) { + for (int j = 0; j <= maxPhase; j++) { + phaseCounts[j] += data[i]; + } + } + + } catch (WigFileException e) { + log.fatal("Error querying data from Wig file!"); + e.printStackTrace(); + throw new CommandLineToolException("Error querying data from Wig file!"); + } + + // Process the next chunk + start = stop - maxPhase + 1; + } + } + + log.debug("Writing output to disk"); + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + for (int i = 0; i < phaseCounts.length; i++) { + writer.write(i+"\t"+phaseCounts[i]); + writer.newLine(); + } + } + } + + public static void main(String[] args) { + new Phasogram().instanceMain(args); + } +} \ No newline at end of file
Binary file java-genomics-toolkit/src/edu/unc/genomics/visualization/._IntervalAverager.java has changed
Binary file java-genomics-toolkit/src/edu/unc/genomics/visualization/._MatrixAligner.java has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/visualization/IntervalAverager.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,118 @@ +package edu.unc.genomics.visualization; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.BedEntry; +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.ReadablePathValidator; +import edu.unc.genomics.io.BedFile; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class IntervalAverager extends CommandLineTool { + + private static final Logger log = Logger.getLogger(IntervalAverager.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (Wig)", required = true) + public WigFile inputFile; + @Parameter(names = {"-l", "--loci"}, description = "Loci file (Bed)", required = true, validateWith = ReadablePathValidator.class) + public Path lociFile; + @Parameter(names = {"-o", "--output"}, description = "Output file (matrix2png format)", required = true) + public Path outputFile; + + private List<BedEntry> loci; + + @Override + public void run() throws IOException { + log.debug("Loading alignment intervals"); + try (BedFile bed = new BedFile(lociFile)) { + loci = bed.loadAll(); + } + + // Compute the matrix dimensions + int leftMax = Integer.MIN_VALUE; + int rightMax = Integer.MIN_VALUE; + for (BedEntry entry : loci) { + int left = Math.abs(entry.getValue().intValue()-entry.getStart()); + int right = Math.abs(entry.getValue().intValue()-entry.getStop()); + if (left > leftMax) { + leftMax = left; + } + if (right > rightMax) { + rightMax = right; + } + } + + int m = loci.size(); + int n = leftMax + rightMax + 1; + int alignmentPoint = leftMax; + log.info("Intervals aligned into: " + m+"x"+n + " matrix"); + log.info("Alignment point: " + alignmentPoint); + + float[] sum = new float[n]; + int[] counts = new int[n]; + int count = 0, skipped = 0; + log.debug("Iterating over all intervals"); + for (BedEntry entry : loci) { + Iterator<WigItem> result = null; + try { + result = inputFile.query(entry); + } catch (WigFileException e) { + skipped++; + continue; + } + + float[] data = WigFile.flattenData(result, entry.getStart(), entry.getStop()); + // Reverse if on the Crick strand + if (entry.isCrick()) { + ArrayUtils.reverse(data); + } + + // Locus alignment point (entry value) should be positioned over the global alignment point + int n1 = alignmentPoint - Math.abs(entry.getValue().intValue()-entry.getStart()); + int n2 = alignmentPoint + Math.abs(entry.getValue().intValue()-entry.getStop()); + for (int bp = n1; bp <= n2; bp++) { + sum[bp] += data[bp-n1]; + counts[bp]++; + } + } + + inputFile.close(); + log.info(count + " intervals processed"); + log.info(skipped + " intervals skipped"); + + log.debug("Computing average"); + float[] avg = new float[n]; + for (int i = 0; i < n; i++) { + if (counts[i] == 0) { + avg[i] = Float.NaN; + } else { + avg[i] = sum[i] / counts[i]; + } + } + + log.debug("Writing average to output"); + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + for (int i = 0; i < n; i++) { + writer.write(i-alignmentPoint + "\t" + avg[i]); + writer.newLine(); + } + } + } + + public static void main(String[] args) { + new IntervalAverager().instanceMain(args); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/visualization/KMeans.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,120 @@ +package edu.unc.genomics.visualization; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.math.stat.clustering.Cluster; +import org.apache.commons.math.stat.clustering.KMeansPlusPlusClusterer; +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.ReadablePathValidator; +import edu.unc.genomics.io.IntervalFileSnifferException; +import edu.unc.genomics.io.WigFileException; + +public class KMeans extends CommandLineTool { + + private static final Logger log = Logger.getLogger(KMeans.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (matrix2png format)", required = true, validateWith = ReadablePathValidator.class) + public Path inputFile; + @Parameter(names = {"-k", "--clusters"}, description = "Number of clusters") + public int k = 10; + @Parameter(names = {"-1", "--min"}, description = "Minimum column to use for clustering") + public int minCol = 1; + @Parameter(names = {"-2", "--max"}, description = "Maximum column to use for clustering") + public Integer maxCol; + @Parameter(names = {"-o", "--output"}, description = "Output file (clustered matrix2png format)", required = true) + public Path outputFile; + + private Map<String, String> rows = new HashMap<String, String>(); + private List<KMeansRow> data = new ArrayList<KMeansRow>(); + + @Override + public void run() throws IOException { + log.debug("Loading data from the input matrix"); + String headerLine = ""; + try (BufferedReader reader = Files.newBufferedReader(inputFile, Charset.defaultCharset())) { + // Header line + int lineNum = 1; + headerLine = reader.readLine(); + int numColsInMatrix = StringUtils.countMatches(headerLine, "\t"); + + // Validate the range info + if (maxCol != null) { + if (maxCol > numColsInMatrix) { + throw new RuntimeException("Invalid range of data specified for clustering ("+maxCol+" > "+numColsInMatrix+")"); + } + } else { + maxCol = numColsInMatrix; + } + + // Loop over the rows and load the data + String line; + while ((line = reader.readLine()) != null) { + lineNum++; + if (StringUtils.countMatches(line, "\t") != numColsInMatrix) { + throw new RuntimeException("Irregular input matrix does not have same number of columns on line " + lineNum); + } + + int delim = line.indexOf('\t'); + String id = line.substring(0, delim); + String[] row = line.substring(delim+1).split("\t"); + String[] subset = Arrays.copyOfRange(row, minCol, maxCol); + float[] rowData = new float[subset.length]; + for (int i = 0; i < subset.length; i++) { + try { + rowData[i] = Float.parseFloat(subset[i]); + } catch (NumberFormatException e) { + rowData[i] = Float.NaN; + } + } + data.add(new KMeansRow(id, rowData)); + rows.put(id, line); + } + } + + // Perform the clustering + log.debug("Clustering the data"); + Random rng = new Random(); + KMeansPlusPlusClusterer<KMeansRow> clusterer = new KMeansPlusPlusClusterer<KMeansRow>(rng); + List<Cluster<KMeansRow>> clusters = clusterer.cluster(data, k, 50); + + // Write to output + log.debug("Writing clustered data to output file"); + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + writer.write(headerLine); + writer.newLine(); + int n = 1; + int count = 1; + for (Cluster<KMeansRow> cluster : clusters) { + int numRowsInCluster = cluster.getPoints().size(); + int stop = count + numRowsInCluster - 1; + log.info("Cluster "+(n++)+": rows "+count+"-"+stop); + count = stop+1; + for (KMeansRow row : cluster.getPoints()) { + writer.write(rows.get(row.getId())); + writer.newLine(); + } + } + } + } + + public static void main(String[] args) throws IOException, WigFileException, IntervalFileSnifferException { + new KMeans().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/visualization/KMeansRow.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,110 @@ +package edu.unc.genomics.visualization; + +import java.io.Serializable; +import java.util.Collection; + +import org.apache.commons.math.stat.clustering.Clusterable; + +/** + * @author timpalpant + * Holds a row of data for the KMeans program + */ +class KMeansRow implements Clusterable<KMeansRow>, Serializable { + + private static final long serialVersionUID = -323598431692368500L; + + private final String id; + /** Point coordinates. */ + private final float[] point; + + /** + * Build an instance wrapping an float array. + * <p>The wrapped array is referenced, it is <em>not</em> copied.</p> + * @param point the n-dimensional point in integer space + */ + public KMeansRow(final String id, final float[] point) { + this.point = point; + this.id = id; + } + + /** + * Get the n-dimensional point in float space. + * @return a reference (not a copy!) to the wrapped array + */ + public float[] getPoint() { + return point; + } + + /** {@inheritDoc} */ + public double distanceFrom(final KMeansRow p) { + double sumSquares = 0; + float[] otherPoint = p.getPoint(); + for (int i = 0; i < point.length; i++) { + sumSquares += Math.pow(point[i]-otherPoint[i], 2); + } + return Math.sqrt(sumSquares); + } + + /** {@inheritDoc} */ + public KMeansRow centroidOf(final Collection<KMeansRow> points) { + float[] centroid = new float[getPoint().length]; + for (KMeansRow p : points) { + for (int i = 0; i < centroid.length; i++) { + centroid[i] += p.getPoint()[i]; + } + } + for (int i = 0; i < centroid.length; i++) { + centroid[i] /= points.size(); + } + return new KMeansRow(id, centroid); + } + + /** {@inheritDoc} */ + @Override + public boolean equals(final Object other) { + if (!(other instanceof KMeansRow)) { + return false; + } + final float[] otherPoint = ((KMeansRow) other).getPoint(); + if (point.length != otherPoint.length) { + return false; + } + for (int i = 0; i < point.length; i++) { + if (point[i] != otherPoint[i]) { + return false; + } + } + return true; + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + int hashCode = 0; + for (Float i : point) { + hashCode += i.hashCode() * 13 + 7; + } + return hashCode; + } + + /** + * {@inheritDoc} + * @since 2.1 + */ + @Override + public String toString() { + final StringBuilder buff = new StringBuilder(id); + for (float value : getPoint()) { + buff.append("\t").append(value); + } + return buff.toString(); + } + + /** + * @return the id + */ + public String getId() { + return id; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/visualization/MatrixAligner.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,145 @@ +package edu.unc.genomics.visualization; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.BedEntry; +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.ReadablePathValidator; +import edu.unc.genomics.io.BedFile; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class MatrixAligner extends CommandLineTool { + + private static final Logger log = Logger.getLogger(MatrixAligner.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (Wig)", required = true) + public WigFile inputFile; + @Parameter(names = {"-l", "--loci"}, description = "Loci file (Bed)", required = true, validateWith = ReadablePathValidator.class) + public Path lociFile; + @Parameter(names = {"-m", "--max"}, description = "Truncate width (base pairs)") + public Integer maxWidth; + @Parameter(names = {"-o", "--output"}, description = "Output file (matrix2png format)", required = true) + public Path outputFile; + + private List<BedEntry> loci; + + @Override + public void run() throws IOException { + log.debug("Loading alignment intervals"); + try (BedFile bed = new BedFile(lociFile)) { + loci = bed.loadAll(); + } + + // Compute the matrix dimensions + int leftMax = Integer.MIN_VALUE; + int rightMax = Integer.MIN_VALUE; + for (BedEntry entry : loci) { + int left = Math.abs(entry.getValue().intValue()-entry.getStart()); + int right = Math.abs(entry.getValue().intValue()-entry.getStop()); + if (left > leftMax) { + leftMax = left; + } + if (right > rightMax) { + rightMax = right; + } + } + + int m = loci.size(); + int n = leftMax + rightMax + 1; + int alignmentPoint = leftMax; + log.info("Intervals aligned into: " + m+"x"+n + " matrix"); + log.info("Alignment point: " + alignmentPoint); + + int leftBound = 0; + int rightBound = n-1; + if (maxWidth != null && maxWidth < n) { + log.info("Truncated to: " + m+"x"+maxWidth); + int leftAlignDistance = alignmentPoint; + int rightAlignDistance = n - alignmentPoint - 1; + int halfMax = maxWidth / 2; + + if (halfMax < leftAlignDistance && halfMax < rightAlignDistance) { + leftBound = alignmentPoint - halfMax; + rightBound = alignmentPoint + halfMax; + } else { + if (leftAlignDistance <= rightAlignDistance) { + rightBound = maxWidth; + } else { + leftBound = n - maxWidth; + } + } + } + + log.debug("Initializing output file"); + int count = 0, skipped = 0; + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + writer.write("ID"); + for (int i = leftBound-alignmentPoint; i <= rightBound-alignmentPoint; i++) { + writer.write("\t"+i); + } + writer.newLine(); + + log.debug("Iterating over all intervals"); + String[] row = new String[n]; + for (BedEntry entry : loci) { + Iterator<WigItem> result = null; + try { + result = inputFile.query(entry); + } catch (WigFileException e) { + skipped++; + continue; + } + + float[] data = WigFile.flattenData(result, entry.getStart(), entry.getStop()); + // Reverse if on the crick strand + if (entry.isCrick()) { + ArrayUtils.reverse(data); + } + + // Position the data in the matrix + // Locus alignment point (entry value) should be positioned over the matrix alignment point + int n1 = alignmentPoint - Math.abs(entry.getValue().intValue()-entry.getStart()); + int n2 = alignmentPoint + Math.abs(entry.getValue().intValue()-entry.getStop()); + assert data.length == n2-n1+1; + + Arrays.fill(row, "-"); + for (int i = 0; i < data.length; i++) { + if (!Float.isNaN(data[i])) { + row[n1+i] = String.valueOf(data[i]); + } + } + + // Write to output + String id = ((entry.getId() == null) ? entry.getId() : "Row "+(count++)); + writer.write(id); + for (int i = leftBound; i <= rightBound; i++) { + writer.write("\t"+row[i]); + } + writer.newLine(); + } + } + + inputFile.close(); + log.info(count + " intervals processed"); + log.info(skipped + " intervals skipped"); + } + + public static void main(String[] args) { + new MatrixAligner().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/visualization/StripMatrix.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,56 @@ +package edu.unc.genomics.visualization; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.ReadablePathValidator; + +public class StripMatrix extends CommandLineTool { + + private static final Logger log = Logger.getLogger(StripMatrix.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file (matrix2png format)", required = true, validateWith = ReadablePathValidator.class) + public Path inputFile; + @Parameter(names = {"-o", "--output"}, description = "Output file (tabular)", required = true) + public Path outputFile; + + public void run() throws IOException { + try (BufferedReader reader = Files.newBufferedReader(inputFile, Charset.defaultCharset())) { + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + String line = reader.readLine(); + // Always copy the first (header) line + writer.write(line); + writer.newLine(); + while ((line = reader.readLine()) != null) { + String[] row = line.split("\t"); + for (int i = 1; i < row.length; i++) { + String cell = row[i]; + if (cell.equalsIgnoreCase("-")) { + writer.write("NaN"); + } else { + writer.write(cell); + } + + if (i > 1) { + writer.write("\t"); + } + } + writer.newLine(); + } + } + } + } + + public static void main(String[] args) { + new StripMatrix().instanceMain(args); + } +} \ No newline at end of file
Binary file java-genomics-toolkit/src/edu/unc/genomics/wigmath/._MovingAverageSmooth.java has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/Add.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,76 @@ +package edu.unc.genomics.wigmath; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineToolException; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class Add extends WigMathTool { + + private static final Logger log = Logger.getLogger(Add.class); + + @Parameter(description = "Input files", required = true) + public List<String> inputFiles = new ArrayList<String>(); + + @Override + public void setup() { + if (inputFiles.size() < 2) { + throw new CommandLineToolException("No reason to add < 2 files."); + } + + log.debug("Initializing input files"); + for (String inputFile : inputFiles) { + try { + addInputFile(WigFile.autodetect(Paths.get(inputFile))); + } catch (IOException | WigFileException e) { + log.error("Error initializing input Wig file: " + inputFile); + e.printStackTrace(); + throw new CommandLineToolException(e.getMessage()); + } + } + log.debug("Initialized " + inputs.size() + " input files"); + } + + @Override + public float[] compute(String chr, int start, int stop) throws IOException, WigFileException { + log.debug("Computing sum for chunk "+chr+":"+start+"-"+stop); + + int length = stop - start + 1; + float[] sum = new float[length]; + + for (WigFile wig : inputs) { + Iterator<WigItem> data = wig.query(chr, start, stop); + while (data.hasNext()) { + WigItem item = data.next(); + for (int i = item.getStartBase(); i <= item.getEndBase(); i++) { + if (i-start >= 0 && i-start < sum.length) { + sum[i-start] += item.getWigValue(); + } + } + } + } + + return sum; + } + + + /** + * @param args + * @throws WigFileException + * @throws IOException + */ + public static void main(String[] args) throws IOException, WigFileException { + new Add().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/Average.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,84 @@ +package edu.unc.genomics.wigmath; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineToolException; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class Average extends WigMathTool { + + private static final Logger log = Logger.getLogger(Average.class); + + @Parameter(description = "Input files", required = true) + public List<String> inputFiles = new ArrayList<String>(); + + int numFiles; + + @Override + public void setup() { + if (inputFiles.size() < 2) { + throw new CommandLineToolException("No reason to add < 2 files."); + } + + log.debug("Initializing input files"); + for (String inputFile : inputFiles) { + try { + addInputFile(WigFile.autodetect(Paths.get(inputFile))); + } catch (IOException | WigFileException e) { + log.error("Error initializing input Wig file: " + inputFile); + e.printStackTrace(); + throw new CommandLineToolException(e.getMessage()); + } + } + log.debug("Initialized " + inputs.size() + " input files"); + + numFiles = inputs.size(); + } + + @Override + public float[] compute(String chr, int start, int stop) throws IOException, WigFileException { + log.debug("Computing average for chunk "+chr+":"+start+"-"+stop); + + int length = stop - start + 1; + float[] avg = new float[length]; + + for (WigFile wig : inputs) { + Iterator<WigItem> data = wig.query(chr, start, stop); + while (data.hasNext()) { + WigItem item = data.next(); + for (int i = item.getStartBase(); i <= item.getEndBase(); i++) { + if (i-start >= 0 && i-start < avg.length) { + avg[i-start] += item.getWigValue(); + } + } + } + } + + for (int i = 0; i < avg.length; i++) { + avg[i] = avg[i] / numFiles; + } + + return avg; + } + + + /** + * @param args + * @throws WigFileException + * @throws IOException + */ + public static void main(String[] args) throws IOException, WigFileException { + new Average().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/Divide.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,64 @@ +package edu.unc.genomics.wigmath; + +import java.io.IOException; +import java.util.Iterator; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class Divide extends WigMathTool { + + private static final Logger log = Logger.getLogger(Divide.class); + + @Parameter(names = {"-n", "--numerator"}, description = "Dividend / Numerator (file 1)", required = true) + public WigFile dividendFile; + @Parameter(names = {"-d", "--denominator"}, description = "Divisor / Denominator (file 2)", required = true) + public WigFile divisorFile; + + @Override + public void setup() { + inputs.add(dividendFile); + inputs.add(divisorFile); + log.debug("Initialized " + inputs.size() + " input files"); + } + + @Override + public float[] compute(String chr, int start, int stop) throws IOException, WigFileException { + log.debug("Computing difference for chunk "+chr+":"+start+"-"+stop); + + Iterator<WigItem> dividendData = dividendFile.query(chr, start, stop); + Iterator<WigItem> divisorData = divisorFile.query(chr, start, stop); + + float[] result = WigFile.flattenData(dividendData, start, stop); + while (divisorData.hasNext()) { + WigItem item = divisorData.next(); + for (int i = item.getStartBase(); i <= item.getEndBase(); i++) { + if (i-start >= 0 && i-start < result.length) { + if (item.getWigValue() != 0) { + result[i-start] /= item.getWigValue(); + } else { + result[i-start] = Float.NaN; + } + } + } + } + + return result; + } + + + /** + * @param args + * @throws WigFileException + * @throws IOException + */ + public static void main(String[] args) throws IOException, WigFileException { + new Divide().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/GaussianSmooth.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,74 @@ +package edu.unc.genomics.wigmath; + +import java.io.IOException; +import java.util.Iterator; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class GaussianSmooth extends WigMathTool { + + private static final Logger log = Logger.getLogger(GaussianSmooth.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file", required = true) + public WigFile inputFile; + @Parameter(names = {"-s", "--stdev"}, description = "Standard deviation of Gaussian (bp)") + public int stdev = 20; + + float[] filter; + + @Override + public void setup() { + inputs.add(inputFile); + + // Use a window size equal to +/- 3 SD's + filter = new float[6*stdev+1]; + float sum = 0; + for (int i = 0; i < filter.length; i++) { + float x = i - 3*stdev; + float value = (float) Math.exp(-(x*x) / (2*stdev*stdev)); + filter[i] = value; + sum += value; + } + for (int i = 0; i < filter.length; i++) { + filter[i] /= sum; + } + } + + @Override + public float[] compute(String chr, int start, int stop) throws IOException, WigFileException { + log.debug("Smoothing chunk "+chr+":"+start+"-"+stop); + + // Pad the query for smoothing + int paddedStart = Math.max(start-3*stdev, inputFile.getChrStart(chr)); + int paddedStop = Math.min(stop+3*stdev, inputFile.getChrStop(chr)); + Iterator<WigItem> result = inputFile.query(chr, paddedStart, paddedStop); + float[] data = WigFile.flattenData(result, start-3*stdev, stop+3*stdev); + + // Convolve the data with the filter + float[] smoothed = new float[stop-start+1]; + for (int i = 0; i < smoothed.length; i++) { + for (int j = 0; j < filter.length; j++) { + smoothed[i] += data[i+j] * filter[j]; + } + } + + return smoothed; + } + + + /** + * @param args + * @throws WigFileException + * @throws IOException + */ + public static void main(String[] args) throws IOException, WigFileException { + new GaussianSmooth().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/LogTransform.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,55 @@ +package edu.unc.genomics.wigmath; + +import java.io.IOException; +import java.util.Iterator; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class LogTransform extends WigMathTool { + + private static final Logger log = Logger.getLogger(LogTransform.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file", required = true) + public WigFile inputFile; + @Parameter(names = {"-b", "--base"}, description = "Logarithm base (default = 2)") + public double base = 2; + + private double baseChange; + + @Override + public void setup() { + baseChange = Math.log(base); + inputs.add(inputFile); + } + + @Override + public float[] compute(String chr, int start, int stop) throws IOException, WigFileException { + log.debug("Computing difference for chunk "+chr+":"+start+"-"+stop); + + Iterator<WigItem> data = inputFile.query(chr, start, stop); + float[] result = WigFile.flattenData(data, start, stop); + + for (int i = 0; i < result.length; i++) { + result[i] = (float) (Math.log(result[i]) / baseChange); + } + + return result; + } + + + /** + * @param args + * @throws WigFileException + * @throws IOException + */ + public static void main(String[] args) throws IOException, WigFileException { + new LogTransform().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/MovingAverageSmooth.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,67 @@ +package edu.unc.genomics.wigmath; + +import java.io.IOException; +import java.util.Iterator; + +import org.apache.commons.math.stat.descriptive.DescriptiveStatistics; +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.PositiveIntegerValidator; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class MovingAverageSmooth extends WigMathTool { + + private static final Logger log = Logger.getLogger(MovingAverageSmooth.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file", required = true) + public WigFile inputFile; + @Parameter(names = {"-w", "--width"}, description = "Width of kernel (bp)") + public int width = 10; + + WigFile input; + DescriptiveStatistics stats; + + @Override + public void setup() { + inputs.add(inputFile); + + log.debug("Initializing statistics"); + stats = new DescriptiveStatistics(); + stats.setWindowSize(width); + } + + @Override + public float[] compute(String chr, int start, int stop) throws IOException, WigFileException { + log.debug("Smoothing chunk "+chr+":"+start+"-"+stop); + // Pad the query so that we can provide values for the ends + int queryStart = Math.max(start-width/2, input.getChrStart(chr)); + int queryStop = Math.min(stop+width/2, input.getChrStop(chr)); + Iterator<WigItem> result = input.query(chr, queryStart, queryStop); + float[] data = WigFile.flattenData(result, queryStart, queryStop); + + float[] smoothed = new float[stop-start+1]; + for (int bp = start; bp <= stop; bp++) { + stats.addValue(data[bp-queryStart]); + if (bp-start-width/2 >= 0) { + smoothed[bp-start-width/2] = (float) stats.getMean(); + } + } + + return smoothed; + } + + + /** + * @param args + * @throws WigFileException + * @throws IOException + */ + public static void main(String[] args) throws IOException, WigFileException { + new MovingAverageSmooth().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/Multiply.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,73 @@ +package edu.unc.genomics.wigmath; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class Multiply extends WigMathTool { + + private static final Logger log = Logger.getLogger(Multiply.class); + + @Parameter(description = "Input files", required = true) + public List<String> inputFiles = new ArrayList<String>(); + + @Override + public void setup() { + log.debug("Initializing input files"); + for (String inputFile : inputFiles) { + try { + addInputFile(WigFile.autodetect(Paths.get(inputFile))); + } catch (IOException | WigFileException e) { + log.error("Error initializing input Wig file: " + inputFile); + e.printStackTrace(); + System.exit(-1); + } + } + log.debug("Initialized " + inputs.size() + " input files"); + } + + @Override + public float[] compute(String chr, int start, int stop) throws IOException, WigFileException { + log.debug("Computing sum for chunk "+chr+":"+start+"-"+stop); + + int length = stop - start + 1; + float[] product = new float[length]; + Arrays.fill(product, 1); + + for (WigFile wig : inputs) { + Iterator<WigItem> data = wig.query(chr, start, stop); + while (data.hasNext()) { + WigItem item = data.next(); + for (int i = item.getStartBase(); i <= item.getEndBase(); i++) { + if (i-start >= 0 && i-start < product.length) { + product[i-start] *= item.getWigValue(); + } + } + } + } + + return product; + } + + + /** + * @param args + * @throws WigFileException + * @throws IOException + */ + public static void main(String[] args) throws IOException, WigFileException { + new Multiply().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/Scale.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,57 @@ +package edu.unc.genomics.wigmath; + +import java.io.IOException; +import java.util.Iterator; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class Scale extends WigMathTool { + + private static final Logger log = Logger.getLogger(Scale.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file", required = true) + public WigFile inputFile; + @Parameter(names = {"-m", "--multiplier"}, description = "Multiplier (scale factor, default = 1/mean)") + public Double multiplier; + + + @Override + public void setup() { + inputs.add(inputFile); + + if (multiplier == null) { + multiplier = inputFile.numBases() / inputFile.total(); + } + } + + @Override + public float[] compute(String chr, int start, int stop) throws IOException, WigFileException { + log.debug("Computing difference for chunk "+chr+":"+start+"-"+stop); + + Iterator<WigItem> data = inputFile.query(chr, start, stop); + float[] result = WigFile.flattenData(data, start, stop); + + for (int i = 0; i < result.length; i++) { + result[i] = (float) (multiplier * result[i]); + } + + return result; + } + + + /** + * @param args + * @throws WigFileException + * @throws IOException + */ + public static void main(String[] args) throws IOException, WigFileException { + new Scale().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/Subtract.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,61 @@ +package edu.unc.genomics.wigmath; + +import java.io.IOException; +import java.util.Iterator; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class Subtract extends WigMathTool { + + private static final Logger log = Logger.getLogger(Subtract.class); + + @Parameter(names = {"-m", "--minuend"}, description = "Minuend (top - file 1)", required = true) + public WigFile minuendFile; + @Parameter(names = {"-s", "--subtrahend"}, description = "Subtrahend (bottom - file 2)", required = true) + public WigFile subtrahendFile; + + @Override + public void setup() { + log.debug("Initializing input files"); + inputs.add(minuendFile); + inputs.add(subtrahendFile); + log.debug("Initialized " + inputs.size() + " input files"); + } + + @Override + public float[] compute(String chr, int start, int stop) throws IOException, WigFileException { + log.debug("Computing difference for chunk "+chr+":"+start+"-"+stop); + + Iterator<WigItem> minuendData = minuendFile.query(chr, start, stop); + Iterator<WigItem> subtrahendData = subtrahendFile.query(chr, start, stop); + + float[] result = WigFile.flattenData(minuendData, start, stop); + while (subtrahendData.hasNext()) { + WigItem item = subtrahendData.next(); + for (int i = item.getStartBase(); i <= item.getEndBase(); i++) { + if (i-start >= 0 && i-start < result.length) { + result[i-start] -= item.getWigValue(); + } + } + } + + return result; + } + + + /** + * @param args + * @throws WigFileException + * @throws IOException + */ + public static void main(String[] args) throws IOException, WigFileException { + new Subtract().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/WigMathTool.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,170 @@ +package edu.unc.genomics.wigmath; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +/** + * Abstract class for writing programs to do computation on Wig files + * Concrete subclasses must implement the compute method + * + * @author timpalpant + * + */ +public abstract class WigMathTool extends CommandLineTool { + + private static final Logger log = Logger.getLogger(WigMathTool.class); + + public static final int DEFAULT_CHUNK_SIZE = 500_000; + + // TODO: Variable resolution output + + @Parameter(names = {"-o", "--output"}, description = "Output file", required = true) + public Path outputFile; + + protected List<WigFile> inputs = new ArrayList<WigFile>(); + + public void addInputFile(WigFile wig) { + inputs.add(wig); + } + + /** + * Setup the computation. Should add all input Wig files + * with addInputFile() during setup + */ + public abstract void setup(); + + /** + * Do the computation on a chunk and return the results + * Must return (stop-start+1) values + * + * @param chr + * @param start + * @param stop + * @return the results of the computation for this chunk + * @throws IOException + * @throws WigFileException + */ + public abstract float[] compute(String chr, int start, int stop) + throws IOException, WigFileException; + + @Override + public void run() throws IOException { + log.debug("Executing setup operations"); + setup(); + + log.debug("Processing files and writing result to disk"); + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + // Write the Wig header + writer.write("track type=wiggle_0"); + writer.newLine(); + + Set<String> chromosomes = getCommonChromosomes(inputs); + log.debug("Found " + chromosomes.size() + " chromosomes in common between all inputs"); + for (String chr : chromosomes) { + int start = getMaxChrStart(inputs, chr); + int stop = getMinChrStop(inputs, chr); + log.debug("Processing chromosome " + chr + " region " + start + "-" + stop); + + // Write the chromosome header to output + writer.write("fixedStep chrom="+chr+" start="+start+" step=1 span=1"); + writer.newLine(); + + // Process the chromosome in chunks + int bp = start; + while (bp < stop) { + int chunkStart = bp; + int chunkStop = Math.min(bp+DEFAULT_CHUNK_SIZE-1, stop); + int expectedLength = chunkStop - chunkStart + 1; + log.debug("Processing chunk "+chr+":"+chunkStart+"-"+chunkStop); + + float[] result = null; + try { + result = compute(chr, chunkStart, chunkStop); + } catch (WigFileException e) { + log.fatal("Wig file error while processing chunk " + chr + " region " + start + "-" + stop); + e.printStackTrace(); + throw new RuntimeException("Wig file error while processing chunk " + chr + " region " + start + "-" + stop); + } + + if (result.length != expectedLength) { + log.error("Expected result length="+expectedLength+", got="+result.length); + throw new RuntimeException("Result is not the expected length!"); + } + + for (int i = 0; i < result.length; i++) { + writer.write(Float.toString(result[i])); + writer.newLine(); + } + + bp = chunkStop + 1; + } + } + } + + for (WigFile wig : inputs) { + wig.close(); + } + } + + public int getMaxChrStart(List<WigFile> wigs, String chr) { + int max = -1; + for (WigFile wig : wigs) { + if (wig.getChrStart(chr) > max) { + max = wig.getChrStart(chr); + } + } + + return max; + } + + public int getMinChrStop(List<WigFile> wigs, String chr) { + if (wigs.size() == 0) { + return -1; + } + + int min = Integer.MAX_VALUE; + for (WigFile wig : wigs) { + if (wig.getChrStop(chr) < min) { + min = wig.getChrStop(chr); + } + } + + return min; + } + + public Set<String> getCommonChromosomes(List<WigFile> wigs) { + if (wigs.size() == 0) { + return new HashSet<String>(); + } + + Set<String> chromosomes = wigs.get(0).chromosomes(); + Iterator<String> it = chromosomes.iterator(); + while(it.hasNext()) { + String chr = it.next(); + for (WigFile wig : wigs) { + if (!wig.includes(chr)) { + it.remove(); + break; + } + } + } + + return chromosomes; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/WigSummary.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,44 @@ +package edu.unc.genomics.wigmath; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.log4j.Logger; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineTool; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; +import edu.unc.genomics.ngs.Autocorrelation; + +public class WigSummary extends CommandLineTool { + + private static final Logger log = Logger.getLogger(Autocorrelation.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file", required = true) + public WigFile inputFile; + @Parameter(names = {"-o", "--output"}, description = "Output file") + public Path outputFile; + + public void run() throws IOException { + String summary = inputFile.toString(); + + if (outputFile != null) { + log.debug("Writing to output file"); + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) { + writer.write(summary); + } + } else { + System.out.println(summary); + } + } + + public static void main(String[] args) throws IOException, WigFileException { + new WigSummary().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/genomics/wigmath/ZScore.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,60 @@ +package edu.unc.genomics.wigmath; + +import java.io.IOException; +import java.util.Iterator; + +import org.apache.log4j.Logger; +import org.broad.igv.bbfile.WigItem; + +import com.beust.jcommander.Parameter; + +import edu.unc.genomics.CommandLineToolException; +import edu.unc.genomics.io.WigFile; +import edu.unc.genomics.io.WigFileException; + +public class ZScore extends WigMathTool { + + private static final Logger log = Logger.getLogger(ZScore.class); + + @Parameter(names = {"-i", "--input"}, description = "Input file", required = true) + public WigFile inputFile; + + double mean; + double stdev; + + @Override + public void setup() { + inputs.add(inputFile); + + mean = inputFile.mean(); + stdev = inputFile.stdev(); + if(stdev == 0) { + log.error("Cannot Z-score a file with stdev = 0!"); + throw new CommandLineToolException("Cannot Z-score a file with stdev = 0!"); + } + } + + @Override + public float[] compute(String chr, int start, int stop) throws IOException, WigFileException { + log.debug("Computing difference for chunk "+chr+":"+start+"-"+stop); + Iterator<WigItem> data = inputFile.query(chr, start, stop); + float[] result = WigFile.flattenData(data, start, stop); + + for (int i = 0; i < result.length; i++) { + result[i] = (float)((result[i] - mean) / stdev); + } + + return result; + } + + + /** + * @param args + * @throws WigFileException + * @throws IOException + */ + public static void main(String[] args) throws IOException, WigFileException { + new ZScore().instanceMain(args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/utils/RomanNumeral.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,57 @@ +package edu.unc.utils; + +// Rudimentary Class for doing Arabic Integer -> Roman Numeral conversion +// Adapted by Timothy Palpant +// File : gui/componenents/calculators/Roman.java +// Description: A static method for converting binary integers to Roman numbers. +// Illustrates: Static inner value class, StringBuffer, throw exceptions. +// Author : Fred Swartz - 2006-12-29 - Placed in public domain. +public class RomanNumeral { + + // This could be alternatively be done with parallel arrays. + // Another alternative would be Pair<Integer, String> + final static RomanValue[] ROMAN_VALUE_TABLE = { + new RomanValue(1000, "M"), + new RomanValue( 900, "CM"), + new RomanValue( 500, "D"), + new RomanValue( 400, "CD"), + new RomanValue( 100, "C"), + new RomanValue( 90, "XC"), + new RomanValue( 50, "L"), + new RomanValue( 40, "XL"), + new RomanValue( 10, "X"), + new RomanValue( 9, "IX"), + new RomanValue( 5, "V"), + new RomanValue( 4, "IV"), + new RomanValue( 1, "I") + }; + + public static String int2roman(int n) { + if (n >= 4000 || n < 1) { + throw new NumberFormatException("Numbers must be in range 1-3999"); + } + StringBuilder result = new StringBuilder(10); + + //... Start with largest value, and work toward smallest. + for (RomanValue equiv : ROMAN_VALUE_TABLE) { + //... Remove as many of this value as possible (maybe none). + while (n >= equiv.intVal) { + n -= equiv.intVal; // Subtract value. + result.append(equiv.romVal); // Add roman equivalent. + } + } + return result.toString(); + } + + private static class RomanValue { + //... No need to make this fields private because they are + // used only in this private value class. + int intVal; // Integer value. + String romVal; // Equivalent roman numeral. + + RomanValue(int dec, String rom) { + this.intVal = dec; + this.romVal = rom; + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/src/edu/unc/utils/SortUtils.java Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,60 @@ +package edu.unc.utils; + +/** + * Custom sorting utilities + * see: http://stackoverflow.com/questions/951848/java-array-sort-quick-way-to-get-a-sorted-list-of-indices-of-an-array + * @author timpalpant + * + */ +public class SortUtils { + public static int[] indexSort(float[] main) { + int[] index = new int[main.length]; + for (int i = 0; i < index.length; i++) { + index[i] = i; + } + + quicksort(main, index, 0, index.length-1); + + return index; + } + + // quicksort a[left] to a[right] + public static void quicksort(float[] a, int[] index, int left, int right) { + if (right <= left) + return; + int i = partition(a, index, left, right); + quicksort(a, index, left, i - 1); + quicksort(a, index, i + 1, right); + } + + // partition a[left] to a[right], assumes left < right + private static int partition(float[] a, int[] index, int left, int right) { + int i = left - 1; + int j = right; + while (true) { + while (a[index[++i]] < a[index[right]]) + // find item on left to swap + ; // a[right] acts as sentinel + while (a[index[right]] < a[index[--j]]) + // find item on right to swap + if (j == left) + break; // don't go out-of-bounds + if (i >= j) + break; // check if pointers cross + exch(a, index, i, j); // swap two elements into place + } + exch(a, index, i, right); // swap with partition element + return i; + } + + // exchange a[i] and a[j] + private static void exch(float[] a, int[] index, int i, int j) { + // Don't swap the data + // float swap = a[i]; + // a[i] = a[j]; + // a[j] = swap; + int b = index[i]; + index[i] = index[j]; + index[j] = b; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/stubFile.sh Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +java -Dlog4j.configuration=log4j.properties -cp "$DIR/../Resources/Java/*" edu.unc.genomics.ToolRunner \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java-genomics-toolkit/toolRunner.sh Mon Feb 13 21:55:55 2012 -0500 @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +if [ $# -eq 0 ] +then + echo "USAGE: toolRunner.sh APPNAME [ARGS]"; + exit; +fi + +if [ "$1" = "list" ] +then + find src/edu/unc/genomics/**/*.java -exec basename -s .java {} \; +fi + +java -Dlog4j.configuration=log4j.properties -cp .:build:lib/* edu.unc.genomics."$@" \ No newline at end of file