diff --git a/.classpath b/.classpath
index 6cb6c677295e1216745131319e1ae767d6ec0707..a071b60b897152574377095ebcbba10e4c73a6e3 100644
--- a/.classpath
+++ b/.classpath
@@ -17,5 +17,11 @@
 	<classpathentry kind="lib" path="lib/picard/picard.jar"/>
 	<classpathentry kind="lib" path="lib/picard/sam.jar"/>
 	<classpathentry kind="lib" path="lib/commons-net-2.2.jar"/>
+	<classpathentry kind="lib" path="lib/batik/batik-awt-util.jar"/>
+	<classpathentry kind="lib" path="lib/batik/batik-dom.jar"/>
+	<classpathentry kind="lib" path="lib/batik/batik-ext.jar"/>
+	<classpathentry kind="lib" path="lib/batik/batik-svggen.jar"/>
+	<classpathentry kind="lib" path="lib/batik/batik-util.jar"/>
+	<classpathentry kind="lib" path="lib/batik/batik-xml.jar"/>
 	<classpathentry kind="output" path="ant-build/classes/main"/>
 </classpath>
diff --git a/ChangeLog b/ChangeLog
index fbadef0ebfb378428aa21c873d7ee1b2038f9b80..7ed00133084c4621843b5c9698d3d2c987357053 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,16 @@
 Version XX
+	Add SVG (scalable vector graphics) support for Artemis, ACT and DNAPlotter.
+	
+	Add support for indexed user graphs using tabix. For example file.plot is a tab
+	delimited file with column 1 containing the sequence name and column 2 the
+	positions:
+	(grep ^"#" file.plot; grep -v ^"#" file.plot | sort -k1,1 -k2,2n) | bgzip > sorted.plot.gz ;
+	tabix -s 1 -b 2 -e 2 sorted.plot.gz
+	
+	Option added to show or hide the average line in the graphs.
+	
+	BAM coverage heatmap view added.
+
 	Add Rfam sequence search from the RUN menu.
 	
 	Base similarity graph for each VCF added to the VCF view.
@@ -13,7 +25,7 @@ Version XX
 	
 	Coverage plots from read alignments (BAM) can be plotted by their strand.
 
-	Addition of a Project File Manager for grouping files together for
+	Addition of a Project File Manager used to group files together for
 	launching in Artemis. When a project has been added or updated the details 
 	are saved at the end of each session in '.artemis.project.properties' 
 	in the user's home directory. 
diff --git a/Makefile b/Makefile
index 2b20f14ece3af9b84a4e24312cf1947a80b95f5e..ed4aa75a3222ede16e40a62782898bcc73ef2423 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ SHELL=/bin/sh
 
 JAVAC := javac -source 1.5 -target 1.5 $(OPT_FLAGS) $(EXTRA_FLAGS)
 
-REAL_CLASSPATH := CLASSPATH=lib/biojava.jar:lib/jemAlign.jar:lib/j2ssh/j2ssh-core.jar:lib/ibatis/ibatis-2.3.4.726.jar:lib/ibatis/log4j-1.2.14.jar:lib/postgresql-8.4-701.jdbc3.jar:lib/picard/picard.jar:lib/picard/sam.jar:lib/commons-net-2.2.jar:.
+REAL_CLASSPATH := CLASSPATH=lib/biojava.jar:lib/jemAlign.jar:lib/j2ssh/j2ssh-core.jar:lib/ibatis/ibatis-2.3.4.726.jar:lib/ibatis/log4j-1.2.14.jar:lib/postgresql-8.4-701.jdbc3.jar:lib/picard/picard.jar:lib/picard/sam.jar:lib/commons-net-2.2.jar:lib/batik/batik-awt-util.jar:lib/batik/batik-dom.jar:lib/batik/batik-ext.jar:lib/batik/batik-svggen.jar:lib/batik/batik-util.jar:lib/batik/batik-xml.jar:.
 
 NAMES:= \
 	uk/ac/sanger/artemis/OptionChangeListener \
diff --git a/act b/act
index f7aa1fae3f11804ae4620735b055c2a48bd6347f..4200521ecdb9b2301b3e989c86fcdd295cd31de7 100755
--- a/act
+++ b/act
@@ -31,6 +31,9 @@ ACT_HOME=`dirname "$PRG"`/.
 
 CLASSPATH=$ACT_HOME:$ACT_HOME/lib/JacORB.jar:$ACT_HOME/lib/jemAlign.jar:$ACT_HOME/lib/jakarta-regexp-1.2.jar:$ACT_HOME/lib/macos.jar:$ACT_HOME/lib/chado-14-interface.jar:$ACT_HOME/lib/postgresql-8.4-701.jdbc3.jar:$CLASSPATH
 
+# batik jars
+CLASSPATH=$CLASSPATH:$ACT_HOME/lib/batik/batik-awt-util.jar:$ACT_HOME/lib/batik/batik-dom.jar:$ACT_HOME/lib/batik/batik-ext.jar:$ACT_HOME/lib/batik/batik-svggen.jar:$ACT_HOME/lib/batik/batik-util.jar:$ACT_HOME/lib/batik/batik-xml.jar
+
 # j2ssh jars
 CLASSPATH=$CLASSPATH:$ACT_HOME/lib/j2ssh/commons-logging.jar:$ACT_HOME/lib/j2ssh/j2ssh-core.jar:$ACT_HOME/lib/j2ssh/
 
diff --git a/art b/art
index 16cf2c2afe8c6c6159ad4871913c25d0eb8c6f4d..16f98d7ddb46a161f3f00f1be7a09da05bfbf2f5 100755
--- a/art
+++ b/art
@@ -6,8 +6,6 @@
 # necessary a symbolic link can be made to this script from
 # /usr/local/bin/ or elsewhere. 
 
-# $Header: //tmp/pathsoft/artemis/art,v 1.26 2009-09-21 15:45:47 tjc Exp $
-
 # resolve links - $0 may be a link
 PRG=$0
 progname=`basename $0`
@@ -30,6 +28,9 @@ LIBDIR=/nfs/pathsoft/prod/javalibs
 
 CLASSPATH=$ARTEMIS_HOME:$ARTEMIS_HOME/lib/biojava.jar:$ARTEMIS_HOME/lib/jemAlign.jar:$ARTEMIS_HOME/lib/jakarta-regexp-1.2.jar:$ARTEMIS_HOME/lib/macos.jar:$ARTEMIS_HOME/lib/postgresql-8.4-701.jdbc3.jar:$CLASSPATH
 
+# batik jars
+CLASSPATH=$CLASSPATH:$ARTEMIS_HOME/lib/batik/batik-awt-util.jar:$ARTEMIS_HOME/lib/batik/batik-dom.jar:$ARTEMIS_HOME/lib/batik/batik-ext.jar:$ARTEMIS_HOME/lib/batik/batik-svggen.jar:$ARTEMIS_HOME/lib/batik/batik-util.jar:$ARTEMIS_HOME/lib/batik/batik-xml.jar
+
 # j2ssh jars
 CLASSPATH=$CLASSPATH:$ARTEMIS_HOME/lib/j2ssh/commons-logging.jar:$ARTEMIS_HOME/lib/j2ssh/j2ssh-core.jar:$ARTEMIS_HOME/lib/j2ssh/
 
diff --git a/etc/log4j.properties b/etc/log4j.properties
index d714f791dc537de7e2620242fe4f862020053fe2..1fcb68fee4c8bd8d66b8299cda3a373952c85c67 100644
--- a/etc/log4j.properties
+++ b/etc/log4j.properties
@@ -37,6 +37,7 @@ log4j.logger.uk.ac.sanger.artemis.components.variant=DEBUG, R
 log4j.logger.uk.ac.sanger.artemis.io.ReadAndWriteEntry=DEBUG, R
 log4j.logger.uk.ac.sanger.artemis.io.GFFStreamFeature=DEBUG, R
 log4j.logger.uk.ac.sanger.artemis.util.FTPSeekableStream=DEBUG, R
+log4j.logger.uk.ac.sanger.artemis.plot.UserDataAlgorithm=DEBUG, R
 
 #log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG, stdout, R
 #log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG, stdout, R
diff --git a/etc/versions b/etc/versions
index 83ee417ea300c88422ad233affd7d903999c84d8..01440428135bbe52ccd3e3e46e320f373727852f 100644
--- a/etc/versions
+++ b/etc/versions
@@ -1,4 +1,4 @@
-Artemis Release 14.2.2
-ACT Release 11.2.2
-DNAPlotter Release 1.8
+Artemis Release 14.2.3
+ACT Release 11.2.3
+DNAPlotter Release 1.9
 BamView 1.2.6
diff --git a/lib/batik/batik-awt-util.jar b/lib/batik/batik-awt-util.jar
new file mode 100644
index 0000000000000000000000000000000000000000..f8d0d8d0aef4defbef79b77cf9ce3e960b24b39e
Binary files /dev/null and b/lib/batik/batik-awt-util.jar differ
diff --git a/lib/batik/batik-dom.jar b/lib/batik/batik-dom.jar
new file mode 100644
index 0000000000000000000000000000000000000000..dab1ab3ba9b27f82062d5d2e000972808f325555
Binary files /dev/null and b/lib/batik/batik-dom.jar differ
diff --git a/lib/batik/batik-ext.jar b/lib/batik/batik-ext.jar
new file mode 100644
index 0000000000000000000000000000000000000000..deaad0cf03a362f3854774104010db6997effb6f
Binary files /dev/null and b/lib/batik/batik-ext.jar differ
diff --git a/lib/batik/batik-svggen.jar b/lib/batik/batik-svggen.jar
new file mode 100644
index 0000000000000000000000000000000000000000..ede092150cd2f19af5d34ae902c3ef4819fbb283
Binary files /dev/null and b/lib/batik/batik-svggen.jar differ
diff --git a/lib/batik/batik-util.jar b/lib/batik/batik-util.jar
new file mode 100644
index 0000000000000000000000000000000000000000..6dd43a696abb84a074f99a45b22c650eb4d8b148
Binary files /dev/null and b/lib/batik/batik-util.jar differ
diff --git a/lib/batik/batik-xml.jar b/lib/batik/batik-xml.jar
new file mode 100644
index 0000000000000000000000000000000000000000..af2fbf6b06948405ff7c30e2c1cea3acb5aafb0b
Binary files /dev/null and b/lib/batik/batik-xml.jar differ
diff --git a/lib/batik/version b/lib/batik/version
new file mode 100644
index 0000000000000000000000000000000000000000..b55ee096feeb1ba544a96cb51064ccd5cfd8e951
--- /dev/null
+++ b/lib/batik/version
@@ -0,0 +1,5 @@
+http://xmlgraphics.apache.org/batik/
+
+SVN (batik-1.8pre) version (13-NOV-2012):
+
+http://people.apache.org/builds/xml-batik/batik-svn-12-11-13.zip
diff --git a/uk/ac/sanger/artemis/circular/PrintDNAImage.java b/uk/ac/sanger/artemis/circular/PrintDNAImage.java
index 603a9bb008ce448cbc55d8fc445148041829647d..74005d93af7f8451d600c8b5e7f572c43bd15106 100644
--- a/uk/ac/sanger/artemis/circular/PrintDNAImage.java
+++ b/uk/ac/sanger/artemis/circular/PrintDNAImage.java
@@ -35,7 +35,13 @@ import java.awt.event.KeyEvent;
 import java.awt.image.BufferedImage;
 import java.awt.image.RenderedImage;
 import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+
 import javax.swing.BorderFactory;
 import javax.swing.Box;
 import javax.swing.JComboBox;
@@ -53,6 +59,17 @@ import javax.swing.JTextField;
 import javax.swing.KeyStroke;
 import javax.swing.border.Border;
 
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGeneratorContext;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.apache.batik.svggen.SVGGraphics2DIOException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
+import uk.ac.sanger.artemis.Options;
+import uk.ac.sanger.artemis.components.PrintArtemis;
+import uk.ac.sanger.artemis.components.StickyFileChooser;
+
 
 
 
@@ -225,18 +242,15 @@ public class PrintDNAImage extends ScrollPanel
     f.setVisible(true);
   }
 
-
   /**
-  *
   * Provide some options for the image created
-  *
   */
   private File showOptions()
   {
-    String cwd = System.getProperty("user.dir");
-    JFileChooser fc = new JFileChooser(cwd);
-    File fselect = new File(cwd+System.getProperty("file.separator")+
-                            "dna.jpg"); 
+    final StickyFileChooser fc = new StickyFileChooser();
+    File fselect = new File(fc.getCurrentDirectory()+
+        System.getProperty("file.separator")+
+        "dnaplotter.png");
     fc.setSelectedFile(fselect);
 
 // file name prefix
@@ -250,10 +264,28 @@ public class PrintDNAImage extends ScrollPanel
     bdown.add(labFormat);
 
     Box bacross = Box.createHorizontalBox();
-    JComboBox formatSelect = 
-       new JComboBox(javax.imageio.ImageIO.getWriterFormatNames());
-    formatSelect.setSelectedItem("jpg");
-    
+    final JComboBox formatSelect = new JComboBox(PrintArtemis.getImageFormats());
+    formatSelect.setSelectedItem("png");
+    formatSelect.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent arg0)
+      {
+        String selected;
+        if(fc.getSelectedFile() != null)
+        {
+          selected = fc.getSelectedFile().getAbsolutePath();
+          String fmts[] = PrintArtemis.getImageFormats();
+          for(int i=0; i<fmts.length; i++)
+            selected = selected.replaceAll("."+fmts[i]+"$", "");
+        }
+        else
+          selected = "dnaplotter";
+        
+        fc.setSelectedFile(new File(selected+"."+
+               formatSelect.getSelectedItem()));
+      }
+    });
+
     Dimension d = formatSelect.getPreferredSize();
     formatSelect.setMaximumSize(d);
     bacross.add(Box.createHorizontalGlue());
@@ -291,9 +323,6 @@ public class PrintDNAImage extends ScrollPanel
       System.out.println("Java 1.4+ is required");
     }
   }
-  
-  
-  
 
   /**
   * Print to one jpeg or png file
@@ -310,10 +339,15 @@ public class PrintDNAImage extends ScrollPanel
     Dimension d = dna.getSize();
     double imageWidth  = d.getWidth();
     double imageHeight = d.getHeight();
-    Paper paper  = format.getPaper();
 
+    if(type.equals("svg"))
+    {
+      createSVG(file, d);
+      return;
+    }
+    
+    Paper paper  = format.getPaper();
     paper.setSize(imageWidth,imageHeight);
-
     paper.setImageableArea(0,0,
                            imageWidth,imageHeight+imageHeight);
     format.setPaper(paper);
@@ -329,6 +363,42 @@ public class PrintDNAImage extends ScrollPanel
             "This option requires Java 1.4 or higher.");
     }
   }
+  
+  private void createSVG(final File fout, Dimension d)
+  {
+    final DOMImplementation domImpl =
+        GenericDOMImplementation.getDOMImplementation();
+    final Document doc = domImpl.createDocument(
+        "http://www.w3.org/2000/svg", "svg", null);
+
+    SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(doc);
+    ctx.setComment("Generated by DNAPlotter with Batik SVG Generator");
+    final SVGGraphics2D svgG = new SVGGraphics2D(ctx, true);
+    svgG.setFont(Options.getOptions().getFont());
+    svgG.setSVGCanvasSize(d);
+    paintComponent(svgG);
+
+    try
+    {
+      final Writer out = new OutputStreamWriter(
+          new FileOutputStream(fout), "UTF-8");
+      svgG.stream(out, true);
+    }
+    catch (UnsupportedEncodingException e)
+    {
+      e.printStackTrace();
+    }
+    catch (SVGGraphics2DIOException e)
+    {
+      e.printStackTrace();
+    }
+    catch (FileNotFoundException e)
+    {
+      e.printStackTrace();
+    }
+
+    return;
+  }
 
 }
 
diff --git a/uk/ac/sanger/artemis/components/AlignmentViewer.java b/uk/ac/sanger/artemis/components/AlignmentViewer.java
index e8d30b680561d660fcc42fe8bfac62ab23be649e..19666975697068eea1cd7a757948defd32395d60 100644
--- a/uk/ac/sanger/artemis/components/AlignmentViewer.java
+++ b/uk/ac/sanger/artemis/components/AlignmentViewer.java
@@ -40,6 +40,9 @@ import java.util.Vector;
 import java.util.Comparator;
 import java.util.Arrays;
 import javax.swing.*;
+
+import org.apache.batik.svggen.SVGGraphics2D;
+
 import java.io.FileWriter;
 import java.io.IOException;
 
@@ -1172,14 +1175,25 @@ public class AlignmentViewer extends CanvasPanel
       if(offscreen == null)
         offscreen = createImage(canvas_width, canvas_height);
 
-      Graphics og = offscreen.getGraphics();
-      og.setClip(0,0,canvas_width,canvas_height);
+      final Graphics og;
+      if(!(g instanceof SVGGraphics2D))
+      {
+        og = offscreen.getGraphics();
+        og.setClip(0,0,canvas_width,canvas_height);
+      }
+      else
+        og = g;
+      
       og.setColor(Color.white);
       og.fillRect(0, 0, canvas_width, canvas_height);
       drawAlignments(og);
       drawLabels(og);
-      g.drawImage(offscreen, 0, 0, null);
-      og.dispose();
+       
+      if(!(g instanceof SVGGraphics2D))
+      {
+        g.drawImage(offscreen, 0, 0, null);
+        og.dispose();
+      }
     }
   }
 
diff --git a/uk/ac/sanger/artemis/components/BasePlot.java b/uk/ac/sanger/artemis/components/BasePlot.java
index 9d595b25bd9fb27d6e2bfbc9066dfe5e759880bf..1d46bfb497a598e6c9c28144bd353318685422a3 100644
--- a/uk/ac/sanger/artemis/components/BasePlot.java
+++ b/uk/ac/sanger/artemis/components/BasePlot.java
@@ -722,6 +722,13 @@ public class BasePlot extends Plot
    **/
   public int drawMultiValueGraph(Graphics g, LineAttributes[] lines) 
   {
+    if( getAlgorithm() instanceof UserDataAlgorithm && 
+        ((UserDataAlgorithm)getAlgorithm()).FORMAT ==  UserDataAlgorithm.TABIX_INDEXED_FORMAT)
+    {
+      ((UserDataAlgorithm) getAlgorithm()).readIndexValues(
+          entryGroup.getSequenceEntry(), getStart(), getEnd());
+    }
+
     if(recalculate_flag)
       recalculateValues();
     
@@ -735,11 +742,9 @@ public class BasePlot extends Plot
     final int window_size = getWindowSize();
 
     // the number of values to plot at each x position
-    final int get_values_return_count =
+    final int nvalues =
       getBaseAlgorithm().getValueCount();
 
-    final int number_of_values = value_array_array[0].length;
-
     boolean isWiggle = false;
     boolean isBlast  = false;
     if(getAlgorithm() instanceof UserDataAlgorithm)
@@ -753,17 +758,16 @@ public class BasePlot extends Plot
         isBlast = true;
     }
     
-    if(number_of_values > 1 && !isWiggle) 
+    if(value_array_array[0].length > 1 && !isWiggle) 
       drawGlobalAverage(g, min_value, max_value);
 
     Stroke stroke = ((Graphics2D)g).getStroke();
-    for(int value_index = 0; value_index < get_values_return_count;
-        ++value_index)
+    for(int i = 0; i < nvalues; ++i)
     {
-      if(value_index < lines.length)
+      if(i < lines.length)
       {
-        g.setColor(lines[value_index].getLineColour());
-        ((Graphics2D)g).setStroke(lines[value_index].getStroke());
+        g.setColor(lines[i].getLineColour());
+        ((Graphics2D)g).setStroke(lines[i].getStroke());
       }
       else
         g.setColor(Color.black);
@@ -778,8 +782,8 @@ public class BasePlot extends Plot
       drawPoints(g, min_value, max_value, step_size, window_size,
                    getWidthInBases(),
                    offset,
-                   value_array_array[value_index], value_index, 
-                   get_values_return_count, isWiggle, isBlast);
+                   value_array_array[i], i, 
+                   nvalues, isWiggle, isBlast);
     }
     ((Graphics2D)g).setStroke(stroke);
     
@@ -870,7 +874,7 @@ public class BasePlot extends Plot
       }
     }
 
-    return get_values_return_count;
+    return nvalues;
   }
 
 
diff --git a/uk/ac/sanger/artemis/components/BioJavaEntrySource.java b/uk/ac/sanger/artemis/components/BioJavaEntrySource.java
index 8f9a64ce7cbf0db3e1d8d4d89c45440407d63214..ca1c454014268b0febef7f0557ed724138c7d1c7 100644
--- a/uk/ac/sanger/artemis/components/BioJavaEntrySource.java
+++ b/uk/ac/sanger/artemis/components/BioJavaEntrySource.java
@@ -25,29 +25,12 @@
 
 package uk.ac.sanger.artemis.components;
 
-import java.net.*;
 import java.io.*;
-import java.util.*;
-import java.lang.RuntimeException;
 
-import org.biojava.bio.program.das.*;
-import org.biojava.bio.BioException;
-import org.biojava.bio.seq.io.SequenceBuilderFactory;
-import org.biojava.bio.seq.io.EmblProcessor;
-import org.biojava.bio.seq.io.SmartSequenceBuilder;
-import org.biojava.bio.seq.io.SymbolTokenization;
-import org.biojava.bio.seq.io.StreamReader;
-import org.biojava.bio.seq.io.SequenceFormat;
 import org.biojava.bio.seq.io.EmblLikeFormat;
-import org.biojava.bio.seq.SequenceIterator;
-import org.biojava.bio.symbol.Alphabet;
-import org.biojava.bio.seq.DNATools;
 
 import uk.ac.sanger.artemis.util.*;
 import uk.ac.sanger.artemis.io.BioJavaEntry;
-import uk.ac.sanger.artemis.io.EntryInformation;
-import uk.ac.sanger.artemis.io.SimpleEntryInformation;
-
 import uk.ac.sanger.artemis.*;
 import uk.ac.sanger.artemis.sequence.*;
 
@@ -145,50 +128,6 @@ public class BioJavaEntrySource implements EntrySource
     public Entry getEntry (final boolean show_progress)
         throws OutOfRangeException, NoSequenceException, IOException
     {
-//       DASSequence dasSeq = null;
-
-//       try {
-//         final URL dbURL =
-//           new URL("http://genome.ornl.gov/das/das.cgi/ecoli");
-// //        new URL("http://genome.cse.ucsc.edu:80/cgi-bin/das/cb1");
-// //        new URL("http://servlet.sanger.ac.uk:8080/das/ens1131cds/");
-//         final DASSequenceDB dasDB = new DASSequenceDB (dbURL);
-        
-//         final Set ids = dasDB.ids();
-
-//         for (Iterator i = ids.iterator(); i.hasNext(); ) {
-//           System.out.println(i.next().toString());
-//         }
-        
-//         // dasSeq = (DASSequence) dasDB.getSequence((String) ids.iterator().next());
-        
-//         SequenceIterator si = dasDB.sequenceIterator();
-        
-//         if (si.hasNext()) {
-//           dasSeq = (DASSequence) si.nextSequence();
-          
-//           System.err.println("Got: " + dasSeq);
-
-//           final BioJavaEntry bioJavaEntry = new BioJavaEntry (dasSeq);
-
-//           return new Entry (bioJavaEntry);
-//         } else {
-//           System.err.println("No more sequences...");
-//         }
-
-        
-//         //       final BioJavaEntry emblEntry =
-//         //         new BioJavaEntry (document, new EmblLikeFormat ());
-        
-//         //      return new Entry (emblEntry);
-//       } catch (MalformedURLException mue) {
-//           mue.printStackTrace();
-//       } catch (BioException be) {
-//           be.printStackTrace();
-//       }
-
-//       return null;
-
       final String fileName = "/nfs/team81/kmr/pow/java2/AE002734.game";
       final FileDocument document = new FileDocument (new File (fileName));
       
@@ -196,14 +135,6 @@ public class BioJavaEntrySource implements EntrySource
         new BioJavaEntry (document, new EmblLikeFormat ());
       
       return new Entry (emblEntry);
-
-//       final String fileName = "/nfs/team81/kmr/pow/java2/AB000095.embl";
-//       final FileDocument document = new FileDocument (new File (fileName));
-      
-//       final BioJavaEntry emblEntry =
-//         new BioJavaEntry (document, new EmblLikeFormat ());
-      
-//       return new Entry (emblEntry);
     }
 
   /**
diff --git a/uk/ac/sanger/artemis/components/FeatureDisplay.java b/uk/ac/sanger/artemis/components/FeatureDisplay.java
index 8c279573a1c5a75526dad041e9ebdf18d7d97d00..bc6cb235cc3856f9fcd2c9b5ac22cd50078475dd 100644
--- a/uk/ac/sanger/artemis/components/FeatureDisplay.java
+++ b/uk/ac/sanger/artemis/components/FeatureDisplay.java
@@ -68,6 +68,8 @@ import javax.swing.UIManager;
 import javax.swing.ImageIcon;
 import javax.swing.JFrame;
 
+import org.apache.batik.svggen.SVGGraphics2D;
+
 /**
  *  This component is used for displaying an Entry.
  *
@@ -1890,8 +1892,19 @@ public class FeatureDisplay extends EntryGroupPanel
 
     // draw fwd bases
     if(getScaleFactor() == 0)
-      g.drawString(forward_visible_bases, offset * getFontWidth(),
-                   yposition + getFontAscent() + 1);
+    {
+      if(!(g instanceof SVGGraphics2D))
+        g.drawString(forward_visible_bases, offset * getFontWidth(),
+            yposition + getFontAscent() + 1);
+      else
+      {
+        // for svg graphics
+        for(int i=0;i<forward_visible_bases.length();i++)
+          g.drawString(String.valueOf(forward_visible_bases.charAt(i)), 
+              (offset+i)*getFontWidth(), 
+              yposition + getFontAscent() + 1);
+      }
+    }
     else
     {
       for(int base_index = 0; base_index < forward_sequence_length;
@@ -1914,8 +1927,19 @@ public class FeatureDisplay extends EntryGroupPanel
 
     // draw bwd bases
     if(getScaleFactor() == 0)
-      g.drawString(reverse_visible_bases, offset * getFontWidth(),
-                   yposition + getFontAscent() + 1);
+    {  
+      if(!(g instanceof SVGGraphics2D))
+        g.drawString(reverse_visible_bases, offset * getFontWidth(),
+            yposition + getFontAscent() + 1);
+      else
+      {
+        // for svg graphics
+        for(int i=0;i<reverse_visible_bases.length();i++)
+          g.drawString(String.valueOf(reverse_visible_bases.charAt(i)), 
+              (offset+i)*getFontWidth(), 
+              yposition + getFontAscent() + 1);
+      }
+    }
     else
     {
       for(int base_index = 0; base_index < reverse_sequence_length;
@@ -2200,8 +2224,15 @@ public class FeatureDisplay extends EntryGroupPanel
     else
        draw_x_position = (int)((offset + frame_start + 1) * getScaleValue());
 
-    g.drawString(codons, draw_x_position,
+    if(!(g instanceof SVGGraphics2D))
+      g.drawString(codons, draw_x_position,
                  draw_y_position + getFontAscent() + 1);
+    else
+    {
+      for(int i=0;i<codons.length();i++)
+        g.drawString(String.valueOf(codons.charAt(i)), draw_x_position+(i*getFontWidth() ), 
+          draw_y_position + getFontAscent() + 1);
+    }
   }
 
   /**
diff --git a/uk/ac/sanger/artemis/components/FeaturePlot.java b/uk/ac/sanger/artemis/components/FeaturePlot.java
index 646f45c368a9789ed1a739fe710bb5d12dd82a7e..6d3425b093317139eac5c5016b5d38432f9e922c 100644
--- a/uk/ac/sanger/artemis/components/FeaturePlot.java
+++ b/uk/ac/sanger/artemis/components/FeaturePlot.java
@@ -25,24 +25,30 @@
 
 package uk.ac.sanger.artemis.components;
 
-import uk.ac.sanger.artemis.sequence.*;
-import uk.ac.sanger.artemis.util.OutOfRangeException;
-import uk.ac.sanger.artemis.util.ReadOnlyException;
-import uk.ac.sanger.artemis.*;
-import uk.ac.sanger.artemis.io.EntryInformationException;
-import uk.ac.sanger.artemis.plot.*;
-import java.awt.*;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+
+import uk.ac.sanger.artemis.Feature;
+import uk.ac.sanger.artemis.FeatureChangeEvent;
+import uk.ac.sanger.artemis.FeatureChangeListener;
+import uk.ac.sanger.artemis.Options;
+import uk.ac.sanger.artemis.plot.FeatureAlgorithm;
+import uk.ac.sanger.artemis.plot.LineAttributes;
+import uk.ac.sanger.artemis.sequence.AminoAcidSequence;
+
 
 /**
  *  The components of this class display a plot of a FeatureAlgorithm for a
  *  particular feature.
- *
  *  @author Kim Rutherford
- *  @version $Id: FeaturePlot.java,v 1.11 2009-07-20 15:11:17 tjc Exp $
  **/
 
 public class FeaturePlot extends Plot
     implements DisplayAdjustmentListener, FeatureChangeListener {
+
+  private static final long serialVersionUID = 1L;
+
   /**
    *  Create a new FeatureDisplay object.
    *  @param algorithm The object that will generate the values we plot in
@@ -102,10 +108,9 @@ public class FeaturePlot extends Plot
   public void displayAdjustmentValueChanged (DisplayAdjustmentEvent event) {
     start_base = event.getStart ();
     end_base = event.getEnd ();
-    width_in_bases = event.getWidthInBases ();
+    //width_in_bases = event.getWidthInBases ();
 
     recalculate_flag = true;
-
     repaint();
   }
 
@@ -138,13 +143,6 @@ public class FeaturePlot extends Plot
     return end_base;
   }
 
-  /**
-   *  Return the width in bases of the display, from the last event.
-   **/
-  private int getWidthInBases () {
-    return width_in_bases;
-  }
-
   /**
    *  This array is used by drawGraph ().  It is reallocated when the scale
    *  changes.
@@ -386,12 +384,6 @@ public class FeaturePlot extends Plot
    **/
   private int end_base;
 
-  /**
-   *  The width in bases of the display, as obtained from the
-   *  DisplayAdjustmentEvent.
-   **/
-  private int width_in_bases;
-
   protected void calculateFeatures(boolean fromPeak)
   {
     // TODO Auto-generated method stub
diff --git a/uk/ac/sanger/artemis/components/MultiComparator.java b/uk/ac/sanger/artemis/components/MultiComparator.java
index b9a64b897040179a9cc5739a90d08ab8ad26dd26..06a393fb88061a2b83333f2d734681cb74525b34 100644
--- a/uk/ac/sanger/artemis/components/MultiComparator.java
+++ b/uk/ac/sanger/artemis/components/MultiComparator.java
@@ -39,8 +39,20 @@ import uk.ac.sanger.artemis.io.EntryInformationException;
 import uk.ac.sanger.artemis.io.DocumentEntryFactory;
 import uk.ac.sanger.artemis.io.DocumentEntry;
 
-import java.awt.*;
-import java.awt.event.*;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.MediaTracker;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
 import java.io.IOException;
 import java.io.File;
 import java.net.URL;
@@ -58,9 +70,7 @@ import javax.swing.JPanel;
  *  This JFrame component contains an arbitrary number of AlignmentViewer
  *  components and FeatureDisplay components along with ComparatorGlue objects
  *  to keep them synchronized.
- *
- *  @author Kim Rutherford <kmr@sanger.ac.uk>
- *  @version $Id: MultiComparator.java,v 1.22 2008-09-03 10:58:33 tjc Exp $
+ *  @author Kim Rutherford
  **/
 
 public class MultiComparator extends JFrame 
@@ -132,9 +142,6 @@ public class MultiComparator extends JFrame
   /** Used to show the progress of loading file. */
   private InputStreamProgressListener progress_listener;
 
-  /** current group used for drag and drop */
-  private int current_group = -1;
-
   /**
    *  Initialise entry_group_array and comparison_data_array and create all
    *  the FeatureDisplay and AlignmentViewer components.
@@ -162,16 +169,10 @@ public class MultiComparator extends JFrame
     this.progress_listener = progress_listener;
     this.entry_sources = Utilities.getEntrySources(this, null);
 
-    final StringBuffer title_buffer = new StringBuffer();
-
-    title_buffer.append("ACT: ");
-
+    final StringBuffer title_buffer = new StringBuffer("ACT: ");
     for(int i = 0; i < entry_group_array.length - 1; ++i) 
-    {
-      final String sequence_name =
-        entry_group_array[i].getDefaultEntry().getName();
-      title_buffer.append(sequence_name).append(" vs ");
-    }
+      title_buffer.append(
+          entry_group_array[i].getDefaultEntry().getName()).append(" vs ");
 
     final EntryGroup last_entry_group =
       entry_group_array[entry_group_array.length - 1];
@@ -206,7 +207,6 @@ public class MultiComparator extends JFrame
                           getGotoEventSourceArray()[i]);
 
       final int scroll_bar_position;
-
       if(i == getEntryGroupArray().length - 1 &&
           getEntryGroupArray().length == 2) 
       {
@@ -255,17 +255,11 @@ public class MultiComparator extends JFrame
                             getAlignmentViewerArray()[i]);
     }
 
-    final Font default_font = getDefaultFont();
-
-    setFont(default_font);
-
+    setFont(getDefaultFont());
     makeMenus();
-
-    GridBagLayout gridbag = new GridBagLayout();
-    getContentPane().setLayout(gridbag);
+    getContentPane().setLayout(new GridBagLayout());
 
     GridBagConstraints c = new GridBagConstraints();
-
     c.gridwidth  = GridBagConstraints.REMAINDER;
     c.fill       = GridBagConstraints.BOTH;
     c.anchor     = GridBagConstraints.NORTH;
@@ -598,7 +592,7 @@ public class MultiComparator extends JFrame
    **/
   private void makeMenus() 
   {
-    final Font default_font = getDefaultFont();
+    //final Font default_font = getDefaultFont();
     final JMenuBar menu_bar = new JMenuBar();
 
     setJMenuBar(menu_bar);
diff --git a/uk/ac/sanger/artemis/components/Plot.java b/uk/ac/sanger/artemis/components/Plot.java
index 9fcc723afc22fc2d14351ac2cb072652b0873014..5a24f1de1757616800c3ed93e3537d071b716282 100644
--- a/uk/ac/sanger/artemis/components/Plot.java
+++ b/uk/ac/sanger/artemis/components/Plot.java
@@ -29,8 +29,15 @@ import uk.ac.sanger.artemis.Options;
 import uk.ac.sanger.artemis.circular.TextFieldFloat;
 import uk.ac.sanger.artemis.plot.*;
 
-import java.awt.*;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.Image;
+import java.awt.Scrollbar;
 import java.awt.event.*;
+import java.util.Vector;
 
 import javax.swing.JMenu;
 import javax.swing.JPanel;
@@ -44,15 +51,16 @@ import javax.swing.JMenuItem;
 import javax.swing.JScrollBar;
 import javax.swing.JPopupMenu;
 
+import org.apache.batik.svggen.SVGGraphics2D;
+
 /**
  *  This class implements a simple plot component.
- *
  *  @author Kim Rutherford
- *  @version $Id: Plot.java,v 1.26 2009-08-18 09:01:44 tjc Exp $
  **/
 
 public abstract class Plot extends JPanel 
 {
+  private static final long serialVersionUID = 1L;
 
   /** scroll bar for changing the window size. */
   private JScrollBar window_changer = null;
@@ -73,12 +81,16 @@ public abstract class Plot extends JPanel
    *  drawScaleLine() is called.
    **/
   private boolean draw_scale;
+  
+  private final int SCROLL_NOB_SIZE = 10;
 
   /**
    *  Set to true if drawMultiValueGraph() should call recalculateValues().
    *  It is reset to false by recalculateValues().
    **/
   protected boolean recalculate_flag = true;
+  
+  private boolean showAverage = true;
 
   /**
    *  The x position of the last click or -1 if the user hasn't clicked
@@ -95,7 +107,7 @@ public abstract class Plot extends JPanel
   /**
    *  A vector of those objects listening for PlotMouse events.
    **/
-  final private java.util.Vector listener_list = new java.util.Vector();
+  final private Vector<PlotMouseListener> listener_list = new Vector<PlotMouseListener>();
 
   /**
    *  Recalculate the values all the state that is used for drawing the plot
@@ -116,10 +128,12 @@ public abstract class Plot extends JPanel
   /** number of graph lines to be drawn */
   private int numPlots;
 
-  /** colour array for graph drawing */
   protected LineAttributes lines[];
   
   private int lastPaintHeight = getHeight();
+  
+  /** the minimum distance in pixels between the labels */
+  private final static int MINIMUM_LABEL_SPACING = 50;
  
   /**
    *  Create a new plot component.
@@ -130,34 +144,27 @@ public abstract class Plot extends JPanel
    **/
   public Plot(Algorithm algorithm, boolean draw_scale) 
   {
-    super();
+    super(new BorderLayout());
     this.algorithm = algorithm;
     this.draw_scale = draw_scale;
 
-    final Font font = Options.getOptions().getFont();
-
-    setFont(font);
-    FontMetrics fm = getFontMetrics(font);
+    setFont(Options.getOptions().getFont());
+    FontMetrics fm = getFontMetrics(getFont());
     font_height = fm.getHeight();
 
-    setLayout(new BorderLayout());
-
     final int MAX_WINDOW;
-
     if(getAlgorithm().getDefaultMaxWindowSize() != null) 
       MAX_WINDOW = getAlgorithm().getDefaultMaxWindowSize().intValue();
     else 
       MAX_WINDOW = 500;
 
     final int MIN_WINDOW;
-
     if(getAlgorithm().getDefaultMinWindowSize() != null) 
       MIN_WINDOW = getAlgorithm().getDefaultMinWindowSize().intValue();
     else 
       MIN_WINDOW = 5;
 
     final int START_WINDOW;
-
     if(getAlgorithm().getDefaultWindowSize() == null) 
       START_WINDOW = 10;
     else 
@@ -189,17 +196,11 @@ public abstract class Plot extends JPanel
       }
     });
 
-
-//  setBackground(Color.white);
     add(window_changer, "East");
-
     addMouseListener(mouse_listener);
     addMouseMotionListener(mouse_motion_listener);
-
   }
 
-  final int SCROLL_NOB_SIZE = 10;
-
   /**
    *  Return the algorithm that was passed to the constructor.
    **/
@@ -220,8 +221,7 @@ public abstract class Plot extends JPanel
   final MouseListener mouse_listener = new MouseAdapter()
   {
     /**
-     *  Listen for mouse press events so that we can do a popup menu and a
-     *  crosshair.
+     *  Listen for mouse press popup menu and crosshair events.
      **/
     public void mousePressed(MouseEvent event) 
     {
@@ -296,10 +296,9 @@ public abstract class Plot extends JPanel
         });
         popup.add(setScale);
 
-        final JCheckBoxMenuItem scaling_toggle =
-          new JCheckBoxMenuItem("Scaling");
 
-        scaling_toggle.setState(getAlgorithm().scalingFlag());
+        final JCheckBoxMenuItem scaling_toggle =
+          new JCheckBoxMenuItem("Scaling",getAlgorithm().scalingFlag());
         scaling_toggle.addItemListener(new ItemListener() 
         {
           public void itemStateChanged(ItemEvent _) 
@@ -309,10 +308,19 @@ public abstract class Plot extends JPanel
             repaint();
           }
         });
-
         popup.add(scaling_toggle);
-        
-        
+
+        final JCheckBoxMenuItem showAverageLn = new JCheckBoxMenuItem("Show average", showAverage);
+        showAverageLn.addItemListener(new ItemListener() 
+        {
+          public void itemStateChanged(ItemEvent _) 
+          {
+            showAverage = showAverageLn.isSelected();
+            repaint();
+          }
+        });
+        popup.add(showAverageLn);
+
         if(Plot.this instanceof BasePlot)
         {
           final JMenuItem showMinMaxValues =
@@ -351,13 +359,11 @@ public abstract class Plot extends JPanel
             }
           });
         }
-        
-        
+
         popup.addSeparator();
 
         final JMenu max_window_size =
               new JMenu("Maximum Window Size");
-
         popup.add(max_window_size);
 
         final int[] window_sizes = 
@@ -366,9 +372,7 @@ public abstract class Plot extends JPanel
           200000, 500000, 1000000
         };
 
-
         JMenuItem window_size_item;
-
         for(int i = 0 ; i < window_sizes.length ; ++i) 
         {
           final int size = i;
@@ -440,7 +444,6 @@ public abstract class Plot extends JPanel
         }
 
         final JSplitPane splitPane = getJSplitPane();
-
         if(splitPane == null)
         {
           popup.addSeparator();
@@ -458,8 +461,7 @@ public abstract class Plot extends JPanel
           {
             public void actionPerformed(ActionEvent e)
             {
-              Dimension d = getSize();
-              rescale((int) (d.height * 0.9f));
+              rescale((int) (getSize().height * 0.9f));
             }
           });
 
@@ -467,8 +469,7 @@ public abstract class Plot extends JPanel
           {
             public void actionPerformed(ActionEvent e)
             {
-              Dimension d = getSize();
-              rescale((int) (d.height * 1.1f));
+              rescale((int) (getSize().height * 1.1f));
             }
           });
 
@@ -486,12 +487,10 @@ public abstract class Plot extends JPanel
 
               if(select == 1)
                 return;
-
               try
               {
-                final int value = Integer
-                    .parseInt(newGraphHgt.getText().trim());
-                rescale(value);
+                rescale(Integer.parseInt(
+                    newGraphHgt.getText().trim()));
               }
               catch(NumberFormatException nfe)
               {
@@ -611,7 +610,7 @@ public abstract class Plot extends JPanel
     PlotMouseListener listener;
     for(int i = 0; i < listener_list.size(); ++i)
     {
-      listener = (PlotMouseListener)listener_list.elementAt(i);
+      listener = listener_list.elementAt(i);
       listener.mouseClick(getPointPosition(cross_hair_position));
     }
   }
@@ -625,7 +624,7 @@ public abstract class Plot extends JPanel
     PlotMouseListener listener;
     for(int i = 0; i < listener_list.size(); ++i) 
     {
-      listener = (PlotMouseListener)listener_list.elementAt(i);
+      listener = listener_list.elementAt(i);
       listener.mouseDrag(getPointPosition(drag_start_position),
                          getPointPosition(cross_hair_position));
     }
@@ -640,7 +639,7 @@ public abstract class Plot extends JPanel
     PlotMouseListener listener;
     for(int i = 0; i < listener_list.size(); ++i) 
     {
-      listener = (PlotMouseListener)listener_list.elementAt(i);
+      listener = listener_list.elementAt(i);
       listener.mouseDoubleClick(getPointPosition(cross_hair_position));
     }
   }
@@ -685,11 +684,17 @@ public abstract class Plot extends JPanel
     if(offscreen == null || lastPaintHeight != height)
       offscreen = createImage(width, height);
 
-    Graphics og = offscreen.getGraphics();
-    og.setClip(0, 0, width, height);
-    og.setColor(Color.WHITE);
-    og.fillRect(0, 0, width, height);
-
+    final Graphics og;
+    if(g instanceof SVGGraphics2D)
+      og = g;
+    else
+    {
+      og = offscreen.getGraphics();
+      og.setClip(0, 0, width, height);
+      og.setColor(Color.WHITE);
+      og.fillRect(0, 0, width, height);
+    }
+    
     // Redraw the graph on the canvas using the algorithm from the
     // constructor.
 
@@ -706,8 +711,12 @@ public abstract class Plot extends JPanel
     
     numPlots = drawMultiValueGraph(og,lines);
     drawLabels(og,numPlots);
-    g.drawImage(offscreen, 0, 0, null);
-    og.dispose();
+    
+    if( !(g instanceof SVGGraphics2D) )
+    {
+      g.drawImage(offscreen, 0, 0, null);
+      og.dispose();
+    }
     lastPaintHeight = height;
   }
 
@@ -737,31 +746,19 @@ public abstract class Plot extends JPanel
     drag_start_position = -1;
   }
 
-  // the minimum distance in pixels between the labels
-  private final static int MINIMUM_LABEL_SPACING = 50;
-
   /**
-   *  Draw the scale line at the bottom of the graph.
+   *  Draw the scale line at the bottom of the graph (used by FeaturePlot).
    *  @param start The base on the left
    *  @param end The base on the right
    **/
   protected void drawScaleLine(final Graphics g,
                                final int start, final int end) 
   {
-    final int width  = getWidth() - window_changer.getWidth();
-    final int height = getHeight();
-
-    final int scale_number_y_pos =  height - 1;
-
+    final int hgt = getHeight();
+    final int scale_number_y_pos =  hgt - 1;
     final float bases_per_pixel = 1.0F;
 
-    // set the spacing so that the labels are at multiples of 10
-    final int base_label_spacing = MINIMUM_LABEL_SPACING;
-
-    final int label_spacing = (int)(base_label_spacing / bases_per_pixel);
-
-    final int possible_index_of_first_label = start / base_label_spacing;
-
+    final int possible_index_of_first_label = start / MINIMUM_LABEL_SPACING;
     final int index_of_first_label;
 
     if(possible_index_of_first_label == 0) 
@@ -769,22 +766,18 @@ public abstract class Plot extends JPanel
     else 
       index_of_first_label = possible_index_of_first_label;
 
-    final int index_of_last_label = end / base_label_spacing;
-
-    String label_string;
+    final int index_of_last_label = end / MINIMUM_LABEL_SPACING;
     for(int i = index_of_first_label; i <= index_of_last_label; i++)
     {
-      label_string = String.valueOf((int)(i * base_label_spacing));
-
       final int scale_number_x_pos =
-        (int)((i * base_label_spacing - start) / bases_per_pixel);
+        (int)((i * MINIMUM_LABEL_SPACING - start) / bases_per_pixel);
 
-      g.drawString(label_string,
+      g.drawString(String.valueOf((int)(i * MINIMUM_LABEL_SPACING)),
                    scale_number_x_pos + 2,
                    scale_number_y_pos);
 
-      g.drawLine(scale_number_x_pos, height - getScaleHeight() / 2,
-                 scale_number_x_pos, height - getScaleHeight());
+      g.drawLine(scale_number_x_pos, hgt - getScaleHeight() / 2,
+                 scale_number_x_pos, hgt - getScaleHeight());
     }
   }
 
@@ -977,7 +970,8 @@ public abstract class Plot extends JPanel
                                     final float max_value) 
   {
     // if a heatmap do not show the average
-    if(lines != null && lines[0].getPlotType().equals(LineAttributes.PLOT_TYPES[2]))
+    if(!showAverage || (
+        lines != null && lines[0].getPlotType().equals(LineAttributes.PLOT_TYPES[2])))
         return;
     
     final Float average = getAlgorithm().getAverage();
@@ -1129,22 +1123,6 @@ public abstract class Plot extends JPanel
   {
     return font_height;
   }
-
-  /**
-   *  Used to get the X coordinate for the tooltip text.
-   *  @param total_unit_count The maximum number of residues/bases we can
-   *    show.  This is used to draw the scale line and to calculate the
-   *    distance (in pixels) between plot points.
-   *  @param start_position The distance from the edge of the canvas (measured
-   *    in residues/bases) to start drawing the plot.
-   *  @param xpos The mouse position on the canvas.
-   **/
-  protected int getXCoordinate(final int total_unit_count,
-                               final int start_position,
-                               final int xpos) 
-  {
-    return (xpos * total_unit_count)/getSize().width + start_position;
-  }
   
   /**
    *  Used to get the Y coordinate for the tooltip text.
@@ -1162,7 +1140,6 @@ public abstract class Plot extends JPanel
       final float plot_values[], int base_pos)
   {
     int ypos = (int)((base_pos - start_position - (window_size/2))/step_size);
-    
     if(ypos < 0)
       ypos = 0;
     else if(ypos > plot_values.length-1)
@@ -1170,5 +1147,4 @@ public abstract class Plot extends JPanel
     
     return plot_values[ypos];
   }
-  
 }
diff --git a/uk/ac/sanger/artemis/components/PrintACT.java b/uk/ac/sanger/artemis/components/PrintACT.java
index 0c3403f5ce10d36bea209722515b04262073ad47..5928f777c2463d516a4dfcba0ff7d2e0b6093c9d 100644
--- a/uk/ac/sanger/artemis/components/PrintACT.java
+++ b/uk/ac/sanger/artemis/components/PrintACT.java
@@ -32,7 +32,12 @@ import java.awt.print.Printable;
 import java.awt.print.PrinterException;
 import java.awt.print.PrinterJob;
 import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
 
 import javax.swing.Box;
 import javax.swing.JCheckBox;
@@ -50,12 +55,18 @@ import javax.swing.JScrollPane;
 import javax.swing.JSeparator;
 import javax.swing.KeyStroke;
 
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGeneratorContext;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.apache.batik.svggen.SVGGraphics2DIOException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
+import uk.ac.sanger.artemis.Options;
 import uk.ac.sanger.artemis.editor.ScrollPanel;
 
 /**
-*
 * Use to print images from ACT
-*
 */
 public class PrintACT extends ScrollPanel implements Printable
 {
@@ -274,18 +285,15 @@ public class PrintACT extends ScrollPanel implements Printable
   }
 
   /**
-  *
   * Print to a jpeg or png file
-  *
   */
   public void print()
   {
     // file chooser
-    String cwd = System.getProperty("user.dir");
-    JFileChooser fc = new JFileChooser(cwd);
-    File fselect = new File(cwd+
-                            System.getProperty("file.separator")+
-                            "act.png");
+    final StickyFileChooser fc = new StickyFileChooser();
+    File fselect = new File(fc.getCurrentDirectory()+
+        System.getProperty("file.separator")+
+        "act.png");
     fc.setSelectedFile(fselect);
      
     // file name prefix
@@ -296,8 +304,27 @@ public class PrintACT extends ScrollPanel implements Printable
     YBox.add(labFormat);
 
     Box bacross = Box.createHorizontalBox();
-    JComboBox formatSelect =
-       new JComboBox(javax.imageio.ImageIO.getWriterFormatNames());
+    final JComboBox formatSelect = new JComboBox(PrintArtemis.getImageFormats());
+    formatSelect.setSelectedItem("png");
+    formatSelect.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent arg0)
+      {
+        String selected;
+        if(fc.getSelectedFile() != null)
+        {
+          selected = fc.getSelectedFile().getAbsolutePath();
+          String fmts[] = PrintArtemis.getImageFormats();
+          for(int i=0; i<fmts.length; i++)
+            selected = selected.replaceAll("."+fmts[i]+"$", "");
+        }
+        else
+          selected = "act";
+        
+        fc.setSelectedFile(new File(selected+"."+
+               formatSelect.getSelectedItem()));
+      }
+    });
     formatSelect.setSelectedItem("png");
 
     Dimension d = formatSelect.getPreferredSize();
@@ -319,6 +346,12 @@ public class PrintACT extends ScrollPanel implements Printable
 
     // remove file extension
     String fsave = fc.getSelectedFile().getAbsolutePath().toLowerCase();
+    if(fsave.endsWith(".svg"))
+    {
+      createSVG(fc.getSelectedFile());
+      return;
+    }
+    
     if(fsave.endsWith(".png") ||
        fsave.endsWith(".jpg") ||
        fsave.endsWith(".jpeg") )
@@ -345,12 +378,46 @@ public class PrintACT extends ScrollPanel implements Printable
     }
   }
 
+  private void createSVG(final File fout)
+  {
+    final DOMImplementation domImpl =
+        GenericDOMImplementation.getDOMImplementation();
+    final Document doc = domImpl.createDocument(
+        "http://www.w3.org/2000/svg", "svg", null);
+
+    SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(doc);
+    ctx.setComment("Generated by ACT with Batik SVG Generator");
+    final SVGGraphics2D svgG = new SVGGraphics2D(ctx, true);
+    svgG.setFont(Options.getOptions().getFont());
+    svgG.setSVGCanvasSize( getImageSize() );
+    paintComponent(svgG);
+
+    try
+    {
+      final Writer out = new OutputStreamWriter(
+          new FileOutputStream(fout), "UTF-8");
+      svgG.stream(out, true);
+    }
+    catch (UnsupportedEncodingException e)
+    {
+      e.printStackTrace();
+    }
+    catch (SVGGraphics2DIOException e)
+    {
+      e.printStackTrace();
+    }
+    catch (FileNotFoundException e)
+    {
+      e.printStackTrace();
+    }
+
+    return;
+  }
+  
   /**
-  *
   *  Returns a generated image
   *  @param pageIndex   page number
   *  @return            image
-  *
   */
   private RenderedImage createImage()
   {
diff --git a/uk/ac/sanger/artemis/components/PrintArtemis.java b/uk/ac/sanger/artemis/components/PrintArtemis.java
index f72fef4d423ef4f2a13579c2d7b5b8707ddcdf41..5c37fd88450813938b079ccc60009130b29de40a 100644
--- a/uk/ac/sanger/artemis/components/PrintArtemis.java
+++ b/uk/ac/sanger/artemis/components/PrintArtemis.java
@@ -29,9 +29,26 @@ import java.awt.print.Printable;
 import java.awt.print.PrinterException;
 import java.awt.print.PrinterJob;
 import java.awt.event.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.HashSet;
+
 import javax.swing.*;
-import java.io.*;
 
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGeneratorContext;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.apache.batik.svggen.SVGGraphics2DIOException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
+import uk.ac.sanger.artemis.Options;
 import uk.ac.sanger.artemis.editor.ScrollPanel;
 
 /**
@@ -66,15 +83,45 @@ public class PrintArtemis extends ScrollPanel implements Printable
   }
 
   /**
-  *
   * Override paintComponent to draw entry
-  *
   */
-  public void paintComponent(Graphics g)
+  public void paintComponent(Graphics g2d)
   {
 // let UI delegate paint first (incl. background filling)
-    super.paintComponent(g);
-    Graphics2D g2d = (Graphics2D)g.create();
+    super.paintComponent(g2d);
+
+    // feature list
+    if(featListDisplay.isSelected())
+    {
+      FeatureList flist = entry.getFeatureList();
+      Point ploc = flist.getViewport().getViewPosition(); 
+      try
+      {
+        int translateX = 0;
+        if(selectDisplay.isSelected())
+          translateX += entry.getSelectionInfoDisplay().getHeight();
+        if(groupsDisplay.isSelected())
+          translateX += entry.getEntryGroupDisplay().getHeight();
+        if(plotsDisplay.isSelected())
+          translateX += entry.getBasePlotGroup().getHeight();
+        if(jamDisplay.isSelected() && entry.getBamPanel() != null && entry.getBamPanel().isVisible())
+          translateX += entry.getBamPanel().getHeight()-1;
+        if(vcfDisplay.isSelected() && entry.getVcfView() != null && entry.getVcfView().isVisible())
+          translateX += entry.getVcfPanel().getHeight();
+        if(onelineDisplay.isSelected())
+          translateX += entry.getOneLinePerEntryDisplay().getHeight();
+        if(featDisplay.isSelected())
+          translateX += entry.getFeatureDisplay().getHeight();
+        if(baseDisplay.isSelected())
+          translateX += entry.getBaseDisplay().getHeight();
+
+        translateX-=2+ploc.y;
+        g2d.translate(0,translateX);
+        flist.paintComponent(g2d);
+        g2d.translate(0,-translateX);
+      }
+      catch(IllegalArgumentException e){} // thrown if the list is not visible
+    }
 
     // selection info
     if(selectDisplay.isSelected())
@@ -128,24 +175,9 @@ public class PrintArtemis extends ScrollPanel implements Printable
       entry.getBaseDisplay().paintComponent(g2d);
       g2d.translate(0,entry.getBaseDisplay().getHeight());
     }
-
-    // feature list
-    if(featListDisplay.isSelected())
-    {
-      FeatureList flist = entry.getFeatureList();
-      Point ploc = flist.getViewport().getViewPosition(); 
-      try
-      {
-        BufferedImage offScreen = new BufferedImage(flist.getViewport().getWidth(), 
-          flist.getViewport().getHeight(), BufferedImage.TYPE_INT_RGB);
-        Graphics og = offScreen.getGraphics();
-        og.translate(0,-ploc.y);
-        flist.paintComponent(og);
-        g2d.drawImage(offScreen, 0, 0, null);
-      }
-      catch(IllegalArgumentException e){} // thrown if the list is not visible
-    }
   }
+  
+  
 
 
   /**
@@ -153,7 +185,7 @@ public class PrintArtemis extends ScrollPanel implements Printable
   * Set the size of the image
   *
   */
-  private void setImageSize()
+  private Dimension getImageSize()
   {
     height = 0;
     width  = entry.getFeatureDisplay().getDisplayWidth();
@@ -185,9 +217,14 @@ public class PrintArtemis extends ScrollPanel implements Printable
 
     if(featListDisplay.isSelected())
       height += entry.getFeatureList().getViewport().getExtentSize().height;
-    setPreferredSize(new Dimension(width,height));
+    return new Dimension(width,height);
   }
 
+  private void setImageSize()
+  {
+    setPreferredSize(getImageSize());
+  }
+  
   /**
   *
   * Display a print preview page
@@ -391,6 +428,21 @@ public class PrintArtemis extends ScrollPanel implements Printable
     f.setVisible(true);
   }
 
+  public static String[] getImageFormats()
+  {
+    final String fmts[] = javax.imageio.ImageIO.getWriterFormatNames();
+    final HashSet<String> list = new HashSet<String>();
+    for(int i=0; i<fmts.length; i++)
+      list.add(fmts[i].toLowerCase());
+
+    final String tmpFmts[] = new String[list.size()+1];
+    System.arraycopy(list.toArray(), 0, tmpFmts, 0, list.size());
+    tmpFmts[tmpFmts.length-1] = "svg";
+    Arrays.sort(tmpFmts);
+
+    return tmpFmts;
+  }
+  
   /**
   *
   * Print to a jpeg or png file
@@ -399,7 +451,7 @@ public class PrintArtemis extends ScrollPanel implements Printable
   public void print()
   {
     // file chooser
-    StickyFileChooser fc = new StickyFileChooser();
+    final StickyFileChooser fc = new StickyFileChooser();
     File fselect = new File(fc.getCurrentDirectory()+
                             System.getProperty("file.separator")+
                             "artemis.png");
@@ -413,9 +465,27 @@ public class PrintArtemis extends ScrollPanel implements Printable
     YBox.add(labFormat);
 
     Box bacross = Box.createHorizontalBox();
-    JComboBox formatSelect =
-       new JComboBox(javax.imageio.ImageIO.getWriterFormatNames());
+    final JComboBox formatSelect = new JComboBox(getImageFormats());
     formatSelect.setSelectedItem("png");
+    formatSelect.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent arg0)
+      {
+        String selected;
+        if(fc.getSelectedFile() != null)
+        {
+          selected = fc.getSelectedFile().getAbsolutePath();
+          String fmts[] = getImageFormats();
+          for(int i=0; i<fmts.length; i++)
+            selected = selected.replaceAll("."+fmts[i]+"$", "");
+        }
+        else
+          selected = "artemis";
+        
+        fc.setSelectedFile(new File(selected+"."+
+               formatSelect.getSelectedItem()));
+      }
+    });
 
     Dimension d = formatSelect.getPreferredSize();
     formatSelect.setMaximumSize(d);
@@ -488,6 +558,13 @@ public class PrintArtemis extends ScrollPanel implements Printable
 
     // remove file extension
     String fsave = fc.getSelectedFile().getAbsolutePath().toLowerCase();
+    
+    if(fsave.endsWith(".svg"))
+    {
+      createSVG(fc.getSelectedFile());
+      return;
+    }
+
     if(fsave.endsWith(".png") ||
        fsave.endsWith(".jpg") ||
        fsave.endsWith(".jpeg") )
@@ -514,6 +591,45 @@ public class PrintArtemis extends ScrollPanel implements Printable
     }
   }
   
+  private void createSVG(final File fout)
+  {
+    final DOMImplementation domImpl =
+        GenericDOMImplementation.getDOMImplementation();
+    final Document doc = domImpl.createDocument(
+        "http://www.w3.org/2000/svg", "svg", null);
+
+    SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(doc);
+    ctx.setComment("Generated by Artemis with Batik SVG Generator");
+    final SVGGraphics2D svgG = new SVGGraphics2D(ctx, true);
+    svgG.setFont(Options.getOptions().getFont());
+    final FontMetrics fm = svgG.getFontMetrics();
+    final Dimension d = getImageSize();
+    svgG.setSVGCanvasSize( new Dimension(
+        d.width+fm.stringWidth(" "), d.height+fm.getHeight()) );
+    paintComponent(svgG);
+
+    try
+    {
+      final Writer out = new OutputStreamWriter(
+          new FileOutputStream(fout), "UTF-8");
+      svgG.stream(out, true);
+    }
+    catch (UnsupportedEncodingException e)
+    {
+      e.printStackTrace();
+    }
+    catch (SVGGraphics2DIOException e)
+    {
+      e.printStackTrace();
+    }
+    catch (FileNotFoundException e)
+    {
+      e.printStackTrace();
+    }
+
+    return;
+  }
+  
   protected void doPrintActions()
   {
     final PrinterJob pj=PrinterJob.getPrinterJob();
@@ -575,7 +691,7 @@ public class PrintArtemis extends ScrollPanel implements Printable
   public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException
   {
     setImageSize();
-    Graphics2D g2 = (Graphics2D) g;
+    Graphics2D g2 = (Graphics2D)g.create();
 
 //  RepaintManager.currentManager(this).setDoubleBufferingEnabled(false);
     Dimension d = this.getSize();    //get size of document
diff --git a/uk/ac/sanger/artemis/components/variant/TabixReader.java b/uk/ac/sanger/artemis/components/variant/TabixReader.java
index a42cdf5431db2708dfed279fcdd60e5883cfd429..102d718982e3eb8575a1deac9b15040eaf33d2f7 100644
--- a/uk/ac/sanger/artemis/components/variant/TabixReader.java
+++ b/uk/ac/sanger/artemis/components/variant/TabixReader.java
@@ -413,8 +413,28 @@ public class TabixReader extends AbstractVCFReader
 	    return mSeq;
 	  }
 	  
-	  protected String getFileName()
+	  public int getStartColumn()
+	  {
+	    return mBc;
+	  }
+	  
+	  public int getEndColumn()
+	  {
+	    return mEc;
+	  }
+	  
+	  public int getSeqColumn()
+	  {
+	    return mSc;
+	  }
+	  
+	  public String getFileName()
 	  {
 	    return mFn;
 	  }
+	  
+      public char getCommentChar() 
+      {
+        return (char)mMeta;
+    }
 }
diff --git a/uk/ac/sanger/artemis/plot/Algorithm.java b/uk/ac/sanger/artemis/plot/Algorithm.java
index 434d20230f527492e21cc714beb43b37426415e0..1ffeb9e5ce2170ccc6d16978a6defdd4b3245f76 100644
--- a/uk/ac/sanger/artemis/plot/Algorithm.java
+++ b/uk/ac/sanger/artemis/plot/Algorithm.java
@@ -143,6 +143,14 @@ public abstract class Algorithm {
   {
      return algorithm_name;
   }
+  
+  /**
+   *  Return the name of this algorithm.
+   **/
+  public void setAlgorithmName (String algorithm_name) 
+  {
+     this.algorithm_name = algorithm_name;
+  }
 
   /**
    *  Return the short (one word) name of this algorithm, as passed tp the
diff --git a/uk/ac/sanger/artemis/plot/UserDataAlgorithm.java b/uk/ac/sanger/artemis/plot/UserDataAlgorithm.java
index 84c6561ab82e46ec20e7cbb4b0dbe5d3ddc011fd..0a69f718add3b0acc61c65572245071d91b9a580 100644
--- a/uk/ac/sanger/artemis/plot/UserDataAlgorithm.java
+++ b/uk/ac/sanger/artemis/plot/UserDataAlgorithm.java
@@ -1,10 +1,7 @@
 /* UserDataAlgorithm.java
- *
- * created: Wed May 10 2000
- *
  * This file is part of Artemis
  *
- * Copyright (C) 2000  Genome Research Limited
+ * Copyright (C) 2000-2012  Genome Research Limited
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -19,52 +16,57 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/plot/UserDataAlgorithm.java,v 1.14 2009-07-22 12:51:54 tjc Exp $
  */
 
 package uk.ac.sanger.artemis.plot;
 
-import uk.ac.sanger.artemis.sequence.*;
-
-import uk.ac.sanger.artemis.util.*;
+import uk.ac.sanger.artemis.Entry;
+import uk.ac.sanger.artemis.sequence.Bases;
+import uk.ac.sanger.artemis.sequence.Strand;
+import uk.ac.sanger.artemis.util.Document;
+import uk.ac.sanger.artemis.util.FileDocument;
+import uk.ac.sanger.artemis.util.LinePushBackReader;
+import uk.ac.sanger.artemis.util.StringVector;
+import uk.ac.sanger.artemis.components.variant.TabixReader;
+import uk.ac.sanger.artemis.io.IndexFastaStream;
 import uk.ac.sanger.artemis.io.ReadFormatException;
-
 import java.awt.Color;
 import java.awt.GridLayout;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.regex.Pattern;
-
 import javax.swing.ButtonGroup;
 import javax.swing.JCheckBox;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 
+import net.sf.samtools.util.BlockCompressedInputStream;
+
 /**
  *  Objects of this class have one useful method - getValues (), which takes a
  *  range of bases and returns a single floating point number.  The number is
  *  calculated by averaging the values from a data file.  The Strand to use is
  *  set in the constructor.
- *
- *  @author Kim Rutherford <kmr@sanger.ac.uk>
- *  @version $Id: UserDataAlgorithm.java,v 1.14 2009-07-22 12:51:54 tjc Exp $
+ *  @author Kim Rutherford
  **/
 
 public class UserDataAlgorithm extends BaseAlgorithm
 {
   /** A base per line file format */
   public static int BASE_PER_LINE_FORMAT  = 1;
-  
   /** Base position is specified in the first column file format */
   public static int BASE_SPECIFIED_FORMAT = 2;
-  
   /** Wiggle format */
   public static int WIGGLE_VARIABLE_STEP_FORMAT = 3;
-  public static int WIGGLE_FIXED_STEP_FORMAT = 4;
-  
-  public static int BLAST_FORMAT = 5;
-  public static int MSPCRUNCH_BLAST_FORMAT = 6;
+  public static int WIGGLE_FIXED_STEP_FORMAT    = 4;
+  public static int BLAST_FORMAT                = 5;
+  public static int MSPCRUNCH_BLAST_FORMAT      = 6;
+  public static int TABIX_INDEXED_FORMAT        = 7;
   
   /** The data read by the constructor - for BASE_PER_LINE_FORMAT */
   private float data[][] = null;
@@ -76,7 +78,6 @@ public class UserDataAlgorithm extends BaseAlgorithm
   
   /** The maximum value in the data array. */
   private float data_max = Float.MIN_VALUE;
-
   /** The minimum value in the data array. */
   private float data_min = Float.MAX_VALUE;
   
@@ -95,8 +96,10 @@ public class UserDataAlgorithm extends BaseAlgorithm
   public int FORMAT = BASE_PER_LINE_FORMAT;
   
   private LineAttributes lines[];
-  
-  public Wiggle wiggle[];
+  private Wiggle wiggle[];
+  private TabixIdxGraph idxReader;
+  private static org.apache.log4j.Logger logger4j = 
+      org.apache.log4j.Logger.getLogger(UserDataAlgorithm.class);
   
   /**
    *  Create a new UserDataAlgorithm object. This reads a file
@@ -109,51 +112,63 @@ public class UserDataAlgorithm extends BaseAlgorithm
    *  @param logTransform true if the log transformation is to be
    *  shown.
    **/
-  public UserDataAlgorithm (final Strand strand, final Document document, 
+  public UserDataAlgorithm (final Strand strand, final Document doc, 
                             final boolean logTransform)
       throws IOException 
   {
-    super (strand, "User algorithm from " + document.getName (), "user");
-
+    super (strand, 
+        (logTransform ? "User log plot " + doc.getName () : 
+                        "User plot " + doc.getName ()), "user");
     this.logTransform = logTransform;
-    final Reader document_reader = document.getReader ();
 
-    LinePushBackReader pushback_reader = new LinePushBackReader (document_reader);
-    String first_line = pushback_reader.readLine (); 
+    if(isIndexed(doc) && doc.getInputStream() instanceof BlockCompressedInputStream)
+    {
+      setAlgorithmName(
+          (logTransform ? "Indexed log plot " + doc.getName () :
+                          "Indexed plot " + doc.getName ()));
+      FORMAT = TABIX_INDEXED_FORMAT;
+      idxReader = new TabixIdxGraph(
+          ((FileDocument) doc).getFile().getAbsolutePath());
+      number_of_values = idxReader.getNumberOfValues();
+      return;
+    }
+    
+    final Reader doc_reader = doc.getReader ();
+    final LinePushBackReader pushback_reader = new LinePushBackReader (doc_reader);
+    String firstLn = pushback_reader.readLine (); 
 
-    Pattern dataPattern = Pattern.compile("^\\s*([\\d\\.-]+\\s*)+$");
-    Pattern blastPattern = Pattern.compile(
+    final Pattern dataPattern = Pattern.compile("^\\s*([\\d\\.-]+\\s*)+$");
+    final Pattern blastPattern = Pattern.compile(
       "^(\\S+\\t+){2}[\\d\\.]+\\t+(\\d+\\t+){7}\\S+\\t+(\\s*\\d+)$");
-    Pattern mspCrunchPattern = Pattern.compile(
+    final Pattern mspCrunchPattern = Pattern.compile(
         "^\\d+\\s[\\d\\.]+(\\s\\d+){2}\\s\\D\\S+(\\s\\d+){2}\\s\\D\\S+.*");
 
-    if(dataPattern.matcher(first_line).matches())
+    if(dataPattern.matcher(firstLn).matches())
       FORMAT = BASE_PER_LINE_FORMAT;
-    else if(blastPattern.matcher(first_line).matches())
+    else if(blastPattern.matcher(firstLn).matches())
       FORMAT = BLAST_FORMAT;
-    else if(mspCrunchPattern.matcher(first_line).matches())
+    else if(mspCrunchPattern.matcher(firstLn).matches())
       FORMAT = MSPCRUNCH_BLAST_FORMAT;
     else
     { 
-      StringBuffer header = new StringBuffer(first_line+"\n");
-
-      while(!dataPattern.matcher(first_line).matches())
+      StringBuffer header = new StringBuffer(firstLn+"\n");
+      while(!dataPattern.matcher(firstLn).matches())
       {
-        first_line = pushback_reader.readLine ().trim();
-        header.append(first_line+"\n");
+        firstLn = pushback_reader.readLine ().trim();
+        header.append(firstLn+"\n");
       }
       
       FORMAT = parseHeader(header);
     }
 
     final Pattern patt = Pattern.compile("\\s+");
-    String tokens[] = patt.split(first_line);
+    String tokens[] = patt.split(firstLn);
     
     if (tokens.length < 1) 
       throw new ReadFormatException ("unknown file type");
 
     this.number_of_values = tokens.length;
-    pushback_reader.pushBack (first_line);
+    pushback_reader.pushBack (firstLn);
     
     if(FORMAT == BASE_PER_LINE_FORMAT)
       data = new float [strand.getSequenceLength ()][tokens.length];
@@ -167,7 +182,20 @@ public class UserDataAlgorithm extends BaseAlgorithm
     else
       readWiggle(pushback_reader);
     pushback_reader.close();
-    document_reader.close();
+    doc_reader.close();
+  }
+  
+  /**
+   * Test if the tabix (.tbi) index is present.
+   * @param doc
+   * @return
+   */
+  private static boolean isIndexed(Document doc)
+  {
+    if(doc instanceof FileDocument)
+      return (new File(
+          ((FileDocument)doc).getFile().getAbsolutePath() + ".tbi")).exists();
+    return false;
   }
 
   /**
@@ -373,8 +401,7 @@ public class UserDataAlgorithm extends BaseAlgorithm
       coordIndexStart = 2;
       coordIndexEnd   = 3;
     }
-    
-    
+
     while ((line = pushback_reader.readLine ()) != null)
     { 
       String tokens[] = patt.split(line.trim());
@@ -488,7 +515,6 @@ public class UserDataAlgorithm extends BaseAlgorithm
   public void getValues (int start, int end, final float [] values) 
   {
     final int value_count = getValueCount ();
-
     if(getStrand ().getDirection() == Bases.REVERSE)
     {
       int tstart = start;
@@ -521,6 +547,8 @@ public class UserDataAlgorithm extends BaseAlgorithm
           values[i] = values[i]/count;
       }
     }
+    else if(FORMAT == TABIX_INDEXED_FORMAT)
+      idxReader.getValues(start, end, values);
     else
     {
       for (int i = 0 ; i < value_count ; ++i) 
@@ -542,7 +570,6 @@ public class UserDataAlgorithm extends BaseAlgorithm
   private int parseHeader(StringBuffer headerText) throws ReadFormatException
   {
     FORMAT = BASE_SPECIFIED_FORMAT;
-    
     BufferedReader reader = new BufferedReader(
         new StringReader(headerText.toString()));
       
@@ -604,7 +631,7 @@ public class UserDataAlgorithm extends BaseAlgorithm
    *
    * @param trackLine
    */
-  private void parseTrackLine(String trackLine)
+  private void parseTrackLine(final String trackLine)
   {
     String colour = "0,0,0";
     int beginIndex = trackLine.indexOf(" color=");
@@ -618,9 +645,9 @@ public class UserDataAlgorithm extends BaseAlgorithm
     incrementLines(LineAttributes.parse(colour));
   }
   
-  private void incrementLines(Color colour)
+  private void incrementLines(final Color c)
   {
-    LineAttributes line = new LineAttributes(colour);
+    LineAttributes line = new LineAttributes(c);
     
     if(lines == null)
       lines = new LineAttributes[1];
@@ -800,7 +827,7 @@ public class UserDataAlgorithm extends BaseAlgorithm
     return wiggle[index].span;
   }
   
-  public boolean isWiggleFormat()
+  protected boolean isWiggleFormat()
   {
     if(FORMAT == WIGGLE_VARIABLE_STEP_FORMAT || 
        FORMAT == WIGGLE_FIXED_STEP_FORMAT)
@@ -808,10 +835,171 @@ public class UserDataAlgorithm extends BaseAlgorithm
     return false;
   }
   
+  public void readIndexValues(Entry seqEntry, int start, int end)
+  {
+    if(start<1)
+      start = 1;
+    idxReader.readValuesForRange(seqEntry, start, end);
+  }
+  
   class Wiggle
   {
     int start;
     int step;
     int span = 0;
   }
+  
+  class TabixIdxGraph
+  {
+    private TabixReader reader;
+    /** number of columns with values */
+    private int nValues = 1;
+    private float[][] rvalues;
+    private boolean startColIsEndCol = true;
+    private int sbeg, send;
+    
+    TabixIdxGraph(final String fName) throws IOException
+    {
+      this.reader = new TabixReader(fName);
+      if(getStartColumn() != getEndColumn())
+        startColIsEndCol = false;
+
+      final StringBuffer headerBuffer = new StringBuffer();
+      String metaChar = String.valueOf(reader.getCommentChar());
+      String hdr;
+      while( (hdr = reader.readLine() ) != null && hdr.startsWith(metaChar) )
+        headerBuffer.append(hdr + "\n");
+      //System.out.println("Header "+headerBuffer.toString());
+
+      // assume base end column is last column before columns of values
+      nValues = reader.readLine().split("\\t").length - getEndColumn();
+    }
+    
+    /**
+     * Return the values between a pair of bases
+     * @param start
+     * @param end
+     * @param values
+     */
+    private void getValues(int start, int end, final float[] values)
+    {
+      for (int i = 0 ; i < getNumberOfValues() ; ++i) 
+      {
+        values [i] = 0;
+        for (int base = start ; base <= end ; ++base) 
+          values [i] += rvalues[base - this.sbeg][i] / (end - start + 1);
+      }
+    }
+    
+    /**
+     * Get the sequence name
+     * @param seqEntry - sequence entry
+     * @return
+     */
+    private String getReferenceName(Entry seqEntry)
+    {
+      String refStr = null;
+      if(seqEntry.getEMBLEntry().getSequence() instanceof IndexFastaStream)
+        refStr = 
+           ((IndexFastaStream)seqEntry.getEMBLEntry().getSequence()).getContig();
+      else if(seqEntry.getHeaderText() != null)
+      {
+        final String hdr = seqEntry.getHeaderText();
+        int idx = hdr.indexOf("ID   ");
+        if (idx == -1)
+        {
+          idx = hdr.indexOf("LOCUS       "); // genbank
+          if (idx > -1)
+            refStr = hdr.substring(idx + 12).split("[;\\s]")[0];
+        }
+        else
+          refStr = hdr.substring(idx + 5).split("[;\\s]")[0];
+      }
+
+      final String seqNames[] = reader.getSeqNames();
+      if(refStr == null || !Arrays.asList(seqNames).contains(refStr))
+      {
+        logger4j.debug(refStr+" NOT FOUND IN "+reader.getFileName()+
+            " SET TO DEFAULT "+seqNames[0]);
+        refStr = reader.getSeqNames()[0];
+      }
+      return refStr;
+    }
+
+    /**
+     * Read the values in a range
+     * @param seqEntry - sequence entry
+     * @param start - start base
+     * @param end   - end base
+     */
+    private void readValuesForRange(Entry seqEntry, int start, int end)
+    {
+      if(end <= start || (start == this.sbeg && end == this.send))
+        return;
+
+      this.sbeg = start;
+      this.send = end;
+      rvalues = new float[end-start+1][getNumberOfValues()];
+      final String r = getReferenceName(seqEntry)+":"+start+"-"+end;
+      try
+      {
+        final TabixReader.Iterator tbxIt = reader.query(r);
+        String ln;
+        while( tbxIt != null &&  (ln = tbxIt.next()) != null )
+        {
+          StringVector parts = StringVector.getStrings(ln, "\t", true);
+          final int base;
+          if(startColIsEndCol)
+            base = Integer.parseInt((String)parts.get(getStartColumn()-1)) - start;
+          else
+          {
+            int b = Integer.parseInt((String)parts.get(getStartColumn()-1));
+            int e = Integer.parseInt((String)parts.get(getEndColumn()-1));
+            base = b + ((b - e)/2) - start;
+          }
+          for(int i=0; i<rvalues[base].length; i++)
+          {
+            float val = Float.parseFloat( (String) parts.get(i+getEndColumn()) );
+            if(logTransform)
+              val = (float) Math.log(val+1);
+
+            if (val > data_max) 
+              data_max = val;
+            if (val < data_min)
+              data_min = val;
+            rvalues[base][i] = val;
+          }
+        }
+      }
+      catch (IOException e)
+      {
+        logger4j.debug("IOException READING RANGE "+r+" FROM "+reader.getFileName());
+        e.printStackTrace();
+      }
+      catch (NumberFormatException e)
+      {
+        logger4j.debug("NumberFormatException READING RANGE "+r+" FROM "+reader.getFileName());
+        e.printStackTrace();
+      }
+    }
+    
+    /**
+     * Number of columns with values
+     * @return
+     */
+    private int getNumberOfValues()
+    {
+      return nValues;
+    }
+    
+    private int getStartColumn()
+    {
+      return reader.getStartColumn();
+    }
+    
+    private int getEndColumn()
+    {
+      return reader.getEndColumn();
+    }
+  }
 }