*/
public class StockholmFile extends AlignFile
{
+ private static final String ANNOTATION = "annotation";
+
+ private static final char UNDERSCORE = '_';
+
private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "(");
private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")");
+ // private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "(");
+ // private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")");
+
public static final Regex DETECT_BRACKETS = new Regex(
"(<|>|\\[|\\]|\\(|\\)|\\{|\\})");
+ // WUSS extended symbols. Avoid ambiguity with protein SS annotations by using NOT_RNASS first.
+ public static final String RNASS_BRACKETS = "<>[](){}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+ // use the following regex to decide an annotations (whole) line is NOT an RNA
+ // SS (it contains only E,H,e,h and other non-brace/non-alpha chars)
+ private static final Regex NOT_RNASS = new Regex(
+ "^[^<>[\\](){}A-DF-Za-df-z]*$");
+
StringBuffer out; // output buffer
- AlignmentI al;
+ private AlignmentI al;
public StockholmFile()
{
}
/**
- * Creates a new StockholmFile object for output.
+ * Creates a new StockholmFile object for output
*/
public StockholmFile(AlignmentI al)
{
String version;
// String id;
Hashtable seqAnn = new Hashtable(); // Sequence related annotations
- LinkedHashMap<String, String> seqs = new LinkedHashMap<String, String>();
+ LinkedHashMap<String, String> seqs = new LinkedHashMap<>();
Regex p, r, rend, s, x;
// Temporary line for processing RNA annotation
// String RNAannot = "";
// logger.debug("Stockholm version: " + version);
}
- // We define some Regexes here that will be used regularily later
+ // We define some Regexes here that will be used regularly later
rend = new Regex("^\\s*\\/\\/"); // Find the end of an alignment
p = new Regex("(\\S+)\\/(\\d+)\\-(\\d+)"); // split sequence id in
// id/from/to
while (j.hasMoreElements())
{
String desc = j.nextElement().toString();
- if ("annotations".equals(desc) && annotsAdded)
+ if (ANNOTATION.equals(desc) && annotsAdded)
{
// don't add features if we already added an annotation row
continue;
int new_pos = posmap[k]; // look up nearest seqeunce
// position to this column
SequenceFeature feat = new SequenceFeature(type, desc,
- new_pos, new_pos, 0f, null);
+ new_pos, new_pos, null);
seqO.addSequenceFeature(feat);
}
if (features.containsKey(this.id2type(type)))
{
// logger.debug("Found content for " + this.id2type(type));
- content = (Hashtable) features.get(this.id2type(type));
+ content = (Hashtable) features
+ .get(this.id2type(type));
}
else
{
// logger.debug("Creating new content holder for " +
// this.id2type(type));
content = new Hashtable();
- features.put(this.id2type(type), content);
+ features.put(id2type(type), content);
}
- String ns = (String) content.get("annotation");
+ String ns = (String) content.get(ANNOTATION);
if (ns == null)
{
}
// finally, append the annotation line
ns += seq;
- content.put("annotation", ns);
+ content.put(ANNOTATION, ns);
// // end of wrapped annotation block.
// // Now a new row is created with the current set of data
strucAnn = new Hashtable();
}
- Vector<AlignmentAnnotation> newStruc = new Vector<AlignmentAnnotation>();
+ Vector<AlignmentAnnotation> newStruc = new Vector<>();
parseAnnotationRow(newStruc, type, ns);
for (AlignmentAnnotation alan : newStruc)
{
private void guessDatabaseFor(Sequence seqO, String dbr, String dbsource)
{
DBRefEntry dbrf = null;
- List<DBRefEntry> dbrs = new ArrayList<DBRefEntry>();
+ List<DBRefEntry> dbrs = new ArrayList<>();
String seqdb = "Unknown", sdbac = "" + dbr;
int st = -1, en = -1, p;
if ((st = sdbac.indexOf("/")) > -1)
Vector<AlignmentAnnotation> annotation, String label,
String annots)
{
- String convert1, convert2 = null;
-
- // convert1 = OPEN_PAREN.replaceAll(annots);
- // convert2 = CLOSE_PAREN.replaceAll(convert1);
+ String convert1, convert2 = null;
+ // String convert1 = OPEN_PAREN.replaceAll(annots);
+ // String convert2 = CLOSE_PAREN.replaceAll(convert1);
// annots = convert2;
String type = label;
}
boolean ss = false, posterior = false;
type = id2type(type);
+
+ boolean isrnass = false;
+
if (type.equalsIgnoreCase("secondary structure"))
{
ss = true;
+ isrnass = !NOT_RNASS.search(annots); // sorry about the double negative
+ // here (it's easier for dealing with
+ // other non-alpha-non-brace chars)
}
if (type.equalsIgnoreCase("posterior probability"))
{
for (int i = 0; i < annots.length(); i++)
{
String pos = annots.substring(i, i + 1);
+ if (UNDERSCORE == pos.charAt(0))
+ {
+ pos = " ";
+ }
Annotation ann;
ann = new Annotation(pos, "", ' ', 0f); // 0f is 'valid' null - will not
// be written out
{
// if (" .-_".indexOf(pos) == -1)
{
- if (DETECT_BRACKETS.search(pos))
+ if (isrnass && RNASS_BRACKETS.indexOf(pos) >= 0)
{
ann.secondaryStructure = Rna.getRNASecStrucState(pos).charAt(0);
ann.displayCharacter = "" + pos.charAt(0);
while ((in < s.length) && (s[in] != null))
{
String tmp = printId(s[in], jvSuffix);
- if (s[in].getSequence().length > max)
- {
- max = s[in].getSequence().length;
- }
+ max = Math.max(max, s[in].getLength());
if (tmp.length() > maxid)
{
if (alAnot != null)
{
Annotation[] ann;
+
for (int j = 0; j < alAnot.length; j++)
{
-
- String key = type2id(alAnot[j].label);
- boolean isrna = alAnot[j].isValidStruc();
-
- if (isrna)
- {
- // hardwire to secondary structure if there is RNA secondary
- // structure on the annotation
- key = "SS";
- }
- if (key == null)
+ if (alAnot[j].annotations != null)
{
+ String key = type2id(alAnot[j].label);
+ boolean isrna = alAnot[j].isValidStruc();
- continue;
- }
+ if (isrna)
+ {
+ // hardwire to secondary structure if there is RNA secondary
+ // structure on the annotation
+ key = "SS";
+ }
+ if (key == null)
+ {
- // out.append("#=GR ");
- out.append(new Format("%-" + maxid + "s").form(
- "#=GR " + printId(s[i], jvSuffix) + " " + key + " "));
- ann = alAnot[j].annotations;
- String seq = "";
- for (int k = 0; k < ann.length; k++)
- {
- seq += outputCharacter(key, k, isrna, ann, s[i]);
+ continue;
+ }
+
+ // out.append("#=GR ");
+ out.append(new Format("%-" + maxid + "s").form(
+ "#=GR " + printId(s[i], jvSuffix) + " " + key + " "));
+ ann = alAnot[j].annotations;
+ String seq = "";
+ for (int k = 0; k < ann.length; k++)
+ {
+ seq += outputCharacter(key, k, isrna, ann, s[i]);
+ }
+ out.append(seq);
+ out.append(newline);
}
- out.append(seq);
- out.append(newline);
}
+
}
out.append(new Format("%-" + maxid + "s")
return out.toString();
}
+
/**
* add an annotation character to the output row
*
String ch = (annot == null)
? ((sequenceI == null) ? "-"
: Character.toString(sequenceI.getCharAt(k)))
- : annot.displayCharacter;
+ : (annot.displayCharacter == null
+ ? String.valueOf(annot.secondaryStructure)
+ : annot.displayCharacter);
+ if (ch == null)
+ {
+ ch = " ";
+ }
if (key != null && key.equals("SS"))
{
+ char ssannotchar = ' ';
+ boolean charset = false;
if (annot == null)
{
// sensible gap character
- return ' ';
+ ssannotchar = ' ';
+ charset = true;
}
else
{
// valid secondary structure AND no alternative label (e.g. ' B')
if (annot.secondaryStructure > ' ' && ch.length() < 2)
{
- return annot.secondaryStructure;
+ ssannotchar = annot.secondaryStructure;
+ charset = true;
}
}
+ if (charset)
+ {
+ return (ssannotchar == ' ' && isrna) ? '.' : ssannotchar;
+ }
}
if (ch.length() == 0)
{
seq = ch.charAt(1);
}
- return seq;
+
+ return (seq == ' ' && key != null && key.equals("SS") && isrna) ? '.'
+ : seq;
}
+ /**
+ * make a friendly ID string.
+ *
+ * @param dataName
+ * @return truncated dataName to after last '/'
+ */
+ private String safeName(String dataName)
+ {
+ int b = 0;
+ while ((b = dataName.indexOf("/")) > -1 && b < dataName.length())
+ {
+ dataName = dataName.substring(b + 1).trim();
+
+ }
+ int e = (dataName.length() - dataName.indexOf(".")) + 1;
+ dataName = dataName.substring(1, e).trim();
+ return dataName;
+ }
+
+
public String print()
{
out = new StringBuffer();
}
}
-
+
protected static String id2type(String id)
{
if (typeIds.containsKey(id))
"Warning : Unknown Stockholm annotation type: " + type);
return key;
}
-
- /**
- * make a friendly ID string.
- *
- * @param dataName
- * @return truncated dataName to after last '/'
- */
- private String safeName(String dataName)
- {
- int b = 0;
- while ((b = dataName.indexOf("/")) > -1 && b < dataName.length())
- {
- dataName = dataName.substring(b + 1).trim();
-
- }
- int e = (dataName.length() - dataName.indexOf(".")) + 1;
- dataName = dataName.substring(1, e).trim();
- return dataName;
- }
}