2 VARNA is a tool for the automated drawing, visualization and annotation of the secondary structure of RNA, designed as a companion software for web servers and databases.
3 Copyright (C) 2008 Kevin Darty, Alain Denise and Yann Ponty.
4 electronic mail : Yann.Ponty@lri.fr
5 paper mail : LRI, bat 490 Universit� Paris-Sud 91405 Orsay Cedex France
7 This file is part of VARNA version 3.1.
8 VARNA version 3.1 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 VARNA version 3.1 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along with VARNA version 3.1.
16 If not, see http://www.gnu.org/licenses.
18 package fr.orsay.lri.varna.models.annotations;
20 import java.awt.Color;
22 import java.awt.geom.Point2D;
23 import java.io.Serializable;
24 import java.text.DecimalFormat;
25 import java.text.NumberFormat;
26 import java.util.ArrayList;
27 import java.util.Collections;
29 import javax.xml.transform.sax.TransformerHandler;
31 import org.xml.sax.SAXException;
32 import org.xml.sax.helpers.AttributesImpl;
34 import fr.orsay.lri.varna.models.rna.ModeleBase;
35 import fr.orsay.lri.varna.VARNAPanel;
36 import fr.orsay.lri.varna.models.VARNAConfigLoader;
37 import fr.orsay.lri.varna.models.rna.ModelBaseStyle;
38 import fr.orsay.lri.varna.models.rna.VARNAPoint;
39 import fr.orsay.lri.varna.utils.XMLUtils;
44 * The annotated text model
46 * @author Darty@lri.fr
49 public class TextAnnotation implements Serializable {
54 private static final long serialVersionUID = 465236085501860747L;
56 public enum AnchorType{
64 public static final String HEADER_TEXT = "TextAnnotation";
69 public static final Color DEFAULTCOLOR = Color.black;
73 public static final Font DEFAULTFONT = new Font("Arial", Font.PLAIN, 12);
76 private AnchorType _typeAnchor;
78 private double _angle;
79 private Object _anchor;
82 public static String XML_ELEMENT_NAME = "textAnnotation";
83 public static String XML_VAR_TYPE_NAME = "type";
84 public static String XML_VAR_COLOR_NAME = "color";
85 public static String XML_VAR_ANGLE_NAME = "angle";
86 public static String XML_VAR_TEXT_NAME = "text";
88 public void toXML(TransformerHandler hd) throws SAXException
90 AttributesImpl atts = new AttributesImpl();
91 atts.addAttribute("","",XML_VAR_TYPE_NAME,"CDATA",""+_typeAnchor);
92 atts.addAttribute("","",XML_VAR_COLOR_NAME,"CDATA",""+XMLUtils.toHTMLNotation(_color));
93 atts.addAttribute("","",XML_VAR_ANGLE_NAME,"CDATA",""+_angle);
94 hd.startElement("","",XML_ELEMENT_NAME,atts);
96 hd.startElement("","",XML_VAR_TEXT_NAME,atts);
97 XMLUtils.exportCDATAString(hd, _text);
98 hd.endElement("","",XML_VAR_TEXT_NAME);
102 ((VARNAPoint)_anchor).toXML(hd,"pos");
105 XMLUtils.toXML(hd, (ModeleBase)_anchor);
108 XMLUtils.toXML(hd, (ArrayList<ModeleBase>)_anchor);
111 XMLUtils.toXML(hd, (ArrayList<ModeleBase>)_anchor);
114 XMLUtils.toXML(hd, _font);
115 hd.endElement("","",XML_ELEMENT_NAME);
119 * creates an annoted text on a VARNAPanel with the specified text
121 * @param texte Textual content of the annotation
123 public TextAnnotation(String texte) {
125 _color = DEFAULTCOLOR;
131 * /** creates an annoted text on a VARNAPanel with the specified text and
138 public TextAnnotation(String texte, double x, double y) {
140 _anchor = new VARNAPoint(x, y);
141 _typeAnchor = AnchorType.POSITION;
145 * creates an annoted text on a VARNAPanel with the specified text fixed to
151 public TextAnnotation(String texte, ModeleBase mb) {
154 _typeAnchor = AnchorType.BASE;
158 * creates an annoted text on a VARNAPanel with the specified text fixed to
159 * a helix (if type is HELIX) or to a loop (if type is LOOP)
166 public TextAnnotation(String texte, ArrayList<ModeleBase> listeBase,
167 AnchorType type) throws Exception {
171 if (type == AnchorType.HELIX)
172 _typeAnchor = AnchorType.HELIX;
173 else if (type == AnchorType.LOOP)
174 _typeAnchor = AnchorType.LOOP;
176 throw new Exception("Bad argument");
180 * creates an annoted text from another one
182 * @param textAnnotation
184 public TextAnnotation(TextAnnotation textAnnotation) {
185 _anchor = textAnnotation.getAncrage();
186 _font = textAnnotation.getFont();
187 _text = textAnnotation.getTexte();
188 _typeAnchor = textAnnotation.getType();
195 public String getTexte() {
199 public void setText(String _texte) {
207 public Font getFont() {
211 public void setFont(Font _font) {
215 public Object getAncrage() {
219 public void setAncrage(ModeleBase mb) {
221 _typeAnchor = AnchorType.BASE;
224 public void setAncrage(double x, double y) {
225 _anchor = new VARNAPoint(x, y);
226 _typeAnchor = AnchorType.POSITION;
229 public void setAncrage(ArrayList<ModeleBase> list, AnchorType type)
232 if (type == AnchorType.HELIX)
233 _typeAnchor = AnchorType.HELIX;
234 else if (type == AnchorType.LOOP)
235 _typeAnchor = AnchorType.LOOP;
237 throw new Exception("Bad argument");
240 public AnchorType getType() {
244 public void setType(AnchorType t) {
249 public Color getColor() {
253 public void setColor(Color color) {
258 public String getHelixDescription()
260 ArrayList<ModeleBase> listeBase = ((ArrayList<ModeleBase>)_anchor);
261 int minA = Integer.MAX_VALUE,maxA = Integer.MIN_VALUE;
262 int minB = Integer.MAX_VALUE,maxB = Integer.MIN_VALUE;
263 for(ModeleBase mb : listeBase)
265 int i = mb.getBaseNumber();
266 if (mb.getElementStructure()>i)
268 minA = Math.min(minA, i);
269 maxA = Math.max(maxA, i);
273 minB = Math.min(minB, i);
274 maxB = Math.max(maxB, i);
277 return "["+minA+","+maxA+"] ["+minB+","+maxB+"]";
280 public String getLoopDescription()
282 ArrayList<ModeleBase> listeBase = ((ArrayList<ModeleBase>)_anchor);
283 int min = Integer.MAX_VALUE,max = Integer.MIN_VALUE;
284 for(ModeleBase mb : listeBase)
286 int i = mb.getBaseNumber();
287 min = Math.min(min, i);
288 max = Math.max(max, i);
290 return "["+min+","+max+"]";
293 public String toString() {
294 String tmp = "["+_text+"] ";
295 switch (_typeAnchor) {
297 NumberFormat formatter = new DecimalFormat(".00");
298 return tmp+" at ("+formatter.format(getCenterPosition().x)+","+formatter.format(getCenterPosition().y)+")";
300 return tmp+" on base "+((ModeleBase) _anchor).getBaseNumber();
302 return tmp+" on helix "+getHelixDescription();
304 return tmp+" on loop "+getLoopDescription();
312 * @return the text position center
314 public Point2D.Double getCenterPosition() {
315 switch (_typeAnchor) {
317 return ((VARNAPoint) _anchor).toPoint2D();
319 return ((ModeleBase) _anchor).getCoords();
321 return calculLoopHelix();
325 return new Point2D.Double(0., 0.);
329 private Point2D.Double calculLoop() {
330 ArrayList<ModeleBase> liste = extractedArrayListModeleBaseFromAncrage();
331 double totalX = 0., totalY = 0.;
332 for (ModeleBase base : liste) {
333 totalX += base.getCoords().x;
334 totalY += base.getCoords().y;
336 return new Point2D.Double(totalX / liste.size(), totalY / liste.size());
339 private Point2D.Double calculLoopHelix() {
340 ArrayList<ModeleBase> liste = extractedArrayListModeleBaseFromAncrage();
341 Collections.sort(liste);
342 double totalX = 0., totalY = 0.;
344 for (int i=0;i<liste.size(); i++) {
345 ModeleBase base =liste.get(i);
346 if ((i>0 && (i<liste.size()-1)) || ((liste.size()/2)%2==0))
348 totalX += base.getCoords().x;
349 totalY += base.getCoords().y;
353 return new Point2D.Double(totalX / num, totalY / num);
357 private ArrayList<ModeleBase> extractedArrayListModeleBaseFromAncrage() {
358 return (ArrayList<ModeleBase>) _anchor;
362 * clone a TextAnnotation
364 public TextAnnotation clone() {
365 TextAnnotation textAnnot = null;
367 switch (_typeAnchor) {
369 textAnnot = new TextAnnotation(_text, (ModeleBase) _anchor);
372 textAnnot = new TextAnnotation(_text,
373 ((VARNAPoint) _anchor).x,
374 ((VARNAPoint) _anchor).y);
377 textAnnot = new TextAnnotation(_text,
378 extractedArrayListModeleBaseFromAncrage(), AnchorType.LOOP);
381 textAnnot = new TextAnnotation(_text,
382 extractedArrayListModeleBaseFromAncrage(), AnchorType.HELIX);
387 } catch (Exception e) {
390 textAnnot.setFont(_font);
391 textAnnot.setColor(_color);
397 * copy a textAnnotation
399 * @param textAnnotation
401 public void copy(TextAnnotation textAnnotation) {
402 _anchor = textAnnotation.getAncrage();
403 _font = textAnnotation.getFont();
404 _text = textAnnotation.getTexte();
405 _typeAnchor = textAnnotation.getType();
406 _color = textAnnotation.getColor();
407 _angle = textAnnotation.getAngleInDegres();
413 * @return the angle in degrees
415 public double getAngleInDegres() {
416 // if (_typeAncrage == TextAnnotation.HELIX)
417 // _angle = calculAngleDegres();
423 * @return the angle in radians
425 public double getAngleInRadians() {
426 return (getAngleInDegres() * Math.PI) / 180.;
429 public void setAngleInDegres(double _angle) {
430 this._angle = _angle;
433 public void setAngleInRadians(double _angle) {
434 this._angle = _angle * 180 / Math.PI;
438 public static TextAnnotation parse(String thisAnn, VARNAPanel vp)
440 String[] data = thisAnn.split(":");
446 TextAnnotation.AnchorType type = TextAnnotation.AnchorType.LOOP;
447 Font font = TextAnnotation.DEFAULTFONT;
448 Color color = TextAnnotation.DEFAULTCOLOR;
449 TextAnnotation ann = null;
451 if (data.length == 2) {
453 String[] data2 = data[1].split(",");
454 for (int j = 0; j < data2.length; j++) {
455 String opt = data2[j];
456 String[] data3 = opt.split("=");
457 if (data3.length == 2) {
458 String name = data3[0].toLowerCase();
459 String value = data3[1];
460 if (name.equals("type")) {
461 if (value.toUpperCase().equals("H")) {
462 type = TextAnnotation.AnchorType.HELIX;
463 } else if (value.toUpperCase().equals("L")) {
464 type = TextAnnotation.AnchorType.LOOP;
465 } else if (value.toUpperCase().equals("P")) {
466 type = TextAnnotation.AnchorType.POSITION;
467 } else if (value.toUpperCase().equals("B")) {
468 type = TextAnnotation.AnchorType.BASE;
470 } else if (name.equals("x")) {
471 x = Integer.parseInt(value);
472 } else if (name.equals("y")) {
473 y = Integer.parseInt(value);
474 } else if (name.equals("anchor")) {
475 anchor = Integer.parseInt(value);
476 } else if (name.equals("size")) {
477 font = font.deriveFont((float) Integer
479 } else if (name.equals("color")) {
480 color = VARNAConfigLoader.getSafeColor(value, color);
486 if ((x != -1) && (y != -1)) {
487 Point2D.Double p = vp
488 .panelToLogicPoint(new Point2D.Double(x, y));
489 ann = new TextAnnotation(text, p.x, p.y);
494 int index = vp.getRNA().getIndexFromBaseNumber(
496 ModeleBase mb = vp.getRNA().get_listeBases()
498 ann = new TextAnnotation(text, mb);
503 ArrayList<ModeleBase> mbl = new ArrayList<ModeleBase>();
504 int index = vp.getRNA().getIndexFromBaseNumber(
506 ArrayList<Integer> il = vp.getRNA()
509 mbl.add(vp.getRNA().get_listeBases().get(k));
511 ann = new TextAnnotation(text, mbl, type);
516 ArrayList<ModeleBase> mbl = new ArrayList<ModeleBase>();
517 int index = vp.getRNA().getIndexFromBaseNumber(
519 ArrayList<Integer> il = vp.getRNA().findLoop(index);
521 mbl.add(vp.getRNA().get_listeBases().get(k));
523 ann = new TextAnnotation(text, mbl, type);
532 } catch (Exception e) {
533 System.err.println("Apply Annotations: " + e.toString());