package jalview.io;
import jalview.analysis.AlignmentUtils;
+import jalview.analysis.Finder;
import jalview.analysis.SequenceIdMatcher;
import jalview.api.AlignViewportI;
import jalview.api.FeatureColourI;
import jalview.api.FeatureRenderer;
import jalview.api.FeaturesSourceI;
+import jalview.api.FinderI;
import jalview.datamodel.AlignedCodonFrame;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.MappedFeatures;
+import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SequenceDummy;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
private static final String ENDFILTERS = "ENDFILTERS";
+ private static final String STARTMOTIFS = "STARTMOTIFS";
+
+ private static final String ENDMOTIFS = "ENDMOTIFS";
+
private static final String ID_NOT_SPECIFIED = "ID_NOT_SPECIFIED";
private static final String NOTE = "Note";
while ((line = nextLine()) != null)
{
+ line = line.trim();
// skip comments/process pragmas
if (line.length() == 0 || line.startsWith("#"))
{
if (gffColumns.length > 0 && gffColumns.length < 4)
{
/*
- * if 2 or 3 tokens, we anticipate either 'startgroup', 'endgroup' or
- * a feature type colour specification
+ * if 2 or 3 tokens, we anticipate one of either
+ * STARTGROUP ENDGROUP STARTFILTERS STARTMOTIFS
+ * or a feature type and colour specification
*/
String ft = gffColumns[0];
if (ft.equalsIgnoreCase(STARTFILTERS))
parseFilters(filters);
continue;
}
+ if (ft.equalsIgnoreCase(STARTMOTIFS))
+ {
+ parseMotifs(align, featureGroup);
+ continue;
+ }
if (ft.equalsIgnoreCase(STARTGROUP))
{
featureGroup = gffColumns[1];
}
else if (ft.equalsIgnoreCase(ENDGROUP))
{
- // We should check whether this is the current group,
- // but at present there's no way of showing more than 1 group
featureGroup = null;
}
else
}
/*
- * if not a comment, GFF pragma, startgroup, endgroup or feature
- * colour specification, that just leaves a feature details line
+ * if not handled above, that just leaves a feature details line
* in either Jalview or GFF format
*/
if (gffVersion == 0)
}
/**
+ * Reads lines up to and including the next ENDMOTIFS, and processes each one
+ * by
+ * <ul>
+ * <li>searching the alignment for the supplied motif (first column)</li>
+ * <li>creating features for matches, with feature type, description and
+ * (optionally) score given in the remaining columns</li>
+ * </ul>
+ *
+ * @param alignment
+ * @param featureGroup
+ * @throws IOException
+ */
+ protected void parseMotifs(AlignmentI alignment, String featureGroup)
+ throws IOException
+ {
+ FinderI finder = new Finder(alignment);
+ String line;
+ while ((line = nextLine()) != null)
+ {
+ if (line.toUpperCase().startsWith(ENDMOTIFS))
+ {
+ return;
+ }
+ String[] tokens = line.split(TAB_REGEX);
+ if (tokens.length != 3 && tokens.length != 4)
+ {
+ System.err.println(String.format("Invalid token count %d for %s",
+ tokens.length, line));
+ }
+ String motif = tokens[0];
+ String featureType = tokens[1];
+ String description = tokens[2];
+ float score = 0f;
+ if (tokens.length > 3)
+ {
+ try
+ {
+ score = Float.valueOf(tokens[3]);
+ } catch (NumberFormatException e)
+ {
+ System.err.println("Invalid score in " + line);
+ }
+ }
+ finder.findAll(motif, true, false);
+ List<SearchResultMatchI> matches = finder.getSearchResults()
+ .getResults();
+ for (SearchResultMatchI match : matches)
+ {
+ SequenceFeature sf = new SequenceFeature(featureType, description,
+ match.getStart(), match.getEnd(), score, featureGroup);
+ match.getSequence().addSequenceFeature(sf);
+ }
+ }
+ }
+
+ /**
* Reads input lines from STARTFILTERS to ENDFILTERS and adds a feature type
* filter to the map for each line parsed. After exit from this method,
* nextLine() should return the line after ENDFILTERS (or we are already at
String[] tokens = line.split(TAB_REGEX);
if (tokens.length != 2)
{
- System.err.println(String.format("Invalid token count %d for %d",
+ System.err.println(String.format("Invalid token count %d for %s",
tokens.length, line));
}
else