Changelog
gmsp 0.4.6
New exported functions
-
TSL2PS(.x, xi = 0.05, Tn = NULL, output = "PSL", D50 = FALSE, D100 = FALSE, nTheta = 180L)is the explicit response-spectrum helper for canonicalTSLtables produced byAT2TS(),VT2TS(), andDT2TS(). It does not exposeBY,COL.s,COL.t, orCOL.ID; grouping metadata is derived from theTSLschema. Projects that currently callTS2PS(TSL, COL.s = "s", COL.t = "t", COL.ID = "ID", Output = "PSL")for canonicalTSLinput should migrate toTSL2PS(TSL, output = "PSL"). - D50 and D100 are part of the canonical
TSL2PS()contract. D50 migration:TSL2PS(TSL, output = "PSL", D50 = TRUE, nTheta = 12L)replacesTS2PS(..., D50 = TRUE, n.theta = 12L). This is a breaking 0.4.6 migration note; other projects should read this changelog before updating. - Canonical table-shape helpers are now exported for downstream pipelines:
TSL2TSW(),TSW2TSL(),TSL2IM(),IML2IMW(),PSL2PSW(), andPSW2PSL(). These replace local project helpers that manually castTSL,IML, andPSLtables with repeateddcast()/melt()code.
Table contract helpers
TSL2TSW(.x, by = "auto", ids = c("AT", "VT", "DT"))converts canonical long time-series tables (t,s,ID,OCID) to wideTSWcolumns such asAT.H1,VT.H1, andDT.H1.TSW2TSL()reverses the projection and accepts eithertor legacy constructortsas the time column.TSL2IM(.x, units.source, units.target = "mm", output = c("IML", "IMW"))is the primary intensity API.getIntensity()remains as a compatibility wrapper and keeps the longIMLdefault. Useoutput = "IMW"orIML2IMW()when a downstream table needs one row per metadata andOCID.PSL2PSW()andPSW2PSL()expose the canonical spectra long/wide conversion. AfterPSW2PSL(),D50andD100are ordinaryOCIDvalues, so scripts can filterOCID %in% c("D50", "D100")instead of parsing column-name suffixes.-
TSL2PS()now accepts vectorxi. A scalarxipreserves the previous schema with noxicolumn. A vectorxiaddsxias metadata:Downstream scripts that currently loop over damping ratios can call
TSL2PS()once and group or filter byxi.
D100 spectra extension
-
TSL2PS()now adds D100 horizontal response spectra beside the existing D50 path:TSL2PS(TSL, output = "PSW", D50 = TRUE, D100 = TRUE, nTheta = 180L)output = "PSL"adds rows withOCID = "D100".output = "PSW"addsPSA.D100,PSV.D100, andSD.D100. Scripts that already consumePSA.D50,PSV.D50, orSD.D50should explicitly include the matching D100 columns when they opt in. Downstream configs/scripts that currently enumerate D50, such as
spectra.D50,DIR_TARGET = "D50", or plot/export direction lists, should addD100explicitly only for runs that requestD100 = TRUE.D100 uses the same rotation grid as D50. It is the maximum over rotated horizontal spectra for each period and spectral ID; the maximizing angle can vary by
Tnand byPSA/PSV/SD. The implementation returns spectra only, not the D100 angle. WhenD50 = TRUEandD100 = TRUE, both derived components are computed from one rotated response matrix.The downstream contract stays canonical
TSL2PS(). Do not migrate scripts toTS2PS(),TS2PSA(),RotD50, orRotD100names. The implementation plan is recorded indev/SoT/PLAN-TSL2PS-D100.md.
API cleanup
getND()has been moved out of the exported package surface todev/legacy/get_ND.R. Its public signature mixed raw heterogeneous units, target units, and Newmark episode controls in a way that needs a separate design before returning to the package.mapOCIDtoDir()has been moved out of the exported package surface todev/legacy/mapOCIDtoDir.R.mapComponents()now owns component classification, andextractRecord()callsmapComponents(..., rotate = FALSE)before alignment. The new SoT compares classification against the old helper and verifies byte-identical raw CSV/JSON outputs for fixture extraction.mapComponents()now acceptsoutput = c("long", "wide")and can consume either longt, OCID, sinput or widet, <OCID1>, <OCID2>, <OCID3>input. The default"long"shape remains the compatible output;output = "wide"returnsdata.table(t, H1, H2, UP). Both outputs preservecomponentMapandrotateattributes; rotated outputs also preservetheta.filterIMF()has been moved out of the exported package surface todev/legacy/filterIMF.R. No current callers were detected ingmsp,AR-S2J2J, orAR-SABP0.R; users should compose filtering workflows directly from canonicalTSL,TS2IMF(), andTSL2PS().The 0.4.x spectra path is closed around canonical
TSLconsumption: spectra code should callTSL2PS(), notTS2PS()withBY,COL.s,COL.t, andCOL.ID.TS2PS()has been removed from the exported package surface. It mixed generic long-table dispatch, grouping autodetection, column-name arguments, and D50 behavior. UseTSL2PS()with canonicalTSLinput.TS2IMF()is now a single-series worker over canonical columnstands. It no longer exposesBY,COL.s,COL.t, orOutput; useoutput. Grouped callers should usedata.tablegrouping, for exampleTSL[ID == "AT", TS2IMF(.SD, output = "TSL"), by = .(RecordID, OCID), .SDcols = c("t", "s")].normalizeTS()now consumes canonicalTSLinput directly:normalizeTS(TSL, norm = "PGA"). It no longer exposesCOL.s,COL.ID,COL.OCID, orBY; grouping is derived from metadata columns plusOCID.-
readTS(),readAT(),readVT(), andreadDT()now use.xfor the selection table andpathfor the records root. This is a named-argument breaking change:# before readTS(SEL = SEL, recordsDir = RecordsDir, kind = "VT") readAT(SEL, recordsDir = RecordsDir) # after readTS(.x = SEL, path = RecordsDir, kind = "VT") readAT(.x = SEL, path = RecordsDir)Positional calls with both arguments, such as
readAT(SEL, RecordsDir), remain valid. The same.x/pathrule applies toreadVT()andreadDT(); do not update callers to keeprecordsDir =. -
buildMaster()now usespathfor the index root:# before buildMaster(indexDir = IndexDir, owners = Owner) # after buildMaster(path = IndexDir, owners = Owner)Positional calls such as
buildMaster(IndexDir, owners = Owner)remain valid. Named callers must not keepindexDir =. -
buildRawFileTable()now usespath.recordsfor the records root andpath.indexfor the index root:# before buildRawFileTable(recordsDir = RecordsDir, indexDir = IndexDir, owners = Owner) # after buildRawFileTable(path.records = RecordsDir, path.index = IndexDir, owners = Owner)Positional calls with both paths remain valid. Named callers must not keep
recordsDir =orindexDir =. -
buildRawRecordTable()andbuildRawIntensityTable()now use the same path argument contract asbuildRawFileTable():# before buildRawRecordTable(recordsDir = RecordsDir, indexDir = IndexDir, owners = Owner) buildRawIntensityTable(recordsDir = RecordsDir, indexDir = IndexDir, owners = Owner) # after buildRawRecordTable(path.records = RecordsDir, path.index = IndexDir, owners = Owner) buildRawIntensityTable(path.records = RecordsDir, path.index = IndexDir, owners = Owner)Named callers must not keep
recordsDir =orindexDir =. -
Single-path raw/archive helpers now use
path:archiveRawOwner(path = StationDir) getRawIntensities(path = StationDir) writeSelection(DT, name = "subset", path = SelectionDir)Named callers must not keep
stationDir =orselectionDir =. -
parseRecord()andextractRecord()now use.xfor the one-record master subset andpathfor the records root:# before parseRecord(masterRows = Rows, recordsDir = RecordsDir) extractRecord(masterRows = Rows, recordsDir = RecordsDir) # after parseRecord(.x = Rows, path = RecordsDir) extractRecord(.x = Rows, path = RecordsDir)Positional calls with both arguments, such as
extractRecord(Rows, RecordsDir), remain valid. Named callers must not keepmasterRows =orrecordsDir =. -
auditParsers()now uses.xfor the master table,ownerfor one OwnerID, andpathfor the records root:# before auditParsers(OwnerID = Owner, master = Master, recordsDir = RecordsDir) # after auditParsers(.x = Master, owner = Owner, path = RecordsDir)Named callers must not keep
OwnerID =,master =, orrecordsDir =. Positional calls must use the new orderauditParsers(Master, Owner, RecordsDir). -
AT2TS(),VT2TS(), andDT2TS()now exposetimeas an input-column selector and always return canonicalTSLcolumnst,s,ID, andOCID. The oldCOL.tandCOL.sarguments are removed.timeis not an output-column name; it is only the name of the time column in the input table. Scripts should migrate as follows:# before AT2TS(Wide, Units = "mm", COL.t = "time", COL.s = "signal", Output = "TSL") # after AT2TS(Wide, units.source = "mm", time = "time", output = "TSL")Downstream code must consume the returned
TSLastands. For example,.SDcols = c("time", "signal")should become.SDcols = c("t", "s"). Calls that already used a column namedtand did not passCOL.t/COL.sdo not need a script change. The constructor family also normalizes the approved public argument names:
Units->units.source,TargetUnits->units.target,Output->output,Verbose->verbose,Audit->audit,isRawData->isRaw,Resample->resample,FlatZeros->flatZeros,TrimZeros->trimZeros,Detrend->detrend, andRegularize->regularize.VT2TS()andDT2TS()additionally useDerivate->derivateandLowPass->lowPass.regularize()is no longer public API. Time-grid regularization is handled insideAT2TS(),VT2TS(),DT2TS(),TS2IMF(), andTSL2PS()via the internal helper.regularize(). External scripts should passtime = "..."to the constructor when the input time column is not namedt; they should not callregularize()directly.setSTFT()is no longer public API. STFT strategy selection is now the internal helper.setSTFT()used byAT2TS(),VT2TS(),DT2TS(), andauditSTFT(). External scripts should configure the public constructors instead of calling the STFT strategy helper directly.
gmsp 0.4.5
New exported functions
-
mapComponents(DT, rotate = TRUE)maps one long(t, OCID, s)record to canonical processed directions. Provider channels remain inOCID, returnedDIRvalues areH1/H2/UP, andattr(out, "componentMap")records theOCIDtoDIRmapping. Withrotate = TRUE, horizontal samples are rotated to principal axes andattr(out, "theta")stores the rotation angle.
Compatibility
-
mapOCIDtoDir()remained exported and unchanged in 0.4.5. It was removed from the exported package surface in 0.4.6. -
extractRecord()and raw CSV/JSON writer contracts are unchanged; raw products continue to preserve providerOCIDvalues.
gmsp 0.4.4
Breaking changes — units contract
-
AT2TS(),VT2TS(),DT2TS(),getIntensity()now require canonical base values forUnitsandTargetUnits:- length basis:
"mm","cm","m"— valid for AT, VT, DT. - acceleration aliases:
"g","gal"— valid forAT2TS()only. -
VT2TS()andDT2TS()reject"g"/"gal"(an acceleration unit passed to a velocity/displacement function is a category error). -
getIntensity()accepts length-base only ("mm"/"cm"/"m") forUnitsandTargetUnits; the same scale factor applies to AT, VT, and DT rows of a long TSL, so only a length base is well-defined. - Verbose forms like
"mm/s","mm/s2","m/s2","cm/s"are rejected with a clear error pointing to the canonical base.
KIND (acceleration / velocity / displacement) is determined by the function called, not by a suffix of the
Unitsstring. Provider string parsers.parseUnits()and.parseKind()continue to accept heterogeneous raw strings (e.g."cm/sec2","G","GALS") — those operate at the ingestion layer and pre-normalize to canonical before flowing into the public API.Migration: callers passing
Units = "mm/s"switch toUnits = "mm"; same for displacement. Callers passingUnits = "g"toVT2TS()/DT2TS()must move toAT2TS().Validated by a Ship-of-Theseus harness (
inst/dev/sot/compare_units_contract.R): Stage A 42/42 (canonical inputs byte-identical to prior gmsp viaidentical()), Stage A-bis 3/3 (current verbose ≡ canonical, documents migration), Stage C-bis 9/9 (illegal inputs error correctly). Verify mode (post-swap-in, in-place edit vs captured baseline) 51/51 PASS. - length basis:
Blasting / velocity-record support
-
readISEE()— Micromate ISEE blasting-seismograph parser (velocity, mm/s). Auto-detects v10 /.TXTand v11 /.CSVfirmware variants from the file content. -
extractRecord()— KIND is routed through the sidecar filename prefix (AT/VT/DT). The JSON peak field is named accordingly:PGA/PGV/PGD. An explicitkind = "VT"override is accepted for records whoseUnitscannot be parsed by.parseKind(). -
buildRawRecordTable()— scansraw/(AT|VT|DT).*.json(no KIND change to the canonical schema).
Bug fixes
-
extractRecord()— full numeric precision preserved in the sidecar JSON (nodigitstruncation). -
extractRecord()/getRawIntensities()— raw CSV columns now consistently remain providerOCIDvalues while the JSON sidecar carries the explicitDIR(H1/H2/UP) toOCIDmapping used by raw intensity indexing. -
TS2PS()— rejects user-suppliedTngrids containing0; the function already prepends theTn = 0peak-value anchor internally. -
TS2PS(COL.ID = ...)— structured long input now treats source time-seriesIDand spectralIDas distinct contracts:AT -> PSA,VT -> PSV, andDT -> SD. -
TS2PS(Output = "PSW")— multi-OCID long input now produces wide OCID-labelled spectral columns such asPSA.H1,PSV.H1, andSD.H1instead of source-ID-labelled spectral columns. Grouped PSW assembly no longer usesrbindlist(fill = TRUE). -
TS2PS(D50 = TRUE)— structured long input can now addOCID = "D50"as the fourth horizontal spectral component.PSA.D50,PSV.D50, andSD.D50are computed independently from rotated AT, VT, and DT respectively.TS2PS(D50 = TRUE)is the public D50 path. -
TS2IMF()— numericimf.removenow treats positive indices as IMFs counted from the start and negative indices as IMFs counted from the end, then removes the union. For example,c(1L, -1L, -2L)removesIMF1plus the last two IMFs. This replaces the previous positive-include / negative-protect behavior, which made mixed selections such asc(1L, -1L)remove nothing. Zero, non-finite, and out-of-range numeric values are ignored. -
TS2IMF()grouped output no longer pads inconsistent per-group schemas withNA. Groups must produce the same output columns, or the bind fails with a schema diagnostic instead of usingrbindlist(fill = TRUE). -
AT2TS(),VT2TS(), andDT2TS()no longer use blindna.omit()for time-step extraction or TSL packing. Non-finite time and signal samples now fail with explicit diagnostics instead of being hidden by regularization or row dropping; finite regular and irregular inputs are unchanged. -
getIntensity()no longer usesrbindlist(fill = TRUE)for the final acceleration/velocity/displacement IM bind. Internal IM schemas must match before binding. -
buildRawIntensityTable()no longer usesfill = TRUEwhen binding new per-station intensity tables or when merging an incremental cache. Raw intensity tables are canonicalized and schema-checked before binding. -
buildRawFileTable()no longer usesrbindlist(fill = TRUE). Provider records are canonicalized to the documented RawFileTable schema before binding; absent canonical provider fields are emitted as typedNAcolumns. -
buildMaster()no longer usesrbindlist(fill = TRUE)across owner outputs. Per-owner master tables must share the same schema before binding. -
wideTrunc()was removed. It had no internal callers and no detected callers in the checked consumer projects (AR-S2J2J,AR-SABP0.R). - Local-only style cleanup renamed STFT/audit temporaries in
AT2TS(),VT2TS(),DT2TS(),auditSTFT(), and.ffilter()without changing public interfaces. The internal source fileR/build_FFT.Ris nowR/buildFFT.R. -
.setSTFT()is tracked separately under Tier 2 SoT. The approved passes remove a dotted boolean local, canonicalize the candidate-logging guard, and inline a short-lived downsample scalar. A later narrow local cleanup removes one-usek.grid, inlines the one-useNP.requiredthreshold, and resolvesNW.max/NWmaxwithout changing candidate/frequency locals. These changes do not alter the STFT strategy or public interfaces.
Documentation
-
vignettes/database.Rmd— documents thereadTS()family and adds the ISEE blasting flow (readVT()+VT2TS()). -
selectRecords()@seealsoupdated to point to thereadTS()family.
gmsp 0.4.0
First CRAN submission. Consolidates the standalone gmdb package (provider-format parsers and per-record indexing) into gmsp so the full strong-motion record pipeline — from raw provider file to processed AT / VT / DT time series — lives in one place.
New exported functions (merged from gmdb)
-
Format parsers (provider file → LONG
(t, OCID, s)):readAT2()(PEER NGA-W2),readV2()/readV2A()(CESMD multi / single-channel + NWZ),readAC()(IGP / UCR),readTR()(Geological Survey of Canada),readTwoCol()(generic two-column ASCII). -
Extraction pipeline:
parseRecord(),mapOCIDtoDir(),alignComponents(),extractRecord(). The orchestrator writes per-recordraw/AT.<RecordID>.csvplus a sidecar JSON carryingDIR/OCID/NP/PGA/dt/Fs/Unitsmetadata.RecordIDis the first 16 hex chars of the WIDE-CSV md5 hash. -
Indexing:
buildRawFileTable(),buildRawRecordTable(),buildRawIntensityTable(),buildMaster()(joins record / event / station / intensity tables with haversineRepiand source-precedencefcoalescefor event scalars; the provider-flatfile + USGS catalog joinbuildEventTable()is still under development and ships ininst/dev/, not yet in the exported API). -
Selection / IO:
selectRecords(),writeSelection(),readAT()(loadsraw/AT.<RecordID>.csvback into the shapeAT2TS()expects),getRawIntensities(). -
Audit:
auditSite()(Vs30 sanity),auditDistances()(lat / lon / Repi / Rhyp),auditParsers()(dry-runparseRecord()per owner). -
Maintenance:
archiveRawOwner()(compress and verify provider files after extraction). - Historical note:
setSTFT()was exported in this line of development, but current 0.4.6 API cleanup internalizes it as.setSTFT().
Breaking changes
The retired
gmdbpackage is no longer maintained. Code that previously calledgmdb::extractRecord(...)should now callgmsp::extractRecord(...).-
Required paths.
parseRecord(),extractRecord(),buildRawFileTable(),buildRawRecordTable(),buildRawIntensityTable(),buildMaster(),auditParsers(),writeSelection()andreadAT()no longer carry hard-coded~/kashimaDB/...defaults for their path arguments (recordsDir/indexDir/selectionDir). The path is now a required argument; the function fails fast with a clear “argument … is missing” error if not supplied, rather than silently reading from a developer-specific location.Validated end-to-end by a Ship-of-Theseus harness: Stage A (explicit-path identity) 16/16 across 4 real provider fixtures (IGP, NGAW, NWZ, UCR); Stage A-bis (no-arg corner-case errors) 10/10. Pipeline regression 22/22 against the Phase 1 baseline.
readAT()signature. NowreadAT(SEL, recordsDir); previously read from the unexported package constantRECORDS, which has been removed.-
Removed fossil parameters. Two parameters that were exposed in the public signature but never reached the function body are dropped:
-
AT2TS(..., Derivate = "time")— the source marked it(future use); no caller used a non-default value and the body never branched on it. -
TS2IMF(..., TrimZeros = FALSE)— the worker’sif (TrimZeros)block was an explicit no-op placeholder.
Callers that passed either argument explicitly (none observed in the gmsp ecosystem) will now get
unused argument. The default behaviour is unchanged. -
License. Changed from
file LICENSE(all-rights-reserved) toMIT + file LICENSE.LICENSEis the CRAN-form two-line declaration;LICENSE.mdships the full MIT text.
Documentation
- Six vignettes ship with the package, replacing the previous Jekyll-only
docs/site:gmsp-quickstart(5-minute runnable hello world),signal-processing,imfs,spectra,intensity-measures(math references with LaTeX), anddatabase(indexing-layer pipeline and file-layout contract). -
_pkgdown.ymlreorganised: navbar lists all six vignettes; reference grouped by signal-processing core, indexing helpers, selection / IO, and audit. -
README.mdcovers both layers (signal-processing + optional indexing) and includes CRAN status / downloads badges, a citation bibentry, and links to all six vignettes.
Internal
-
R/local.RandR/global.Rconsolidated intoR/gmsp-package.Rwith a singleutils::globalVariables()block and a singleTARGET_UNITSdeclaration. - Dropped
gmsp::self-prefix on the call togetIntensity()ingetRawIntensities.R. -
@param LowPassadded toDT2TS()andVT2TS()(was undocumented). -
R CMD check --as-cran: 0 errors, 0 warnings, 0 notes.
gmsp 0.3.0
Final pre-merge release of the standalone signal-processing package. Public API: AT2TS(), VT2TS(), DT2TS(), TS2IMF(), getIntensity(), getND(), regularize().