X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fio%2FStockholmFile.java;h=344c4e1e940f9c295bf35b4f8ef6f34a26b179b6;hb=3609d4b908fa64cab35f2348401baab3347188fc;hp=606540f5b4196d2eac2beab31f685da364d9239b;hpb=bab4b08733a9543bdce5c0b9d1c32ca7d18ad9e3;p=jalview.git diff --git a/src/jalview/io/StockholmFile.java b/src/jalview/io/StockholmFile.java index 606540f..344c4e1 100644 --- a/src/jalview/io/StockholmFile.java +++ b/src/jalview/io/StockholmFile.java @@ -28,12 +28,14 @@ import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.Annotation; import jalview.datamodel.DBRefEntry; +import jalview.datamodel.DBRefSource; import jalview.datamodel.Mapping; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.schemes.ResidueProperties; import jalview.util.Comparison; +import jalview.util.DBRefUtils; import jalview.util.Format; import jalview.util.MessageManager; @@ -76,10 +78,15 @@ 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( "(<|>|\\[|\\]|\\(|\\)|\\{|\\})"); @@ -93,14 +100,14 @@ public class StockholmFile extends AlignFile 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) { @@ -205,7 +212,7 @@ public class StockholmFile extends AlignFile String version; // String id; Hashtable seqAnn = new Hashtable(); // Sequence related annotations - LinkedHashMap seqs = new LinkedHashMap(); + LinkedHashMap seqs = new LinkedHashMap<>(); Regex p, r, rend, s, x; // Temporary line for processing RNA annotation // String RNAannot = ""; @@ -227,7 +234,7 @@ public class StockholmFile extends AlignFile // 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 @@ -332,17 +339,14 @@ public class StockholmFile extends AlignFile if (accAnnotations != null && accAnnotations.containsKey("AC")) { - if (dbsource != null) + String dbr = (String) accAnnotations.get("AC"); + if (dbr != null) { - String dbr = (String) accAnnotations.get("AC"); - if (dbr != null) - { - // we could get very clever here - but for now - just try to - // guess accession type from source of alignment plus structure - // of accession - guessDatabaseFor(seqO, dbr, dbsource); - - } + // we could get very clever here - but for now - just try to + // guess accession type from type of sequence, source of alignment plus + // structure + // of accession + guessDatabaseFor(seqO, dbr, dbsource); } // else - do what ? add the data anyway and prompt the user to // specify what references these are ? @@ -527,6 +531,9 @@ public class StockholmFile extends AlignFile treeName = an.stringMatched(2); treeString = new StringBuffer(); } + // TODO: JAL-3532 - this is where GF comments and database references are lost + // suggest overriding this method for Stockholm files to catch and properly + // process CC, DR etc into multivalued properties setAlignmentProperty(an.stringMatched(1), an.stringMatched(2)); } } @@ -635,14 +642,15 @@ public class StockholmFile extends AlignFile 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); @@ -666,7 +674,7 @@ public class StockholmFile extends AlignFile strucAnn = new Hashtable(); } - Vector newStruc = new Vector(); + Vector newStruc = new Vector<>(); parseAnnotationRow(newStruc, type, ns); for (AlignmentAnnotation alan : newStruc) { @@ -718,7 +726,7 @@ public class StockholmFile extends AlignFile private void guessDatabaseFor(Sequence seqO, String dbr, String dbsource) { DBRefEntry dbrf = null; - List dbrs = new ArrayList(); + List dbrs = new ArrayList<>(); String seqdb = "Unknown", sdbac = "" + dbr; int st = -1, en = -1, p; if ((st = sdbac.indexOf("/")) > -1) @@ -755,6 +763,12 @@ public class StockholmFile extends AlignFile st = -1; } } + if (dbsource == null) + { + // make up an origin based on whether the sequence looks like it is nucleotide + // or protein + dbsource = (seqO.isProtein()) ? "PFAM" : "RFAM"; + } if (dbsource.equals("PFAM")) { seqdb = "UNIPROT"; @@ -817,10 +831,9 @@ public class StockholmFile extends AlignFile Vector 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; @@ -834,6 +847,7 @@ public class StockholmFile extends AlignFile type = id2type(type); boolean isrnass = false; + if (type.equalsIgnoreCase("secondary structure")) { ss = true; @@ -850,6 +864,10 @@ public class StockholmFile extends AlignFile 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 @@ -930,6 +948,11 @@ public class StockholmFile extends AlignFile return annot; } + private String dbref_to_ac_record(DBRefEntry ref) + { + return ref.getSource().toString() + " ; " + + ref.getAccessionId().toString(); + } @Override public String print(SequenceI[] s, boolean jvSuffix) { @@ -942,8 +965,10 @@ public class StockholmFile extends AlignFile int maxid = 0; int in = 0; Hashtable dataRef = null; + boolean isAA = s[in].isProtein(); while ((in < s.length) && (s[in] != null)) { + String tmp = printId(s[in], jvSuffix); max = Math.max(max, s[in].getLength()); @@ -953,17 +978,33 @@ public class StockholmFile extends AlignFile } if (s[in].getDBRefs() != null) { - for (int idb = 0; idb < s[in].getDBRefs().length; idb++) + if (dataRef == null) + { + dataRef = new Hashtable(); + } + List primrefs = s[in].getPrimaryDBRefs(); + if (primrefs.size() >= 1) + { + dataRef.put(tmp, dbref_to_ac_record(primrefs.get(0))); + } + else { - if (dataRef == null) + for (int idb = 0; idb < s[in].getDBRefs().length; idb++) { - dataRef = new Hashtable(); + DBRefEntry dbref = s[in].getDBRefs()[idb]; + dataRef.put(tmp, dbref_to_ac_record(dbref)); + // if we put in a uniprot or EMBL record then we're done: + if (isAA && DBRefSource.UNIPROT + .equals(DBRefUtils.getCanonicalName(dbref.getSource()))) + { + break; + } + if (!isAA && DBRefSource.EMBL + .equals(DBRefUtils.getCanonicalName(dbref.getSource()))) + { + break; + } } - - String datAs1 = s[in].getDBRefs()[idb].getSource().toString() - + " ; " - + s[in].getDBRefs()[idb].getAccessionId().toString(); - dataRef.put(tmp, datAs1); } } in++; @@ -996,7 +1037,8 @@ public class StockholmFile extends AlignFile String type = (String) dataRef.remove(idd); out.append(new Format("%-" + (maxid - 2) + "s") .form("#=GS " + idd.toString() + " ")); - if (type.contains("PFAM") || type.contains("RFAM")) + if (isAA && type.contains("UNIPROT") + || (!isAA && type.contains("EMBL"))) { out.append(" AC " + type.substring(type.indexOf(";") + 1)); @@ -1016,36 +1058,40 @@ public class StockholmFile extends AlignFile 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") @@ -1109,6 +1155,7 @@ public class StockholmFile extends AlignFile return out.toString(); } + /** * add an annotation character to the output row * @@ -1127,7 +1174,13 @@ public class StockholmFile extends AlignFile 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 = ' '; @@ -1149,11 +1202,7 @@ public class StockholmFile extends AlignFile } if (charset) { - if (ssannotchar == ' ' && isrna) - { - ssannotchar = '.'; - } - return ssannotchar; + return (ssannotchar == ' ' && isrna) ? '.' : ssannotchar; } } @@ -1174,6 +1223,26 @@ public class StockholmFile extends AlignFile : 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(); @@ -1211,7 +1280,7 @@ public class StockholmFile extends AlignFile } } - + protected static String id2type(String id) { if (typeIds.containsKey(id)) @@ -1244,23 +1313,4 @@ public class StockholmFile extends AlignFile "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; - } }