{
private static final String NAME = "Secondary Structure Similarity";
+ //label in secondary structure annotation data model from 3d structures
private static final String SS_ANNOTATION_LABEL = "Secondary Structure";
+ //label in secondary structure annotation data model from JPred
private static final String SS_ANNOTATION_FROM_JPRED_LABEL = "jnetpred";
+ //label in secondary structure annotation data model from JPred
+ private static final String JPRED_WEBSERVICE = "JPred";
+
private String description;
- //maximum distance score is defined as 2 as the possible number of unique ss is 2.
+ //maximum distance score is defined as 2 as the possible number of unique secondary structure is 2.
private static final int MAX_SCORE = 2;
- //minimum distance score is defined as 2 as the possible number of unique ss is 2.
+ //minimum distance score is defined as 2 as the possible number of unique secondary structure is 2.
private static final int MIN_SCORE = 0;
+ //character used to represent coil in secondary structure
private static final char COIL = 'C';
FeatureRenderer fr;
+
+ /*
+ * Annotation label for available sources of secondary structure
+ */
+ private static final String[] SS_ANNOTATION_LABELS = {
+ SS_ANNOTATION_LABEL,
+ SS_ANNOTATION_FROM_JPRED_LABEL
+ };
/**
* Constructor
int noseqs = seqs.length; //no of sequences
int cpwidth = 0; // = seqData.getWidth();
double[][] distances = new double[noseqs][noseqs]; //matrix to store distance score
-
+ //secondary structure source parameter selected by the user from the drop down.
+ String ssSource = params.getSecondaryStructureSource();
+
+ //defining the default value for secondary structure source as 3d structures
+ //or JPred if user selected JPred
+ String selectedSSSource = SS_ANNOTATION_LABEL;
+ if(ssSource.equals(JPRED_WEBSERVICE))
+ selectedSSSource = SS_ANNOTATION_FROM_JPRED_LABEL;
+
// need to get real position for view position
int[] viscont = seqData.getVisibleContigs();
- Map<String, HashSet<String>> calcIdMapInAlignmentAnnotation = new HashMap<String,HashSet<String>>();
- AlignmentAnnotation[] alignAnnotList = fr.getViewport().getAlignment().getAlignmentAnnotation();
- if(alignAnnotList.length > 0) {
-
+ /*
+ * Add secondary structure annotations that are added to the annotation track
+ * to the map
+ */
+ Map<String, HashSet<String>> ssAlignmentAnnotationForSequences
+ = new HashMap<String,HashSet<String>>();
+
+ AlignmentAnnotation[] alignAnnotList = fr.getViewport().getAlignment()
+ .getAlignmentAnnotation();
+
+ if(alignAnnotList.length > 0) {
for (AlignmentAnnotation aa: alignAnnotList) {
- if (SS_ANNOTATION_LABEL.equals(aa.label) || SS_ANNOTATION_FROM_JPRED_LABEL.equals(aa.label)) {
- calcIdMapInAlignmentAnnotation.computeIfAbsent(aa.getCalcId(), k -> new HashSet<>()).add(aa.description);
- }
-
+ if (selectedSSSource.equals(aa.label)) {
+ ssAlignmentAnnotationForSequences.computeIfAbsent(
+ aa.sequenceRef.getName(), k -> new HashSet<>())
+ .add(aa.description);
+ }
}
}
-
- Set<SeqCigar> seqsWithUndefinedSS = findSeqsWithUndefinedSS(seqs, calcIdMapInAlignmentAnnotation);
-
+ /*
+ * Get the set of sequences which are not considered for the calculation.
+ * Following sequences are added:
+ * 1. Sequences without a defined secondary structure from the selected
+ * source.
+ * 2. Sequences whose secondary structure annotations are not added to
+ * the annotation track
+ */
+ Set<SeqCigar> seqsWithUndefinedSS
+ = findSeqsWithUndefinedSS(seqs, ssAlignmentAnnotationForSequences);
/*
* scan each column, compute and add to each distance[i, j]
//secondary structure is fetched only if the current column is not
//gap for the sequence
- if(!gap1 && !undefinedSS1) {
- secondaryStructure1.addAll(
- findSSAnnotationForGivenSeqAndCol(seqs[i], cpos));
+ if(!gap1 && !undefinedSS1) {
+ secondaryStructure1.addAll(
+ findSSAnnotationForGivenSeqAndCol(seqs[i], cpos));
}
- if(!gap2 && !undefinedSS2) {
- secondaryStructure2.addAll(
- findSSAnnotationForGivenSeqAndCol(seqs[j], cpos));
+ if(!gap2 && !undefinedSS2) {
+ secondaryStructure2.addAll(
+ findSSAnnotationForGivenSeqAndCol(seqs[j], cpos));
}
/*
if ((!gap1 && !gap2) || params.includeGaps())
{
int seqDistance = SetUtils.countDisjunction(
- secondaryStructure1, secondaryStructure2);
+ secondaryStructure1, secondaryStructure2);
distances[i][j] += seqDistance;
}
}
/*
* position is not a gap
*/
- seqsWithoutGapAtCol.add(seq);
+ seqsWithoutGapAtCol.add(seq);
}
}
return seqsWithoutGapAtCol;
}
+
/**
- * Builds and returns a set containing sequences (SeqCigar) which have
- * no secondary structures defined
- *
+ * Builds and returns a set containing sequences (SeqCigar) which
+ * are not considered for the similarity calculation.
+ * Following sequences are added:
+ * 1. Sequences without a defined secondary structure from the selected
+ * source.
+ * 2. Sequences whose secondary structure annotations are not added to
+ * the annotation track
* @param seqs
- * (0..)
+ * @param ssAlignmentAnnotationForSequences
* @return
*/
- private static final String[] SS_ANNOTATION_LABELS = {
- SS_ANNOTATION_LABEL,
- SS_ANNOTATION_FROM_JPRED_LABEL
- };
-
- protected Set<SeqCigar> findSeqsWithUndefinedSS(SeqCigar[] seqs, Map<String, HashSet<String>> calcIdMapInAlignmentAnnotation) {
+ protected Set<SeqCigar> findSeqsWithUndefinedSS(SeqCigar[] seqs,
+ Map<String, HashSet<String>> ssAlignmentAnnotationForSequences) {
Set<SeqCigar> seqsWithUndefinedSS = new HashSet<>();
for (SeqCigar seq : seqs) {
- if (isSSUndefinedOrNotAdded(seq, calcIdMapInAlignmentAnnotation)) {
+ if (isSSUndefinedOrNotAdded(seq, ssAlignmentAnnotationForSequences)) {
seqsWithUndefinedSS.add(seq);
}
}
return seqsWithUndefinedSS;
}
-
- private boolean isSSUndefinedOrNotAdded(SeqCigar seq, Map<String, HashSet<String>> calcIdMapInAlignmentAnnotation) {
+
+
+ /**
+ * Returns true if a sequence (SeqCigar) should not be
+ * considered for the similarity calculation.
+ * Following conditions are checked:
+ * 1. Sequence without a defined secondary structure from the selected
+ * source.
+ * 2. Sequences whose secondary structure annotations are not added to
+ * the annotation track
+ * @param seq
+ * @param ssAlignmentAnnotationForSequences
+ * @return
+ */
+ private boolean isSSUndefinedOrNotAdded(SeqCigar seq,
+ Map<String, HashSet<String>> ssAlignmentAnnotationForSequences) {
for (String label : SS_ANNOTATION_LABELS) {
AlignmentAnnotation[] annotations = seq.getRefSeq().getAnnotation(label);
if (annotations != null) {
for (AlignmentAnnotation annotation : annotations) {
- HashSet<String> descriptionList = calcIdMapInAlignmentAnnotation.get(annotation.getCalcId());
- if (descriptionList.contains(annotation.description)) {
- // Secondary structure annotation is present and added to the track, no need to add seq
+ HashSet<String> descriptionSet = ssAlignmentAnnotationForSequences
+ .get(annotation.sequenceRef.getName());
+ if (descriptionSet != null)
+ if (descriptionSet.contains(annotation.description)) {
+ // Secondary structure annotation is present and
+ //added to the track, no need to add seq
return false;
}
}
* @return
*/
private Set<String> findSSAnnotationForGivenSeqAndCol(
- SeqCigar seq, int columnPosition)
+ SeqCigar seq, int columnPosition)
{
- Set<String> secondaryStructure = new HashSet<String>();
+ Set<String> secondaryStructure = new HashSet<String>();
- char ss;
-
- //fetch the position in sequence for the column and finds the
- //corresponding secondary structure annotation
- //TO DO - consider based on priority
- int seqPosition = seq.findPosition(columnPosition);
- AlignmentAnnotation[] aa = seq.getRefSeq().getAnnotation(SS_ANNOTATION_LABEL);
-
- if(aa == null) {
- aa = seq.getRefSeq().getAnnotation(SS_ANNOTATION_FROM_JPRED_LABEL);
- }
-
- if (aa != null) {
- if (aa[0].getAnnotationForPosition(seqPosition) != null) {
- Annotation a = aa[0].getAnnotationForPosition(seqPosition);
- ss = a.secondaryStructure;
-
- //There is no representation for coil and it can be either ' ' or null.
- if (ss == ' ' || ss == '-') {
- ss = COIL;
- }
- }
- else {
- ss = COIL;
- }
- secondaryStructure.add(String.valueOf(ss));
- }
-
- return secondaryStructure;
+ char ss;
+
+ //fetch the position in sequence for the column and finds the
+ //corresponding secondary structure annotation
+ //TO DO - consider based on priority
+ int seqPosition = seq.findPosition(columnPosition);
+ AlignmentAnnotation[] aa = seq.getRefSeq().getAnnotation(SS_ANNOTATION_LABEL);
+
+ if(aa == null) {
+ aa = seq.getRefSeq().getAnnotation(SS_ANNOTATION_FROM_JPRED_LABEL);
+ }
+
+ if (aa != null) {
+ if (aa[0].getAnnotationForPosition(seqPosition) != null) {
+ Annotation a = aa[0].getAnnotationForPosition(seqPosition);
+ ss = a.secondaryStructure;
+
+ //There is no representation for coil and it can be either ' ' or null.
+ if (ss == ' ' || ss == '-') {
+ ss = COIL;
+ }
+ }
+ else {
+ ss = COIL;
+ }
+ secondaryStructure.add(String.valueOf(ss));
+ }
+
+ return secondaryStructure;
}
@Override
public String toString()
{
- return "Score between sequences based on hamming distance between binary vectors marking secondary structure displayed at each column";
+ return "Score between sequences based on hamming distance between binary "
+ + "vectors marking secondary structure displayed at each column";
}
}
\ No newline at end of file
import jalview.bin.Cache;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
import jalview.util.MessageManager;
/**
private static final int MIN_TREE_SELECTION = 3;
private static final int MIN_PCA_SELECTION = 4;
+
+ private static final String SS_ANNOTATION_LABEL = "Secondary Structure";
+
+ private static final String SS_ANNOTATION_FROM_JPRED_LABEL = "jnetpred";
AlignFrame af;
JRadioButton averageDistance;
JComboBox<String> modelNames;
+
+ JComboBox<String> ssSourceDropdown;
JButton calculate;
pca.addActionListener(calcChanged);
neighbourJoining.addActionListener(calcChanged);
averageDistance.addActionListener(calcChanged);
+
+
+ //to do
+ ssSourceDropdown = buildSSSourcesOptionsList();
+ ssSourceDropdown.setVisible(false); // Initially hide the dropdown
/*
* score models drop-down - with added tooltips!
*/
modelNames = buildModelOptionsList();
+ // Step 3: Show or Hide Dropdown Based on Selection
+ modelNames.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String selectedModel = modelNames.getSelectedItem().toString();
+ if (selectedModel.equals("Secondary Structure Similarity")) {
+ ssSourceDropdown.setVisible(true);
+ } else {
+ ssSourceDropdown.setVisible(false);
+ }
+ }
+ });
JPanel scoreModelPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
scoreModelPanel.setOpaque(false);
scoreModelPanel.add(modelNames);
-
+ scoreModelPanel.add(ssSourceDropdown);
+
/*
* score model parameters
*/
paramsPanel.add(matchGaps);
paramsPanel.add(includeGappedColumns);
paramsPanel.add(shorterSequence);
-
+
/*
* OK / Cancel buttons
*/
}
this.add(actionPanel, BorderLayout.SOUTH);
- int width = 350;
+ int width = 365;
int height = includeParams ? 420 : 240;
setMinimumSize(new Dimension(325, height - 10));
return scoreModelsCombo;
}
+
+ private JComboBox<String> buildSSSourcesOptionsList()
+ {
+ final JComboBox<String> comboBox = new JComboBox<>();
+ Object curSel = comboBox.getSelectedItem();
+ DefaultComboBoxModel<String> sourcesModel = new DefaultComboBoxModel<>();
+
+ List<String> ssSources = getApplicableSecondaryStructureSources();
+
+ boolean selectedIsPresent = false;
+ for (String source : ssSources)
+ {
+ if (curSel != null && source.equals(curSel))
+ {
+ selectedIsPresent = true;
+ curSel = source;
+ }
+ sourcesModel.addElement(source);
+
+ }
+
+ if (selectedIsPresent)
+ {
+ sourcesModel.setSelectedItem(curSel);
+ }
+ comboBox.setModel(sourcesModel);
+
+ return comboBox;
+ }
+
+
private void updateScoreModels(JComboBox<String> comboBox,
List<String> toolTips)
{
return filtered;
}
+
+ protected List<String> getApplicableSecondaryStructureSources()
+ {
+ List<String> ssSources = new ArrayList<>();
+
+ AlignmentAnnotation[] annotations = af.getViewport().getAlignment().getAlignmentAnnotation();
+ boolean has3DStructure = false, hasJPred = false;
+ if(annotations.length > 0) {
+
+ for (AlignmentAnnotation annotation : annotations) {
+ has3DStructure |= SS_ANNOTATION_LABEL.equals(annotation.label);
+ hasJPred |= SS_ANNOTATION_FROM_JPRED_LABEL.equals(annotation.label);
+
+ if (has3DStructure && hasJPred)
+ break;
+ }
+ }
+ if(has3DStructure)
+ ssSources.add("3D Structures");
+ if(hasJPred)
+ ssSources.add("JPred");
+
+ return ssSources;
+ }
+
/**
* Open and calculate the selected tree or PCA on 'OK'
*/
{
boolean doPCA = pca.isSelected();
String modelName = modelNames.getSelectedItem().toString();
- SimilarityParamsI params = getSimilarityParameters(doPCA);
-
+ String ssSource = ssSourceDropdown.getSelectedItem().toString();
+ SimilarityParams params = getSimilarityParameters(doPCA);
+ if(ssSource.length()>0)
+ params.setSecondaryStructureSource(ssSource);
if (doPCA)
{
openPcaPanel(modelName, params);
* @param doPCA
* @return
*/
- protected SimilarityParamsI getSimilarityParameters(boolean doPCA)
+ protected SimilarityParams getSimilarityParameters(boolean doPCA)
{
// commented out: parameter choices read from gui widgets
// SimilarityParamsI params = new SimilarityParams(