Skip to contents

LAGOtrials 1.1.0

  • Fixed an outcome goal or a power goal failing when the outcome column has missing values. The check of the outcome goal’s direction compared it against the outcome mean without removing missing values, so any missing outcome stopped lago_optimization() with “missing value where TRUE/FALSE needed”. The power calculation counted a row with a missing outcome toward its arm’s size but made the arm’s sum missing, so the default unconditional approach failed the same way and the conditional approach silently returned a power-implied outcome of 0, which dropped the power goal. Both now use only rows with an observed outcome, as the final treatment-versus-control test does, and a power goal now needs a group column with both arms present and an observed outcome in each.

  • Fixed the in-browser playground misreading a column named like a built-in JavaScript property (for example constructor or toString). Ticked as an intervention component, it made the generated R code, Run, the sensitivity sweep and the budget search fail, and its bounds and unit cost came up collapsed or blank instead of the column’s defaults. As a center characteristic, its held-at value came up blank and was left out of the call.

  • The in-browser playground now supports a power goal (binary outcomes): tick “Power goal” to plan for the next stage’s statistical power alongside, or instead of, the outcome goal, matching lago_optimization()’s power_goal, num_centers_in_next_stage, patients_per_center_in_next_stage, power_goal_approach, icc and power_goal_cluster_id. The treatment arm comes from the data’s own group column when it has one (used as is, so it must hold only “treatment” and “control” with both present), otherwise from a complete 0/1 column you pick (pre_post for BB_data, as in the package tests), and the shown R code includes the lines that build it on a copy of the data. Direction must be Maximize, and Run stays disabled with a hint until the power settings are complete. The ICC cluster column list offers only columns with at least two non-missing centers with an observed outcome in each arm, checked when an ICC is entered. The sensitivity sweep can vary the power goal, and the budget search and Share link carry the settings. On BB_data the stage-1 data already powers the comparison, so the power goal alone recommends no intervention, and the printed result reports the power-implied outcome.

  • The in-browser playground now has an optional “Additional covariates” section: tick any columns (numeric or not, for example a site or arm label) to adjust the outcome model for them, matching lago_optimization()’s additional_covariates. A column can play only one role at a time (intervention component, center characteristic, or additional covariate). The chosen covariates ride along in the Share link.

  • The in-browser playground now supports fixed time effects: when the loaded data has a period column (so, an uploaded CSV, since no bundled dataset has one) a “Fixed time effects” checkbox appears with a period value to optimize at, matching lago_optimization()’s include_time_effects and time_effect_optimization_value. (Time effects are not carried in the Share link, which is offered only for bundled datasets.)

  • The in-browser playground now has an optional “Interaction terms” section: with two or more intervention components ticked, tick a pair to model their product (for example coaching_updt × launch_duration). It sets include_interaction_terms = TRUE and main_components, appends the a:b term to intervention_components, and prepends the line that creates the interaction’s product column so the shown R code stays copy-pasteable. Bounds, costs and the confidence set stay per main component, and the sensitivity sweep, budget search and Share link inherit the interactions.

  • The in-browser playground’s “Share link” now carries the whole page, not just the core optimization: the center characteristics and their held-at values, the interaction terms, the additional covariates, a budget you have entered, and the sensitivity sweep’s input, range and step count all round-trip through the URL, so an opened link reproduces the full setup. Older or hand-trimmed links that omit these simply keep the page’s own defaults for those controls.

  • The in-browser playground now has an optional “Center characteristics” section: tick numeric columns (for example a center’s birth volume) and set the value each is held at, and the recommendation is computed for a center with those characteristics, matching lago_optimization()’s center_characteristics and center_characteristics_optimization_values. The sensitivity sweep and budget search inherit the same setting. A column can be an intervention component or a center characteristic but not both.

  • The in-browser playground now has a “Budget” section that surfaces lago_budget(): enter a cost budget and it finds the best outcome reachable within it and the intervention that reaches it (the reverse of setting an outcome goal). It reports the recommendation, its cost and estimated outcome (or that no intervention fits), notes when the budget does not bind, and draws the cost/outcome frontier as an interactive D3 chart with the budget line and the chosen point marked. The budget field auto-fills a sensible default from the current costs and bounds until it is edited.

  • Added lago_budget(), which answers the reverse of the usual LAGO question: given a fixed cost budget, what is the best outcome reachable, and with which intervention? It searches the outcome goal along the least-cost frontier lago_optimization() traces out and returns the most ambitious reachable goal whose recommended cost fits the budget (the lowest reachable outcome within budget for outcome_goal_intention = "minimize"), with print() and plot() methods and a frontier of the cost-vs-outcome points searched. Like lago_sensitivity(), it reuses a fitted lago result’s call or takes the arguments directly, and it never computes the confidence set. It reports whether the budget is feasible and whether it binds.

  • Fixed the in-browser playground’s default configuration not producing a result. It prefilled the first binary column as the outcome, which for BB_data is the pre_post pre/post period flag: perfectly separable from the coaching components, so the outcome model never converged and Run (and the sensitivity sweep) errored out of the box. Each bundled dataset now starts from a preset that fits (BB_data uses the pp3_oxytocin_mother outcome with the coaching_updt and launch_duration components; mtcars uses mpg with gear and qsec), and switching datasets or pressing Reset lands on that dataset’s runnable preset. Uploaded CSVs keep the generic prefill.

  • The in-browser playground now has a “Sensitivity sweep” section that re-runs the recommendation across a range of one input, using lago_sensitivity(). Pick the input to vary (the outcome goal or a cost multiplier), a from/to range and a number of steps, and it draws how the recommended cost moves as an interactive D3 line (with each run’s per-component recommendation, estimated outcome and status in a table beneath). The confidence set is skipped during the sweep for speed, and a failed run is shown as a gap rather than aborting the sweep.

  • The in-browser playground now has a “Share link” button that encodes the whole current setup (bundled dataset, outcome column and type, intervention components, their bounds and costs, the goal and direction) into the page URL and copies it to the clipboard. Opening that link restores the configuration on load, ready to run. Costs are encoded as per-component coefficient vectors, so a curve shaped in the cost designer is preserved along with plain unit costs. Sharing is offered only for the bundled datasets, since an uploaded CSV cannot be carried in a URL.

  • The in-browser playground and the cost designer now round-trip. A “Shape costs in the designer” button opens visualize_cost() in the browser pre-loaded with the intervention components, bounds and unit costs configured in the playground (the designer reads this from its page URL query and falls back to its built-in example when the query is absent or malformed; a plain visualize_cost(...) call is unchanged). In the designer, a “Use these costs in the playground” button sends the shaped cost functions back to the playground tab, which then uses them as cost_list_of_vectors for the optimization (shown in the reproducible R code) instead of the linear unit cost; adjusting a component’s unit cost reverts it.

  • visualize_cost() now has a “Cost function form” toggle that switches all components between the linear and cubic cost functions live, instead of the form being fixed for the whole session by default_cost_fxn_type. Switching resets each component to that form’s initial coefficients and shows the right number of coefficient sliders (2 for linear, 5 for the cubic’s degree-4 total cost). The cubic form opens on a visibly curved (but still valid) demo cost rather than the near-linear one cost_fxn_calculator() returns for typical unit costs, so the toggle clearly shows a cubic. This also gives the in-browser cost designer a cubic option.

  • The total cost curve in visualize_cost() can now be reshaped by dragging: each curve carries a draggable handle at several points along it, and dragging one refits the cost function through the new set of points (and updates the sliders), instead of the single right-endpoint handle that only rescaled the whole curve.

  • The fitted outcome model’s Call:, shown in the “Outcome model fit” section of print() and summary(), now displays the actual model formula instead of the literal word formula. This also makes the console output identical across R versions: a change in recent R to how the unrecorded formula deparses had otherwise made the output (and its snapshot tests) version dependent.

  • Added a live in-browser demo to the documentation site (live-demo.html) that runs the real package client-side with webR (R compiled to WebAssembly), so anyone can try lago_optimization() with no installation, plus an interactive playground (playground.html) where you pick a bundled dataset or upload a CSV, configure the model with sliders and toggles, and see the recommendation drawn with the package’s own D3 charts alongside a copy-pasteable R snippet. A GitHub Actions workflow builds the package to WebAssembly with the rwasm toolchain and publishes it as a small CRAN-like repository alongside the site.

  • Added a browser version of visualize_cost(): the same Shiny cost-function designer now runs client-side on the documentation site (/visualize-cost/), exported with shinylive, so you can shape each component’s cost curve and copy the coefficient list with no install. visualize_cost() was refactored to build its app object separately from launching it, so the local and in-browser versions share one implementation.

  • lago_report() now renders an interactive HTML dashboard: the confidence set is a hover-enabled D3 plot (a scatter for two components, a strip for one) with the recommended intervention highlighted, and each intervention component gets interactive total-cost and marginal-cost curves. The report stays a single self-contained offline file (D3 is inlined, no CDN or server) and its API is unchanged; rendering now also uses jsonlite (a new Suggests).

  • Added an MCP (Model Context Protocol) server to the Python package (python -m lago.mcp_server) that exposes optimize and sensitivity as tools any MCP-aware AI agent can call, plus a sensitivity() function in the Python wrapper.

  • Added lago_sensitivity(), which re-runs an optimization across a sweep of one input (an outcome or power goal, or a "cost_multiplier" that scales all costs) and reports how the recommended intervention, its cost, and the estimated outcome move, with print() and plot() methods.

  • The package is now installed and loaded as LAGOtrials (call library(LAGOtrials)); the previous LAGO identifier clashed with an archived CRAN package. Function names, the lago result class, and the LAGO method name are unchanged.

  • visualize_cost() now stores the returned cost list in the lago_cost_list option instead of assigning it to the global environment; retrieve it with getOption("lago_cost_list").

  • Added tests for the interaction-terms optimization path and the outcome-model fit warnings, and excluded the interactive visualize_cost() app from the coverage figure so it reflects the testable R code.

  • Added a CITATION.cff so the repository can be cited, plus contributing guidelines, a code of conduct and issue/pull-request templates. (#86)

  • Added test-coverage reporting, cross-platform (macOS, Windows, Linux) continuous integration, project-status and coverage badges, and a social-preview card. (#83, #84, #85)

  • Added a Python wrapper (in python/, importable as lago) that calls LAGOtrials through rpy2. (#81)

  • visualize_cost() now draws its cost curves client-side with D3, with hover read-outs, a draggable curve endpoint, and invalid-state highlighting. (#80)

  • The clustered variance estimator for logit outcomes is now computed by a compiled Rcpp kernel, so Rcpp is a new dependency. (#79)

  • lago_optimization() now refuses an additional covariate whose column is entirely NA, naming it. (#77)

  • A rank-deficient outcome model is now refused up front with an error naming the aliased terms. (#74, #76)

  • Added a warning when glm() drops an additional covariate as collinear. (#76)

  • Fixed confidence-interval bounds for a binary logit outcome being reported outside [0, 1]. (#75)

  • Fixed the estimated outcome being scaled by center weights that did not sum to 1. (#72, #75)

  • Added a warning when a binary outcome’s estimated outcome is reported outside [0, 1]. (#75)

  • Added a warning when a numeric additional covariate observed away from 0 is held at 0 for the confidence set. (#75)

  • Fixed the confidence interval and set being computed on the logit scale for an identity-link binomial model. (#74)

  • center_weights_for_outcome_goal must now be numeric, finite and non-negative, checked at both entry points. (#73, #74)

  • Fixed the numerical optimizer failing with an opaque error when every restart failed, so it now gives an actionable message. (#73)

  • Fixed a factor covariate named like “center” or “period” being miscounted as a fixed effect when get_confidence_set() is called directly. (#73)

  • Fixed outcome_goal_intention = "minimize" ignoring the outcome goal on a logit link. (#70)

  • Fixed the recommended intervention sometimes falling outside the intervention bounds. (#70)

  • Fixed the numerical optimisation returning its most expensive candidate solution instead of the cheapest. (#70)

  • Fixed the estimated outcome being wrong when more than one center characteristic was supplied. (#70)

  • link = "probit" and link = "log" are no longer accepted, since only logit and identity were ever implemented. (#70)

  • Fixed $est_outcome_ci sometimes reporting the wrong interval instead of the one at the recommended intervention. (#68)

  • Fixed the confidence set occasionally dropping one of its qualifying interventions. (#68)

  • Fixed confidence_set_size_percentage understating the size of the confidence set. (#68)

  • A confidence set containing exactly one grid intervention is no longer discarded as empty. (#68)

  • Fixed confidence-interval bounds being attached to the wrong interventions under two-way clustering. (#68)

  • get_confidence_set() now returns rec_int_ci, the interval at the recommended intervention (its return shape changed for direct callers). (#68)

  • The confidence set, its size, and the estimated-outcome interval can differ from earlier releases wherever the previous values were wrong. (#68)

  • Fixed get_confidence_set() pairing the prediction matrix with the model coefficients by position instead of by name. (#68)

  • Fixed the estimated outcome being reported as 0 for the reference period when fixed time effects were included. (#68)

  • Fixed the estimated-outcome interval being computed at the wrong time period. (#68)

  • Fixed an additional covariate or center characteristic named like “center” being miscounted as a fixed center effect. (#68)

  • Fixed a factor or character additional covariate or center characteristic being paired with the wrong coefficient or erroring. (#68)

  • Fixed the confidence set changing when the rows of data were reordered. (#68)

  • Fixed passing more than one center characteristic to the confidence set failing or duplicating a column. (#68)

  • Added runnable @examples to every exported function that lacked them. (#67)

  • Restyled the print() and summary() console output with boxed cli sections. (#65)

  • The fitted outcome model ($model) and the estimated-outcome interval ($est_outcome_ci) are now returned on the result. (#65)

  • Added lago_report(), which renders a self-contained HTML report of a result. (#64)

  • lago_optimization() now returns a "lago" object with print(), summary(), and plot() methods. (#61)

  • Added an “Optimizing an intervention with LAGO” vignette. (#61)

  • Added a hex logo and refreshed the README header. (#56, #61)

  • Added a quiet argument to lago_optimization() that skips progress messages. (#60)

  • visualize_cost() gained a copy-to-clipboard button, a numeric cost summary, and returns the cost list on close. (#59)

  • Expanded the reference documentation for the bundled datasets. (#58)

  • Added a GPL-3 LICENSE file. (#56)

  • Fixed a crash when a single intervention component was used. (#54)

  • Added a pkgdown documentation site published to GitHub Pages. (#53)

  • The overall intervention-effect test result is now returned in the result object. (#49)

  • Added an automated test suite (testthat) and continuous-integration checks. (#45)

  • lago_optimization() now accepts a standalone power goal, an outcome goal, or both together. (#40)

  • Added non-fatal outcome-model fit diagnostics. (#36)

  • visualize_cost() sliders now support per-component default and custom ranges. (#34)

  • Supplying optimization_grid_search_step_size now switches the optimization method to grid search automatically. (#32)

  • Added an icc argument so the power goal can account for within-center clustering. (#29)

Known limitations

  • The confidence set is the set of interventions whose confidence interval covers the outcome goal, which is a two sided test and does not depend on outcome_goal_intention. Under outcome_goal_intention = "minimize" it can therefore contain interventions whose estimated outcome is above the goal, and which cost more than the recommendation, because their interval still reaches the goal from above. Read the confidence set as the interventions the data cannot distinguish from the goal, not as the interventions that meet it. The estimated outcome and its interval, reported as est_outcome_goal and est_outcome_ci, are computed at the recommended intervention and are direction independent, so they are unaffected.