Changelog
tma 0.3.12
Released with qe-tma 0.1.11 (tag python/v0.1.11), tma-wasm 0.1.6 (wasm/v0.1.6) and libtma 0.3.12 (conan/v0.3.12). New vignette and qe-tma notebook on accumulation results (connections, misses, self-connections); tma-wasm’s README lists all 15 exported functions and its examples run in the browser on qe-libs.org; libtma’s Conan docs gain a main page.
TMA.jl 0.1.6 (released on its own, tag
julia/v0.1.6) gets the high-level accumulation of R tma and qe-tma:TMA.accumulate(data, units, conversations, codes; tensor, time_col, ordered, binary, weight_by, misses, self_connections, split_by)returns aTMAAccumulation(connection / self / miss counts, the per-line tables,meta, unit labels, connection names, adjacency key), withcontext_tensor,contexts(split_by, per-context time axis),rulesandconversation_rules. Any Tables.jl table is accepted. Results equal R tma’s: the R reference values of qe-tma’s tests and the interleaved- conversation fixture (unsplit and split by conversation), 62 tests.accumulateis called asTMA.accumulate(Base has one). TMA.jl now depends on LibQE (>= 0.2.1, for the connection layout, as qe-tma uses qe-lib) and Tables.qe-tma’s
accumulate()takeshoo_rules=(keyword only), ascontexts()does: horizon-of-observation rules, so a unit’s context can be other than its conversation (R tma’scontexts(hoo_rules =)).conversationsis now optional; give it,hoo_rules, or both (ORed). Equal to R tma on the getting-started vignette, ordered and unordered.qe-tma ships R’s
test_mockdataastma.datasets.load_test_mockdata().qe-tma has a getting-started walkthrough,
python/docs/getting-started.ipynb, the Python port of the R vignette, published with the API docs at https://qe-libs.org/py/docs/qe-tma/getting-started.html (dev builds:py/dev/docs/qe-tma/). The README quick start now runs as written, on the bundled data.
tma 0.3.11
0.3.10 (libtma 0.3.10, qe-tma 0.1.8 / 0.1.9, tma-wasm 0.1.4, TMA.jl 0.1.4) was tagged but never published; its changes ship here.
-
Data: the email addresses in
RS.data(2 messages) andRS.data.multimodal- are replaced by
[EMAIL], as in rENA’sRS.data(whosetextcolumnRS.data’s now matches); nothing else in either dataset changes. Thetest_redditandtest_reddit2datasets, which held real Reddit usernames and posts and were not used by any test or vignette, are removed.
- are replaced by
-
qe-tma’s
accumulate()matches R’s on data where conversations interleave or a unit is in several conversations:-
contexts()/accumulate()gainsplit_by(= R’scontexts(split_rules = <columns>)): each unit’s context is split by those columns, each split accumulated on its own (windows never cross one) and summed per unit. rENA’s accumulation splits by the conversation; withsplit_by=<conversation>, qe-tma equals the stanza window exactly. - Without
time_col, a row’s time is its position within its context (= R’s context row id), not its row number in the whole data, so windows count the lines a unit can see. Results were wrong whenever other conversations’ rows came in between. Tests: R tma reference (python/tests/fixtures/contexts-split.R), unsplit and split, binary / product / ordered.
-
accumulate_unit()andaccumulate_unit_with_rows()withordered = FALSE(the default) counted every connection twice: they built the undirected connection matrix and then folded it as if it were directed. They now accumulate directed and fold once, asaccumulate_unit_networks()and tma’s originalaccumulate_network()do, so unordered output is the folded ordered output (A then B = 2 gave A & B = 4; now 2). Binary results were unaffected; weighted / non-binary counts halve.accumulate_unit_with_rows()’srow_networksare now directed in both modes. Same fix in qe-tma, tma-wasm and TMA.jl.qe-tma (Python) accumulates only, as R’s tma does; modeling is qe-ena’s. Breaking:
TMA().fit()is replaced bytma.accumulate(), which returns aTMAAccumulationwith R’s fields –connection_counts_,self_connection_counts_,miss_counts_,self_miss_counts_, the per-linerow_*tables,meta(one row per unit),unit_labels_,codes_,connection_names_,adjacency_key_,ordered_– and gainsself_connections(unordered A & A columns, as R). The normalization, SVD and node positions thatTMA.fit()ran are gone: model the accumulation with qe-ena (ena.ENA().fit(accum)), as rENA models tma’s in R. qe-tma no longer depends on qe-ena (it imported it for node positions since the libqe split); it requires qe-lib >= 0.2.1.
tma 0.3.9
-
accumulate(self_connections = TRUE)(unordered networks; defaultFALSE) also puts each code’s self-connection intoconnection.countsand the per-line table – and with misses, each self-miss intomiss.counts– so a model built on them includes self-connections. Columns run A & A, A & B, B & B, A & C, … (the upper triangle with the diagonal), as the adjacency key says (adjacency_key(codes, diagonal = TRUE)). Off by default, so existing results and column layouts are unchanged; ordered networks always carry the diagonal.self.connection.countsis kept separately either way. - libtma
finalize_row_connections(),aggregate_row_connections()andaccumulate_unit_networks()takediagonal(defaultfalse; in tma-wasm an optional trailing argument), using libqe’s diagonal fold (n_connections(),fold_directed_network(v, diagonal)). - Requires libqe >= 0.2.1 (DESCRIPTION, the libtma Conan recipe and
scripts/sync-headers.sh).
tma 0.3.8
-
accumulate()now keeps missed co-occurrences by default (misses = TRUE): every result carriesmiss.counts,model$row.miss.countsand the self-miss tables. Passmisses = FALSEto skip them, e.g. for many codes or long data (the per-line miss table has one column per directed pair when ordered). qe-tmaTMA.fit()follows (misses=True). Existing fields are unchanged. - libtma
accumulate_unit_networks()returns one unit’s finished networks in one call – fold (unordered), per-line weight model, unit sum and the self-connection diagonal, for hits and misses – and is exported in R, qe-tma, tma-wasm and TMA.jl.accumulate()andTMA.fit()use it instead of folding and aggregating in R / Python, which makesaccumulate()faster (about 40% on 15k lines and 12 codes with misses). - libtma
weight_rows()applies the weight model per line to rows that are already folded (unordered) or directed (ordered) – the weight step offinalize_row_connections()on its own – so callers ofaccumulate_unit_networks()that need per-line weighted rows (rena-wasm’srowConnectionCounts) get them from libtma. Exported in R, qe-tma, tma-wasm and TMA.jl. -
accumulate()keeps self-connections:self.connection.counts(one column per code) andmodel$row.self.connection.counts(raw, per line). A code’s self-connection on a line is its ground count times its response count – the ordered network’s diagonal, which unordered networks drop when they fold to the upper triangle – weighted per line byweight_byand summed per unit, for ordered and unordered models alike. Withmisses = TRUE, alsoself.miss.counts/model$row.self.miss.counts(the code in the ground, absent from the response). Not used in the model yet. - libtma
finalize_self_connections()/aggregate_self_connections()compute them fromapply_tensor_unit’s per-line rows, exported in R, qe-tma, tma-wasm and TMA.jl. qe-tmaTMA.fit()storesself_networks_(andself_miss_networks_withmisses=True).
tma 0.3.7
-
accumulate(misses = TRUE)also accumulates missed co-occurrences: for each response line, the window-weighted ground count of code i when code j is absent from the response, with no response self-term. Misses go through the same steps as connection counts: directed for ordered models, folded to the upper triangle for unordered ones,weight_byapplied per line. Results land inmiss.countsandmodel$row.miss.counts. Backed by libtma’smiss_matrix()andapply_tensor_unit(..., return_misses = true);apply_tensor()gainsmisses = FALSE. - Misses in every binding: qe-tma
apply_tensor_unit(..., misses=False)andTMA.fit(misses=False)(→miss_networks_); tma-wasmaccumulate_tensor_unit_misses()(same arguments asaccumulate_tensor_unit); TMA.jlaccumulate_tensor_unit(...; misses=false). Results gainmiss_counts/row_miss_countsonly when misses are asked for, so existing callers see no change. - qe-tma
TMA.fit()fixes:-
connection_names_match R’sadjacency_key(): ordered labels were transposed (position j*n+i is ground i -> response j, labelled “i & j”), and unordered labels come from libqe’sconnection_names(“A & B”, was “A&B”). - Units with a single visible line are no longer skipped: as in R, the response self-term connects their co-occurring codes. (A single-row selection is read-only under pandas copy-on-write, so the code matrix is now copied before it reaches the extension.)
-
- Works with libqe 0.2.0, which drops its copy of the accumulation code (tma no longer uses it). qe-tma 0.1.4 allows
qe-lib<0.3; tma-wasm allows@qe-libs/libqe-wasm0.2 (its libqe-wasm parity tests skip the functions 0.2 removed). - CI installs qe-ena from qe-libs.org instead of building rENA’s
develop.
tma 0.3.6
- tma is a compiled package again. The accumulation C++ (stanza windows, context tensors, row connections, weight models) moved out of libqe into tma as the header-only layer libtma (
inst/include/libtma/, wrapped insrc/libtma_rcpp.cpp), so libqe can return to generic numerics. Results are unchanged: the code and its tests moved verbatim. tma now exports the accumulation functions libqe did (apply_tensor,apply_tensor_members,accumulate_stanza,rolling_window_sum,row_connections,aggregate_row_connections,finalize_row_connections, …). Installing from source needs a C++ toolchain (Rtools on Windows); requires libqe >= 0.1.9. - The Python package pyTMA (
import pytma, never published) is now qe-tma (import tma), with libtma compiled in (tma.libtma) instead of calling libqe’s copy. Node positions come from qe-ena and generic numerics from qe-lib (it imported the oldpylibqename, so it no longer installed). - New npm package
@qe-libs/tma-wasm(wasm/): libtma compiled to WebAssembly, replacing libqe-wasm’s accumulation functions (same signatures). - New Julia package TMA.jl (
julia/,using TMA) replaces LibQE.jl’s accumulation functions, adding the weight models (aggregate_row_connections,finalize_row_connections). libtma is also published as a Conan package (conan/).
tma 0.3.5
-
accumulate()now looks each sender, receiver and mode value up in the tensor’s own levels (the sorted levelscontext_tensor()built from the whole dataset). It previously re-encoded character-valued columns withas.factor()inside each unit’s context, so a context containing only some levels mapped them to the wrong tensor slice – for example, a context with only “Second” used “First”’s weight and window. Numeric columns were used directly as positions, so values other than 1..k (such as 0/1) pointed outside the tensor and could crash R. Models whose contexts contain every level, and models built with the default tensor, are unchanged. - Values that are not levels of the tensor now raise a clear error.
tma 0.3.4
-
accumulate()gainsweight_by, the weight model applied to each line’s connection counts before they are summed per unit (= rENA’sweight.by):"binary","product"(raw counts),"sqrt"or"log1p"(alias"log"). For unordered networks the weight is applied after each line is folded to the upper triangle; for ordered networks, to each directed cell. It defaults frombinary("binary"whenTRUE,"product"whenFALSE), so existing calls produce identical results;"binary"on ordered networks keeps the raw directed counts, as before.model$row.connection.countsstill holds the raw, unweighted line counts, andweight_byis recorded in_function.params. - The per-unit aggregation now uses libqe’s shared
aggregate_row_connections()kernel; the R package requires libqe 0.1.5 or newer. - pytma 0.1.2:
TMA.fit()gains the sameweight_byargument and requires pylibqe 0.1.5 or newer. -
contexts()now warns when a conversation rule compares a column toUNITwith==(e.g.GroupName == UNIT$GroupName) and a unit has more than one value for that column.UNIT$<col>holds every value across the unit’s rows, so==recycles and silently selects the wrong rows; use%in%instead.
tma 0.3.3
- Added door smoothing helpers for lookback, EMA, and LOESS workflows.
- Added
door_accumulation()as a convenience wrapper for the standard ETMdoor()plusreplace_door()workflow. - Added trajectory helpers for polynomial curve fitting, derivative profiles, curve distances, lagged distances, signed turn-lag analysis, and stability grids.
- Updated the R package dependency to require libqe 0.1.2 or newer for the shared door and trajectory kernels.
tma 0.3.1
CRAN release: 2025-09-19
- added exports: ATTR_NAMES, adjacency_key
- added class as and is S3 methods for: qe.metadata, qe.data, qe.code, qe.unit, qe.horizon
- moved jsonlite to Suggests, only required in less often used tma::view()
tma 0.3.0
CRAN release: 2025-08-25
- context_tensor function for controlling weights and windows across modalities
- deprecated prior implementations: windows_weights, accum_multidim, decay, simple_window