diff --git a/uk/ac/sanger/artemis/components/BasePlot.java b/uk/ac/sanger/artemis/components/BasePlot.java
index e30a13ee62857fec5f462efbf4a97470bfd8b2b1..42815fdc4ea86a64749898389f55eb244803bb48 100644
--- a/uk/ac/sanger/artemis/components/BasePlot.java
+++ b/uk/ac/sanger/artemis/components/BasePlot.java
@@ -20,7 +20,7 @@
  * 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/components/BasePlot.java,v 1.17 2009-06-26 15:52:48 tjc Exp $
+ * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/BasePlot.java,v 1.18 2009-07-15 12:20:30 tjc Exp $
  **/
 
 package uk.ac.sanger.artemis.components;
@@ -54,7 +54,7 @@ import org.apache.log4j.Level;
  *  scale is tied to a FeatureDisplay component.
  *
  *  @author Kim Rutherford
- *  @version $Id: BasePlot.java,v 1.17 2009-06-26 15:52:48 tjc Exp $
+ *  @version $Id: BasePlot.java,v 1.18 2009-07-15 12:20:30 tjc Exp $
  **/
 
 public class BasePlot extends Plot
@@ -738,7 +738,14 @@ public class BasePlot extends Plot
 
     final int number_of_values = value_array_array[0].length;
 
-    if(number_of_values > 1) 
+    boolean isWiggle = false;
+    if(getAlgorithm() instanceof UserDataAlgorithm)
+    {
+      if( ((UserDataAlgorithm)getAlgorithm()).wiggle != null )
+        isWiggle = true;
+    }
+    
+    if(number_of_values > 1 && !isWiggle) 
       drawGlobalAverage(g, min_value, max_value);
 
     Stroke stroke = ((Graphics2D)g).getStroke();
@@ -760,10 +767,16 @@ public class BasePlot extends Plot
       else
         offset = 0;
 
-      drawPoints(g, min_value, max_value, step_size, window_size,
-                 getWidthInBases(),
-                 offset,
-                 value_array_array[value_index]);
+      if(!isWiggle)
+        drawPoints(g, min_value, max_value, step_size, window_size,
+                   getWidthInBases(),
+                   offset,
+                   value_array_array[value_index]);
+      else
+        drawWiggle(g, min_value, max_value, step_size, window_size,
+                   getWidthInBases(),
+                   offset,
+                   value_array_array[value_index], value_index);
     }
     ((Graphics2D)g).setStroke(stroke);
     
@@ -856,6 +869,140 @@ public class BasePlot extends Plot
 
     return get_values_return_count;
   }
+  
+  
+  /**
+   *  Plot the given wiggle format onto a Graphics object.
+   *  @param min_value The minimum of the plot_values.
+   *  @param max_value The maximum of the plot_values.
+   *  @param step_size The current step size for this algorithm.  This is
+   *    never greater than window_size.
+   *  @param window_size The window size used in calculating plot_values.
+   *  @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 plot_values The values to plot.
+   **/
+  protected void drawWiggle(final Graphics g,
+                            final float min_value, final float max_value,
+                            final int step_size, final int window_size,
+                            final int total_unit_count,
+                            final int start_position,
+                            final float [] plot_values,
+                            final int value_index) 
+  {
+    final float residues_per_pixel =
+      (float) total_unit_count / getSize().width;
+
+    // this is the height of the graph (slightly smaller than the canvas for
+    // ease of viewing).
+    final int graph_height = getSize().height -
+      getLabelHeight() -       // leave room for the algorithm name
+      getScaleHeight() -       // leave room for the scale
+      2;
+
+    // too small to draw
+    if(graph_height < 5) 
+      return;
+
+    String wiggleType = lines[value_index].getWiggleType();
+    Color definedColours[] = null;
+    int NUMBER_OF_SHADES = 100;
+    if(wiggleType.equals(LineAttributes.WIGGLE_TYPES[2]))
+    {
+      definedColours = makeColours(lines[value_index].getLineColour(),
+                                   NUMBER_OF_SHADES);
+    }
+    
+    final int number_of_values = plot_values.length;
+    int start_residue;
+    int end_residue;
+    int start_x;
+    int end_x;
+
+    for(int i = 0; i<number_of_values - 1; ++i) 
+    {
+      if(plot_values[i] == 0)
+        continue;
+      
+      int span = ((UserDataAlgorithm)getAlgorithm()).getWiggleSpan(value_index);
+      
+      start_residue = window_size / 2 + i * step_size + start_position;
+      end_residue   = start_residue + span;
+
+      start_x = (int)(start_residue / residues_per_pixel);
+      end_x = (int)(end_residue / residues_per_pixel);
+
+      // this is a number between 0.0 and 1.0
+      final float scaled_start_value =
+        (plot_values[i] - min_value) / (max_value - min_value);
+      final int start_y =
+        graph_height - (int)(scaled_start_value * graph_height) +
+        getLabelHeight() + 1;
+
+      if(wiggleType.equals(LineAttributes.WIGGLE_TYPES[0]))
+      {
+        g.drawLine(start_x, graph_height+getLabelHeight() + 1, start_x, start_y);
+        g.drawLine(start_x, start_y, end_x, start_y);
+        g.drawLine(end_x, graph_height+getLabelHeight() + 1, end_x, start_y); 
+      }
+      else if(wiggleType.equals(LineAttributes.WIGGLE_TYPES[1]))
+        g.fillRect(start_x, start_y, end_x-start_x, graph_height+getLabelHeight() + 1);
+      else
+      {
+        // set color based on value
+        int colourIndex = 
+          (int)(definedColours.length * 0.999 * scaled_start_value);
+
+        if(colourIndex > definedColours.length - 1)
+          colourIndex = definedColours.length - 1;
+        else if (colourIndex < 0)
+          colourIndex = 0;
+        
+        g.setColor(definedColours[ colourIndex ]);
+        g.fillRect(start_x, getLabelHeight() + 1, 
+             end_x-start_x, graph_height+getLabelHeight() + 1);
+      }
+    }
+  }
+  
+  /**
+   * Generate the colours for heat map plots.
+   * @param col
+   * @param NUMBER_OF_SHADES
+   * @return
+   */
+  private Color[] makeColours(Color col, int NUMBER_OF_SHADES)
+  {
+    Color definedColour[] = new Color[NUMBER_OF_SHADES];
+    for(int i = 0; i < NUMBER_OF_SHADES; ++i)
+    {
+      int R = col.getRed();
+      int G = col.getGreen();
+      int B = col.getBlue();
+
+      float scale = ((float)(NUMBER_OF_SHADES-i) * (float)(255 / NUMBER_OF_SHADES )) ;
+      
+      if((R+scale) < 253)
+        R += scale;
+      else
+        R = 253;
+      if((G+scale) < 253)
+        G += scale;
+      else
+        G = 253;
+      if((B+scale) < 253)
+        B += scale;
+      else
+        B = 253;
+
+      definedColour[i] = new Color(R,G,B);
+    }
+    return definedColour;
+  }
+
 
   /**
    *  Get the position in the Feature of the given canvas x position.  This
diff --git a/uk/ac/sanger/artemis/plot/LineAttributes.java b/uk/ac/sanger/artemis/plot/LineAttributes.java
index 7d0e12d13fbe53ae28f09ee8b705a024d1ce832c..aeec06a02e234b313f7c1d89e0d338029bbb81cd 100644
--- a/uk/ac/sanger/artemis/plot/LineAttributes.java
+++ b/uk/ac/sanger/artemis/plot/LineAttributes.java
@@ -81,6 +81,11 @@ public class LineAttributes
   private static BasicStroke[] STROKES = 
        new BasicStroke[]{ style1, style2, style3 };
   
+  /** fill in underneath wiggle plots */
+  public static String WIGGLE_TYPES[]    = 
+          { "Open", "Filled", "Heat Map" };
+  private String wiggleType = WIGGLE_TYPES[0];
+
   /**
    * Contruct a LineAttributes instance
    * @param lineColour
@@ -135,6 +140,11 @@ public class LineAttributes
       return 0;
   }
   
+  public String getWiggleType()
+  {
+    return wiggleType;
+  }
+
   public static LineAttributes[]  init(int numPlots)
   {
     final Color frameColour[] = { 
@@ -213,23 +223,39 @@ public class LineAttributes
     else
       thislines = lines;
 
+    boolean isWiggle = false;
+    if(plot.getAlgorithm() instanceof UserDataAlgorithm)
+    {
+      if(((UserDataAlgorithm)plot.getAlgorithm()).isWiggleFormat())
+        isWiggle = true;
+    }
+    
+    int gridx = 0;
     c.gridy = 0;
-    c.gridx = 0;
+    c.gridx = gridx++;
+    gridx++;
     panel.add(new JLabel("Colour"), c);
-    c.gridx = 2;
+    c.gridx = gridx++;
     panel.add(new JLabel("Line style"), c);
-    c.gridx = 3;
+    
+    if(isWiggle)
+    {
+      c.gridx = gridx++;
+      panel.add(new JLabel("Plot style"), c);
+    }
+    c.gridx = gridx;
     panel.add(new JLabel("Line size"), c);
     
     for(int i=0; i<numPlots; i++)
     {
       c.gridy = i+1;
       final int colourNumber = i;
+      gridx = 0;
 
       final JLabel colourLabel = new JLabel("   ");
       colourLabel.setBackground(thislines[i].getLineColour());
       colourLabel.setOpaque(true);
-      c.gridx = 0;
+      c.gridx = gridx++;
       panel.add(colourLabel,c);
 
       JButton butt = new JButton("Select");
@@ -244,7 +270,7 @@ public class LineAttributes
           plot.repaint();
         }
       });
-      c.gridx = 1;
+      c.gridx = gridx++;
       panel.add(butt, c);
       
       // line style
@@ -266,9 +292,27 @@ public class LineAttributes
           setLineSize(plot, slider, thislines, colourNumber);
         }
       });
-      c.gridx = 2;
+      c.gridx = gridx++;
       panel.add(lineStyle, c);
       
+      // open / filled
+      if(isWiggle)
+      {
+        final JComboBox openPlot = new JComboBox(WIGGLE_TYPES);
+        openPlot.setSelectedItem(thislines[colourNumber].wiggleType);
+        openPlot.addActionListener(new ActionListener()
+        {
+          public void actionPerformed(ActionEvent e)
+          {
+            thislines[colourNumber].wiggleType =
+              (String) openPlot.getSelectedItem();
+             plot.repaint();
+          }
+        });
+        c.gridx = gridx++;
+        panel.add(openPlot, c);
+      }
+      
       // line size
       slider.addChangeListener(new ChangeListener()
       {
@@ -277,7 +321,7 @@ public class LineAttributes
           setLineSize(plot, slider, thislines, colourNumber);
         }
       });
-      c.gridx = 3;
+      c.gridx = gridx;
       panel.add(slider, c);
       
     }
diff --git a/uk/ac/sanger/artemis/plot/UserDataAlgorithm.java b/uk/ac/sanger/artemis/plot/UserDataAlgorithm.java
index 70ce68b33bf48740a4fc1554e31d05fd91d0a456..b7b26be86dd724a29c1c4f9387ac0d854dabb10d 100644
--- a/uk/ac/sanger/artemis/plot/UserDataAlgorithm.java
+++ b/uk/ac/sanger/artemis/plot/UserDataAlgorithm.java
@@ -20,7 +20,7 @@
  * 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.9 2009-07-07 14:37:44 tjc Exp $
+ * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/plot/UserDataAlgorithm.java,v 1.10 2009-07-15 12:20:30 tjc Exp $
  */
 
 package uk.ac.sanger.artemis.plot;
@@ -30,6 +30,7 @@ import uk.ac.sanger.artemis.sequence.*;
 import uk.ac.sanger.artemis.util.*;
 import uk.ac.sanger.artemis.io.ReadFormatException;
 
+import java.awt.Color;
 import java.io.*;
 import java.util.HashMap;
 import java.util.regex.Pattern;
@@ -41,7 +42,7 @@ import java.util.regex.Pattern;
  *  set in the constructor.
  *
  *  @author Kim Rutherford <kmr@sanger.ac.uk>
- *  @version $Id: UserDataAlgorithm.java,v 1.9 2009-07-07 14:37:44 tjc Exp $
+ *  @version $Id: UserDataAlgorithm.java,v 1.10 2009-07-15 12:20:30 tjc Exp $
  **/
 
 public class UserDataAlgorithm extends BaseAlgorithm
@@ -52,11 +53,17 @@ public class UserDataAlgorithm extends BaseAlgorithm
   /** Base position is specified in the first column file format */
   private static int BASE_SPECIFIED_FORMAT = 2;
   
+  /** Wiggle format */
+  private static int WIGGLE_VARIABLE_STEP_FORMAT = 3;
+  private static int WIGGLE_FIXED_STEP_FORMAT = 4;
+  
   /** The data read by the constructor - for BASE_PER_LINE_FORMAT */
   private float data[][] = null;
   
-  /** The data read by the constructor - for BASE_SPECIFIED_FORMAT */
-  private HashMap<Integer, float[]> dataMap;
+  /** The data read by the constructor - for BASE_SPECIFIED_FORMAT 
+                                       - and WIGGLE_VARIABLE_STEP_FORMAT
+                                       - and WIGGLE_FIXED_STEP_FORMAT */
+  private HashMap<Integer, Float[]> dataMap;
   
   /** The maximum value in the data array. */
   private float data_max = Float.MIN_VALUE;
@@ -80,6 +87,8 @@ public class UserDataAlgorithm extends BaseAlgorithm
   
   private LineAttributes lines[];
   
+  public Wiggle wiggle[];
+  
   /**
    *  Create a new UserDataAlgorithm object. This reads a file
    *  which can be one of two types of formats:
@@ -101,23 +110,24 @@ public class UserDataAlgorithm extends BaseAlgorithm
     final Reader document_reader = document.getReader ();
 
     LinePushBackReader pushback_reader = new LinePushBackReader (document_reader);
-
-    String first_line = pushback_reader.readLine ();
-    if(first_line.startsWith("#"))
+    String first_line = pushback_reader.readLine (); 
+    
+    Pattern dataPattern = Pattern.compile("^\\s*([\\d\\.]+\\s*)+$");
+    if(dataPattern.matcher(first_line).matches())
+      FORMAT = BASE_PER_LINE_FORMAT;
+    else
     {
-      readLineAttributes(first_line);
-      FORMAT = BASE_SPECIFIED_FORMAT;
-      first_line = pushback_reader.readLine ().trim();
-      readLineAttributes(first_line);
-      while(first_line.equals("") || first_line.startsWith("#"))
+      StringBuffer header = new StringBuffer(first_line+"\n");
+
+      while(!dataPattern.matcher(first_line).matches())
       {
         first_line = pushback_reader.readLine ().trim();
-        readLineAttributes(first_line);
+        header.append(first_line+"\n");
       }
+      
+      FORMAT = parseHeader(header);
     }
-    else
-      FORMAT = BASE_PER_LINE_FORMAT;
-    
+
     final Pattern patt = Pattern.compile("\\s+");
     String tokens[] = patt.split(first_line);
     
@@ -130,7 +140,11 @@ public class UserDataAlgorithm extends BaseAlgorithm
     if(FORMAT == BASE_PER_LINE_FORMAT)
       data = new float [strand.getSequenceLength ()][tokens.length];
     
-    readData (pushback_reader);
+    if(FORMAT == BASE_SPECIFIED_FORMAT ||
+       FORMAT == BASE_PER_LINE_FORMAT)
+      readData(pushback_reader);
+    else
+      readWiggle(pushback_reader);
     pushback_reader.close();
   }
 
@@ -157,13 +171,13 @@ public class UserDataAlgorithm extends BaseAlgorithm
         throw new ReadFormatException ("line has the wrong number of fields:\n"+line);
       
       int base = 0;
-      
-      float line_data[] = new float[tokens.length-1];
+      Float line_data[] = new Float[tokens.length-1];
       for (int i = 0 ; i < tokens.length ; ++i)
       {
         try 
         {
-          if(FORMAT == BASE_SPECIFIED_FORMAT && i == 0)
+          if( FORMAT == BASE_SPECIFIED_FORMAT &&
+              i == 0)
           {
             int last_base = base;
             base = (int) Float.parseFloat(tokens[i]);
@@ -176,7 +190,7 @@ public class UserDataAlgorithm extends BaseAlgorithm
                (base - last_base) > 0)
               estimate_window_size = base - last_base;
             if(dataMap == null)
-              dataMap = new HashMap<Integer, float[]>();
+              dataMap = new HashMap<Integer, Float[]>();
             continue;
           }
             
@@ -218,6 +232,88 @@ public class UserDataAlgorithm extends BaseAlgorithm
         default_window_size = estimate_window_size;
     }
   }
+  
+  /**
+   *  Read all from buffered_reader into data.
+   **/
+  private void readWiggle (final LinePushBackReader pushback_reader)
+      throws IOException
+  {
+    String line = null;
+    int count = 0;
+    int stepCount = 0;
+    final int seqLength = getStrand ().getSequenceLength ();
+    final Pattern patt = Pattern.compile("\\s+");
+
+    dataMap = new HashMap<Integer, Float[]>();
+    this.number_of_values = 1;
+    
+    while ((line = pushback_reader.readLine ()) != null)
+    {
+      if(line.startsWith("track"))
+      {
+        parseTrackLine(line);
+        continue;
+      }
+      else if(line.startsWith("variableStep ") ||
+              line.startsWith("fixedStep"))
+      {
+        FORMAT = parseWiggle(line);
+        stepCount = 0;
+        this.number_of_values++;
+        continue;
+      }
+      else if(line.startsWith("#"))
+        continue;
+      
+      String tokens[] = patt.split(line.trim()); 
+      int base = 0;
+
+      int valueIndex = 0;
+      try 
+      {
+        if(FORMAT == WIGGLE_VARIABLE_STEP_FORMAT)
+        {
+          base = (int) Float.parseFloat(tokens[0]);
+          valueIndex = 1;
+        }
+        else
+        {
+          base  = wiggle[wiggle.length-1].start + 
+           (stepCount*wiggle[wiggle.length-1].step);
+        }
+        
+        if(base > seqLength)
+          throw new ReadFormatException (
+                "the base position ("+base+") is greater than the sequence length:\n"+line);
+    
+        float value = Float.parseFloat(tokens[valueIndex]);
+        if(logTransform)
+          value = (float) Math.log(value+1);
+
+        if (value > data_max) 
+          data_max = value;
+        if (value < data_min)
+          data_min = value;
+        
+        Float valueArray[] = new Float[number_of_values];
+        valueArray[number_of_values-1] = value;
+        dataMap.put(base, valueArray);
+  
+        count++;
+        stepCount++;
+        average_value += value;
+      } 
+      catch (NumberFormatException e) 
+      {
+        throw new ReadFormatException ("cannot understand this number: " +
+                                       tokens[valueIndex] + " - " +e.getMessage ());
+      } 
+    }
+
+    average_value = average_value/count;
+    default_window_size = 1;
+  }
 
   /**
    *  Return the value of the function between a pair of bases.
@@ -238,7 +334,9 @@ public class UserDataAlgorithm extends BaseAlgorithm
       start = getStrand().getBases().getComplementPosition(tend);
     }
     
-    if(FORMAT == BASE_SPECIFIED_FORMAT)
+    if(FORMAT == BASE_SPECIFIED_FORMAT ||
+       FORMAT == WIGGLE_VARIABLE_STEP_FORMAT ||
+       FORMAT == WIGGLE_FIXED_STEP_FORMAT)
     {
       for (int i = 0 ; i < value_count ; ++i) 
       {
@@ -246,9 +344,11 @@ public class UserDataAlgorithm extends BaseAlgorithm
         int count = 0;
         for (int base = start ; base <= end ; ++base) 
         {
-          if(dataMap.containsKey(base))
+          if(dataMap.containsKey(base) && 
+             ((Float[])dataMap.get(base)).length > i &&
+             ((Float[])dataMap.get(base))[i] != null)
           {
-            values[i] += ((float[])dataMap.get(base))[i];
+            values[i] += ((Float[])dataMap.get(base))[i];
             count++;
           }
         }
@@ -269,33 +369,175 @@ public class UserDataAlgorithm extends BaseAlgorithm
   }
 
   /**
-   * Read the line colour from the header. There should be
+   * Determine the graph file format.
+   * Read the line colour from the header, there should be
    * one per line and space separated.
    * @param line
+   * @throws ReadFormatException 
    */
-  private void readLineAttributes(String line)
+  private int parseHeader(StringBuffer headerText) throws ReadFormatException
   {
-    if(line.indexOf("colour") == -1 &&
-       line.indexOf("color")  == -1)
-      return;
+    FORMAT = BASE_SPECIFIED_FORMAT;
     
-    int index = line.indexOf("colour");
-    if(index == -1)
-      index = line.indexOf("color");
+    BufferedReader reader = new BufferedReader(
+        new StringReader(headerText.toString()));
+      
+    String line = null;
+    try
+    {
+      while ((line = reader.readLine()) != null) 
+      {
+        if((line.indexOf("colour") == -1 && 
+            line.indexOf("color")  == -1 ) ||
+            line.startsWith("track"))
+        {
+          if(line.startsWith("track "))
+            parseTrackLine(line);
+          else  if(line.startsWith("variableStep ") ||
+                   line.startsWith("fixedStep"))
+            FORMAT = parseWiggle(line);
+
+          continue;
+        }
+
+        int index = line.indexOf("colour");
+        if (index == -1)
+          index = line.indexOf("color");
+
+        index = line.indexOf(" ", index + 1);
+        line = line.substring(index).trim();
+        String rgbValues[] = line.split(" ");
+
+        lines = new LineAttributes[rgbValues.length];
+        for (int j = 0; j < rgbValues.length; j++)
+          lines[j] = new LineAttributes(LineAttributes.parse(rgbValues[j]));
+      }
+    }
+    catch (NumberFormatException e) 
+    {
+      throw new ReadFormatException ("cannot understand this number: " +
+                                     line + " - " +e.getMessage ());
+    } 
+    catch (Exception e)
+    {
+      e.printStackTrace();
+    }
+    return FORMAT;
+  }
+  
+  /**
+   * http://genome.ucsc.edu/goldenPath/help/hgWiggleTrackHelp.html
+   * 
+   * All options are placed in a single line separated by spaces:
+   *
+   *  track type=wiggle_0 name=track_label description=center_label
+   *        visibility=display_mode color=r,g,b altColor=r,g,b
+   *        priority=priority autoScale=on|off
+   *        gridDefault=on|off maxHeightPixels=max:default:min
+   *        graphType=bar|points viewLimits=lower:upper
+   *        yLineMark=real-value yLineOnOff=on|off
+   *        windowingFunction=maximum|mean|minimum smoothingWindow=off|2-16
+   *
+   * @param trackLine
+   */
+  private void parseTrackLine(String trackLine)
+  {
+    String colour = "0,0,0";
+    int beginIndex = trackLine.indexOf(" color=");
+    if(beginIndex > -1)
+    {
+      beginIndex+=7;
+      int endIndex   = trackLine.indexOf(" ", beginIndex);
+      colour = trackLine.substring(beginIndex, endIndex);
+    }
     
-    index = line.indexOf(" ", index+1);
-    line = line.substring(index).trim();
-    String rgbValues[] = line.split(" ");
+    incrementLines(LineAttributes.parse(colour));
+  }
+  
+  private void incrementLines(Color colour)
+  {
+    LineAttributes line = new LineAttributes(colour);
     
-    try
+    if(lines == null)
+      lines = new LineAttributes[1];
+    else
     {
-      lines = new LineAttributes[rgbValues.length];   
-      for(int i=0; i<rgbValues.length; i++)
-        lines[i] = new LineAttributes(LineAttributes.parse(rgbValues[i]));
+      LineAttributes linesTmp[] = new LineAttributes[lines.length];
+      System.arraycopy(lines, 0, linesTmp, 0, lines.length);
+      lines = new LineAttributes[linesTmp.length+1];
+      System.arraycopy(linesTmp, 0, lines, 0, linesTmp.length);
     }
-    catch(Exception e){ e.printStackTrace(); }
+    lines[lines.length-1] = line;
   }
   
+  /**
+   * Wiggle formats  (default: span=1) :
+   * variableStep  chrom=chrN  [span=windowSize]
+   * fixedStep  chrom=chrN  start=position  step=stepInterval  [span=windowSize]
+   * @param line
+   * @return
+   */
+  private int parseWiggle(String line) throws NumberFormatException
+  {
+    if(line.startsWith("variableStep "))
+      FORMAT = WIGGLE_VARIABLE_STEP_FORMAT;
+    else if (line.startsWith("fixedStep "))
+      FORMAT = WIGGLE_FIXED_STEP_FORMAT;
+    
+    if(wiggle == null)
+    {
+      wiggle = new Wiggle[lines.length];
+      for(int i=0; i<wiggle.length; i++)
+        wiggle[i] = new Wiggle();
+    }
+    else
+    {
+      Wiggle wiggleTmp[] = new Wiggle[wiggle.length];
+      System.arraycopy(wiggle, 0, wiggleTmp, 0, wiggle.length);
+      wiggle = new Wiggle[wiggleTmp.length+1];
+      System.arraycopy(wiggleTmp, 0, wiggle, 0, wiggleTmp.length);
+      wiggle[wiggle.length-1] = new Wiggle();
+    }
+    
+    if(wiggle.length > lines.length)
+      incrementLines(lines[lines.length-1].getLineColour());
+    
+    if(FORMAT == WIGGLE_FIXED_STEP_FORMAT)
+    {
+      wiggle[wiggle.length-1].start = 
+        Integer.parseInt(getSubString(" start=" ,line));
+
+      wiggle[wiggle.length-1].step = 
+        Integer.parseInt(getSubString(" step=" ,line));
+    }
+    
+    int beginIndex = line.indexOf(" span=");
+    if(beginIndex > -1)
+    {
+      wiggle[wiggle.length-1].span = 
+        Integer.parseInt(getSubString(" span=" ,line));
+    }
+    
+    return FORMAT;
+  }
+
+
+  /**
+   * Find the value of a key within a string.
+   * @param key
+   * @param line
+   * @return
+   */
+  private String getSubString(String key, String line)
+  {
+    int beginIndex = line.indexOf(key)+key.length();
+    int endIndex   = line.indexOf(" ", beginIndex);
+    if(endIndex == -1)
+      endIndex = line.length();
+    return line.substring(beginIndex, endIndex);
+  }
+
+
   /**
    * Return any LineAttributes read from the header (for
    * BASE_SPECIFIED_FORMAT).
@@ -313,7 +555,7 @@ public class UserDataAlgorithm extends BaseAlgorithm
   public int getValueCount () 
   {
     if(FORMAT == BASE_SPECIFIED_FORMAT)
-      return number_of_values -1;
+      return number_of_values - 1;
     return number_of_values;
   }
 
@@ -383,5 +625,29 @@ public class UserDataAlgorithm extends BaseAlgorithm
   {
     return new Float (average_value);
   }
-
+  
+  public int getWiggleStart(int index)
+  {
+    return wiggle[index].start;
+  }
+  
+  public int getWiggleSpan(int index)
+  {
+    return wiggle[index].span;
+  }
+  
+  public boolean isWiggleFormat()
+  {
+    if(FORMAT == WIGGLE_VARIABLE_STEP_FORMAT || 
+       FORMAT == WIGGLE_FIXED_STEP_FORMAT)
+      return true;
+    return false;
+  }
+  
+  class Wiggle
+  {
+    int start;
+    int step;
+    int span = 0;
+  }
 }