                       Changes in version 2.11.0                        

BUG FIXES

  - procspec() took the minimum and maximum used by opt = "minimum" and
    opt = "maximum" once, up front, before fixneg and before either
    scaling step ran. Each was then applied with the extremes of the
    data as it arrived rather than as it stood, so opt = c("minimum",
    "maximum") reported scaling to a maximum of 1 while returning (R -
    min) / max, which reaches 1 only for a spectrum whose minimum was
    already zero. fixneg combined with either scaling was off the same
    way. The extremes are now taken where they are used.
  - adjacent() returned Rab as exactly 1 for every image. The
    background-only mask was built with the same two lines as the
    animal-only mask, so the two transition sets were identical. It now
    masks the complement: everything inside the focal outline, or every
    colour class that is not a bkgID.
  - adjacent() computed B from two sampling grids built by different
    rules, a constant pixel step for the scene and a fixed number of
    points per axis for the animal. They agree only on square images,
    and B was inflated by roughly the aspect ratio on everything else.
    All three masks now share one grid.
  - adjacent() computed B and Rt against the whole scene's transitions
    rather than the object-background ones they are documented as ratios
    of, B = O_a_a / O_a_b and Rt = St_a_a / St_a_b. B was bounded in
    [0, 1] as a result, which the documented ratio is not.
    Object-background transitions are now taken as what the scene has
    left once the within-object and within-background transitions are
    removed.
  - adjacent() returned Inf for B, Rt and Rab together whenever either
    the focal object or the background lacked class-change transitions.
    Each is now guarded by the transitions it is built from, so a
    single-class background keeps B and Rt and reports Rab as NA.
  - voloverlap() now returns the correct result when x, y (and possibly
    z) columns in colsp1 and colsp2 are not in the same order.

                 Changes in version 2.10.0 (2026-09-14)                 

MAJOR CHANGES

  - sensmodel() gains a template argument, selecting the visual pigment
    template used to generate sensitivity curves. It names both the
    author and the chromophore, since a template's shape depends on
    both, and defaults to "govardovskii_a1", which is what every
    previous version of the function used. "govardovskii_a2" adds the
    vitamin A2 template from the same paper, and "ssh_a1" and "ssh_a2"
    the two from Stavenga, Smits and Hoenders (1993). The A2 templates
    cover porphyropsin pigments, found in freshwater fish, amphibians,
    and species that switch chromophore seasonally, which pavo
    previously could not model at all: an A2 band is close to 20%
    broader than the A1 band at the same peak sensitivity, so it is not
    recovered by adjusting peaksens. "govardovskii_a2" is the one to
    reach for, since pairing it with the default compares chromophores
    without also changing template family. The template used is recorded
    as a "template" attribute on the result. Note that beta = FALSE is
    recommended with either SSH template: their beta band has a fixed
    peak wavelength rather than one that scales with peaksens, so for
    short-wavelength pigments it pulls the maximum of the summed curve
    several nm away from the value asked for, and sensmodel() warns
    where that shift exceeds 5 nm. The alpha band on its own is
    unaffected, both Govardovskii beta bands scale with peaksens and do
    not have this problem, and Stavenga (2010) notes the fixed beta peak
    to be a known shortcoming.

  - bootcoldist() gains a ci.type argument, allowing bias-corrected and
    accelerated (BCa) confidence limits as an alternative to the
    percentile limits it has always returned. Colour distances are
    bounded below by zero and typically right-skewed, so percentile
    limits tend to sit off-centre; BCa corrects for that skew and for
    where the empirical distance falls in the bootstrap distribution.
    The acceleration term comes from a jackknife leaving out one row at
    a time, or one cluster where cluster is supplied. The default
    remains "perc".

  - bootcoldist() gains a cluster argument for hierarchically structured
    data, such as several patches per individual, or repeated
    measurements of one individual. Bootstrap replicates then resample
    whole clusters rather than rows, so non-independent observations
    stay together and the effective sample size is the number of
    clusters. The nesting argument controls whether clusters span the
    levels of by ("crossed", one draw shared across groups, preserving
    their pairing) or sit within one level ("nested", drawn
    independently per group), and defaults to detecting which applies.
    Empirical means are unaffected, and results are unchanged when
    cluster is NULL.

  - bootcoldist() gains a correct argument, which removes the upward
    bias in the distance between group means that comes of those means
    being estimated rather than known. Distance is convex in the error
    of a mean, so two noisy centroids sit further apart than the true
    ones, and two samples of one population are separated by an
    apparently non-zero distance. On the squared scale the displacement
    is the sum over groups of the mean squared pairwise distance among a
    group's observations divided by twice their number, so it is worst
    for small, variable groups and does not fall away as the true
    separation approaches zero. It is therefore largest exactly where
    discriminability is in question. correct = TRUE subtracts it from
    the empirical distance and from every bootstrap replicate, each
    using the observations it drew.
    
    Where cluster is supplied the correction works on clusters rather
    than rows, matching what is resampled; from rows it can understate
    the displacement several-fold. Where the design is crossed, the two
    group means are correlated and the correction uses each individual's
    own paired difference, which carries that covariance; treating the
    groups as independent would subtract several times too much. Partly
    crossed designs are refused, as is nesting = "nested" where clusters
    in fact span groups.
    
    The subtraction is exactly unbiased on the squared scale. Its square
    root errs slightly low, so a corrected distance is a little
    conservative. Exactness also assumes clusters of roughly equal size;
    under marked imbalance the between-cluster part is under-corrected
    and the within-cluster part over-corrected, so the net direction
    depends on which dominates. The correction is unavailable under
    quantum noise, in the CIELAB, CIELCh and coc spaces, for achromatic
    contrast in a colourspace model, and with ci.type = "bca". The
    default is FALSE, so results are unchanged unless it is asked for.

  - procspec() gains a new "clip" option, controlled by the new
    clip_range argument to remove entire regions of the spectra and
    replace them by linear interpolation. Code contributed for by
    @rscherrer, addressing issue #271.

  - the rimg2cimg() function has been removed in favour of a custom
    as.cimg() method.

MINOR CHANGES

  - bootcoldist() with correct = TRUE now returns the signed corrected
    square as the "dS.sq" attribute of the result. Flooring at zero is a
    presentation choice, since a negative squared distance cannot be
    reported as a distance, but the signed value is the quantity the
    correction is unbiased for and the one to carry into a further
    calculation.
  - bootcoldist() now validates achromatic, erroring where it is not a
    single TRUE or FALSE.
  - bootcoldist() now says how many bootstrap replicates failed and why,
    where it previously discarded the error and reported only that
    "Bootstrap sampling encountered errors". A run in which every
    replicate failed used to produce an unrelated error about a
    comparison of length zero, and is now reported like any other
    failure.
  - bootcoldist() now fails with an informative error when boot.n is too
    small for the requested alpha. Previously the lower quantile index
    rounded down to zero, and the interval failed to assemble with an
    unrelated message about mismatched dimnames. With the default alpha
    this affected any boot.n below 20.
  - default values for some arguments in explorespec() and sensmodel()
    are now explicit in the function definition.
  - as.rspec() now works out of the box with tibble, rather than
    requiring users to pass a standard data.frame.
  - argument checks in colspace() internal functions (dispace(),
    trispace(), hexagon(), etc.) have been refactored (#263), with two
    minor user-facing consequences:
      - some messages in tcspace() have been converted to warnings for
        consistency with the other internal colspace functions
      - some error messages are been reorder, which means that errors
        produced for inputs invalid for multiple reasons may appear in a
        different order than in previous versions.
  - pavo now uses R 4.1 (released in 2021) as the minimum required R
    version.

BUG FIXES

  - coldist() with noise = "quantum" built the photon-noise term from
    log-transformed quantum catches whenever qcatch = "Qi", rather than
    from the catches themselves. The term is 2 / (Qa + Qb) and was being
    computed as 2 / (log Qa + log Qb), which inflates the noise,
    deflates the resulting distances, and leaves the quantum model short
    of the neural one however bright the illuminant. Results were
    correct for qcatch = "fi" input throughout. If you have run
    coldist() or bootcoldist() with noise = "quantum" and qcatch = "Qi"
    on any version from 2.4.0 onward, those distances need
    recalculating. Reported by Changku Kang, issue #281.
  - Following the above, quantum catches below one are no longer an
    error in coldist(). They describe a dim, photon-limited stimulus,
    and give small distances rather than negative log catches.
    Non-positive catches remain an error, since the noise term is
    undefined for them.
  - coldist() with noise = "quantum" and achromatic = TRUE returned NA
    for the achromatic distances to the reference stimuli that anchor
    jnd2xyz(). Those were then read as zeros, putting the achromatic
    reference on top of the data. Luminance coordinates from jnd2xyz()
    change for quantum-noise models; under the default center = TRUE
    only the stored reference coordinates move.
  - sensmodel() now generates the same sensitivity curve for a given
    peaksens whatever range is requested. The alpha-band expression of
    Govardovskii et al. (2000) contains a constant of 300 nm, which was
    coded as range[1]. Since the two coincide at the default range =
    c(300, 700), curves were correct for that range and for any range
    sharing its lower bound. Users who called sensmodel() with a lower
    bound other than 300 nm should consider regenerating their
    sensitivities and rerun any downstream vismodel() or coldist()
    results. Everyone else is unaffected and results are unchanged.
  - jndrot() and by extension jnd2xyz() have been adjusted for
    trichromats to only allow rotations in the 2D plane. Until now, 3D
    rotations were allowed and the result was projected back in 2D but
    this meant that the output was no longer representing JNDs
    distances. Because rotate = TRUE is the default in jnd2xyz(), we
    recommend you re-run any jnd2xyz() computation on trichromats. From
    our tests, results stay qualitatively similar but specific values
    may change.
  - bootcoldist() now summarises colspace() objects by the arithmetic
    mean of their coordinates, rather than a geometric mean of
    coordinates shifted by an arbitrary constant of 100. Distances in a
    colour space are measured in the coordinates themselves, so a
    group's centroid is their arithmetic mean. Quantum catches and
    luminance channels stay geometric, since those distances are linear
    in the logged values. Colspace distances change slightly. CIELAB,
    CIELCh and segment, whose coordinates can be negative, previously
    returned NaN and now work.
  - bootcoldist() now summarises qcatch = "fi" models by an arithmetic
    mean of the log catches rather than a geometric one, so reported
    distances for such models change. fi values are already log(Qi), and
    their geometric mean is not a centroid: "Qi" and "fi" models of the
    same data disagreed by around 6% on the bundled sicalis data, and
    the distance depended on the factor the illuminant was scaled by,
    though scaling shifts every log catch equally and cannot change a
    chromatic distance. Calls that returned NaN because an unscaled
    illuminant made log catches negative now work.
  - bootcoldist() now takes qcatch from a vismodel or colspace object's
    attribute, as coldist() always has, rather than letting an argument
    override it. Results change only where the two disagreed, in which
    case the old behaviour was wrong.
  - bootcoldist() now errors where any bootstrapped distance is NA,
    rather than silently taking confidence limits from the wrong order
    statistics. The usual cause is achromatic = TRUE on a model built
    without an achromatic channel.
  - bootcoldist(raw = TRUE) now returns bootstrap distances in replicate
    order. Each contrast was previously sorted independently before
    being returned, so values sharing a row came from different
    resamplings, and neither different contrasts nor dS and dL could be
    compared with one another. The values themselves are unchanged, only
    their order.
  - the values of avg.uv and avg.v visual systems used in sensdata() and
    vismodel() have been updated to match exactly the ones provided in
    the original source (Endler & Mielke 2005). This may result in
    minute changes in the values returned by vismodel() if you are using
    these parameters.

INTERNAL CHANGES

  - dependency on the viridisLite package has been removed in favour of
    recent base R functions

                 Changes in version 2.9.0 (2023-09-24)                  

NEW FEATURES AND SIGNIFICANT CHANGES

  - Added a new function simulate_spec(), which allows for the flexible
    simulation of naturalistic spectra (inc. reflectance, irradiance,
    radiance, absorbance). See ?simulate_spec for examples and
    information, and the handbook for further discussion.
  - plot.rspec() now accepts a logical labels argument (and labels.cex),
    to control whether text labels identifying each spectrum should be
    added to the outer plot margins. This was previously only available,
    and was required, for 'stacked' plot types, but is now optional for
    both 'overlay' (the default) and 'stacked' spectral plots.
  - the wlmin and wlmax arguments in summary.rspec() are being
    deprecated in favour of a single lim argument, for consistency
    across functions.

MINOR FEATURES AND BUG FIXES

  - summary.rspec() has been rewritten for efficiency, and now only
    calculates the required variables when subset is used. As a result,
    the function is also slightly slower (0.5 x) when calculating the
    full set of variables, but much faster (10 x) when calculating a
    subset.
  - Removed the start-up message.
  - Removed the previously-deprecated margins argument from various
    colourspace plots.
  - Replace rgl.triangles with triangles3d() internally to avoid a
    deprecation issue.
  - Fixed a bug in the categorical colourspace, so it now returns
    sensible category values when x and/or y is equal to 0.

                 Changes in version 2.8.0 (2022-08-16)                  

MINOR FEATURES AND BUG FIXES

  - Updated documentation to fix broken HTML5 equation rendering
  - Line width in the legend of aggplot() (as specified by lwd) is now
    consistent with line width on the plot (#235)
  - procspec(spec, opt = "smooth") now works correctly with
    uninterpolated spectra. Previously, it was causing a shift of the
    spectra towards long-wavelengths (#234).
  - coldist() now returns Euclidean distances when given data from the
    ciexyz model.
  - as.rspec() now preserves numeric column names when converting from a
    tibble.

                 Changes in version 2.7.1 (2021-09-21)                  

MINOR FEATURES AND BUG FIXES

  - Minor release to avoid breaking changes to tests.

                 Changes in version 2.7.0 (2021-03-23)                  

NEW FEATURES AND SIGNIFICANT CHANGES

  - It is now possible to filter images according to the AcuityView 2.0
    algorithm (Caves et al. 2018) in order to to model the visual acuity
    of animals, prior to analysis. The functionality is implemented in
    procimg(), with details and examples available in the function's
    help documentation and the vignette.
  - Added the argument raw to bootcoldist(). When TRUE, the full raw
    list of bootstrapped colour-distances are returned (equal in length
    to the number of replicates specified by boot.n), rather than the
    summary statistics which are returned by default.
  - Added the visual phenotype of the Vinegar fly Drosophila
    melanogaster (Sharkey et al. 2020). See ?vismodel() or ?sensdata()
    for instructions on selecting it.
  - coldist() now uses the package farver when calculating CIE2000
    colour distances between points in the CIELab and CIELch spaces.

MINOR FEATURES AND BUG FIXES

  - Fixed a bug where procimg() would fail when using resize/rotate
    followed by further options, on single images.
  - vignettes have been moved to https://book.colrverse.com/ and now use
    a book format
  - Fixed a bug in plot.colspace(gamut = TRUE) (as well as triplot(),
    tcsplot(), tetraplot()) where it would incorrectly display "Max
    gamut cannot be plotted." and fail to plot the max gamut each time.
  - Fixed a recent bug whereby the D65 illuminant was expressed in units
    of radiant flux, by default. It has instead been converted to photon
    flux (umol.s-1.m-2).
  - Added an informative error message when raw quantum catch estimates
    are < 1, and an attempt is made to calculate colour distances in the
    receptor-noise model using noise = 'quantum'. Taking the root of
    negative values following log-transformation, as required when noise
    = 'quantum', would previously produce an uninformative error, which
    has been rectified.
  - The margins argument has been deprecated for cie, coc, hexagon,
    segment, projplot, di-, tri-, and tetra-chromatic plots. It was
    causing problems when later adding points to plots, and
    margin-handling is best left to the user anyway. The default plots
    may therefore look slightly different, but the margins can be
    adjusted to taste using the standard par(mar = c()) pathway.
  - Fixed a bug where bootcoldist() would not run until supplied with
    receptor-noise model arguments (n, weber, weber.ref), even when not
    running the receptor-noise model.
  - Fixed a bug where bootcoldist() would sometimes fail when given data
    from colourspace models containing lots of negative coordinate
    values. This was particularly common for the hexagon model.
  - Improved safety and error handling in adjacent().

                 Changes in version 2.6.1 (2020-12-18)                  

MINOR FEATURES AND BUG FIXES

  - Minor fix to a vignette to avoid installation issues.
  - options() and par() are now always set locally, including in
    vignettes and examples, as to prevent spillover of these changes in
    the user session

                 Changes in version 2.6.0 (2020-12-09)                  

MINOR FEATURES AND BUG FIXES

  - bootcoldist() and adjacent() now use a random number generator that
    generates statistically sound values, even when ran in parallel. The
    output of these functions is thus expected to slightly change, even
    if you set the seed before.
  - The alphashape3d package has been moved to Suggests, which means it
    will not be installed automatically when you install pavo from CRAN
    and that you will need to install it yourself if you need it (for
    vol(type = "alpha"), vol(type = "alpha") and voloverlap(type =
    "alpha"))

                 Changes in version 2.5.0 (2020-11-12)                  

NEW FEATURES AND SIGNIFICANT CHANGES

  - Add ability to compute colour volume by using alphashapes instead of
    convex hulls. The functions vol(), tcsvol() and voloverlap() gain a
    new argument type = c("convex", "alpha") to decide how you want to
    compute the colour volume. Please refer to the vignette
    vignette("pavo-5-alphashapes", package = "pavo") for more
    information. As a result, the argument order in these 3 function has
    changed. Check the documentation to update your scripts accordingly.
    The function summary.colspace() also gains an additional column that
    returns that colour volume computed with an alpha-shape of parameter
    alpha* in the case of tcs objects.

MINOR FEATURES AND BUG FIXES

  - getimg() now imports image files with uppercase extensions (e.g.,
    JPG or PNG), such as those produced by some camera brands or
    processing software.
  - Maximum quantum catches computation (data.maxqcatches attribute) now
    works for segment "visual model" as well. As a side effect, this
    removes a warning that occurred when users ran vismodel(..., visual
    = "segment").
  - sensmodel() now accepts the argument sensnames, for specifying the
    names of the resulting sensitivity curves on-the-fly.
  - CIE models now accept data created outside of vismodel(), by
    allowing users to specify the illuminant and viewer sensitivity
    function used when estimating XYZ values (via illum and visual
    arguments in colspace()).
  - bootcoldist() is now laxer in its argument checks and accept objects
    that are neither vismodel or colspace objects. This means you can
    now use this function on quantum catches dataframe that you obtained
    outside of pavo, such as the MICA toolbox.
  - summary.colspace() now prints a more explicit error when the by
    argument value is not a multiple of the number of rows in the
    colspace object (i.e., the number of spectra)
  - Added a continuous measure of hue to the output of the categorical
    model of Troje (1993)
  - teal example dataset columns have been renamed to add an additional
    zero in front of single digit numbers, so that column names now sort
    in the correct order by default.
  - Some very small negative values in the built-in visual system data
    have been corrected .
  - as.rspec() is now more lenient for wavelength trimming when interp =
    FALSE and now works even if the specified lims do not correspond to
    actual wl values from the input object.

                 Changes in version 2.4.0 (2020-02-08)                  

NEW FEATURES AND SIGNIFICANT CHANGES

  - Fixed a bug introduced in version 2.3.0 that gave wrong values for
    S1UV and S1V in summary.rspec().
  - several plot() functions for colspace (triplot(), tcsplot(),
    tetraplot()) gain a new gamut argument to plot the maximum gamut for
    a given visual system and illuminant. summary.colspace() also now
    returns the maximum colour volume for a given visual system and
    illuminant that you can use to compare to the realised volume by a
    given dataset. More information in PR #180.
  - parallel processing now relies on the future package, which offers
    windows and high performance computing (HPC) environments support.
    The progress bar is produced by the progressr package and can be
    customised as well. As a consequence, the cores argument in
    getspec(), adjacent() and classify() has been deprecated.

MINOR FEATURES AND BUG FIXES

  - fixed a plotting bug introduced in version 2.3.0 where it was
    required to run projplot() twice for the background grid to be
    displayed.
  - fixed a bug in summary.colspace() where NULL was returned instead of
    summary.data.frame() for non-tcs colourspaces.
  - fix partial matching warnings in examples and in bootcooldist()
  - the package has a new website at pavo.colrverse.com
  - fixed a bug in coldist()that prevented the calculation of achromatic
    contrast when using custom quantum catch data

                 Changes in version 2.3.0 (2019-12-11)                  

NEW FEATURES AND SIGNIFICANT CHANGES

  - plot.rspec() now adds a linear spectrum alongside the x-axis to show
    the hues corresponding to each wavelength (controlled by the
    wl.guide boolean argument).
  - cieplot() (and therefore plot.colspace() for CIEXYZ model) now adds
    the background of the CIEXYZ colour space by default. This can be
    turned off by switching the ciebg argument to FALSE.
  - voloverlap() uses a different algorithm to determine volume
    overlaps, which means:
      - computation is now much more efficient
      - voloverlap() now works for trispace() objects as well
      - accordingly, first two arguments of voloverlap() has been
        renamed colsp1 and colsp2 instead of tcsres1 and tcsres2
      - slow and possibly inaccurate montecarlo option has been
        deprecated

MINOR FEATURES AND BUG FIXES

  - errors during argument checks in vismodel() now have more explicit
    messages.
  - all pavo functions (excepted vismodel() and spec2rgb()) now work
    with sub-nm precision, for rspec objects with non-integer
    wavelengths.
  - summary.colspace() no longer fails for tcs objects with only one
    row.
  - vismodel() now works for monochromats as well.
  - procspec(opt = "bin") no longer counts bin edges twice (once in each
    consecutive bin). This will cause changes in the bin stops compared
    to earlier versions of this function.
  - coc() and categorical() spaces now return Weber luminance contrast
    by default when passed through coldist(), rather than nothing (as
    per the original publications).
  - coldist() can now take multiple values for weber, when Weber
    fractions are known for all receptor classes
  - summary.rspec() no longer errors for a single spectrum when the
    wavelength range does not contain 450-700nm

                 Changes in version 2.2.0 (2019-06-25)                  

NEW FEATURES AND SIGNIFICANT CHANGES

  - added k-medoids clustering as an option in classify()
  - coldist() now returns unweighted Euclidean distances for generic
    di-, tri-, and tetra-chromatic colspace() models. Users wishing to
    estimate noise-weighted distances (i.e. via the receptor-noise
    limited model) should continue to use coldist() directly on
    vismodel() objects, as previously.

MINOR FEATURES AND BUG FIXES

  - added a message to indicate what distance metric is being calculated
    during calls to coldist()
  - vismodel(), colspace(), and coldist() now always return lum and dL
    columns, for consistency
  - irrad2flux() and flux2irrad() use slightly more precise constant
    values, which may lead to slightly different results (less than 0.1%
    difference between this new version and the previous versions)
  - getimg() can now import images from URL's
  - the cores argument in getimg() is deprecated, as image import is
    vectorised
  - fixed a small bug in classify() when using refID and kcols for
    multiple images
  - the resize argument in procimg() now takes a percentage, rather than
    scaling factor
  - fixed a bug where colspace(space = segment) would return both a B
    and (redundant) lum column
  - fixed a bug where the rod sensitivity of Canis familiaris was
    inaccessible through vismodel()
  - fixed an issue in getspec() where badly encoded characters in some
    spectral files would cause failure
  - fixed a bug where coldist() would attempt to estimate receptor-noise
    weighted distances rather than cie-distances for cielch model
    results

                 Changes in version 2.1.0 (2019-03-06)                  

NEW FEATURES AND POTENTIALLY BREAKING CHANGES

  - added the argument reclass to procimg(), which allows users to
    interactively correct areas within images that have been
    misclassified
  - added the rod sensitivity of Canis familiaris
  - peakshape() uses a completely different algorithm to find the FWHM.
    It now works as expected for spectra with multiple peaks. See PR
    #137 for a detailed overview of the changes.
  - data used internally by pavo (bgandilum, transmissiondata, ttvertex,
    vissyst) is no longer exposed to users

MINOR FEATURES AND BUG FIXES

  - new functions is.vismodel() and is.colspace() are exported to test
    whether an object is of class vismodel or colspace, respectively
  - fixed a bug where images would sometimes be wrongly detected as
    user-classified in as.rimg()
  - the UV-sensitive cone is now only always named "u", even for VS
    species (such as pfowl and avg.v in vismodel() and sensdata()). This
    removes an unnecessary but harmless warning when colspace() was used
    to place quantum catches of such species in the tetrahedral colour
    space.
  - the achro argument in coldist() has been changed for achromatic to
    better match the arguments from vismodel(). Older scripts that use
    achro should not be affected and still work as before.
  - the package imager is no longer a dependency, and is only loaded if
    using some features of procimg().
  - the package mapproj is no longer a dependency, and is only loaded if
    using projplot().
  - added the argument labels.stack to plot.rspec, which allows the use
    of custom spectra labels in stacked plots.
  - users now receive a warning when interpolating beyond the limits of
    the data using as.rspec, and can control the behaviour with the new
    argument exceed.limits.
  - all deprecated functions and arguments have now been fully removed.
  - as.rspec() now accepts both numeric and character vectors to
    identify the wavelength column using whichwl (eg. whichwl = "wl").\
  - Reference images in classify() can now be specified using either a
    numeric vector (to identify by image position in a list) or
    character vector (to identify by image name).\
  - fixed a bug in aggspec() when wavelength column was previously
    removed by the user.
  - fixed a bug where cocplot() would failed whenever type graphical
    parameter was specified.
  - spec2rgb() has been simplified to rely more on vismodel(). As a
    result, output values may be slightly different but upon testing, we
    found that differences between the old and the new version were
    barely noticeable.
  - the vignette have been split into three smaller parts, which should
    help new users to get started with pavo
  - numerous under-the-hood changes for stability and speed, with thanks
    to three reviewers and an associate editor at MEE.

                 Changes in version 2.0.0 (2018-09-22)                  

NEW FEATURES

  - image-based workflow for the combined analysis of colour and pattern
    geometry
  - added the visual systems of the (trichromatic) jumping spider
    Habronattus pyrrithrix and the (trichromatic) triggerfish
    Rhinecanthus aculeatus
  - getspec() can now read Avantes binary files (.TRM files)

MINOR FEATURES AND BUG FIXES

  - Carotenoid chroma (S9) in summary.rspec() has been fixed to (R700 -
    R450)/R700. This gives the same result as before but with a flipped
    sign, and better reflects the original formula in the literature.
  - cieLAB values have been rescaled, and are expressed in the more
    standard range: L [0,100], ab [-128,127]
  - getspec() has an additional argument ignore.case set to TRUE by
    default to ignore case in file extension matching
  - fix a bug where getspec() would sometimes fail with files including
    numbers in scientific format
  - add a new option in tetraplot() to add cone names (u,s,m,l)

                 Changes in version 1.4.0 (2018-07-11)                  

NEW FEATURES

  - getspec() can now read OceanOptics .ProcSpec files
  - added the visual system of Ctenophorus ornatus, the (trichromatic)
    ornate dragon lizard

MAJOR CHANGES

  - getspecf() (and the argument fast = TRUE in getspec()) have been
    deprecated
  - summary.rspec() returned incorrect values for S7. If you use S7,
    please re-run your analyses

MINOR FEATURES AND BUG FIXES

  - summary.rspec() now properly outputs NA for monotonically decreasing
    spectra
  - fixed warning when subset.rspec() was provided with a logical vector
  - fixed harmless warning when summary.colspace() was used on a tcs
    object
  - by argument in merge.rspec() is no longer ignored
  - fixed bug in voloverlap() when plot = TRUE
  - fixed bug in vismodel() when transmission has more than one column
  - fixed bug in vismodel() that applied von Kries correction to
    achromatic channel
  - added argument fill=FALSE in voloverlap()
  - fixed bug in jndplot() when suppressing the plotting of arrows
  - better handling of subset data when using summary.colspace() and
    summary.vismodel()
  - fixed bug in coldist() when noise = "quantum" and achro = TRUE were
    used
  - fixed bug in jndplot() when arrow = "none" and achro = TRUE
  - spec2rgb() now takes into account the 390-400 nm wavelength range
    into account when possible
  - as.rspec() no longer fails with tibbles
  - bin option of procspec() now works for all values of bins
  - non-relative quantum catches from dataframe object were not
    correctly scaled in "di", "tri", "categorical" and "coc" colorspaces
  - fixed a bug in colspace() where it would incorrectly infer a
    preference for a general trichromatic space, when a cie model is
    more appropriate
  - fixed a bug so that cie color matching functions can be more easily
    be used in a general trichromatic space (i.e. maxwell triangle)

                 Changes in version 1.3.1 (2017-10-02)                  

NEW FUNCTIONS

  - bootcoldist() uses bootstrap to calculate the confidence intervals
    on the mean color distance between samples

MINOR FEATURES AND BUG FIXES

  - fixed bug in coldist() when fewer samples than the number of
    photoreceptors
  - fixed bug in getspec() that would cause it to crash with errors
  - fixed bug in tetraplot() when saving images

                 Changes in version 1.3.0 (2017-09-20)                  

NEW FUNCTIONS

  - jnd2xyz() converts distances (in JND, resulting from a coldist()
    call) into cartesian coordinates
  - plot() methods for objects resulting from jnd2xyz()
  - jndrot() produces rotations of Cartesian coordinates resulting from
    jnd2xyz()
  - coldist2mat() converts coldist() result from a pairwise data.frame
    to a distance matrix
  - sensdata() function for retrieving and/or visualising pavo's
    in-build spectral data

MAJOR CHANGES

  - tetraplot() and cieplot() have been completely rewritten to allow
    finer viewing control
  - tetraplot() allows forced perspective using size to denote distance
  - voloverlap() and vol() have also been changed to work with the new
    tetraplot() options
  - getspec() has been rewritten to be faster, more general, and allow
    parallel processing
  - subset functions now allow more than one argument to be used, and
    allow further attributes to be passed onto grep (e.g. invert = TRUE)

MINOR FEATURES AND BUG FIXES

  - fixed bug in coldist() on log-transformation when object was neither
    of class vismodel nor colspace
  - fixed bug in dL calculation when input is a colspace object
  - fixed bug in vismodel() when a data frame, matrix or rspec object
    was passed as the background
  - fixed bug in colspace() models when using non-standard receptor
    names or ordering
  - fixed bug in hexagon() model when calculating location & metrics for
    achromatic stimuli
  - fixed location of red vertex in tetraplot()
  - fixed bug in the argument names for expanding text labels in
    colspace plots
  - removed na.rm argument from aggspec() that was causing a bug when
    the error function did not have that argument. User should pass it
    as an argument to the function if necessary.
  - changed default to achro=FALSE in coldist()
  - replaced the modelled receptor sensitivities of the honeybee Apis
    mellifera with the empirical sensitivities from Peitsch et al (1992)
  - the built-in 'green' background spectrum is no longer normalized
  - removed wavelength limitations in the calculation of H3 from
    summary.rspec
  - all visual systems (except CIE) have been normalized to have an
    integral of 1

                        Changes in version 1.2.0                        

MAJOR CHANGES

  - added the CIELch model accessed via colspace(space = 'cielch')
  - added the sensdata() function for retrieving and/or visualising
    pavo's in-build spectral data

MINOR FEATURES AND BUG FIXES

  - vignettes have been amalgamated & the single, main vignette is now
    up-to-date
  - added more informative labels for the segment analysis plot

                 Changes in version 1.1.0 (2017-05-05)                  

NEW FUNCTIONS

  - segspace() replaces the deprecated segclass(), and is accessed via
    the colspace() argument space = 'segment'. The results of segspace()
    are also now compatible with coldist() for the estimation of
    Euclidean colour-distances.
  - segplot() is a plot for Endler's (1990) segment analysis, and is
    accessed --- along with all other 2d plots --- via plot.colspace()

MINOR FEATURES AND BUG FIXES

  - the use of relative quantum catches is now optional in the
    categorical colorspace (though still produces a warning), for
    greater flexibility
  - updated several functions to work when rspec object has only one
    spectrum
  - fixed bug in voloverlap where interactive plots would result in
    error
  - fixed incorrect labels in the maxwell triangle plot
  - fixed a bug in as.rspec() in which lim was not applied when
    interpolate = FALSE
  - fixed bug in aggplot() which resulted in error when using lty, lwd
    arguments
  - warning if ocular media is being used in both vismodel() and
    sensmodel()
  - added an 'all' option to the achromatic argument in vismodel()
  - added the ability to calculate dL for cielab models in coldist()
  - added some more informative messages and warnings

                         Changes in version 1.0                         

  - See vignette for detailed description of changes.

MAJOR CHANGES

  - coldist() arguments have been changed. Now the empirically estimated
    value for the Weber fraction must be entered, instead of the
    noise-to-signal ratio. The noise-to-signal ratio is then calculated
    based on the empirically estimated Weber fraction for the reference
    cone type, and applied to the remaining cone types. This should
    avoid confusion between empirically estimated values for the Weber
    fraction and the noise-to-signal ratio, which are currently
    prevalent in the literature.
  - coldist() now has an additional argument, weber.achro, so that the
    value for the Weber fraction to be used to calculate achromatic
    contrast can be input independently of the cone ratios.
  - tcs() is deprecated, replaced by colspace().

NEW FUNCTIONS

  - colspace() replaces tcs() and introduces several new colorspaces
  - plot() methods for several colspace() outputs, including a static
    tetrahedral colorspace
  - projpoints() allows the plotting of points in a projplot() figure
  - vol() draws volume polygons in static tetrahedral plots
  - axistetra() draws reference x, y and z axis arrows in static
    tetrahedral plots
  - legendtetra() adds legends to static tetrahedral plots

MINOR FEATURES AND BUG FIXES

  - summary.colspace() for tcs spaces now returns relative color volume
    as well as absolute
  - tcsvol() and voloverlap() now allow control for line width
  - procspec() fixed error when attempting to smooth rspec object
    without column names
  - procspec() handles smoothing before fixing negatives to avoid
    re-adding negatives when smoothing
  - procspec(), aggplot() accept additional arguments to summary
    functions (e.g., na.rm=TRUE)
  - peakshape() default wavelength limits (lim) now taken from rspec
    object rather than 300-700
  - peakshape() returns warning if a spectrum contains duplicate
    reflectance values
  - summary.rspec() works with single spectra
  - aggplot() and aggspec() fixed bug on ordering of levels when they
    don't match the sequence in the rspec object
  - aggplot() added logical argument "legend" for automatically adding a
    legend to the plot
  - vismodel() returns error if bkg=NULL
  - getspec() patched to stop returning warnings in Yosemite
  - getspec() has a faster (~5-10X), but less flexible, algorithm used
    when all input files are from the same source.

                 Changes in version 0.5-6 (2016-10-20)                  

BUG FIXES

  - fixed bug in calculation of dichromat contrast in coldist()

                 Changes in version 0.5-5 (2016-03-09)                  

MINOR FEATURES AND BUG FIXES

  - fixed bug in calculation of H3 in summary.rspec()

                 Changes in version 0.5-4 (2016-01-28)                  

MINOR FEATURES AND BUG FIXES

  - changed default values for coldist()

                 Changes in version 0.5-2 (2015-06-11)                  

MINOR FEATURES AND BUG FIXES

  - fixes to the blue tit visual system, changed vismodel() argument to
    "bluetit"

                 Changes in version 0.5-1 (2013-09-04)                  

MINOR FEATURES AND BUG FIXES

  - vismodel() accepts matrix, data.frame or rspec objects for the
    illuminant, updated warning messages associated with this use
  - vismodel() accepts user-defined achromatic receptors
  - tcsplot(), tcsvol() & tcspoints(): transparency control passed to
    user
  - getspec() works with OceanView files

                  Changes in version 0.5 (2013-06-09)                   

  - updated citation()

MINOR FEATURES AND BUG FIXES

  - vismodel() vonkries = TRUE does not return a NULL result
  - vismodel() works with a single spectrum object
  - tcsplot() allows greater control of tetrahedron appearance
  - summary.rspec() allows for user-defined minimum wavelength (for
    calculation of UV variables)

                 Changes in version 0.3-1 (2013-05-06)                  

NEW FUNCTIONS

  - irrad2flux() and flux2irrad() to convert illuminant measurements

MINOR FEATURES AND BUG FIXES

  - vismodel() less cryptic error messages
  - as_rspec() fix message pertaining wavelength column
  - getspec() now removes empty columns (generated by bad tabulation)
  - plot.rspec() fix color labelling issue (previously, when user
    specified fewer colors than number of spectra, 'stack' and 'overlay'
    colored spectra differently)

                  Changes in version 0.3 (2013-04-23)                   

NEW FUNCTIONS

  - subset() class methods for rspec, vismodel and tcs
  - summary() method for vismodel, returns attributes used in visual
    model

VISUAL MODEL

  - vismodel() output includes only Qi or fi (as selected by qcatch
    argument)
  - vismodel() von Kries correction is now an optional argument
  - coldist() subset argument for partial filtering
  - Updated sensitivity curves

MINOR FEATURES

  - getspec() works with Avasoft 8 output
  - aggspec() if no "by" argument is supplied, applies function to all
    spectra

BUG FIXES

  - tcs() accepts receptor names other than usml, issues warning
  - aggplot() allows control for different line types per spectra
  - voloverlap() now assigns darkgrey color for overlap if color vector
    is of length 1 or 2

                 Changes in version 0.1-2 (2013-01-12)                  

NEW FUNCTIONS

  - merge.rspec() combines rspec objects in a single object

VISUAL MODEL

  - Changed vismodel() output: von Kries correction is now an optional
    argument, output includes only Qi and fi
  - vismodel() accepts a scale parameter (multiplies illuminant in order
    to make it in flux units)
  - coldist() includes option for receptor noise calculation
  - Updated sensitivity curves

MINOR FEATURES

  - sensmodel() accepts user-defined ocular media transmission
  - voloverlap() allows greater user control of plotting options
  - voloverlap() includes Monte Carlo option for overlap calculation
  - as.rspec() accepts "whichwl" argument for user-defined wavelength
    column selection
  - as.rspec() includes "interp" argument; updated automatic search for
    wavelength column
  - aggspec() aggregates spectra by multiple vectors (e.g. average
    spectra by species and sex using by=list(species,sex) )
  - peakshape() gives plot titles, allows ask=TRUE and mfrow

BUG FIXES

  - explorespec() "free" argument fixed
  - summary.rspec() S5 variable fixed; segments now divided by B1
    (brightness-independent measure of saturation)
  - summary.rspec() checks for positive values when bmaxneg is
    calculated, returns NA
  - tcs() accepts "v" cone class
  - aggspec() fixed matching of names
  - procspec() works with rspec objects that include a single
    reflectance spectrum
  - peakshape() minor fixes
