==============================================================================
===  TO DO  ==================================================================
==============================================================================
    Suport -sigdig flag
    Write README, instructions, etc.
    Create SilkGui
    Allow "energy" conversion to be done at user-specified temperature?
    Add NDimTable.writeNDT() -- a *sparse* binary format
    Let -wrap be specified per dimension
    Make climbHills return a List of peaks
        This is a bit hard, because you probably want the peak heights too.
        Which are gone when you overwrite them with peak labels.
        Maybe classifyByHills() shouldn't alter the table after all?

==============================================================================
===  CHANGE LOG  =============================================================
==============================================================================

### 0.96 ### dak
- Cleaned up code in util.RotamerSampler & added minor features; e.g. now can
  output commented peak coords before samples derived from that peak - could
  help with clustering the sample points later
- Added -hillassign mode: assign each discrete input data sample to nearest
  peak; sort & tally by peak
- Change to hillassign mode: now finds closest hill grid point to each data 
  sample *then* gets hill ID, rather than interpolating hill ID from neighbor
  hill grid points
- Fixed bug where -hills thought all hill IDs were ~equal b/c program was
  erroneously using density values in place of integer peak labels
...
- Changed a < to a <= in SilkCmdLine.doOutput(..) for -hillmodes output
- Fixed a hillmodes/hillassign bug involving the fictional "hill 0"

### 0.95 ### dak
- Tweaks to RotamerSampler...
- Added util.MonteCarlo class to sample dihedrals from Silk -energy output

### 0.94 ### dak
- Added -hillmodes option to output modal peak coordinates and values
- Sampling by util.RotamerSampler now starts at, not around, the min/max bounds
- util.RotamerSampler now accepts a modal peaks file and -degrees flag for 
  local sampling

### 0.93 ###
- added the "-counts" postprocessing option -- useful for Bayesian stats?
- clarified meaning of default output in the .help file
- added simple Bayesian mode (so far untested)
- did some simple tests of Bayesian mode; behaves as expected.
- added -color flag; updated help documentation.
- added @title to kinemage output

### 0.92 ###
- added "color" field to DataSample
- tried devising k-means algorithm for optimal sampling, but no luck yet

### 0.91 ###
- added more progress msgs to SilkEngine
- fixed NullPointer bug in hill-climbing code
- fixed modulo bug in
    chiropraxis.rotarama.NDFloatTable
    driftwood.isosurface.CrystalVertexSource
    silk.SilkEngine
  This second bug in Silk only affected the pre-wrapping of data points. Since
  NDimTable wraps again, the only effect SHOULD be on kinemage plots of points.
- added SilkOptions.aniso for anisotropic scaling of input data
  When used, it could potentially break the sparse table (it did once due to a
  bug). When not used (ie, == 1), it really shouldn't cause problems.
- documented the new -aniso and -crop switches
- implemented -crop for limiting data ranges

### 0.90 ###
- split NDimTable into abstract base class plus _Dense and _Sparse variants
  in preparation for trying the 7-D RNA backbone rotamers problem.
- pre-existing bug in wrapbin() -- this made previous results slightly wrong?
- finished out most functions in sparse (except i/o); we now allow rehashing
- made hill climbing separate from the other post-ops; it should always be last
- allowed NDimTable_Dense to read text files with "x y z 0.0" lines dropped
- moved writeText() to NDimTable itself
- tested text read and write for dense and sparse to ensure same results on all
- removed writeNDFT() from the public API
- altered hill climbing code so it could go into NDimTable; tested subclasses
- timing comparison for "make rota4":
    DENSE   user    4m05.483s
    SPARSE  user    4m42.074s
  Dense is slightly faster, but sparse can handle higher-dimensional data
  and requires less memory. I think I'll make sparse the default for now.
- finally wrote help page for SilkCmdLine

### 0.84 ###
- created KarplusTableToNDFT
- added documentation for Vince in the form of an OmniGraffle flowchart
- added "energy" postop for converting energies from probabilities

### 0.83 ###
- fixed bug in NDFT reading that zeroed out realcount for no reason.
- added ability to read back in the text data files that are written out.
- tested text read/write: output is identical to input
- created the silk.util package for task-specific helper programs
- created util.RotamerSampling for Homme's rotamer sampling task

### 0.82 ###
- accounted for merger of driftwood.string into driftwood.util

### 0.81 ###
- made TabDataLoader ignore lines starting with hash (#)
- fixed bug in SilkEngine where halfwidth and weight parameters to
  tallyGaussian and tallyCosine were reversed.
- same bug in SilkEngine.processDensityDependent
- started KinfilePlotter
- added wrapData() to SilkEngine
- made SilkEngine actually obey the -scale switch
- bundled with Top500-Angles package

### 0.80 ###
- created most classes
- started reworking NDFloatTable ==> NDimTable
- added recursiveCount to NDimTable
- wrote SilkOptions
- wrote DataSample
- wrote TabDataLoader
- wrote SilkCmdLine
- wrote SilkEngine