[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 &lt;/sciobj&gt;
     */
    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("&gt;") ;
            else if ( chr =3D=3D '<' )
                sb.append("&lt;") ;
            else if ( chr =3D=3D '&' )
                sb.append("&amp;") ;
            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--