Newer
Older
/* Selector.java
*
* created: Tue Apr 11 2000
*
* This file is part of Artemis
*
* Copyright(C) 2000,2001,2002 Genome Research Limited
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or(at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/Selector.java,v 1.11 2008-01-17 16:00:31 tjc Exp $
*/
package uk.ac.sanger.artemis.components;
import uk.ac.sanger.artemis.*;
import uk.ac.sanger.artemis.sequence.AminoAcidSequence;
import uk.ac.sanger.artemis.sequence.Strand;
import uk.ac.sanger.artemis.sequence.Bases;
import uk.ac.sanger.artemis.io.Location;
import uk.ac.sanger.artemis.io.Range;
import uk.ac.sanger.artemis.io.RangeVector;
import uk.ac.sanger.artemis.util.StringVector;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* This component allows the user to set the selection by filtering the
* features in an EntryGroup on key and contents.
*
* @author Kim Rutherford <kmr@sanger.ac.uk>
* @version $Id: Selector.java,v 1.11 2008-01-17 16:00:31 tjc Exp $
**/
public class Selector extends JFrame
implements EntryGroupChangeListener {
private JCheckBox by_key_button;
private JCheckBox by_qualifier_button;
private JCheckBox by_motif_button;
private JCheckBox less_than_bases_button;
private JCheckBox greater_than_bases_button;
private JCheckBox less_than_exons_button;
private JCheckBox greater_than_exons_button;
private JCheckBox ignore_case_checkbox;
private JCheckBox match_any_word_checkbox;
private JCheckBox forward_strand_checkbox;
private JCheckBox reverse_strand_checkbox;
private JCheckBox intron_pattern_button;
private KeyChoice key_selector;
private QualifierChoice qualifier_selector;
private JTextField qualifier_text;
private JTextField motif_text;
private JTextField less_than_bases_text;
private JTextField greater_than_bases_text;
private JTextField less_than_exons_text;
private JTextField greater_than_exons_text;
/**
* If checked the search text is allowed to match a substring of a
* qualifier value.
**/
/**
* The EntryGroup object that was passed to the constructor.
**/
/**
* This is the Selection that was passed to the constructor.
**/
final private Selection selection;
public static org.apache.log4j.Logger logger4j =
org.apache.log4j.Logger.getLogger(Selector.class);
/**
* Create a new Selector that van set the given Selection.
* @param selection The Selection that the commands in the menu will
* operate on.
* @param entry_group The component will choose features from this
* EntryGroup.
* @param goto_event_source The object the we will call gotoBase() on.
* @param base_plot_group The BasePlotGroup associated with this JMenu -
* needed to call getCodonUsageAlgorithm()
**/
public Selector(final Selection selection,
final GotoEventSource goto_event_source,
final EntryGroup entry_group,
final BasePlotGroup base_plot_group)
{
super("Artemis Feature Selector");
this.selection = selection;
this.entry_group = entry_group;
final Font default_font = Options.getOptions().getFont();
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.WEST;
c.weighty = 0;
c.gridwidth = GridBagConstraints.REMAINDER;
final JLabel top_label = new JLabel("Select by:");
gridbag.setConstraints(top_label, c);
getContentPane().add(top_label);
by_key_button = new JCheckBox("Key: ", false);
final JPanel by_key_panel = new JPanel();
by_key_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
by_key_panel.add(by_key_button);
gridbag.setConstraints(by_key_panel, c);
getContentPane().add(by_key_panel);
// final EntryInformation default_entry_information =
// Options.getArtemisEntryInformation();
Entry default_entry = getEntryGroup().getDefaultEntry();
if(default_entry == null)
default_entry = getEntryGroup().elementAt(0);
key_selector = new KeyChoice(default_entry_information);
gridbag.setConstraints(key_selector, c);
getContentPane().add(key_selector);
key_selector.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent _)
{
by_key_button.setSelected(true);
by_key_button.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent e)
{
if(!by_key_button.isSelected())
by_qualifier_button.setSelected(false);
by_qualifier_button = new JCheckBox("Qualifier: ", false);
final JPanel by_qualifier_panel = new JPanel();
by_qualifier_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
by_qualifier_panel.add(by_qualifier_button);
gridbag.setConstraints(by_qualifier_panel, c);
getContentPane().add(by_qualifier_panel);
if(getEntryGroup().getDefaultEntry() != null &&
getEntryGroup().getDefaultEntry().getEMBLEntry() instanceof GFFDocumentEntry)
qualifier_selector = new QualifierChoice(default_entry_information,
key_selector.getSelectedItem(),
gridbag.setConstraints(qualifier_selector, c);
getContentPane().add(qualifier_selector);
qualifier_selector.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent _)
{
by_qualifier_button.setSelected(true);
by_key_button.setSelected(true);
key_selector.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent _)
{
qualifier_selector.setKey(key_selector.getSelectedItem());
by_qualifier_button.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent e)
{
if(by_qualifier_button.isSelected())
{
if(!by_key_button.isSelected())
by_key_button.setSelected(true);
new JLabel(" Containing this text: ");
gridbag.setConstraints(qualifier_text_label, c);
getContentPane().add(qualifier_text_label);
qualifier_text = new JTextField("", 18);
gridbag.setConstraints(qualifier_text, c);
getContentPane().add(qualifier_text);
ignore_case_checkbox = new JCheckBox("Ignore Case", true);
final JPanel ignore_case_panel = new JPanel();
ignore_case_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
ignore_case_panel.add(ignore_case_checkbox);
gridbag.setConstraints(ignore_case_panel, c);
getContentPane().add(ignore_case_panel);
partial_match_checkbox = new JCheckBox("Allow Partial Match", true);
final JPanel partial_match_panel = new JPanel();
partial_match_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
partial_match_panel.add(partial_match_checkbox);
gridbag.setConstraints(partial_match_panel, c);
getContentPane().add(partial_match_panel);
match_any_word_checkbox = new JCheckBox("Match Any Word", false);
final JPanel match_any_word_panel = new JPanel();
match_any_word_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
match_any_word_panel.add(match_any_word_checkbox);
gridbag.setConstraints(match_any_word_panel, c);
getContentPane().add(match_any_word_panel);
less_than_bases_button = new JCheckBox("Up to: ", false);
final JPanel less_than_bases_panel = new JPanel();
less_than_bases_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
less_than_bases_panel.add(less_than_bases_button);
gridbag.setConstraints(less_than_bases_panel, c);
getContentPane().add(less_than_bases_panel);
less_than_bases_text = new JTextField("", 18);
gridbag.setConstraints(less_than_bases_text, c);
getContentPane().add(less_than_bases_text);
final JLabel less_than_bases_label = new JLabel(" bases long");
gridbag.setConstraints(less_than_bases_label, c);
getContentPane().add(less_than_bases_label);
greater_than_bases_button = new JCheckBox("At least: ", false);
final JPanel greater_than_bases_panel = new JPanel();
greater_than_bases_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
greater_than_bases_panel.add(greater_than_bases_button);
gridbag.setConstraints(greater_than_bases_panel, c);
getContentPane().add(greater_than_bases_panel);
greater_than_bases_text = new JTextField("", 18);
gridbag.setConstraints(greater_than_bases_text, c);
getContentPane().add(greater_than_bases_text);
final JLabel greater_than_bases_label = new JLabel(" bases long");
gridbag.setConstraints(greater_than_bases_label, c);
getContentPane().add(greater_than_bases_label);
andSeparator(gridbag, c);
less_than_exons_button = new JCheckBox("Up to: ", false);
final JPanel less_than_exons_panel = new JPanel();
less_than_exons_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
less_than_exons_panel.add(less_than_exons_button);
gridbag.setConstraints(less_than_exons_panel, c);
getContentPane().add(less_than_exons_panel);
less_than_exons_text = new JTextField("", 18);
gridbag.setConstraints(less_than_exons_text, c);
getContentPane().add(less_than_exons_text);
final JLabel less_than_exons_label = new JLabel(" exons long");
gridbag.setConstraints(less_than_exons_label, c);
getContentPane().add(less_than_exons_label);
greater_than_exons_button = new JCheckBox("At least: ", false);
final JPanel greater_than_exons_panel = new JPanel();
greater_than_exons_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
greater_than_exons_panel.add(greater_than_exons_button);
gridbag.setConstraints(greater_than_exons_panel, c);
getContentPane().add(greater_than_exons_panel);
greater_than_exons_text = new JTextField("", 18);
gridbag.setConstraints(greater_than_exons_text, c);
getContentPane().add(greater_than_exons_text);
final JLabel greater_than_exons_label = new JLabel(" exons long");
gridbag.setConstraints(greater_than_exons_label, c);
getContentPane().add(greater_than_exons_label);
andSeparator(gridbag, c);
intron_pattern_button = new JCheckBox("Contains introns without GT/GC start and AG end", false);
final JPanel intron_pattern_panel = new JPanel();
intron_pattern_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
intron_pattern_panel.add(intron_pattern_button);
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(intron_pattern_panel, c);
getContentPane().add(intron_pattern_panel);
final JLabel blank_label = new JLabel("");
gridbag.setConstraints(blank_label, c);
getContentPane().add(blank_label);
final JLabel and_label = new JLabel("And by:");
gridbag.setConstraints(and_label, c);
getContentPane().add(and_label);
by_motif_button = new JCheckBox("Amino acid motif: ", false);
final JPanel by_motif_panel = new JPanel();
by_motif_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
by_motif_panel.add(by_motif_button);
gridbag.setConstraints(by_motif_panel, c);
getContentPane().add(by_motif_panel);
gridbag.setConstraints(motif_text, c);
getContentPane().add(motif_text);
final JLabel blank_label = new JLabel("");
gridbag.setConstraints(blank_label, c);
getContentPane().add(blank_label);
final JPanel strand_panel = new JPanel();
strand_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
forward_strand_checkbox = new JCheckBox("Forward Strand Features", true);
strand_panel.add(forward_strand_checkbox);
forward_strand_checkbox.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent _)
{
if(!forward_strand_checkbox.isSelected() &&
!reverse_strand_checkbox.isSelected())
reverse_strand_checkbox.setSelected(true);
reverse_strand_checkbox = new JCheckBox("Reverse Strand Features", true);
strand_panel.add(reverse_strand_checkbox);
reverse_strand_checkbox.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent _)
{
if(!reverse_strand_checkbox.isSelected() &&
!forward_strand_checkbox.isSelected())
forward_strand_checkbox.setSelected(true);
gridbag.setConstraints(strand_panel, c);
getContentPane().add(strand_panel);
final JButton select_button = new JButton("Select");
select_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
selection.set(getSelected());
final JButton view_button = new JButton("View");
view_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
new FeatureFromVectorPredicate(getSelected());
if(by_key_button.isSelected())
title += " with key \"" + key_selector.getSelectedItem() + "\"";
if(by_qualifier_button.isSelected())
{
if(qualifier_text.getText().trim().length() > 0)
title += " with qualifier \"" + qualifier_selector.getSelectedItem() +
"\" containing text \"" + qualifier_text.getText() + "\"";
else
title += " with qualifier \"" +
qualifier_selector.getSelectedItem() + "\"";
if(forward_strand_checkbox.isSelected() &&
!reverse_strand_checkbox.isSelected())
if(!forward_strand_checkbox.isSelected() &&
reverse_strand_checkbox.isSelected())
if(by_motif_button.isSelected())
title += " with motif: " + motif_text.getText().trim().toUpperCase();
if(less_than_bases_button.isSelected())
title += " at most " + less_than_bases_text.getText().trim() +
" bases long";
if(greater_than_bases_button.isSelected())
title += " at least " + greater_than_bases_text.getText().trim() +
" bases long";
if(less_than_exons_button.isSelected())
title += " at most " + less_than_exons_text.getText().trim() +
" exons long";
if(greater_than_exons_button.isSelected())
title += " at least " + greater_than_exons_text.getText().trim() +
" exons long";
if(intron_pattern_button.isSelected())
title += " containing introns without GT/GC start and AG end";
new FilteredEntryGroup(entry_group, predicate, title);
new FeatureListFrame(title,
getSelection(),
goto_event_source, filtered_entry_group,
base_plot_group);
final JButton close_button = new JButton("Close");
close_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Selector.this.dispose();
new FlowLayout(FlowLayout.CENTER, 15, 5);
final JPanel bottom_button_panel = new JPanel(flow_layout);
bottom_button_panel.add(select_button);
bottom_button_panel.add(view_button);
bottom_button_panel.add(close_button);
gridbag.setConstraints(bottom_button_panel, c);
getContentPane().add(bottom_button_panel);
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent event)
{
getEntryGroup().removeEntryGroupChangeListener(Selector.this);
Selector.this.dispose();
getEntryGroup().addEntryGroupChangeListener(this);
pack();
final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
setLocation(new Point((screen.width - getSize().width) / 2,
(screen.height - getSize().height) / 2));
private void andSeparator(GridBagLayout gridbag,
GridBagConstraints c)
{
// leave a blank line to give the user a visual clue
final JLabel blank_label = new JLabel("");
gridbag.setConstraints(blank_label, c);
getContentPane().add(blank_label);
final JLabel and_label = new JLabel("And:");
gridbag.setConstraints(and_label, c);
getContentPane().add(and_label);
}
/**
* Implementation of the EntryGroupChangeListener interface. We listen to
* EntryGroupChange events so that we can get rid of the Navigator when the
* EntryGroup is no longer in use(for example when the EntryEdit is
public void entryGroupChanged(final EntryGroupChangeEvent event)
{
switch(event.getType())
{
case EntryGroupChangeEvent.DONE_GONE:
getEntryGroup().removeEntryGroupChangeListener(this);
dispose();
break;
}
}
/**
* Return those features that match the current setting of the Selector.
**/
private FeatureVector getSelected()
{
final FeaturePredicate key_and_qualifier_predicate;
final FeaturePredicate motif_predicate;
if(by_key_button.isSelected())
{
if(by_qualifier_button.isSelected())
{
final String search_text = qualifier_text.getText().trim();
(String) qualifier_selector.getSelectedItem();
new FeatureKeyQualifierPredicate(key_selector.getSelectedItem(),
qualifier_name,
true);
}
else
{
if(match_any_word_checkbox.isSelected())
{
//final StringVector words =
// StringVector.getStrings(search_text, " ");
final StringTokenizer tok = new StringTokenizer(search_text, " \n");
final String this_word = tok.nextToken().trim();
new FeatureKeyQualifierPredicate(key_selector.getSelectedItem(),
qualifier_name,
this_word,
partial_match_checkbox.isSelected(),
ignore_case_checkbox.isSelected());
new FeaturePredicateConjunction(temp_predicates,
FeaturePredicateConjunction.OR);
}
else
{
new FeatureKeyQualifierPredicate(key_selector.getSelectedItem(),
qualifier_name,
search_text,
partial_match_checkbox.isSelected(),
ignore_case_checkbox.isSelected());
}
else
{
final String search_text = qualifier_text.getText().trim();
if(search_text.length() == 0)
{
new FeatureKeyPredicate(key_selector.getSelectedItem());
}
else
{
if(match_any_word_checkbox.isSelected())
{
StringVector.getStrings(search_text, " ");
for(int i = 0 ; i < words.size() ; ++i)
{
final String this_word =(String)words.elementAt(i);
new FeatureKeyQualifierPredicate(key_selector.getSelectedItem(),
null, // match any qialifier
this_word,
partial_match_checkbox.isSelected(),
ignore_case_checkbox.isSelected());
temp_predicates.add(new_predicate);
new FeaturePredicateConjunction(temp_predicates,
FeaturePredicateConjunction.OR);
}
else
{
new FeatureKeyQualifierPredicate(key_selector.getSelectedItem(),
null, // match any qialifier
search_text,
partial_match_checkbox.isSelected(),
ignore_case_checkbox.isSelected());
if(by_motif_button.isSelected())
{
new AminoAcidSequence(motif_text.getText().trim());
new FeaturePatternPredicate(amino_acid_sequence);
}
else
FeaturePredicate less_than_bases_predicate = null;
if(less_than_bases_button.isSelected() &&
less_than_bases_text.getText().trim().length() > 0)
{
try
{
Integer.valueOf(less_than_bases_text.getText().trim()).intValue();
less_than_bases_predicate = new FeaturePredicate()
{
public boolean testPredicate(final Feature feature)
{
if(feature.getBaseCount() <= less_than_bases_int)
}
catch(NumberFormatException e)
{
new MessageDialog(this,
FeaturePredicate greater_than_bases_predicate = null;
if(greater_than_bases_button.isSelected() &&
greater_than_bases_text.getText().trim().length() > 0)
{
try
{
Integer.valueOf(greater_than_bases_text.getText().trim()).intValue();
greater_than_bases_predicate = new FeaturePredicate()
{
public boolean testPredicate(final Feature feature)
{
if(feature.getBaseCount() >= greater_than_bases_int)
}
catch(NumberFormatException e)
{
new MessageDialog(this,
"warning this is not a number: " +
greater_than_bases_text.getText());
FeaturePredicate less_than_exons_predicate = null;
if(less_than_exons_button.isSelected() &&
less_than_exons_text.getText().trim().length() > 0)
{
try
{
Integer.valueOf(less_than_exons_text.getText().trim()).intValue();
less_than_exons_predicate = new FeaturePredicate()
{
public boolean testPredicate(final Feature feature)
{
if(feature.getSegments().size() <= less_than_exons_int)
}
catch(NumberFormatException e)
{
new MessageDialog(this,
"warning this is not a number: " +
less_than_exons_text.getText());
FeaturePredicate greater_than_exons_predicate = null;
if(greater_than_exons_button.isSelected() &&
greater_than_exons_text.getText().trim().length() > 0)
{
try
{
Integer.valueOf(greater_than_exons_text.getText().trim()).intValue();
greater_than_exons_predicate = new FeaturePredicate()
{
public boolean testPredicate(final Feature feature)
{
if(feature.getSegments().size() >= greater_than_exons_int)
}
catch(NumberFormatException e)
{
new MessageDialog(this,
"warning this is not a number: " +
greater_than_exons_text.getText());
}
FeaturePredicate intron_pattern_predicate = null;
if(intron_pattern_button.isSelected())
intron_pattern_predicate = getIntronPredicate();
if(!by_key_button.isSelected() && !by_motif_button.isSelected())
{
predicate = new FeaturePredicate()
{
public boolean testPredicate(final Feature feature)
{
}
else
{
if(motif_predicate != null && key_and_qualifier_predicate != null)
{
new FeaturePredicateConjunction(key_and_qualifier_predicate,
motif_predicate,
FeaturePredicateConjunction.AND);
}
else
{
if(motif_predicate != null)
if(less_than_bases_predicate != null)
{
new FeaturePredicateConjunction(predicate,
less_than_bases_predicate,
FeaturePredicateConjunction.AND);
if(greater_than_bases_predicate != null)
{
new FeaturePredicateConjunction(predicate,
greater_than_bases_predicate,
FeaturePredicateConjunction.AND);
}
if(less_than_exons_predicate != null)
{
new FeaturePredicateConjunction(predicate,
less_than_exons_predicate,
FeaturePredicateConjunction.AND);
if(greater_than_exons_predicate != null)
{
new FeaturePredicateConjunction(predicate,
greater_than_exons_predicate,
FeaturePredicateConjunction.AND);
if(intron_pattern_predicate !=null)
{
predicate =
new FeaturePredicateConjunction(predicate,
intron_pattern_predicate,
FeaturePredicateConjunction.AND);
}
final FeatureEnumeration test_enumerator = entry_group.features();
final FeatureVector return_features = new FeatureVector();
while(test_enumerator.hasMoreFeatures())
{
final Feature this_feature = test_enumerator.nextFeature();
if(predicate.testPredicate(this_feature))
{
if(this_feature.isForwardFeature())
{
if(forward_strand_checkbox.isSelected())
return_features.add(this_feature);
}
else
{
if(reverse_strand_checkbox.isSelected())
return_features.add(this_feature);
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
protected static FeaturePredicate getIntronPredicate()
{
return new FeaturePredicate()
{
public boolean testPredicate(final Feature feature)
{
if(feature.getSegments().size() < 2)
return false;
final Location location = feature.getLocation().copy();
final RangeVector ranges = location.getRanges();
Collections.sort(ranges, new Comparator<Range>(){
public int compare(final Range r1, final Range r2)
{
return r1.getStart()-r2.getStart();
}
});
final Strand strand = feature.getStrand();
for(int i = 0; i < ranges.size () -1; ++i)
{
final int end_of_range_1 =
((Range)ranges.elementAt(i)).getEnd ();
final int start_of_range_2 =
((Range)ranges.elementAt(i+1)).getStart ();
// ignore - the exons overlap so there is no room for an intron
if(end_of_range_1 > start_of_range_2)
continue;
try
{
Range feature_range = new Range(end_of_range_1 + 1,
start_of_range_2 - 1);
final char bases[];
if(location.isComplement())
{
final char tmp_bases[] = strand.getRawSubSequenceC(feature_range);
final char tmp2_bases[] = new char[feature_range.getCount()];
for(int j=0; j<tmp2_bases.length; j++)
tmp2_bases[j] = tmp_bases[j];
bases = Bases.reverseComplement( tmp2_bases );
}
else
bases = strand.getRawSubSequenceC(feature_range);
if(bases.length < 3)
return true;