Changeset 250


Ignore:
Timestamp:
Mar 30, 2007, 5:09:34 PM (16 years ago)
Author:
Johan Enell
Message:

there were some buggs ...

Location:
trunk/se/lu/onk/BaseFile/src/basefile
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/se/lu/onk/BaseFile/src/basefile/BASEFile.java

    r248 r250  
    2626import java.io.File;
    2727import java.io.IOException;
     28import java.io.PrintWriter;
    2829import java.io.RandomAccessFile;
    2930import java.util.ArrayList;
    30 import java.util.List;
     31import java.util.HashMap;
    3132
    3233public class BASEFile<R, S>
    3334{
     35  private final File file;
    3436  private final RandomAccessFile raf;
    35   private BASEFileAssaySection assaySection;
    36   private List<BASEFileSpotSection<R, S>> spotSections;
    37   private List<BASEFileSection> sections;
     37  private final boolean write;
     38  private BASEFileAssaySection assaySection = null;
     39  private ArrayList<BASEFileSpotSection<R, S>> spotSections = new ArrayList<BASEFileSpotSection<R,S>>();
     40  private ArrayList<BASEFileSection> sections = new ArrayList<BASEFileSection>();
     41  private HashMap<Integer, long[]> sectionPointers = new HashMap<Integer, long[]>();
     42 
    3843  private BASEFileSection currentSection = null;
    3944 
    40   public BASEFile(File file) throws BASEFileException
    41   {
    42     try
    43     {
    44       this.raf = new RandomAccessFile(file, "r");
     45  @SuppressWarnings("unchecked")
     46  public BASEFile(File file, String mode) throws BASEFileException
     47  {
     48    try
     49    {
     50      this.file = file;
     51      if ("r".equals(mode))
     52      {
     53        write = false;
     54        raf = new RandomAccessFile(file, "r");
     55        String line = raf.readLine();
     56        if (!"BASEfile".equals(line))
     57        {
     58          throw new BASEFileException("File "+file.getAbsolutePath()+" is no basefile. First line must be 'BASEfile'");
     59        }
     60        BASEFileSection bfs = readSection();
     61        while (bfs != null)
     62        {
     63          if (bfs instanceof BASEFileAssaySection)
     64          {
     65            if (assaySection != null)
     66            {
     67              throw new BadFormatException("This basefile already has an assay section");
     68            }
     69            assaySection = (BASEFileAssaySection) bfs;
     70          }
     71          else if (bfs instanceof BASEFileSpotSection)
     72          {
     73            spotSections.add((BASEFileSpotSection<R, S>) bfs);
     74          }
     75          else
     76          {
     77            sections.add(bfs);
     78          }
     79          bfs = readSection();
     80        }
     81      }
     82      else if("rw".equals(mode))
     83      {
     84        write = true;
     85        raf = new RandomAccessFile(file, "rwd");
     86      }
     87      else
     88      {
     89        throw new IllegalArgumentException("Mode must be 'r' or 'rw'");
     90      }
     91    }
     92    catch (IOException e)
     93    {
     94      throw new BASEFileException(e);
     95    }
     96  }
     97
     98  private BASEFileSection readSection() throws BASEFileException
     99  {
     100    try
     101    {
    45102      String line = raf.readLine();
    46       if (!"BASEFile".equals(line))
    47       {
    48         throw new BASEFileException("File "+file.getAbsolutePath()+" is no basefile. First line must be 'BASEFile'.");
    49       }
    50       spotSections = new ArrayList<BASEFileSpotSection<R,S>>();
    51       sections = new ArrayList<BASEFileSection>();
    52       BASEFileSection bfs = readSection();
    53       while (bfs != null)
    54       {
    55         if (bfs.isType("assays"))
    56         {
    57           this.assaySection = new BASEFileAssaySection(bfs);
    58           this.assaySection.setDataPointer(raf.getFilePointer());
    59         }
    60         else if (bfs.isType("spots"))
    61         {
    62           BASEFileSpotSection<R, S> spotSection = new BASEFileSpotSection<R, S>(bfs);
    63           spotSection.setDataPointer(raf.getFilePointer());
    64           this.spotSections.add(new BASEFileSpotSection<R, S>(bfs));
    65         }
    66         else
    67         {
    68           this.sections.add(bfs);
    69         }
    70        
    71         bfs = readSection();
    72       }
    73     }
    74     catch (IOException e)
    75     {
    76       throw new BASEFileException(e);
    77     }
    78   }
    79 
    80   private BASEFileSection readSection() throws IOException
    81   {
    82     long pointer = raf.getFilePointer();
    83     String line = raf.readLine();
    84     BASEFileSection bfs = null;
    85     while(line == null)
    86     {
    87       String[] head = line.split("\t", 2);
    88       if(head[0].equals("section") && head.length == 2)
    89       {
    90         bfs = new BASEFileSection();
    91         bfs.setStartPointer(pointer);
    92         bfs.setType(head[1]);
    93       }
    94       else if (head[0].equals("%") && bfs != null)
    95       {
    96         return bfs;
    97       }
    98       else if (bfs != null && head.length == 2)
    99       {
    100         bfs.setHeader(head[0], head[1]);
    101       }
    102       pointer = raf.getFilePointer();
    103       line = raf.readLine();
     103      BASEFileSection bfs = null;
     104      while(line != null)
     105      {
     106        String[] head = line.split("\t", 2);
     107        if(head[0].equals("section") && head.length == 2)
     108        {
     109          bfs = newSection(head[1]);
     110          sectionPointers.put(bfs.hashCode(), new long[]{raf.getFilePointer(), -1L});
     111        }
     112        else if (head[0].equals("%") && bfs != null)
     113        {
     114          bfs.init();
     115          if (bfs instanceof BASEFileDataSection)
     116          {
     117            sectionPointers.get(bfs.hashCode())[1] = raf.getFilePointer();
     118          }
     119          return bfs;
     120        }
     121        else if (bfs != null && head.length == 2)
     122        {
     123          bfs.setHeader(head[0], head[1]);
     124        }
     125        line = raf.readLine();
     126      }
     127    }
     128    catch (IOException e)
     129    {
     130      throw new BASEFileException(e);
    104131    }
    105132    return null;
    106133  }
    107 
     134 
     135  public final void addSpotSection(BASEFileSpotSection<R, S> bfss) throws BASEFileException
     136  {
     137    if (!write)
     138      throw new BASEFileException("Onlu aloud to set assaysection in write mode");
     139    spotSections.add(bfss);
     140  }
     141
     142  private BASEFileSection newSection(String type)
     143  {
     144    if (type.equals("assays"))
     145    {
     146      return new BASEFileAssaySection();
     147    }
     148    else if (type.equals("spots"))
     149    {
     150      return new BASEFileSpotSection();
     151    }
     152    else
     153    {
     154      return new BASEFileSection(type);
     155    }
     156  }
     157 
    108158  /**
    109159   * Get the assay section.
     
    122172   * @return a spot section.
    123173   */
    124   public BASEFileSpotSection<R, S> getSpotSection()
    125   {
    126     return spotSections.get(0);
    127   }
    128 
     174  public BASEFileSpotSection<R, S> getSpotSection() throws BASEFileException
     175  {
     176    if (spotSections.size() == 0)
     177    {
     178      throw new BASEFileException("No spot section avalible");
     179    }
     180    return getSpotSection(0);
     181  }
     182
     183  public BASEFileSpotSection<R, S> getSpotSection(int i)
     184  {
     185    return spotSections.get(i);
     186  }
     187
     188  public final void setAssaySection(BASEFileAssaySection bfas) throws BASEFileException
     189  {
     190    if (assaySection != null)
     191      throw new BASEFileException("Assaysection is already set");
     192    if (!write)
     193      throw new BASEFileException("Only aloud to set assaysection in write mode");
     194     
     195    assaySection = bfas;
     196  }
     197 
    129198  /**
    130    * Sets the current section two this section and sets the reading pointer to
     199   * Sets the current section to this section and sets the reading pointer to
    131200   * the data pointer of this section if it is a data section. If it an ordinary
    132201   * section the reading pointer is set to the start point.
    133202   *
    134203   * @param bfs the section
     204   * @throws BASEFileException if thee isn't part of this basefile or if the section
     205   *  lacks filepointer
    135206   */
    136207  public void setCurrentSection(BASEFileSection bfs) throws BASEFileException
    137208  {
    138     this.currentSection = bfs;
    139     try
    140     {
    141       if (bfs instanceof BASEFileDataSection)
    142       {
    143         this.raf.seek(((BASEFileDataSection) bfs).getDataPointer());
     209    try
     210    {
     211      long[] pointers = sectionPointers.get(bfs.hashCode());
     212      if (pointers == null)
     213      {
     214        throw new BASEFileException("This section is not part of this basefile");
     215      }
     216      currentSection = bfs;
     217      if (pointers[1] != -1)
     218      {
     219        raf.seek(pointers[1]);
     220      }
     221      else if (pointers[0] != -1)
     222      {
     223        raf.seek(pointers[0]);
    144224      }
    145225      else
    146226      {
    147         this.raf.seek(bfs.getStartPointer());
     227        throw new BASEFileException("This section has no file pointer");
    148228      }
    149229    }
     
    177257      if (line == null || line.equals(""))
    178258      {
    179         this.currentSection = null;
     259        currentSection = null;
     260        raf.seek(0);
    180261        return null;
    181262      }
    182263      else
    183264      {
    184         return line.split("\t", bfds.getDataLineLength());
    185       }
    186     }
    187     catch (IOException e)
    188     {
    189       throw new BASEFileException(e);
    190     }
    191    
     265        String[] ret = line.split("\t", -1);
     266        if (ret.length != bfds.getDataLineLength())
     267        {
     268          throw new BASEFileException("Dataline must have "+bfds.getDataLineLength()+" fields");
     269        }
     270        return ret;
     271      }
     272    }
     273    catch (IOException e)
     274    {
     275      throw new BASEFileException(e);
     276    }
     277  }
     278 
     279  public void validate() throws BASEFileException
     280  {
     281    assaySection.validate();
     282    for (BASEFileSpotSection<R, S> bfss : spotSections)
     283    {
     284      bfss.validate();
     285    }
     286    for (BASEFileSection bfs : sections)
     287    {
     288      bfs.validate();
     289    }
     290  }
     291
     292  public void write() throws BASEFileException
     293  {
     294    if (!write)
     295      throw new BASEFileException("This basefile isn't writable");
     296    try
     297    {
     298      validate();
     299     
     300      PrintWriter out = new PrintWriter(file);
     301      out.println("BASEfile");
     302      if (assaySection != null)
     303      {
     304        out.println(assaySection);
     305        for (int i = 0; i < assaySection.getHeight(); ++i)
     306        {
     307          assaySection.getDataLine(i);
     308        }
     309        out.println();
     310      }
     311      for (BASEFileSpotSection<R, S> bfss : spotSections)
     312      {
     313        out.println(bfss.toString());
     314        out.println("DATA");
     315        out.println();
     316      }
     317      out.close();
     318    }
     319    catch (IOException e)
     320    {
     321      throw new BASEFileException(e);
     322    }
    192323  }
    193324}
  • trunk/se/lu/onk/BaseFile/src/basefile/BASEFileAssaySection.java

    r249 r250  
    3030public class BASEFileAssaySection extends BASEFileDataSection
    3131{
    32   private final ArrayList<String> data;
     32  private final ArrayList<String> data = new ArrayList<String>();
    3333 
    3434  private final HashMap<Integer, Integer> idIndex = new HashMap<Integer, Integer>();
     35 
     36  public BASEFileAssaySection()
     37  {
     38    super("assays");
     39  }
    3540 
    3641  public BASEFileAssaySection(BASEFileSection bfs) throws BASEFileException
     
    4146      throw new BASEFileException("Section must be of type 'assays' to create an assay section.");
    4247    }
    43     int height = bfs.findIntOpt("count");
    44     int width = bfs.findStringOpts("columns").length;
    45     this.height = height;
    46     this.width = width;
    47     this.data = new ArrayList<String>(height*width);
     48    init();
    4849  }
    4950 
     
    6869  }
    6970 
     71  public final int getDataSize()
     72  {
     73    return data.size();
     74  }
     75 
    7076  public final List<String> getAnnotationColumns()
    7177  {
    72     return this.findFieldList("annotationColumns");
     78    return findFieldList("annotationColumns");
     79  }
     80 
     81  public final int getAnnotationColumnsColIndex(String col) throws BASEFileException
     82  {
     83    return getColIndex("annotationColumns", col);
    7384  }
    7485 
    7586  public final List<String> getColumns()
    7687  {
    77     return this.findFieldList("columns");
     88    return findFieldList("columns");
    7889  }
    7990 
    80   @Override
    81   public final int getCount()
     91  public final int getColumnsColIndex(String col) throws BASEFileException
    8292  {
    83     return this.findIntOpt("count");
     93    return getColIndex("columns", col);
    8494  }
    8595
     96  public final String setColumns(Object... values)
     97  {
     98    return setHeader("columns", values);
     99  }
     100
     101  public final String setAnnotationColumns(Object... values)
     102  {
     103    return setHeader("annotationColumns", values);
     104  }
     105 
    86106  @Override
    87107  public int getDataLineLength()
     
    89109    return getColumns().size();
    90110  }
     111
     112  @Override
     113  public String getDataLine(int i)
     114  {
     115    int index = i * getWidth();
     116    String line = data.get(index);
     117    for (int j = 1; j < getWidth(); ++j)
     118    {
     119      line += "\t" + data.get(index + j);
     120    }
     121    return line;
     122  }
     123
     124  @Override
     125  protected void init() throws BASEFileException
     126  {
     127    super.init();
     128    setHeight(getCount());
     129    setWidth(getColumns().size());
     130    data.ensureCapacity(getHeight()*getWidth());
     131  }
     132
     133  @Override
     134  public void addData(Object... data)
     135    throws BASEFileException
     136  {
     137    super.addData(data);
     138    addData((String[]) data);
     139  }
    91140 
     141  public void addData(String... data) throws BASEFileException
     142  {
     143    super.addData((Object[]) data);
     144    if (data.length != getWidth())
     145    {
     146      throw new BASEFileException("The data line must contain "+getWidth()+" items");
     147    }
     148    int idcol = getColumnsColIndex("id");
     149    int namecol = getColumnsColIndex("name");
     150    idIndex.put(new Integer(data[idcol]), this.data.size() + namecol - 1);
     151    for (String s : data)
     152    {
     153      this.data.add(s);
     154    }
     155  }
     156
     157  @Override
     158  public void validate()
     159    throws BASEFileException
     160  {
     161    super.validate();
     162    if (getHeader("annotationColumns") == null) throw new BadSectionException("Data section must contain annotationColumns header");
     163    if (getHeader("columns") == null) throw new BadSectionException("Data section must contain columns header");
     164    if (getDataSize() != getHeight() * getWidth()) throw new BadSectionException("The size of the data list is missmatch");
     165  }
    92166}
  • trunk/se/lu/onk/BaseFile/src/basefile/BASEFileDataSection.java

    r248 r250  
    3030 
    3131  protected int width;
    32 
    33   private long dataPointer;
    34  
    35   protected BASEFileDataSection()
    36   {
    37     super();
    38     dataPointer = -1;
    39   }
    4032 
    4133  public BASEFileDataSection(BASEFileSection bfs) throws BASEFileException
    4234  {
    4335    super(bfs);
    44     dataPointer = -1;
    4536  }
    4637 
    4738  public BASEFileDataSection(BASEFileDataSection bfds) throws BASEFileException
    4839  {
    49     super(bfds);
    50     dataPointer = bfds.getDataPointer();
     40    this((BASEFileSection)bfds);
     41    this.setWidth(bfds.getWidth());
     42    this.setHeight(bfds.getHeight());
    5143  }
    5244 
     45  protected BASEFileDataSection(String type)
     46  {
     47    super(type);
     48  }
     49
    5350  public int getCount()
    5451  {
    5552    return this.findIntOpt("count");
    56   }
    57  
    58   public long getDataPointer()
    59   {
    60     return this.dataPointer;
    6153  }
    6254
     
    7062    return width;
    7163  }
    72 
    73   public void setDataPointer(long pointer)
     64 
     65  public final String setCount(int c)
    7466  {
    75     this.dataPointer = pointer;
     67    return setHeader("count", c);
    7668  }
    7769
     
    8779
    8880  public abstract int getDataLineLength();
     81 
     82  public abstract String getDataLine(int i);
     83 
     84  public void addData(Object... data)
     85    throws BASEFileException
     86  {
     87    if (!isInitiated())
     88    {
     89      init();
     90    }
     91  }
     92
     93  @Override
     94  protected void init() throws BASEFileException
     95  {
     96    super.init();
     97  }
     98
     99  @Override
     100  public void validate() throws BASEFileException
     101  {
     102    super.validate();
     103    if (getHeader("count") == null) throw new BadSectionException("Data section must contain count header");
     104  }
    89105}
  • trunk/se/lu/onk/BaseFile/src/basefile/BASEFileSection.java

    r248 r250  
    6262  private String type;
    6363
    64   private long pointer;
     64  private boolean init = false;
    6565
    6666  /**
    6767   * Creates a new BASEFileSection.
    6868   */
     69  @Deprecated
    6970  public BASEFileSection()
    7071  {
    7172    startLine = -1;
    72     pointer = -1;
    7373    dataStartLine = -1;
    7474    type = "";
    7575  }
    7676
     77  /**
     78   * Creates a new BASEFileSection.
     79   */
     80  public BASEFileSection(String type)
     81  {
     82    startLine = -1;
     83    dataStartLine = -1;
     84    this.type = type;
     85  }
     86 
    7787  public BASEFileSection(BASEFileSection bfs) throws BASEFileException
    7888  {
     
    8292    }
    8393    startLine = bfs.getStartLine();
    84     pointer = bfs.getStartPointer();
    8594    dataStartLine = bfs.getDataStartLine();
    8695    type = bfs.getType();
     
    361370    return type;
    362371  }
     372 
     373  protected boolean isInitiated()
     374  {
     375    return init;
     376  }
    363377
    364378  /**
     
    378392   * @return the new type
    379393   */
     394  @Deprecated
    380395  public final void setType(String type)
    381396  {
     
    393408    this.dataStartLine = dataStartLine;
    394409  }
    395 
    396   public final void setStartPointer(long pointer)
    397   {
    398     this.pointer = pointer;
    399   }
    400 
    401410  public final int getStartLine()
    402411  {
     
    404413  }
    405414 
    406   public final long getStartPointer()
    407   {
    408     return pointer;
    409   }
    410 
    411415  public final void setStartLine(int startLine)
    412416  {
     
    434438    return ret;
    435439  }
     440
     441  protected void init() throws BASEFileException
     442  {
     443    if (init)
     444    {
     445      throw new BASEFileException("This section has already been initiated");
     446    }
     447    init  = true;
     448  }
     449
     450  public void validate() throws BASEFileException
     451  {}
    436452}
  • trunk/se/lu/onk/BaseFile/src/basefile/BASEFileSpotSection.java

    r248 r250  
    2929{
    3030
    31   private final ArrayList<S> spotData;
    32   private final ArrayList<R> reporterData;
    33    
     31  private final ArrayList<S> spotData = new ArrayList<S>();
     32  private final ArrayList<R> reporterData = new ArrayList<R>();
     33 
     34  public BASEFileSpotSection()
     35  {
     36    super("spots");
     37  }
     38 
    3439  public BASEFileSpotSection(BASEFileSection bfs) throws BASEFileException
    3540  {
     
    3944      throw new BASEFileException("Section must be of type 'spots' to create an assay section.");
    4045    }
    41     this.setHeight(bfs.findIntOpt("count"));
    42     this.setWidth(bfs.findStringOpts("assayFields").length * bfs.findStringOpts("assays").length + bfs.findStringOpts("columns").length - 1);
    43     this.spotData = new ArrayList<S>(height*width);
    44     this.reporterData = new ArrayList<R>(height);
     46    init();
    4547  }
    4648 
     
    4850  public BASEFileSpotSection(int height, int width)
    4951  {
    50     this.setType("spots");
     52    this();
    5153    this.height = height;
    5254    this.width = width;
    53     this.spotData = new ArrayList<S>(height*width);
    54     this.reporterData = new ArrayList<R>(height);
    5555  }
    5656 
     
    7878    return spotData.iterator();
    7979  }
    80 
    81   public boolean addData(R reporter, S... spots)
    82   {
    83     if (spotData == null || reporterData == null) return false;
    84     if (spots.length != width) return false;
    85     return reporterData.add(reporter) && spotData.addAll(Arrays.asList(spots));
     80 
     81  @SuppressWarnings("unchecked")
     82  @Override
     83  public void addData(Object... data)
     84    throws BASEFileException
     85  {
     86    super.addData(data);
     87    if (data.length < 2)
     88    {
     89      throw new BASEFileException("Must have at least two objects to add");
     90    }
     91    S[] spots = (S[]) new Object[data.length - 1];
     92    System.arraycopy(data, 1, spots, 0, spots.length);
     93    reporterData.add((R) data[0]);
     94    spotData.addAll(Arrays.asList(spots));
     95  }
     96
     97  public void addData(R reporter, S... spots) throws BASEFileException
     98  {
     99    Object[] data = new Object[spots.length + 1];
     100    data[0] = reporter;
     101    System.arraycopy(spots, 0, data, 1, spots.length);
     102    addData(data);
    86103  }
    87104 
     
    112129  }
    113130 
    114   public List<String> getColumnHeader()
     131  public List<String> getColumns()
    115132  {
    116133    return this.findFieldList("columns");
     
    122139  }
    123140
    124   public List<Integer> getAssaysHeader()
     141  public List<Integer> getAssays()
    125142  {
    126143    return this.findFieldIntList("assays");
     
    132149  }
    133150
    134   public List<String> getAssayFieldsHeader()
     151  public List<String> getAssayFields()
    135152  {
    136153    return this.findFieldList("assayFields");
     
    142159  }
    143160 
    144   public int getCountHeader()
    145   {
    146     return this.findIntOpt("count");
    147   }
    148  
    149161  public boolean isValid()
    150162  {
    151     if (getColumnHeader() == null) return false;
    152     if (getAssayFieldsHeader() == null) return false;
    153     if (getAssaysHeader() == null) return false;
     163    if (getColumns() == null) return false;
     164    if (getAssayFields() == null) return false;
     165    if (getAssays() == null) return false;
    154166    return true;
    155167  }
     
    185197  }
    186198
     199  public final int getChannels()
     200  {
     201    return findIntOpt("channels");
     202  }
     203 
     204  public final String setChannels(int channels)
     205  {
     206    return setHeader("channels", channels);
     207  }
     208
     209  public final String setExtraFloats(Object... values)
     210  {
     211    return setHeader("setExtraFloats", values);
     212  }
     213
     214  public final String setAssayFields(Object... values)
     215  {
     216    return setHeader("assayFields", values);
     217  }
     218
     219  public final String setColumns(Object... values)
     220  {
     221    return setHeader("columns", values);
     222  }
     223
     224  public final String setAssays(Integer... values)
     225  {
     226    return setHeader("assays", (Object[]) values);
     227  }
     228
    187229  @Override
    188230  public int getDataLineLength()
    189231  {
    190     int length = this.getColumnHeader().size() -1;
    191     length += this.getAssayFieldsHeader().size() * this.getAssaysHeader().size();
     232    int length = this.getColumns().size() -1;
     233    length += this.getAssayFields().size() * this.getAssays().size();
    192234    return length;
    193235  }
     236
     237  @Override
     238  public String getDataLine(int i)
     239  {
     240   
     241    return null;
     242  }
     243
     244  @Override
     245  protected void init() throws BASEFileException
     246  {
     247    super.init();
     248    setHeight(getCount());
     249    setWidth(getAssays().size());
     250    spotData.ensureCapacity(getHeight()*getWidth());
     251    reporterData.ensureCapacity(getHeight());
     252  }
     253
     254  @Override
     255  public void validate() throws BASEFileException
     256  {
     257    super.validate();
     258    if (getHeader("channels") == null) throw new BadSectionException("Data section must contain channels header");
     259    if (getHeader("assays") == null) throw new BadSectionException("Data section must contain assays header");
     260    if (getHeader("assayFields") == null) throw new BadSectionException("Data section must contain assayFields header");
     261    if (getHeader("columns") == null) throw new BadSectionException("Data section must contain columns header");
     262    if (getHeader("setExtraFloats") != null)
     263    {
     264      List<String> assayFields = getAssayFields();
     265      for (String s : findFieldList("setExtraFloats"))
     266      {
     267        if (!assayFields.contains(s))
     268        {
     269          throw new BadSectionException("Header assayFields must contain "+s);
     270        }
     271      }
     272    }
     273    if (getReporterSize() != getHeight()) throw new BadSectionException("The size of the reporter list and height doesn't match");
     274    if (getSpotSize() != getHeight()*getWidth()) throw new BadSectionException("The size of the spot list and height*width doesn't match");
     275  }
    194276}
Note: See TracChangeset for help on using the changeset viewer.