package moduls.frm.children; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FileDialog; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.LinkedList; import genomeObjects.AnnotatedGenome; import genomeObjects.CSDisplayData; import genomeObjects.GenomicElement; import genomeObjects.GenomicElementAndQueryMatch; import javax.swing.JButton; import javax.swing.JEditorPane; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import org.biojava3.core.sequence.DNASequence; import org.biojava3.core.sequence.RNASequence; import org.biojava3.core.sequence.Strand; import org.biojava3.core.sequence.io.DNASequenceCreator; import org.biojava3.core.sequence.io.FastaReaderHelper; import org.biojava3.core.sequence.io.FastaWriterHelper; import org.biojava3.core.sequence.template.CompoundSet; import org.biojava3.core.sequence.template.Sequence; import contextViewer.GeneColorLegendFrame; import moduls.frm.ContextLeaf; import moduls.frm.FrmPrincipalDesk; import moduls.frm.Panels.Jpan_btn_NEW; public class FrmSearchResults extends JPanel implements ActionListener, TreeSelectionListener{ //Fields //Management private FrmPrincipalDesk fr; //master CSD available here private CSDisplayData CSD; //The local CSD //Tree components private JTree SearchResults; private DefaultMutableTreeNode Query; private LinkedHashMap<String, DefaultMutableTreeNode> TreeNodeMapping; private boolean SelectedbyMouse = true; //GUI Components private JPanel TreeDisplay; private JPanel ButtonPanel; private JButton btnExpandAll; private JButton btnCollapseAll; private String strExpandAll = "Expand All"; private String strCollapseAll = "Collapse All"; public CustomSeqExportData CSED = null; //Constants private int FastaSeqLineLength = 70; private int FastaTitleLineLength = 70; //data retrieval public LinkedHashMap<DefaultMutableTreeNode, GenomicElement> LeafData = new LinkedHashMap<DefaultMutableTreeNode, GenomicElement>(); public LinkedHashMap<DefaultMutableTreeNode, String> LeafSource = new LinkedHashMap<DefaultMutableTreeNode, String>(); //pop-up window private JPopupMenu ExportMenu; //export frame information //constructor public FrmSearchResults(final FrmPrincipalDesk f, CSDisplayData CSD){ //base variables this.fr = f; this.CSD = CSD; //initialize this.InitializeSequenceExportMenu(); //get panel this.getPanel(); } //dummy constructor public FrmSearchResults(){ } // ====== Export-Related ======= // //sequence export class public class ExportSequencesWorker extends SwingWorker<Void, Void>{ public ActionEvent evt; //Strings final String ExportSeqsCustom = "Custom Sequence Export"; final String ExportDNASeqs = "Export Genes (DNA Sequences)"; final String ExportProtSeqs = "Export Protein Sequences"; final String ExportSegments = "Export Genomic Grouping Segments (DNA)"; final String ExportDataAsShortTable = "Export Data as Table (short)"; final String ExportDataAsLongTable = "Export Data as Table (long)"; //constructor public ExportSequencesWorker(ActionEvent e){ this.evt = e; } @Override protected Void doInBackground() throws Exception { //switch cursor Component glassPane = fr.getRootPane().getGlassPane(); glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); glassPane.setVisible(true); /* * EXPORT SEQUENCES */ //export DNA sequence of whole segment if (evt.getActionCommand().equals(ExportSegments)){ ExportSegments(); } //export DNA segment of selected genes if (evt.getActionCommand().equals(ExportDNASeqs)) { CSED = null; // no customizations SWExportGeneSequences(false); } //export protein sequence if (evt.getActionCommand().equals(ExportProtSeqs)){ CSED = null; // no customizations SWExportGeneSequences(true); } //create customization prior to export if (evt.getActionCommand().equals(ExportSeqsCustom)){ SWCustomExport(); } /* * EXPORT DATA TABLE */ //export data table - short version if (evt.getActionCommand().equals(ExportDataAsShortTable)){ ExportTable(false); } //export data table - long version if (evt.getActionCommand().equals(ExportDataAsLongTable)){ ExportTable(true); } //switch cursor back to normal glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); glassPane.setVisible(false); return null; } //perform a more complicated export public void SWCustomExport(){ //Retrieve information from a pop-up window new ManageCustomSeq(FrmSearchResults.this); //proceed to export, if not cancelled if (CSED != null){ //proceed to ordinary gene export SWExportGeneSequences(false); } } //export a file DNA or protein sequences public void SWExportGeneSequences(boolean isProtein){ String Title = ""; if (isProtein){ Title = "Export protein sequences of selected genes"; } else { Title = "Export DNA sequences of selected genes"; //if other parameters exist to modify the export, change title if (CSED != null){ Title = "Custom export of DNA associated with selected genes"; } } //Create + Show file dialog window final FileDialog fd = new FileDialog(fr, Title, FileDialog.SAVE); fd.setDirectory(fr.getFileChooserSource().getAbsolutePath()); fd.setFile(".fasta"); fd.setVisible(true); //if a file is specified, export the data to file. if (fd.getFile() != null){ //recover data for file String sPath = fd.getDirectory() + fd.getFile(); final File OutputFile = new File(sPath); //update file chooser fr.setFileChooserSource(OutputFile.getParentFile()); //a data structure to hold the selected node data LinkedList<TreeNode> SelectedNodes = new LinkedList<TreeNode>(); //iterate through tree nodes, retrieve selected, export int[] SelectedElements = SearchResults.getSelectionRows(); for (int i = 0; i < SelectedElements.length; i++){ //retrieve the appropriate node DefaultMutableTreeNode TN = (DefaultMutableTreeNode) SearchResults.getPathForRow(SelectedElements[i]).getLastPathComponent(); //ignore root note if (!TN.isRoot()){ //an individual gene / genes if (TN.isLeaf() && !TN.getAllowsChildren()){ if (!SelectedNodes.contains(TN)){ SelectedNodes.add(TN); } //find appropriate genes within a whole set of genes } else { int ChildCount = TN.getChildCount(); for (int j = 0; j < ChildCount; j++){ if (!SelectedNodes.contains(TN.getChildAt(j))){ SelectedNodes.add(TN.getChildAt(j)); } } } } } //hash maps to store data // Node, Sequence LinkedHashMap<TreeNode,String> Genes4Export = new LinkedHashMap<TreeNode, String>(); boolean FailedExport = false; //for progress bar int NumCounter = 0; //iterate through output for (TreeNode TN : SelectedNodes){ //retrieve all bioinfo. GenomicElement E = LeafData.get(TN); AnnotatedGenome AG = fr.getOS().getSpecies().get(LeafSource.get(TN)); if (AG.getGenomeSequenceFile() != null){ //Initialize sequence String str = ""; //no customizations - simple gene or protein if (CSED == null){ str = AG.DNASequence(E.getContig(), E.getStart(), E.getStop(), E.getStrand()); //if these are proteins, modify to protein sequences. if (isProtein){ //convert string to protein sequence DNASequence d = new DNASequence(str); str = d.getReverseComplement().getSequenceAsString(); RNASequence rna = d.getRNASequence(); str = rna.getProteinSequence().toString(); } //customizations - modify the coordinates appropriately } else { //coordinates for export int startCoord; int stopCoord; //positive strand case if (E.getStrand().equals(Strand.POSITIVE)){ //starting position //start relative to start coordinate if (CSED.start_Start == true){ startCoord = E.getStart() - CSED.start_Before; //start relative to stop coordinate } else { startCoord = E.getStop() - CSED.start_Before; } //ending position //stop relative to start coordinate if (CSED.stop_Stop == false){ stopCoord = E.getStart() - CSED.stop_Before; //stop relative to stop coordinate } else { stopCoord = E.getStop() - CSED.stop_Before; } //reverse strand case: } else { //starting position //start relative to start coordinate if (CSED.start_Start == true){ stopCoord = E.getStop() + CSED.start_Before; //start relative to stop coordinate } else { stopCoord = E.getStart() + CSED.start_Before; } //ending position //stop relative to start coordinate if (CSED.stop_Stop == false){ startCoord = E.getStop() + CSED.stop_Before; //stop relative to stop coordinate } else { startCoord = E.getStart() + CSED.stop_Before; } } //Retrieve sequence, if appropriate if (startCoord < stopCoord){ str = AG.DNASequence(E.getContig(), startCoord, stopCoord, E.getStrand()); } else { String id = E.getGeneID(); if (id.equals("")){ id = E.getContig() + "_[" + E.getStart() + ":" + E.getStop() + "]"; } System.out.println("Range for gene " + id + " is invalid, no sequence exported."); } } //cancel at this point if (!Thread.currentThread().isInterrupted()){ //store values Genes4Export.put(TN, str); NumCounter++; //adjust progress bar // update progress bar int progress = (int) Math .round(100 * ((double) NumCounter / SelectedNodes.size())); System.out.println("Exported " + NumCounter + "/" + SelectedNodes.size() + " Sequences."); setProgress(progress); } else{ setProgress(0); break; } //if not explicit files associated, try to retrieve data from associate feature. } else if (AG.getGFM().GetTranslation){ //retrieve directly from the genomic element. String str = E.getTranslation(); //cancel at this point if (!Thread.currentThread().isInterrupted()){ //store values Genes4Export.put(TN, str); NumCounter++; //adjust progress bar // update progress bar int progress = (int) Math .round(100 * ((double) NumCounter / SelectedNodes.size())); System.out.println("Exported " + NumCounter + "/" + SelectedNodes.size() + " Sequences."); setProgress(progress); } else{ setProgress(0); break; } } else { FailedExport = true; } } //export sequences when the process has not been cancelled. if (!Thread.currentThread().isInterrupted()){ //write sequence to file try { //open file stream BufferedWriter bw = new BufferedWriter(new FileWriter(OutputFile)); for (TreeNode TN : Genes4Export.keySet()){ //Header bw.write(FastaHeaderReformat(TN)); bw.flush(); //body bw.write(FastaBodyReformat(Genes4Export.get(TN))); bw.flush(); } //close file stream bw.close(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "The gene sequences could not be exported.", "Sequence Export Error",JOptionPane.ERROR_MESSAGE); } //when a genome does not exist, failed export. if (FailedExport){ JOptionPane.showMessageDialog(null, "One or more of the genes selected for export do " + "not have an associated sequence file.\nTo associate a genome with a sequence file, " + "select \"Load Genome Sequence File(s)\" from the Load drop-down menu.", "Sequence Export Error",JOptionPane.ERROR_MESSAGE); } } } } //export a file of contiguous DNA stretches in all appropriate segments public void SWExportSegments(){ //Create + Show file dialog window final FileDialog fd = new FileDialog(fr, "Export DNA Sequences of Selected Genomic Groupings", FileDialog.SAVE); fd.setDirectory(fr.getFileChooserSource().getAbsolutePath()); fd.setFile(".fasta"); fd.setVisible(true); //if a file is specified, export the data to file. if (fd.getFile() != null){ //recover data for file String sPath = fd.getDirectory() + fd.getFile(); final File OutputFile = new File(sPath); //update file chooser fr.setFileChooserSource(OutputFile.getParentFile()); //a data structure to hold the source data LinkedList<TreeNode> SelectedNodes = new LinkedList<TreeNode>(); //iterate through tree nodes, retrieve selected, export int[] SelectedElements = SearchResults.getSelectionRows(); for (int i = 0; i < SelectedElements.length; i++){ //retrieve the appropriate node DefaultMutableTreeNode TN = (DefaultMutableTreeNode) SearchResults.getPathForRow(SelectedElements[i]).getLastPathComponent(); //ignore root note if (!TN.isRoot()){ //retrieve whole set if (!(TN.isLeaf() && !TN.getAllowsChildren())){ SelectedNodes.add(TN); } } } // Header, Sequence LinkedHashMap<TreeNode,String> Genes4Export = new LinkedHashMap<TreeNode, String>(); //export fails because genomes not loaded. boolean FailedExport = false; if (SelectedNodes.size() > 0){ //print output to table for (TreeNode TN : SelectedNodes){ //retrieve from CSD LinkedList<GenomicElementAndQueryMatch> Elements = CSD.getEC().getContexts().get(TN.toString()); //split up this list into smaller lists LinkedHashMap<String, LinkedList<GenomicElement>> ContigSplits = new LinkedHashMap<String, LinkedList<GenomicElement>>(); GenomicElement E = null; for (GenomicElementAndQueryMatch GandE : Elements){ //retrieve element E = GandE.getE(); //organize by hash map if (ContigSplits.get(E.getContig()) != null){ LinkedList<GenomicElement> L = ContigSplits.get(E.getContig()); L.add(E); ContigSplits.put(E.getContig(), L); } else { LinkedList<GenomicElement> L = new LinkedList<GenomicElement>(); L.add(E); ContigSplits.put(E.getContig(),L); } } //retrieve bioinfo. AnnotatedGenome AG = fr.getOS().getSpecies().get(CSD.getEC().getSourceSpeciesNames().get(TN.toString())); int NumCounter = 0; if (AG.getGenomeSequenceFile() != null){ //segment by sequence for (String contigkey : ContigSplits.keySet()){ //retrieve all appropriate elements LinkedList<GenomicElement> LL = ContigSplits.get(contigkey); int MinStart = 99999999; int MaxStop = -1; for (GenomicElement E1 : LL){ if (E1.getStart() < MinStart){ MinStart = E1.getStart(); } if (E1.getStop() > MaxStop){ MaxStop = E1.getStop(); } } //retrieve sequence String str = AG.DNASequence(contigkey, MinStart, MaxStop, Strand.POSITIVE); //cancel at this point if (!Thread.currentThread().isInterrupted()){ //store values Genes4Export.put(TN, str); NumCounter++; //adjust progress bar // update progress bar int progress = (int) Math .round(100 * ((double) NumCounter / SelectedNodes.size())); System.out.println("Exported " + NumCounter + "/" + SelectedNodes.size() + " Sequences."); setProgress(progress); } else{ setProgress(0); break; } } } else { FailedExport = true; } } //export if the current thread has not been interrupted. if (!Thread.currentThread().isInterrupted()){ //write sequence to file try { //open file stream BufferedWriter bw = new BufferedWriter(new FileWriter(OutputFile)); for (TreeNode TN : Genes4Export.keySet()){ //Header bw.write(FastaHeaderReformat(TN)); bw.flush(); //body bw.write(FastaBodyReformat(Genes4Export.get(TN))); bw.flush(); } //close file stream bw.close(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "The sequences could not be exported.", "Sequence Export Error",JOptionPane.ERROR_MESSAGE); } //when a genome does not exist, failed export. if (FailedExport){ JOptionPane.showMessageDialog(null, "One or more of the genes selected for export do " + "not have an associated sequence file.\nTo associate a genome with a sequence file, " + "select \"Load Genome Sequence File(s)\" from the Load drop-down menu.", "Sequence Export Error",JOptionPane.ERROR_MESSAGE); } } } else { JOptionPane.showMessageDialog(null, "No genomic groupings are selected.\n" + "Please select one or more groupings to export associated sequences.", "No Groupings Selected",JOptionPane.ERROR_MESSAGE); } } } //post-processing public void done(){ //reset progress bar setProgress(0); //switch cursor back to normal Component glassPane = fr.getRootPane().getGlassPane(); glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); glassPane.setVisible(false); } } //create the pop-up menu object private void InitializeSequenceExportMenu(){ //Strings final String ExportSeqsCustom = "Custom Sequence Export"; final String ExportDNASeqs = "Export Genes (DNA Sequences)"; final String ExportProtSeqs = "Export Protein Sequences"; final String ExportSegments = "Export Genomic Grouping Segments (DNA)"; final String ExportDataAsShortTable = "Export Data as Table (short)"; final String ExportDataAsLongTable = "Export Data as Table (long)"; //create action listener ActionListener exportAction = new ActionListener(){ public void actionPerformed(final ActionEvent evt) { //New SwingWorker ExportSequencesWorker ESW = new ExportSequencesWorker(evt); ESW.addPropertyChangeListener(fr.getPanBtn()); //add to main frame fr.setCurrentESW(ESW); //execute action ESW.execute(); //reset swing worker in main frame fr.setCurrentESW(null); } }; //set export menu this.ExportMenu = new JPopupMenu(); //create menu items final JMenuItem me0 = new JMenuItem(ExportDNASeqs); final JMenuItem me1 = new JMenuItem(ExportProtSeqs); final JMenuItem me2 = new JMenuItem(ExportSegments); final JMenuItem me3 = new JMenuItem(ExportDataAsShortTable); final JMenuItem me4 = new JMenuItem(ExportDataAsLongTable); final JMenuItem me5 = new JMenuItem(ExportSeqsCustom); //add action listeners me0.addActionListener(exportAction); me1.addActionListener(exportAction); me2.addActionListener(exportAction); me3.addActionListener(exportAction); me4.addActionListener(exportAction); me5.addActionListener(exportAction); //build menu ExportMenu.add(me0); ExportMenu.add(me1); ExportMenu.add(me2); ExportMenu.add(me5); ExportMenu.addSeparator(); ExportMenu.add(me3); ExportMenu.add(me4); } //export short table private void ExportTable(boolean isLongTable){ //Create + Show file dialog window final FileDialog fd = new FileDialog(fr, "Export Search Results Data", FileDialog.SAVE); fd.setDirectory(fr.getFileChooserSource().getAbsolutePath()); fd.setFile(".txt"); fd.setVisible(true); //if a file is specified, export the data to file. if (fd.getFile() != null){ //recover data for file String sPath = fd.getDirectory() + fd.getFile(); final File OutputFile = new File(sPath); //update file chooser fr.setFileChooserSource(OutputFile.getParentFile()); //a data structure to hold the selected node data LinkedList<TreeNode> SelectedNodes = new LinkedList<TreeNode>(); //iterate through tree nodes, retrieve selected, export int[] SelectedElements = SearchResults.getSelectionRows(); for (int i = 0; i < SelectedElements.length; i++){ //retrieve the appropriate node DefaultMutableTreeNode TN = (DefaultMutableTreeNode) SearchResults.getPathForRow(SelectedElements[i]).getLastPathComponent(); //ignore root note if (!TN.isRoot()){ //an individual gene / genes if (TN.isLeaf() && !TN.getAllowsChildren()){ if (!SelectedNodes.contains(TN)){ SelectedNodes.add(TN); } //a whole set of genes } else { int ChildCount = TN.getChildCount(); for (int j = 0; j < ChildCount; j++){ if (!SelectedNodes.contains(TN.getChildAt(j))){ SelectedNodes.add(TN.getChildAt(j)); } } } } } try { //open file stream BufferedWriter bw = new BufferedWriter(new FileWriter(OutputFile)); //short table header if (!isLongTable){ String Header = "#GeneID\tClusterID\tAnnotation\n"; bw.write(Header); bw.flush(); //long table header } else { String Header = "#Organism\tContig\tStart\tStop\tStrand\tAnnotation\tClusterID\tGeneID\n"; bw.write(Header); bw.flush(); } //print output to table for (TreeNode TN : SelectedNodes){ //retrieve all bioinfo. GenomicElement E = LeafData.get(TN); String OrgName = LeafSource.get(TN); //overall string to output to file String str = ""; //short table if (!isLongTable){ String ClusterID = ""; if (E.getClusterID() != -1){ ClusterID = String.valueOf(E.getClusterID()); } else { ClusterID = "none"; } String GeneID = ""; if (E.getGeneID() != null){ GeneID = E.getGeneID(); } else{ GeneID = "none"; } //export as tab-delimited str = GeneID + "\t" + ClusterID + "\t" + E.getAnnotation() + "\n"; bw.write(str); bw.flush(); //long table } else { String ClusterID = ""; if (E.getClusterID() != -1){ ClusterID = String.valueOf(E.getClusterID()); } else { ClusterID = "none"; } String GeneID = ""; if (E.getGeneID() != null){ GeneID = E.getGeneID(); } else{ GeneID = "none"; } String TheStrand = ""; if (E.getStrand().equals(Strand.POSITIVE)){ TheStrand = "1"; } else{ TheStrand = "-1"; } //export all the bioinfo. str = OrgName + "\t" + E.getContig() + "\t" + String.valueOf(E.getStart()) + "\t" + String.valueOf(E.getStop()) + "\t" + TheStrand + "\t" + E.getAnnotation() + "\t" + ClusterID + "\t" + GeneID + "\n"; bw.write(str); bw.flush(); } } //close file stream bw.close(); } catch (Exception e) { JOptionPane.showMessageDialog(null, "The data in the table could not be exported.", "Table Export Error",JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } } //export a file DNA or protein sequences public void ExportGeneSequences(boolean isProtein){ //Create + Show file dialog window final FileDialog fd = new FileDialog(fr, "Export DNA Sequences of Selected Genes", FileDialog.SAVE); fd.setDirectory(fr.getFileChooserSource().getAbsolutePath()); fd.setFile(".fasta"); fd.setVisible(true); //if a file is specified, export the data to file. if (fd.getFile() != null){ //recover data for file String sPath = fd.getDirectory() + fd.getFile(); final File OutputFile = new File(sPath); //update file chooser fr.setFileChooserSource(OutputFile.getParentFile()); //a data structure to hold the selected node data LinkedList<TreeNode> SelectedNodes = new LinkedList<TreeNode>(); //iterate through tree nodes, retrieve selected, export int[] SelectedElements = SearchResults.getSelectionRows(); for (int i = 0; i < SelectedElements.length; i++){ //retrieve the appropriate node DefaultMutableTreeNode TN = (DefaultMutableTreeNode) SearchResults.getPathForRow(SelectedElements[i]).getLastPathComponent(); //ignore root note if (!TN.isRoot()){ //an individual gene / genes if (TN.isLeaf() && !TN.getAllowsChildren()){ String s = TN.toString(); if (!SelectedNodes.contains(TN)){ SelectedNodes.add(TN); } //find appropriate genes within a whole set of genes } else { int ChildCount = TN.getChildCount(); for (int j = 0; j < ChildCount; j++){ if (!SelectedNodes.contains(TN.getChildAt(j))){ SelectedNodes.add(TN.getChildAt(j)); } } } } } //hash maps to store data // Node, Sequence LinkedHashMap<TreeNode,String> Genes4Export = new LinkedHashMap<TreeNode, String>(); boolean FailedExport = false; //iterate through output for (TreeNode TN : SelectedNodes){ //retrieve all bioinfo. GenomicElement E = LeafData.get(TN); AnnotatedGenome AG = fr.getOS().getSpecies().get(LeafSource.get(TN)); if (AG.getGenomeSequenceFile() != null){ //retrieve sequence //String str = AG.retrieveSequence(E.getContig(), E.getStart(), E.getStop(), E.getStrand()); String str = AG.DNASequence(E.getContig(), E.getStart(), E.getStop(), E.getStrand()); //if these are proteins, modify to protein sequences. if (isProtein){ //convert string to protein sequence DNASequence d = new DNASequence(str); str = d.getReverseComplement().getSequenceAsString(); RNASequence rna = d.getRNASequence(); str = rna.getProteinSequence().toString(); } //store values Genes4Export.put(TN, str); } else { FailedExport = true; } } //write sequence to file try { //open file stream BufferedWriter bw = new BufferedWriter(new FileWriter(OutputFile)); for (TreeNode TN : Genes4Export.keySet()){ //Header bw.write(FastaHeaderReformat(TN)); bw.flush(); //body bw.write(FastaBodyReformat(Genes4Export.get(TN))); bw.flush(); } //close file stream bw.close(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "The gene sequences could not be exported.", "Sequence Export Error",JOptionPane.ERROR_MESSAGE); } //when a genome does not exist, failed export. if (FailedExport){ JOptionPane.showMessageDialog(null, "One or more of the genes selected for export do " + "not have an associated sequence file.\nTo associate a genome with a sequence file, " + "select \"Load Genome Sequence File(s)\" from the Load drop-down menu.", "Sequence Export Error",JOptionPane.ERROR_MESSAGE); } } } //export a file of contiguous DNA stretches in all appropriate segments public void ExportSegments(){ //Create + Show file dialog window final FileDialog fd = new FileDialog(fr, "Export DNA Sequences of Selected Genomic Groupings", FileDialog.SAVE); fd.setDirectory(fr.getFileChooserSource().getAbsolutePath()); fd.setFile(".fasta"); fd.setVisible(true); //if a file is specified, export the data to file. if (fd.getFile() != null){ //recover data for file String sPath = fd.getDirectory() + fd.getFile(); final File OutputFile = new File(sPath); //update file chooser fr.setFileChooserSource(OutputFile.getParentFile()); //a data structure to hold the source data LinkedList<TreeNode> SelectedNodes = new LinkedList<TreeNode>(); //iterate through tree nodes, retrieve selected, export int[] SelectedElements = SearchResults.getSelectionRows(); for (int i = 0; i < SelectedElements.length; i++){ //retrieve the appropriate node DefaultMutableTreeNode TN = (DefaultMutableTreeNode) SearchResults.getPathForRow(SelectedElements[i]).getLastPathComponent(); //ignore root note if (!TN.isRoot()){ //retrieve whole set if (!(TN.isLeaf() && !TN.getAllowsChildren())){ SelectedNodes.add(TN); } } } // Header, Sequence LinkedHashMap<TreeNode,String> Genes4Export = new LinkedHashMap<TreeNode, String>(); //export fails because genomes not loaded. boolean FailedExport = false; if (SelectedNodes.size() > 0){ //print output to table for (TreeNode TN : SelectedNodes){ //retrieve from CSD LinkedList<GenomicElementAndQueryMatch> Elements = CSD.getEC().getContexts().get(TN.toString()); //split up this list into smaller lists LinkedHashMap<String, LinkedList<GenomicElement>> ContigSplits = new LinkedHashMap<String, LinkedList<GenomicElement>>(); GenomicElement E = null; for (GenomicElementAndQueryMatch GandE : Elements){ //retrieve element E = GandE.getE(); //organize by hash map if (ContigSplits.get(E.getContig()) != null){ LinkedList<GenomicElement> L = ContigSplits.get(E.getContig()); L.add(E); ContigSplits.put(E.getContig(), L); } else { LinkedList<GenomicElement> L = new LinkedList<GenomicElement>(); L.add(E); ContigSplits.put(E.getContig(),L); } } //retrieve bioinfo. AnnotatedGenome AG = fr.getOS().getSpecies().get(CSD.getEC().getSourceSpeciesNames().get(TN.toString())); if (AG.getGenomeSequenceFile() != null){ //segment by sequence for (String contigkey : ContigSplits.keySet()){ //retrieve all appropriate elements LinkedList<GenomicElement> LL = ContigSplits.get(contigkey); int MinStart = 99999999; int MaxStop = -1; for (GenomicElement E1 : LL){ if (E1.getStart() < MinStart){ MinStart = E1.getStart(); } if (E1.getStop() > MaxStop){ MaxStop = E1.getStop(); } } //retrieve sequence String str = AG.DNASequence(contigkey, MinStart, MaxStop, Strand.POSITIVE); //store values Genes4Export.put(TN, str); } } else { FailedExport = true; } } //write sequence to file try { //open file stream BufferedWriter bw = new BufferedWriter(new FileWriter(OutputFile)); for (TreeNode TN : Genes4Export.keySet()){ //Header bw.write(FastaHeaderReformat(TN)); bw.flush(); //body bw.write(FastaBodyReformat(Genes4Export.get(TN))); bw.flush(); } //close file stream bw.close(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "The sequences could not be exported.", "Sequence Export Error",JOptionPane.ERROR_MESSAGE); } //when a genome does not exist, failed export. if (FailedExport){ JOptionPane.showMessageDialog(null, "One or more of the genes selected for export do " + "not have an associated sequence file.\nTo associate a genome with a sequence file, " + "select \"Load Genome Sequence File(s)\" from the Load drop-down menu.", "Sequence Export Error",JOptionPane.ERROR_MESSAGE); } } else { JOptionPane.showMessageDialog(null, "No genomic groupings are selected.\n" + "Please select one or more groupings to export associated sequences.", "No Groupings Selected",JOptionPane.ERROR_MESSAGE); } } } //general method to reformat a string into fasta header public String FastaHeaderReformat(TreeNode TN){ //initialize output String formattedString = ""; if (LeafData.get(TN) != null){ //retrieve data GenomicElement E = LeafData.get(TN); String OrgName = LeafSource.get(TN); //build header from data - either gene ID, or sequence info if (!E.getGeneID().equals("")){ formattedString = ">" + E.getGeneID(); } else { //ordering of gene start/stop follows the strand String StartPos; String StopPos; if (E.getStrand().equals(Strand.POSITIVE)){ StartPos = String.valueOf(E.getStart()); StopPos = String.valueOf(E.getStop()); } else { StartPos = String.valueOf(E.getStop()); StopPos = String.valueOf(E.getStart()); } //build string formattedString = ">" + OrgName + " " + E.getContig() + " [" + StartPos + ":" + StopPos + "]"; //remove white space formattedString = (String) formattedString.replaceAll(" ", "_"); } } else { //name of whole segment formattedString = ">" + TN.toString(); } //trim to fit size constraints if (formattedString.length() > FastaTitleLineLength){ formattedString = (String) formattedString.subSequence(0, FastaTitleLineLength); } //add new line formattedString = formattedString + "\n"; //return return formattedString; } //general method to reformat a string into fasta body public String FastaBodyReformat(String Body){ //initialize output String formattedString = ""; //Body, segmented into appropriate number of lines boolean SeqCompleted = false; int BlockStart = 0; int BlockStop = Math.min(FastaSeqLineLength, Body.length()); while (!SeqCompleted){ //line for export formattedString = formattedString + (String) Body.subSequence(BlockStart,BlockStop) + "\n"; //conclude when sequence done exporting. if (BlockStop >= Body.length()){ //if you've written to the end of the sequence, no need to keep writing. SeqCompleted = true; } else { //move to next segment BlockStart = BlockStop; BlockStop = Math.min(Body.length(), BlockStop+FastaSeqLineLength); } } //final new line at end of string block formattedString = formattedString + "\n"; return formattedString; } // ======== // //create panel public void getPanel(){ //create top panel TreeDisplay = new JPanel(); TreeDisplay.setLayout(new GridLayout(1,0)); //Create the nodes. Query = new DefaultMutableTreeNode(CSD.getEC().getName()); //create nodes method this.CreateNodes(Query); SearchResults = new JTree(Query); SearchResults.addTreeSelectionListener(this); //adapter for export menu MouseAdapter ml = new MouseAdapter(){ public void mouseClicked(MouseEvent e){ //right-clicking on panel if (SwingUtilities.isRightMouseButton(e)){ //trigger pop-up menu display ExportMenu.show(e.getComponent(), e.getXOnScreen(), e.getYOnScreen()); //reposition appropriately ExportMenu.setLocation(e.getXOnScreen(),e.getYOnScreen()); } } }; SearchResults.addMouseListener(ml); //Create the scroll pane and add the tree to it. JScrollPane treeView = new JScrollPane(SearchResults); Dimension D = treeView.getPreferredSize(); treeView.setPreferredSize(new Dimension(D.height-20,D.width)); //add to top panel TreeDisplay.add(treeView); //create bottom panel ButtonPanel = new JPanel(); ButtonPanel.setLayout(new GridLayout(1,2)); //Expand/Collapse buttons btnExpandAll = new JButton(strExpandAll); btnExpandAll.addActionListener(this); ButtonPanel.add(btnExpandAll); btnCollapseAll = new JButton(strCollapseAll); btnCollapseAll.addActionListener(this); ButtonPanel.add(btnCollapseAll); this.setLayout(new BorderLayout()); this.add(TreeDisplay, BorderLayout.CENTER); this.add(ButtonPanel, BorderLayout.SOUTH); } //add all hits (nodes) public void CreateNodes(DefaultMutableTreeNode root){ String GeneInfo; String GeneIDNum; String ClusterIDNum; //Initialize the hash map TreeNodeMapping = new LinkedHashMap<String, DefaultMutableTreeNode>(); //iterate through all contexts //for (String S : CSD.getEC().getContexts().keySet()){ for (ContextLeaf CL : CSD.getGraphicalContexts()){ //create a new node, with the consistent name DefaultMutableTreeNode SM = new DefaultMutableTreeNode(CL.getName()); CL.setSearchResultsTreeNode(SM); //Retrieve individual gene information LinkedList<GenomicElementAndQueryMatch> Genes = CSD.getEC().getContexts().get(CL.getName()); //store mapping //TreeNodeMapping.put(S,SM); for (GenomicElementAndQueryMatch GandE : Genes){ //Retrieve Gene ID number if (GandE.getE().getGeneID() == ""){ GeneIDNum = "none"; } else { GeneIDNum = GandE.getE().getGeneID(); } //Retrieve Cluster ID number if (GandE.getE().getClusterID() == 0){ ClusterIDNum = "none"; } else { ClusterIDNum = Integer.toString(GandE.getE().getClusterID()); } //Retrieve Annotation GeneInfo = "GENEID: " + GeneIDNum + " CLUSTERID: " + ClusterIDNum + " ANNOTATION: " + GandE.getE().getAnnotation(); //add node to tree DefaultMutableTreeNode GM = new DefaultMutableTreeNode(GeneInfo); GM.setAllowsChildren(false); SM.add(GM); //store node data in hash maps LeafData.put(GM, GandE.getE()); LeafSource.put(GM, CSD.getEC().getSourceSpeciesNames().get(CL.getName())); //String GeneInfoWithSource = "SOURCE: " + CL.getName() + ": " + GeneInfo; //TreeNodeMapping.put(GeneInfoWithSource, GM); } //add tree node to root root.add(SM); } } //actions: expand/contract @Override public void actionPerformed(ActionEvent evt) { //expand rows if (evt.getSource().equals(btnExpandAll)){ for (int i = 0; i < SearchResults.getRowCount(); i++){ SearchResults.expandRow(i); } } //collapse rows if (evt.getSource().equals(btnCollapseAll)){ for (int i = 1; i < SearchResults.getRowCount(); i++){ SearchResults.collapseRow(i); } } //re-draw figure (adjust button sizes) this.repaint(); } public void UpdateNodes(){ //This method is only called when not invoked by mouse event. SelectedbyMouse = false; //retrieve updated CSD this.CSD = fr.getCurrentFrame().getInternalFrameData().getQD().getCSD(); //mark selected nodes for (ContextLeaf CL : CSD.getGraphicalContexts()){ if (CL.isSelected()){ SearchResults.addSelectionPath(new TreePath(CL.getSearchResultsTreeNode().getPath())); } else { SearchResults.removeSelectionPath(new TreePath(CL.getSearchResultsTreeNode().getPath())); } } //Now that nodes no longer affected, revert to old protocol SelectedbyMouse = true; } @Override public void valueChanged(TreeSelectionEvent e) { //only do things when selected by mouse. if (SelectedbyMouse){ //retrieve updated CSD this.CSD = fr.getCurrentFrame().getInternalFrameData().getQD().getCSD(); // //debugging. // System.out.println("Debugging, tree nodes:"); // for (ContextLeaf CL : CSD.getGraphicalContexts()){ // System.out.println(CL.getName()); // } //Update selected/deselected TreePath[] SelectionChanges = e.getPaths(); for (ContextLeaf CL : CSD.getGraphicalContexts()){ for (int i = 0; i < SelectionChanges.length; i++){ if (SelectionChanges[i].equals(new TreePath(CL.getSearchResultsTreeNode().getPath()))){ if (CL.isSelected()){ CL.setSelected(false); } else { CL.setSelected(true); } break; } } } //update master CSD fr.getCurrentFrame().getInternalFrameData().getQD().setCSD(CSD); //call main frame to update this and all other panels. this.fr.UpdateSelectedNodes(); } } public void setCSD(CSDisplayData cSD) { CSD = cSD; } public CSDisplayData getCSD() { return CSD; } }