[Biojava-l] svg file generator
Hanning Ni
HanningN@doubletwist.com
Fri, 4 Jan 2002 09:55:17 -0800
This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.
------_=_NextPart_000_01C19548.F7C4FA70
Content-Type: text/plain;
charset="iso-8859-1"
I wrote some code to generate svg file from biojava sequence object several
month ago. I wish sometimes it will be useful.
Happy New Year
Hanning Ni
------_=_NextPart_000_01C19548.F7C4FA70
Content-Type: application/octet-stream;
name="SVGGenerator.java"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="SVGGenerator.java"
/*
* BioJava development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public Licence. This should
* be distributed with the code. If you do not have a copy,
* see:
*
* http://www.gnu.org/copyleft/lesser.html
*
* Copyright for this code is held jointly by the individual
* authors. These should be listed in @author doc comments.
*
* For more information on the BioJava project and its aims,
* or to join the biojava-l mailing list, visit the home page
* at:
*
* http://www.biojava.org/
*
*/
package org.biojava.bio.seq.io;
import java.io.*;
import java.util.*;
import org.biojava.bio.*;
import org.biojava.bio.seq.*;
import org.biojava.bio.seq.impl.*;
import org.biojava.bio.seq.io.*;
import org.biojava.bio.seq.genomic.*;
import org.biojava.bio.symbol.*;
import org.biojava.utils.*;
/**
* Translate Sequence object into sgv file
* @author Hanning Ni Doubletwist Inc, 2001-7-22
*/
public class SVGGenerator
{
/** source code version */
public static final String VER_ID =3D "$Header: $";
// this part should not be hard coded. will change later ...
public static final String CONTAMINATION =3D "contamination" ;
public static final String REPEAT=3D "repeat" ;
public static final int LABEL_LENGTH =3D 50 ;
public static final int WINDOW_WIDTH =3D 800 + LABEL_LENGTH;
public static final int WINDOW_HEIGHT =3D 600 ;
/** The XML writer */
protected PrintWriter mOut;
//define some global variable, some of them will be removed in the =
future
/** the height of each row */
protected int row_height =3D 0 ;
/** ratio of sequence length to WINDOW_WIDTH */
protected float ratio =3D 0.0f ;
/** contains label of sequence_map --> the maximum rows this =
label will occupy */
Hashtable table_forward ;
Hashtable table_complement ;
/** contain label of sequence_map --> the i-th of row in view */
Hashtable forward_row_loc ;
Hashtable complement_row_loc ;
/** contains all the components which will be draw in the final =
view */
Vector comp2svg ;
private int mId ;
private int total_length ;
private int total_rows ;
/**
* Constructor.
* @param out Writer for the XML output.
*/
public SVGGenerator(Writer out)
{
mOut =3D new PrintWriter(out);
mId =3D 0 ;
total_length =3D 0 ;
total_rows =3D 0 ;
table_forward =3D new Hashtable() ;
table_complement =3D new Hashtable();
forward_row_loc =3D new Hashtable() ;
complement_row_loc =3D new Hashtable();
comp2svg =3D new Vector() ;
}
public void close()
{
mOut.close() ;
}
/**
* Write XML version information and DOCTYPE tag for svg
*/
private void
writeDocumentType()
{
mOut.println("<?xml version=3D\"1.0\" =
encoding=3D\"iso-8859-1\"?>");
mOut.println("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20000303 =
Stylable//EN\" =
\"http://www.w3.org/TR/2000/03/WD-SVG-20000303/DTD/svg-20000303-stylable=
.dtd\">");
}
/**
* Write object.
*
*/
public void
write(Sequence seq) throws IOException
{
try
{
init( seq ) ;
writeDocumentType() ;
writeHeader( );
writeBody( );
writeFooter();
}
catch(Exception e)
{
throw new IOException(e.getMessage() );
}finally{
clear() ;
}
}
private void init(Sequence sequence) throws Exception
{
//get the total dna length
total_length =3D getLength( sequence ) ;
//get the total rows which will show in the view
total_rows =3D getRows( sequence ) ;
row_height =3D WINDOW_HEIGHT / total_rows ;
ratio =3D WINDOW_WIDTH / (float) total_length ;
}
private void clear()
{
mId =3D 0 ;
total_length =3D 0 ;
total_rows =3D 0 ;
row_height =3D 0 ;
ratio =3D 0.0f ;
table_forward.clear();
table_complement.clear();
forward_row_loc.clear();
complement_row_loc.clear();
comp2svg.clear() ;
}
/** dump the svg header which defines how to draw each type of gene =
component */
private void
writeHeader( ) throws Exception
{
//currently we use one basepair <-> one pixel
// LABEL_LENGTH =3D (total_length / 5 > 50 ? total_length /5 : =
50 ) ;
int x =3D WINDOW_WIDTH ; // total_length + LABEL_LENGTH ;
//total_row does not include dna row yet
int y =3D WINDOW_HEIGHT ; // ( total_rows + 1 ) * ROW_HEIGHT ;
String head =3D"<svg onload=3D\"init(evt)\" =
xml:space=3D\"preserve\" width=3D\"100%\" heigth=3D\"100%\" =
viewBox=3D\"0 0 " + x + " " + y + "\">" ;
mOut.println( head );
//javascript here
mOut.println("<script language=3D\"Javascript\">") ;
mOut.println("<![CDATA[") ;
mOut.println(" var svgdoc; ") ;
mOut.println(" function init(event) { ") ;
mOut.println(" svgdoc =3D =
event.getTarget().getOwnerDocument(); " ) ;
mOut.println(" } " ) ;
mOut.println(" function showproperty( evt ) { " ) ;
mOut.println(" var svgstyle; " ) ;
mOut.println(" var svgobj ; " ) ;
mOut.println(" svgobj =3D svgdoc.getElementById( =
evt.getTarget().getId() + \"t\"); " );
mOut.println(" svgstyle =3D svgobj.getStyle(); ") ;
mOut.println(" svgstyle.setProperty('visibility', 'visible'); ") ;
mOut.println( "}" ) ;
mOut.println(" function hideproperty( evt ) { " ) ;
mOut.println(" var svgobj; " ) ;
mOut.println(" var svgstyle; " ) ;
mOut.println(" svgobj =3D =
svgdoc.getElementById(evt.getTarget().getId() + \"t\"); " ) ;
mOut.println(" svgstyle =3D svgobj.getStyle(); ") ;
mOut.println(" svgstyle.setProperty('visibility', 'hidden'); ") ;
mOut.println( "}" ) ;
mOut.println(" ]]> </script> " ) ;
mOut.println("<defs>") ;
mOut.println("<g id=3D\"genebox\"> ") ;
mOut.println("<rect x=3D\"0\" y=3D\"0\" width=3D\"10\" =
height=3D\"30\" style=3D\"fill: rgb(240,65,25);") ;
mOut.println(" fill-opacity: 0.5; \" />") ;
mOut.println("</g>") ;
mOut.println("<g id=3D\"exonbox\">") ;
mOut.println("<rect x=3D\"0\" y=3D\"0\" width=3D\"10\" =
height=3D\"20\" style=3D\"fill: rgb(240,240,25);") ;
mOut.println(" fill-opacity: 0.5;\" />") ;
mOut.println("</g>") ;
mOut.println("<g id=3D\"intronbox\">") ;
mOut.println("<rect x=3D\"0\" y=3D\"2.5\" width=3D\"10\" =
height=3D\"10\" style=3D\"fill: rgb(240,65,250);") ;
mOut.println(" fill-opacity: 0.5;\" />") ;
mOut.println("</g>") ;
mOut.println("<g id=3D\"region\">") ;
mOut.println("<rect x=3D\"0\" y=3D\"2.5\" width=3D\"10\" =
height=3D\"10\" style=3D\"fill: rgb(240,265,250);") ;
mOut.println(" fill-opacity: 0.5;\" />") ;
mOut.println("</g>") ;
mOut.println("<g id=3D\"intronbox\">") ;
mOut.println("<rect x=3D\"0\" y=3D\"2.5\" width=3D\"10\" =
height=3D\"10\" style=3D\"fill: rgb(240,65,250);") ;
mOut.println(" fill-opacity: 0.5; \" />") ;
mOut.println("</g>") ;
mOut.println("<g id=3D\"forwardfragment\">") ;
mOut.println("<rect x=3D\"0\" y=3D\"10\" width=3D\"10\" =
height=3D\"10\" style=3D\"fill: rgb(240,65,250);") ;
mOut.println(" fill-opacity: 0.5; \" />") ;
mOut.println(" <rect x=3D\"7.5\" y=3D\"10\" width=3D\"2.5\" =
height=3D\"10\" style=3D\"fill: rgb(240,240,240); " ) ;
mOut.println(" fill-opacity: 0.8;\" />") ;
mOut.println("</g>") ;
mOut.println("<g id=3D\"reversefragment\">") ;
mOut.println("<rect x=3D\"0\" y=3D\"10\" width=3D\"10\" =
height=3D\"30\" style=3D\"fill: rgb(240,65,25);") ;
mOut.println(" fill-opacity: 0.5; \" />") ;
mOut.println(" <rect x=3D\"2.5\" y=3D\"10\" width=3D\"2.5\" =
height=3D\"10\" style=3D\"fill: rgb(240,240,240); " ) ;
mOut.println(" fill-opacity: 0.8;\" />") ;
mOut.println("</g>") ;
mOut.println("<g id=3D\"unorderedfragment\">") ;
mOut.println("<rect x=3D\"0\" y=3D\"0\" width=3D\"10\" =
height=3D\"30\" style=3D\"fill: rgb(240,65,250);") ;
mOut.println(" fill-opacity: 0.5; \" />") ;
mOut.println("</g>") ;
mOut.println("</defs>") ;
}
/**
* first write all the labels of sequence_map
* then write all the gene component
* pre-condition : after call write_header, which all ready store =
all the infomation into Vector
*/
private void writeBody()
{
//write all the labels
write_label() ;
//write all the compoments
for(int i =3D 0 ; i < comp2svg.size() ; i ++ )
{
//can be dna fragment, gene , exon and intron
Component comp =3D (Component) comp2svg.elementAt(i) ;
//add the length of label
comp.start_x =3D Math.round( comp.start_x * ratio ) + =
LABEL_LENGTH ;
//calculate the real start_y value , which need the =
information about algorihtm type and row
if( comp.isForward && forward_row_loc.get( comp.row_type =
) !=3D null )
comp.start_y =3D ( (Integer) forward_row_loc.get( =
comp.row_type )).intValue() * row_height ;
else if(( ! comp.isForward ) && complement_row_loc.get( =
comp.row_type ) !=3D null )
comp.start_y =3D ( (Integer) complement_row_loc.get( =
comp.row_type )).intValue() * row_height ;
//now , dumping
// System.out.println("writing : " + comp.start_y + " : " + =
comp.row_type );
mOut.println( comp.toString() ) ;
}
}
/**
* first calculate all the location of sequence_map in the final =
view
* then dumping
*/
private void write_label()
{
// calculate all the location of sequence_map
cal_row_loc() ;
//dumping the labels in the forward strand, include DNA
Enumeration nums =3D forward_row_loc.keys() ;
while( nums.hasMoreElements() )
{
String this_label =3D (String) nums.nextElement() ;
int row =3D ( (Integer) forward_row_loc.get( this_label =
)).intValue() ;
print_text( this_label, 0 , row * row_height ) ;
}
//dumping the labels in the complement strand
nums =3D complement_row_loc.keys() ;
while( nums.hasMoreElements() )
{
String this_label =3D (String) nums.nextElement() ;
int row =3D ( (Integer) complement_row_loc.get( this_label =
)).intValue() ;
print_text( this_label, 0 , row * row_height ) ;
}
}
/****
* dumping the svg text
**/
private void print_text(String label, int x, int y)
{
int id =3D mId ++ ;
mOut.println( "<g font-family=3D\"Verdana\"> "
+ "<text id=3D\"" + id + "t" + "\" x=3D\"" + x + =
"\" y=3D\"" + y + "\" font-size=3D\"50\" fill =3D \"rgb(255,164,0)\" =
textLength =3D \"" + LABEL_LENGTH + "\">"
+ label
+ "</text>"
+ "</g>" );
}
/**
* calculate the real location of each sequence_map
* must put nr pro into the out most level
* and it is nice to put comtamination /repeat /genbank near dna =
sequence
*/
private void cal_row_loc()
{
//write label first (dont care )
int row =3D 0 ;
Object o ;
String contamination =3D"";
String repeat =3D "" ;
Enumeration nums =3D table_forward.keys() ;
while( nums.hasMoreElements() )
{
String this_label =3D (String) nums.nextElement() ;
if( this_label.indexOf( CONTAMINATION ) !=3D -1 )
{
contamination =3D this_label ;
continue ;
}
if( this_label.indexOf( REPEAT ) !=3D -1 )
{
repeat =3D this_label ;
continue ;
}
o =3D table_forward.get( this_label ) ;
forward_row_loc.put( this_label , new Integer( row ) ) ; =
//System.out.println(this_label + " : " + row ) ;
row +=3D ((Integer)o ).intValue() ;
}
//put contamination , repeat near dna
o =3D table_forward.get( contamination ) ;
if( o !=3D null )
{
forward_row_loc.put( contamination , new Integer( row ) ) =
;
row +=3D ((Integer)o).intValue() ;
}
o =3D table_forward.get( repeat ) ;
if( o !=3D null )
{
forward_row_loc.put( repeat , new Integer( row ) ) ; =
//System.out.println(REPEAT + " : " + row ) ;
row +=3D ((Integer)o).intValue() ;
}
//put dna into forward_row_loc for easy use.
forward_row_loc.put( "DNA", new Integer( row ) ) ; =
//System.out.println("DNA" + " : " + row ) ;
row ++ ;
//put complement label in the reverse order
o =3D table_complement.get( repeat ) ;
if( o !=3D null )
{
complement_row_loc.put( repeat , new Integer( row ) ) ; =
//System.out.println(REPEAT + " -: " + row ) ;
row +=3D ((Integer)o).intValue() ;
}
o =3D table_complement.get( contamination ) ;
if( o !=3D null )
{
complement_row_loc.put( contamination , new Integer( row ) =
) ;
row +=3D ((Integer)o).intValue() ;
}
nums =3D table_complement.keys() ;
while( nums.hasMoreElements() )
{
String this_label =3D (String) nums.nextElement() ;
if( this_label.indexOf( CONTAMINATION ) !=3D -1 || =
this_label.indexOf( REPEAT ) !=3D -1 )
{
continue ;
}
o =3D table_complement.get( this_label ) ;
complement_row_loc.put( this_label , new Integer( row ) ) ; =
//System.out.println(this_label + " -: " + row ) ;
row +=3D ((Integer)o ).intValue() ;
}
}
/**
* Write </sciobj>
*/
private void
writeFooter()
{
mOut.println("</svg>");
}
/**
* get the total length of dna sequence
*
*/
private int getLength(Sequence seq) throws Exception
{
return seq.length() ;
}
/**
* actaully two function together, it is not good for design, just =
for performance
* . (1) get the maximun rows each feature
* (2) put every gene component into list, for easy dumping
*/
private int getRows(Sequence seq) throws Exception
{
int rows =3D 0 ;
int length =3D 0 ;
/** store seq_map --> max rows **/
if( seq instanceof SimpleAssembly)
cal_sequence_row((SimpleAssembly) seq, length) ;
else
cal_sequence_row( seq , length) ;
//sum up the total rows
Enumeration nums =3D table_forward.keys() ;
while( nums.hasMoreElements() )
{
rows +=3D ((Integer)table_forward.get( nums.nextElement() ) =
).intValue() ;
}
nums =3D table_complement.keys() ;
while( nums.hasMoreElements() )
{
rows +=3D ((Integer)table_complement.get( =
nums.nextElement() ) ).intValue() ;
}
return rows ;
}
private void cal_sequence_row(Sequence seq, int length)
{
String prop =3D annot2string( seq.getAnnotation() ) ;
int x =3D 0 ;
int y =3D -1 ;
int len =3D seq.length() ;
String row_type =3D "DNA" ;
comp2svg.addElement( new Component(x, y, len, =
Component.FORWARD, prop, row_type, true, mId++) );
cal_feature_row( seq, length) ;
}
private void cal_sequence_row(SimpleAssembly seq , int length)
{
for(Iterator i =3D seq.features(); i.hasNext(); )
{
ComponentFeature child =3D (ComponentFeature) i.next();
int type =3D (( child.getStrand() =3D=3D =
StrandedFeature.NEGATIVE ) ? Component.REVERSE : Component.FORWARD );
String prop =3D annot2string( child.getAnnotation() ) ;
int x =3D child.getLocation().getMin() ;
int y =3D -1 ;
int len =3D seq.length() ;
String row_type =3D "DNA" ;
comp2svg.addElement( new Component(x, y, len, type, prop, =
row_type, true, mId++) );
cal_feature_row( child.getComponentSequence(), x ) ;
}
}
/**
* return : feature source -> list of features
*/
private HashMap clusterSubFeatures(FeatureHolder feature)
{
HashMap maps =3D new HashMap();
for(Iterator i =3D feature.features(); i.hasNext(); )
{
Feature child =3D (Feature) i.next();
String source =3D child.getType() ;
if( source =3D=3D null )
source =3D child.getSource() ;
if( source =3D=3D null )
source =3D "UNKOWN" ;
// System.out.println( source ) ;
Object o =3D maps.get( source ) ;
if( o =3D=3D null )
{
List list =3D new ArrayList() ;
list.add (child ) ;
maps.put( source, list ) ;
}else{
((List)o).add( child ) ;
}
}
// System.out.println( maps.size());
return maps;
}
/**
* (1) calculate the rows for contig
* (2) put info of each genecomponent inot Component
*/
private void cal_feature_row(Sequence seq, int length)
{
//decide strandness
HashMap maps =3D clusterSubFeatures((FeatureHolder)seq ) ;
for(Iterator it =3D maps.keySet().iterator(); it.hasNext();)
{
String label =3D (String) it.next() ;
cal_map_row( (List) maps.get( label ), label , length) ;
}
}
/**
* (1) calculate the max row in this fragment
* (2) store all the gene /exon of this map type in this fragment
*/
private void cal_map_row(List list, String label , int length)
{
//first store sequence_map label at this level
Vector regions_for =3D new Vector() ;
Vector regions_com =3D new Vector() ;
Iterator fs =3D list.iterator() ;
while(fs.hasNext())
{
Feature f =3D (Feature) fs.next();
cal_map_row(f, regions_for, regions_com, label, length) ;
}
// get the maximun rows in this fragment
int rows =3D cal_row_each_map_in_fragment( regions_for ) ;
Object o =3D table_forward.get( label ) ;
//store the max value for all BAC
if( rows >=3D1 )
{
if( o !=3D null )
{
if( ((Integer)o).intValue() < rows )
table_forward.put( label, new Integer( rows )) ;
}
else
table_forward.put( label, new Integer( rows ) );
}
// get the maximun rows in this fragment
rows =3D cal_row_each_map_in_fragment( regions_com ) ;
o =3D table_complement.get( label ) ;
//store the max value for all BAC
if( rows >=3D1 )
{
if( o !=3D null )
{
if( ((Integer)o).intValue() < rows )
table_complement.put( label, new Integer( rows )) ;
}
else
table_complement.put( label, new Integer( rows ) );
}
}
private void cal_map_row(Feature f, Vector region_for, Vector =
region_com, String label, int length)
{
Location loc =3D f.getLocation() ;
boolean forward =3D true ;
if( f instanceof StrandedFeature )
{
forward =3D (((StrandedFeature)f).getStrand() !=3D =
StrandedFeature.NEGATIVE ) ;
}
if( forward )
region_for.addElement( loc );
else
region_com.addElement( loc );
dump_result( f, length, label , forward) ;
for(Iterator it =3D f.features(); it.hasNext() ;)
{
cal_map_row( (Feature) it.next() , region_for, region_com, =
label, length) ;
}
}
/**
* store the info of comp_result into Component
* currently I only choose some info. for final show
*/
private void dump_result(Feature f, int length, String row_type, =
boolean forward)
{
String prop =3D annot2string( f.getAnnotation() ) ;
int start =3D f.getLocation().getMin() ;
int end =3D f.getLocation().getMax() ;
String type =3D f.getType() ;
int x =3D length + start;
int y =3D -1 ;
int len =3D end - start + 1 ;
int comtype =3D Component.EXON ; //default value
if( type.indexOf("gene") !=3D -1 || f instanceof Gene )
comtype =3D Component.GROUP ;
else if( type.indexOf("exon") !=3D -1 || f instanceof Exon)
comtype =3D Component.EXON ;
else if( type.indexOf("intron") !=3D -1 )
comtype =3D Component.INTRON ;
comp2svg.addElement( new Component(x, y, len, comtype, prop, =
row_type, forward, mId++) );
}
/** cal the #rows this set of regions will occupy */
private int cal_row_each_map_in_fragment( Vector regions )
{
if( regions.size() <2 )
return regions.size() ;
return cal_bins_for_one_vector( regions ).size() ;
}
/** regions must have at least two elements
* algorithm :
*<p> init : create one bin, and put first region into it.
*<p> for each region aa in regions-A
*<p> for each bin bb in bins-B
*<p> check if aa can put into bb withou overlap any =
element
*<p> if can, put aa into bb and break ;
*<p> if can not, create new bin bb-new ,and put bb-new into =
bins-B
*<p> put aa into =
bb-new
*<p> finally, the number of bins in bins-B is the number of rows
*<p> need.
*<p>
**/
private Vector cal_bins_for_one_vector(Vector regions )
{//System.out.println("entering bin : " + regions.size());
//init
Vector bins =3D new Vector() ;
Vector one_bin =3D new Vector() ;
one_bin.addElement( regions.elementAt(0) ) ;
bins.addElement( one_bin ) ;
//loop...
try{
for(int i =3D 1 ; i < regions.size() ; i++)
{
Location region =3D (Location) regions.elementAt(i) ;
int start =3D region.getMin() ;
int end =3D region.getMax() ;
boolean found_bin =3D false ;
//check the already created bin
for( int j =3D 0 ; j < bins.size() ; j++)
{
Vector this_bin =3D (Vector) bins.elementAt( j ) ;
//check if region can be put into this bin
boolean overlap =3D false ;
for(int k =3D 0 ; k < this_bin.size() ; k++)
{
Location this_region =3D (Location) =
this_bin.elementAt( k ) ;
int ov =3D Math.min(end, this_region.getMax() ) - =
Math.max(start, this_region.getMin() );
if( ov > 0 ) //can not fit into this bin
{
overlap =3D true ;
break ;
}
}
if( ! overlap ) //can fit into this bin
{
this_bin.addElement( region ) ;
found_bin =3D true ;
break ;
}
}
if( ! found_bin ) //can not found a suitable bin, so =
create a new one..
{
Vector new_bin =3D new Vector() ;
new_bin.addElement( region ) ;
bins.addElement( one_bin ) ;
}
}
}catch(Exception e ){}
// System.out.println("leaving bin : " + bins.size());
return bins ;
}
private String annot2string(Annotation seqAn)
{
StringBuffer sb =3D new StringBuffer() ;
for (Iterator i =3D seqAn.keys().iterator(); i.hasNext(); )
{
Object key =3D i.next();
Object value =3D seqAn.getProperty(key);
sb.append( key + " : " + filter( value.toString() ) + "\n") =
;
}
return sb.toString();
}
private String filter( String target)
{
StringBuffer sb =3D new StringBuffer( ) ;
for(int i =3D 0 ; i < target.length() ; i++)
{
char chr =3D target.charAt(i) ;
if( chr =3D=3D '>' )
sb.append(">") ;
else if ( chr =3D=3D '<' )
sb.append("<") ;
else if ( chr =3D=3D '&' )
sb.append("&") ;
else
sb.append(chr);
}
return sb.toString() ;
}
/**
* private class used for store location info for each gene =
components
* for performance issue, I use all the public variables
*/
class Component
{
//start point in view
public int start_x ;
//start point in view
public int start_y ;
//should be label of sequence_map
public String row_type ;
//should be type of genecomponent
public int type ;
public int id;
public static final int GROUP =3D 0 ;
public static final int EXON =3D 1 ;
public static final int INTRON =3D 2 ;
public static final int FORWARD =3D 3;
public static final int REVERSE =3D 4 ;
public static final int UNORDER =3D 5 ;
//should be the length of this component
public int length ;
//currently used for view to show the info
public String property ;
//which side
public boolean isForward ;
//construct..
public Component(int x, int y, int len, int type, String prop , =
String row, boolean forward, int id){
start_x =3D x;
start_y =3D y ;
length =3D len ;
this.type =3D type ;
property =3D prop ;
row_type =3D row ;
isForward =3D forward;
this.id =3D id ;
}
//help method to get the type of svg element
private String getSVGType(int type)
{
String s =3D " ";
switch(type)
{
case GROUP : s =3D "genebox"; break;
case EXON : s =3D "exonbox"; break;
case INTRON : s =3D "intronbox"; break;
case FORWARD : s =3D "forwardfragment"; break;
case REVERSE : s =3D "reversefragment"; break;
case UNORDER : s =3D "unorderedfragment"; break;
}
return s;
}
public String toString()
{
String svgtype =3D getSVGType( type ) ;
int len =3D ( length / 10 > 1 ? length/10 : 1 ) ;
StringBuffer prop =3D new StringBuffer("") ;
int index1 , index2;
String breakline =3D System.getProperty( "line.separator" ) ;
index1 =3D index2 =3D 0 ;
if( property !=3D null )
if( property.indexOf("\n") =3D=3D -1 )
prop.append( property ) ;
else
while( (index1 =3D property.indexOf("\n", index2) ) !=3D =
-1 )
{
prop.append( "<tspan x=3D\"" + start_x + "\" =
dy=3D\"1em\">" + property.substring(index2, index1) + "</tspan>\n" ) ;
index2 =3D index1 + 1 ;
}
return " <g transform=3D\"translate(" + start_x + ", " + =
start_y + " ) scale(" + len + ",1)\">"
+ "<use id=3D\"" + id + "\" xlink:href=3D\"#" + =
svgtype +
"\" onmouseover=3D\"showproperty(evt)\" =
onmouseout=3D\"hideproperty(evt)\" />\""
+ "</g>"
+ "<g>"
+ "<text id=3D\"" + id + "t" + "\" x=3D\"" + start_x=
+ "\" y=3D\"" + start_y + "\" font-size=3D\"45\" fill =3D \"blue\" =
visibility=3D\"hidden\">"
+ prop.toString()
+ "</text>"
+ "</g>" ;
}
}
}
------_=_NextPart_000_01C19548.F7C4FA70--