CHANGELOG

    ==============================================================================
    ===  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