Releases: ncss-tech/aqp
aqp 2.2
Release for CRAN version 2.2 on 2025-02-15
Major Changes
The functions plotProfileDendrogram() and aggregateColorPlot() have been migrated from the sharpshootR package into aqp. The next release of sharpshootR will mark those versions as deprecated. Managing dependencies for aqp should be a little simpler as the ape, colorspace, and digest packages have been moved from "suggests" to "imports".
Other Changes
evalGenHz()now usesstats::cmdscale()instead ofMASS:isoMDS()- fix for
hz_segment()andNCSP()with data.tableSoilProfileCollectionobjects (#320) - fix for
generalize.hz()to handle missing depths better and addedna.rmargument (#321) - finally dropping plyr from suggests (#157)
profile_compare()removed, seeNCSP()for a replacement
Full Changelog: v2.1...v2.2
aqp 2.1
Release for CRAN version 2.1.0 on 2024/10/19
What's Changed
- Update site-data.csv by @swsalley in #300
- Update horizon-data.csv by @swsalley in #299
flagOverlappingHz()performance improvements by @brownag in #308- Remove
"original.order"from SPC metadata by @brownag in #310 - Fix to enforce character data type for ID in diagnostics and restriction slots of SPC by @brownag in #313
- Add
thicknessOf()by @brownag in #306 - Deprecate 'guessing' functions for horizon-level column names by @brownag in #309
- Fix compatibility with R <4.1/4.2 by @brownag in #317
- Add half-value Munsell chips beyond 2.5 by @dylanbeaudette in #319
- Move {sp} to suggests by @brownag in #303
- Control section of Histosols and Histels by @brownag in #284
- Add
collapseHz()by @brownag in #307 - mutate_profile: dynamic column and expression upgrades by @brownag in #315
New Contributors
Full Changelog: v2.0...v2.1
aqp 2.0
This is an abbreviated version of the "What is new in aqp 2.0?" vignette. Many thanks to @brownag, @smroecker, @pierreroudier, @jskovlin, @jjmaynard, and all of the other contributors to this version of aqp.
This is a major update to aqp that may create some issues for code depending on specific inputs/outputs in aqp < 1.42, particularly those relying on slice(), slab(), and profile_compare(). slice() and profile_compare() are now deprecated, but will continue to work for the rest of calendar year 2023. There are no plans to maintain these functions beyond aqp 2.0. The new version of slab() is a drop-in replacement for the previous version of the function.
New Vignettes:
Notable changes include:
- deprecation of
slice()in favor of the new, faster, more robust implementation indice() - complete overhaul of
slab(), with new arguments, faster back-end, and weighted aggregation implemented (finally) - deprecation of
profile_compare()in favor of theNCSP()--a complete overhaul based on Maynard et al., 2020- site level attributes now handled by
compareSites() - variable weights now possible via argument
- site level attributes now handled by
perturb()andestimatePSCS()are now vectorized, and optimized for larger collectionsmixMunsell()now usesmixingMethod = 'exact'by default for the simulation of subtractive mixturesgowerpackage moved to SUGGESTSplotColorMixture()now using grid graphics functions to determine color swatch geometry and setting overlap detection threshold- removal of
PMS2Munsell()and support data - deprecation of
coordinates()<-andproj4string()<-in favor ofinitSpatial()<- - removal of
rruff.sampleexample XRD patterns get.ml.hz()no longer uses thenameargument
Major changes to plotSPC():
- The maximum depth range of the figure is now based on
max.depthormax(x). This means that sketches generated with aqp 2.x will generally have less white space at the bottom of the figure. Make more room for additional annotation or visual effect by setting the desired depth range with themax.depthargument. - now uses
electroStatics_1D()for fixing horizon depth label overlap, solutions are deterministic and almost always better - better depth axis interval heuristics (if not specified), varying based on figure depth range
- depth axis adjustments via new argument
depth.axis, logical or list - deprecation of arguments:
plot.depth.axis: set viadepth.axis = TRUE,depth.axis = FALSE, or customizedepth.axis = list(...)cex.depth.axis: set viadepth.axis = list(cex = 1)axis.line.offset: set viadepth.axis = list(line = -2)
New features:
- example data,
wilson2022 - fast prototyping of SPCs via
quickSPC()and list / character templates - re-use arguments to
plotSPC()viaoptions(.aqp.plotSPC.args = list(...)) - coarse fragment classification via
fragmentSieve()andfragmentClasses() - S4
as.data.frame(<SPC>)as shorthand foras(<SPC>, 'data.frame') plotSPC()now marks truncated profiles with a ragged bottomfixOverlap()now has two label-placement solvers, based on 1) electrostatics and 2) simulated annealing- new depth axis styles in
plotSPC()
Incremental changes, should have no effect on previous code:
- bug fix in
plotSPC()whenfixLabelCollisions = TRUE, adjustments suggested tofixOverlap()are now scaled correctly explainPlotSPC()reports label adjustment index when label collision repair is enabled- aesthetic cleanup in
explainPlotSPC() soilColorSignature()gains arguments and perceptual color distances (dE00) via farver packageas(<SPC>, "data.frame"): Replaceplyr::join()withmerge()correctAWC(): NA handling - return NA when frags are NAmutate_profile(): Faster (data.table-based) evaluation of profile-level expressions (#255)profileApply: Add support for customlapply()-like function (APPLY.FUN) for processing chunks (#256)- Add
.interpretHorizonColor()outputs tolast_spc_plotinaqp.envfor use in customlegend()(#254) - Add
simplifyargument toSoilTextureLevels()andssc_to_texcl()to optionally convert to an ordered factor with maximum of 12 levels (rather than 21). This smaller list of classes excludes sand grain size variants such as fine sand, loamy coarse sand, and very fine sandy loam.
aqp 1.42
This is a retroactive release to tag the commit corresponding to last CRAN version (1.42) prior to the v2.0 release.
What's Changed
- Test persistence of attributes and metadata in SoilProfileCollection by @brownag in #236
- Remove aqp::filter by @brownag in #238
- Implement
requiredargument for SPC metadata by @brownag in #237 - Add
as.character(<SoilProfileCollection>)by @brownag in #239 - Add
accumulateDepths()by @brownag in #235 - fixes to estimateSoilDepth by @dylanbeaudette in #242
- repairMissingHzDepths: Use
spc_horizonOffset()by @brownag in #246 - Empty SPC prototype should be able to preserve horizon names by @brownag in #245
- Texture by @smroecker in #244
- "spatial predicates" for horizon data by @brownag in #247
slab(): passformulaargument to aggregate.formula(x, ...) by @brownag in #248spc2mpspline(): upgrades by @brownag in #250
Full Changelog: 1.31...1.42
aqp 1.31
Enhancements / Bug Fixes
- bug fix in
checkHzDepthLogic()whenbyhz = TRUE aggregateColor()now usesmixMunsellfor the estimation of soil color mixturesplotColorMixture()will respect "names" attribute of colors-to-mix, without erroneous alpha-sortingparseMunsell()now more robust and faster, c/o P. RoudiermixMunsell:- new method
exactfor direct conversion of mixture spectra to sRGB or closest Munsell chip (viaspec2Munsell())
- new method
glom()z1andz2arguments vectorized to allow for profile-specific intervalsz1andz2support non-standard evaluation based on column names insiteNames(p), and also can take character vector (length 1) with column names insiteNames(p)
depthOf(),minDepthOf(),maxDepthOf(),getSurfaceHorizonDepth(),getMineralSoilSurfaceDepth(),getPlowLayerDepth()can now be applied to multiple profiles.- If the input
SoilProfileCollectionhas more than one profile then result is adata.framecontaining profile ID, top or bottom depths, horizon designation and pattern
- If the input
New Functions / Data
- new function
colorChart()for graphical depiction of Munsell chip frequency by group uniquemethod forSoilProfileCollectionobjects now returns aSoilProfileCollectionby default- this may break existing code! use the new argument
SPC = FALSEfor previous behavior (#159)
- this may break existing code! use the new argument
- new convenience function
PMS2Munsell()for converting PMS codes -> closest Munsell chip (#124)
aqp 1.27
Enhancements / Bug Fixes
mixMunsellnow relies on suggested package {gower} for 5-10x speed bump- {aqp} no longer imports from {reshape} (less one dependency), all transformations from wide<->long are done via {data.table}
- methods from {data.table} are now imported by {aqp} (new dependency)
- Major overhaul of
plotColorQuantiles(), now using {lattice} graphics - Argillic critical clay contents
crit.clay.argillicrounded to whole numbers per NSSH Part 614, subpart B, sections 614.13 and 614.14 mutate_profileusesdata.table::rbindlist(fill=TRUE)to combine site- and horizon-level transformations- updates to horizon boundary encoding functions (
hzTopographyCodeToOffset,hzTopographyCodeToLineType,hzDistinctnessCodeToOffset) plotSPCupdates:- argument named changes:
hz.boundary.ltyis a horizon-level attribute that contains line type codes hz.topography.offseta horizon-level attribute that contains representative offsets that encode horizon boundary topographyplotSPCnow encodeshz.topography.offsetusing a vertical "bump" (chevron)
- argument named changes:
addBracketcan now accept multiple bracket annotations per profile
New Functions / Data
- New dataset
equivalent_munselland methodequivalentMunsellChipsfor "equivalent" Munsell chips lookup list based on all pairwise dE00 contrasts for integer "chips" in {aqp}munselldata set - new function
L1_profilescomputes multivariate (L1) medians, compare to marginal medians viaslab
aqp 1.25
This release of aqp marks a significant step towards major changes planed for version 2.0. Since 1.17, there have been major changes to the internals of the SoilProfileCollection object (thanks to @brownag) and associated methods. We expect some evolution (but less drastic as compared to the previous release) before version 2.0.
See NEWS.md for a complete listing of changes.
Important Changes
estimateSoilDepthlosestopandbottomarguments, these are automatically extractedcombinereplaces/expandsaqp::uniondue to conflicts withbase::unionsplitreceives some upgrades to the S4 definition to increase parity withsplit.defaultfilteris now an alias for new methodsubset, which mirrorsbase::subset- default horizon ID (
hzID) is now acharacterdata type
Enhancements
SoilProfileCollection Internals
- new function
duplicatewill makes copies of profiles within aSoilProfileCollection - two new SoilProfileCollection wrapper methods:
munsell2SPC,spc2mpspline - improvements to
glom(..., invert=TRUE),glomApply, and better tests - new wrapper method around
glomApply:truncfor cases when top and bottom depth interval is the same for all profiles in a SoilProfileCollection - enhanced SoilProfileCollection object validity checks via S4; new method
spc_in_sync(#152) - optimization of
[subset method and optional use ofdata.table(#155) depths<-has been optimized and minimally validates input datacombineusesdepths<-internally; explicitly enforcing profile ID + top depth order in horizon data is safer but results in different ordering ifunion-ing IDs that "intermingle" (need to be re-sorted).- new experimental method is
permute_profile; similar tosimbut for boundaries. The interface to this function is likely to change/be expanded. - basic support for promotion of
tbl_dfanddata.tableto SoilProfileCollection - new method
aqp_df_classto determine class name in use in a SoilProfileCollection object - optimization of
[i,][,j]subset methods for data.frame-based slots (#135) - new verbs:
mutate,mutate_profile(#118) - define
[[subsetting method; an "ambivalent" accessor for site- or horizon-level properties - new subset verbs
grepSPC,filter,subApplyfor use in%>%-lines
Color / Visualization
- simulate subtractive mixtures of Munsell colors with
mixMunsell- see companion function
plotColorMixturefor visualization of spectra / mixture
- see companion function
- complete overhaul of
textureTriangleSummary:- uses
soiltexturepackage for visualization (plotriximplementation dropped) - argument names changes (! may break old code, sorry)
- dropped simulation via
sim = TRUEargument, seebootstrapSoilTexturefor a better approach
- uses
- new function
bootstrapSoilTexturefor simulating realistic sand/silt/clay compositions - add
returnDataargument tocontrastChart plotSPCupgrades (#146)
Everything Else
- new methods related to mollic epipedon:
mollic.thickness.requirement,hasDarkColors - new
estimateSoilDepth-like methods for depth to multiple features via pattern matching:depthOf,minDepthOf,maxDepthOf - soil texture helper functions:
ssc_to_texcl,texcl_to_ssc,texmod_to_fragvoltot,texture_to_taxpartsizec/o @smroecker - added
segmentc/o @smroecker
Additions
- new lookup table
pms.munsell.lutfor converting Pantone spot color codes to (closest) Munsell chip - new example data
us.state.soils: 50 state soils + PR and VI soils - ROSETTA centroids and water retention by texture class (#131)
Bug Fixes
- fix for routing of
NULLthrough$<-andhorizons<-orsite<-(#163) - fix handling of missing metadata in (old) serialized SoilProfileCollection objects
- fix for promotion of
data.tablewith character vector (not formula) interface - fix for unit-length and zero-length legends in
plotSPC - fix for
plotgeneric to showaqp::plotin?plot - fix for
getSurfaceHorizonDepthwith buried horizons / non-contiguous instances of matching horizons (#132) - fix for default
plotSPCwith small number of profiles (#128) - remove implicit conversion to SpatialPointsDataFrame with unit-length
[j-index subset ((#125) - fix in slab when
slab.structure[2] > max(x)
New Compatibility with Pipe-based Workflows!
The SoilProfileCollection object is now compatible with {magrittr} pipe %>% based workflows. Here is an example using select soil morphologic data from Jacobs (2002) "Redoximorphic Features as Indicators of Seasonal Saturation, Lowndes County, Georgia", a sample dataset available in {aqp} (jacobs2000)
# {aqp} + {magrittr} pipes
library(aqp)
library(magrittr)
# see ?jacobs2000 for details
data("jacobs2000", package = "aqp")
# create a base plot to inspect full dataset
par(mar=c(0,0,0,2))
plot(jacobs2000, color = "matrix_color",
plot.order = order(jacobs2000$time_saturated))
# select 3 profiles along gradient, and truncate 50-150cm interval
jacobs.sub <- jacobs2000 %>%
subset(profile_id(.) %in% c("92-2","92-4",'92-7')) %>%
trunc(50, 150)
# create a base plot
plot(jacobs.sub, color = "matrix_color")
# add redox concentrations
jacobs.sub %>% addVolumeFraction('concentration_pct',
col = .$concentration_color,
pch = 16, cex.max = 1)
# add redox depletions
jacobs.sub %>% addVolumeFraction('depletion_pct',
col = .$depletion_color,
pch = 16, cex.max = 1)aqp v1.17
This is the last major release of the 1.x series. Future development will focus on the 2.x series of releases.
Important Changes
SoilProfileCollection
Pre-v1.17 soilProfileCollection objects can be checked and rebuilt using ideas from #74. Further documentation pendning.
Structure before v1.17.
Formal class 'SoilProfileCollection' [package "aqp"] with 7 slots
..@ idcol : chr "soil"
..@ depthcols : chr [1:2] "top" "bottom"
..@ metadata :'data.frame': 1 obs. of 1 variable:
..@ horizons :'data.frame': 1539 obs. of 18 variables:
..@ site :'data.frame': 296 obs. of 1 variable:
..@ sp :Formal class 'SpatialPoints' [package "sp"] with 3 slots
..@ diagnostic:'data.frame': 0 obs. of 0 variables
Structure as of v1.17, note the new hzidcol slot.
Formal class 'SoilProfileCollection' [package "aqp"] with 8 slots
..@ idcol : chr "soil"
..@ hzidcol : chr "hzID"
..@ depthcols : chr [1:2] "top" "bottom"
..@ metadata :'data.frame': 1 obs. of 1 variable:
..@ horizons :'data.frame': 1539 obs. of 18 variables:
..@ site :'data.frame': 296 obs. of 1 variable:
..@ sp :Formal class 'SpatialPoints' [package "sp"] with 3 slots
..@ diagnostic:'data.frame': 0 obs. of 0 variables
rbind.SoilProfileCollection
Has been deprecated in favor of aqp::union(), and gains new functionality.
Enhancements
Soil Color Related
aggregateColor()gets a new feature, similar colors can be grouped viacluster::pam()- new functions:
previewColors(),colorQuantiles(),plotColorQuantiles()
SoilProfileCollection Management
horizonDepths()<-, edit top/bottom names afterSoilProfileCollectioninitprofile_id()<-, edit profile IDs after init; be careful!hzID()andhzID()<-, get/set unique horizon IDshzidname()andhzidname()<-, get/set column containing unique horizon IDscheckSPCandrebuildSPC
Soil Taxonomy Related
argillic.clay.increase.depthcrit.clay.argillicestimatePSCSget.increase.depthsget.increase.matrixgetArgillicBoundsgetSurfaceHorizonDepth
Horizon Intersection (glom) Related
clod.hz.idsglom
New / Updated Documentation
Bug Fixes
- sanity checks within
horizonNames()<-
Misc. Changes
Note that some un-used sample data have been removed. The sp5 sample dataset has been re-made to include the new @hzidcol slot.
