package org.seqcode.projects.seqview.components; import java.awt.*; import java.awt.event.*; import javax.swing.*; import org.seqcode.data.seqdata.SeqLocatorMatchedAligns; import org.seqcode.genome.Genome; import org.seqcode.genome.Species; import org.seqcode.genome.location.Gene; import org.seqcode.genome.location.NamedTypedRegion; import org.seqcode.gsebricks.RegionExpanderFactoryLoader; import org.seqcode.gseutils.Closeable; import org.seqcode.gseutils.NotFoundException; import org.seqcode.projects.seqview.SeqViewOptions; import java.util.Collection; import java.util.List; import java.util.ResourceBundle; import java.util.HashMap; import java.io.*; public class SeqViewOptionsPane extends JTabbedPane implements ItemListener, ActionListener, Closeable { //Current genome settings Genome currGen = null; Species currSpecies = null; // regexes get special handling at the moment because there's no gui component for them, // so cache them if neccessary private HashMap<String,String> regexes; private boolean handlingChange, closed; private RegionExpanderFactoryLoader<Gene> gfLoader; private RegionExpanderFactoryLoader<NamedTypedRegion> annotLoader; private JPanel speciesLocationPanel, annotationsPanel, seqPanel, optionsPanel; private SeqViewOptions createdFrom; // species/location tab private JComboBox speciesCBox, genomeCBox; private JTextField position, gene; private JLabel specieslabel, genomelabel, positionlabel, genelabel; // options tab private JCheckBox hash, oldchipseq; // seqdata tab private SeqAlignmentSelectPanel seqSelect; // annotations tab private JList genes, ncrnas, otherfeats; private DefaultListModel genesmodel, ncrnasmodel, otherfeatsmodel; private JCheckBox seqletters, polyA, gccontent, pyrpurcontent, cpg, regexmatcher; private JLabel geneslabel, ncrnaslabel, otherfeatslabel, seqlimitlabel; // file-based tracks private FileBasedTracksPanel filetracks; public SeqViewOptionsPane () throws NotFoundException { super(); gfLoader = new RegionExpanderFactoryLoader<Gene>("gene"); annotLoader = new RegionExpanderFactoryLoader<NamedTypedRegion>("annots"); handlingChange = true; init(null); handlingChange = false; closed = false; setSpeciesGenomeDefaults(); } public SeqViewOptionsPane(SeqViewOptions opts) throws NotFoundException { super(); gfLoader = new RegionExpanderFactoryLoader<Gene>("gene"); annotLoader = new RegionExpanderFactoryLoader<NamedTypedRegion>("annots"); closed = false; handlingChange=true; init(opts); handlingChange=false; if (opts.getGenome() == null) { setSpeciesGenomeDefaults(); } regexes = opts.regexes; } public boolean isClosed() { return closed; } public void close() { seqSelect.close(); closed = true; } private void reloadGenome() { String orgName = (String)speciesCBox.getSelectedItem(); String genName = (String)genomeCBox.getSelectedItem(); if(orgName != null && genName != null && (!orgName.equals(currSpecies.getName()) || !genName.equals(currGen.getVersion()))) { Species org; try { org = Species.getSpecies(orgName); currSpecies = org; Genome gen = new Genome(org, genName); currGen = gen; } catch (NotFoundException e) { e.printStackTrace(); throw new IllegalArgumentException(orgName + ":" + genName); } } } public void init(SeqViewOptions opts) throws NotFoundException { speciesLocationPanel = new JPanel(); annotationsPanel = new JPanel(); seqPanel = new JPanel(); optionsPanel = new JPanel(); createdFrom = opts; // First tab lets the user select the species, genome version, // and the genomic coordinates they want to view specieslabel = new JLabel("Species"); genomelabel = new JLabel("Genome Version"); positionlabel = new JLabel("Genome position\nto view"); genelabel = new JLabel("Gene to view"); speciesCBox = new JComboBox(); genomeCBox = new JComboBox(); speciesCBox.addItemListener(this); genomeCBox.addItemListener(this); position = new JTextField(); position.setText("1:100-200"); gene = new JTextField(); /* need to fill the species and genome boxes here */ Collection<String> organisms = Species.getAllSpeciesNames(false); for (String o : organisms) { speciesCBox.addItem(o); } //Set selected species & genome if (opts!=null && opts.getGenome() != null) { speciesCBox.removeItemListener(this); genomeCBox.removeItemListener(this); speciesCBox.setSelectedItem(opts.getGenome().getSpeciesName()); Collection<String> genomes = opts.getGenome().getSpecies().getGenomeNames(); genomeCBox.removeAllItems(); for (String o : genomes) { genomeCBox.addItem(o); } genomeCBox.setSelectedItem(opts.getGenome().getVersion()); currSpecies = opts.getGenome().getSpecies(); currGen = opts.getGenome(); genomeCBox.addItemListener(this); speciesCBox.addItemListener(this); } else { updateGenomeSelection(); setSpeciesGenomeDefaults(); } //Location panel speciesLocationPanel.setLayout(new GridLayout(4,2)); speciesLocationPanel.add(specieslabel); speciesLocationPanel.add(speciesCBox); speciesLocationPanel.add(genomelabel); speciesLocationPanel.add(genomeCBox); speciesLocationPanel.add(positionlabel); speciesLocationPanel.add(position); speciesLocationPanel.add(genelabel); speciesLocationPanel.add(gene); // seqdata tab seqSelect = new SeqAlignmentSelectPanel(); seqPanel.setLayout(new BorderLayout()); seqPanel.add(seqSelect, BorderLayout.CENTER); // Options tab optionsPanel.setLayout(new GridLayout(4,1)); hash = new JCheckBox("Show chromosome coordinates"); oldchipseq = new JCheckBox("Use old ChipSeq painter"); hash.setSelected(true); optionsPanel.add(hash); optionsPanel.add(oldchipseq); // Annotations tab JPanel lists = new JPanel(); lists.setLayout(new GridLayout(3,2)); JPanel boxes = new JPanel(); boxes.setLayout(new GridLayout(4,2)); genesmodel = new DefaultListModel(); ncrnasmodel = new DefaultListModel(); otherfeatsmodel = new DefaultListModel(); genes = new JList(genesmodel); ncrnas = new JList(ncrnasmodel); otherfeats = new JList(otherfeatsmodel); genes.setVisibleRowCount(7);genes.setLayoutOrientation(JList.VERTICAL); otherfeats.setVisibleRowCount(7); otherfeats.setLayoutOrientation(JList.VERTICAL); ncrnas.setVisibleRowCount(7); ncrnas.setLayoutOrientation(JList.VERTICAL); seqlimitlabel=new JLabel("Sequence features (visible only below "+SeqViewOptions.DEFAULT_MAX_SEQUENCE_VIEW+"bp):"); seqletters = new JCheckBox("DNA sequence"); seqletters.setSelected(true); polyA = new JCheckBox("PolyA sequences"); gccontent = new JCheckBox("GC content"); pyrpurcontent = new JCheckBox("Pyr/Pur content"); cpg = new JCheckBox("CpG"); regexmatcher = new JCheckBox("Regex Matcher"); geneslabel = new JLabel("Genes"); ncrnaslabel = new JLabel("ncRNAs"); otherfeatslabel = new JLabel("Other annotations"); lists.add(geneslabel); lists.add(new JScrollPane(genes)); lists.add(ncrnaslabel); lists.add(new JScrollPane(ncrnas)); lists.add(otherfeatslabel); lists.add(new JScrollPane(otherfeats)); boxes.add(seqlimitlabel); boxes.add(new JLabel("")); boxes.add(seqletters); boxes.add(polyA); boxes.add(gccontent); boxes.add(pyrpurcontent); boxes.add(cpg); boxes.add(regexmatcher); annotationsPanel.setLayout(new BorderLayout()); annotationsPanel.add(lists,BorderLayout.CENTER); annotationsPanel.add(boxes,BorderLayout.SOUTH); // file tracks tab filetracks = new FileBasedTracksPanel(); // use this to make the spacing be not-stupid JPanel dummy = new JPanel(); dummy.add(speciesLocationPanel); dummy.add(new JPanel()); addTab("Species & Location",new JScrollPane(dummy)); dummy = new JPanel(); dummy.add(annotationsPanel); dummy.add(new JPanel()); addTab("Annotations",new JScrollPane(dummy)); addTab("Seq Data", seqPanel); dummy = new JPanel(); dummy.add(filetracks); dummy.add(new JPanel()); addTab("File Tracks",new JScrollPane(dummy)); dummy = new JPanel(); dummy.setLayout(new BorderLayout()); dummy = new JPanel(); dummy.add(optionsPanel); dummy.add(new JPanel()); addTab("Display Options",new JScrollPane(dummy)); if(opts !=null){ if (opts.gene != null && !opts.gene.equals("")) { gene.setText(opts.gene); } hash.setSelected(opts.hash); gccontent.setSelected(opts.gccontent); pyrpurcontent.setSelected(opts.pyrpurcontent); polyA.setSelected(opts.polya); cpg.setSelected(opts.cpg); regexmatcher.setSelected(opts.regexmatcher); seqletters.setSelected(opts.seqletters); oldchipseq.setSelected(!opts.seqHistogramPainter); seqlimitlabel.setText("Sequence features (visible only below "+opts.maxSequenceQuery+"bp):"); int[] selected = new int[opts.genes.size()]; for (int i = 0; i < opts.genes.size(); i++) { selected[i] = genesmodel.indexOf(opts.genes.get(i)); } genes.setSelectedIndices(selected); selected = new int[opts.ncrnas.size()]; for (int i = 0; i < opts.ncrnas.size(); i++) { selected[i] = ncrnasmodel.indexOf(opts.ncrnas.get(i)); } ncrnas.setSelectedIndices(selected); selected = new int[opts.otherannots.size()]; for (int i = 0; i < opts.otherannots.size(); i++) { selected[i] = otherfeatsmodel.indexOf(opts.otherannots.get(i)); } otherfeats.setSelectedIndices(selected); if (opts.position != null && !opts.position.equals("")) { position.setText(opts.position); } else { if (opts.chrom != null && !opts.chrom.equals("")) { position.setText(opts.chrom + ":" + opts.start + "-" + opts.stop); } } seqSelect.addToSelected(opts.seqExpts); filetracks.fill(opts.regionTracks); } //Update the experiment list updateExptSelection(); } public void setSpeciesGenomeDefaults() { String species = null, genome = null; try { ResourceBundle res = ResourceBundle.getBundle("defaultgenome"); species = res.getString("species"); genome = res.getString("genome"); } catch (Exception e) { // don't do anything. If it fails, then we just fall back to the defaults. } if (species == null || genome == null) { try { String homedir = System.getenv("HOME"); String basename = "defaultSpeciesGenome"; String fname = homedir + "/." + basename; File propfile = new File(fname); if (!(propfile.exists() && propfile.canRead())) { homedir = System.getProperty("user.dir"); fname = homedir + "/" + basename; propfile = new File(fname); } if (propfile.exists() && propfile.canRead()) { InputStream is = new FileInputStream(propfile); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line; while ((line = reader.readLine()) != null) { int p = line.indexOf('='); String key = line.substring(0,p); String value = line.substring(p+1); if (key.equals("species")) { species = value; } if (key.equals("genome")) { genome = value; } } } } catch (Exception e) { // don't do anything. If it fails, then we just fall back to the defaults. } } if (species == null || genome == null) { species = (String)this.speciesCBox.getSelectedItem(); genome = (String)this.genomeCBox.getSelectedItem(); } this.speciesCBox.setSelectedItem(species); this.genomeCBox.setSelectedItem(genome); } /* fills in and returns a SeqViewOptions object based on the current selections */ public SeqViewOptions parseOptions() { SeqViewOptions these = new SeqViewOptions(); // parse the species and location tab String speciesStr = speciesCBox.getSelectedItem().toString(); String genomeStr = genomeCBox.getSelectedItem().toString(); try { Species org = new Species(speciesStr); these.setGenome(Genome.findGenome(genomeStr)); } catch (NotFoundException e) { e.printStackTrace(); throw new IllegalArgumentException(genomeStr); } these.position = position.getText(); these.gene = gene.getText(); // parse the options tab these.hash = hash.isSelected(); these.seqletters = seqletters.isSelected(); these.seqHistogramPainter = !oldchipseq.isSelected(); // parse the annotations tab for (Object o : genes.getSelectedValues()) { these.genes.add(o.toString()); } for (Object o : ncrnas.getSelectedValues()) { these.ncrnas.add(o.toString()); } for (Object o : otherfeats.getSelectedValues()) { these.otherannots.add(o.toString()); } these.gccontent = gccontent.isSelected(); these.pyrpurcontent = pyrpurcontent.isSelected(); these.polya = polyA.isSelected(); these.cpg = cpg.isSelected(); these.regexmatcher = regexmatcher.isSelected(); // parse the expression tab //Collection<Experiment> expts = exprSelect.getSelected(); //these.exprExperiments.addAll(expts); //Parse sequencing experiments for(SeqLocatorMatchedAligns lme : seqSelect.getSelected()) { these.seqExpts.add(lme); } filetracks.parse(these.regionTracks); these.regexes = regexes; return these; } public SeqViewOptions parseAndDiff() { SeqViewOptions these = parseOptions(); // need to see if we have existing options and if they're compatible. // if they are, return the difference. Otherwise, return the complete // options. if (createdFrom != null && these.getGenome().equals(createdFrom.getGenome())) { these.differenceOf(createdFrom); } return these; } /* updates the choice of experiments based on the currently selected genome and species */ private void updateExptSelection() { reloadGenome(); seqSelect.setGenome(currGen); // update the set of Gene annotations genesmodel.clear(); otherfeatsmodel.clear(); if(currGen != null) { for(String type : gfLoader.getTypes(currGen)) { genesmodel.addElement(type); } for(String type : annotLoader.getTypes(currGen)) { otherfeatsmodel.addElement(type); } List<String> chroms = currGen.getChromList(); if (chroms.size() == 0) { throw new RuntimeException("Empty chromosome list for " + currGen); } java.util.Collections.sort(chroms); position.setText(chroms.get(0) + ":10000-20000"); } } private void updateGenomeSelection () { try { Species org = new Species(speciesCBox.getSelectedItem().toString()); Collection<String> genomes = org.getGenomeNames(); genomeCBox.removeAllItems(); for (String o : genomes) { genomeCBox.addItem(o); } genomeCBox.setSelectedIndex(0); } catch (NotFoundException ex) { System.err.println("Couldn't find species " + speciesCBox.getSelectedItem()); ex.printStackTrace(); } } public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { if (handlingChange) {return;} Object source = e.getItemSelectable(); if (source == speciesCBox) { updateGenomeSelection(); } if (source == genomeCBox) { synchronized(this) { if (!handlingChange) { handlingChange = true; updateExptSelection(); handlingChange = false; } } } } } public void actionPerformed (ActionEvent e) { } }