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 agroupcolumn 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
constructorortoString). 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()’spower_goal,num_centers_in_next_stage,patients_per_center_in_next_stage,power_goal_approach,iccandpower_goal_cluster_id. The treatment arm comes from the data’s owngroupcolumn 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_postforBB_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. OnBB_datathe 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()’sadditional_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
periodcolumn (so, an uploaded CSV, since no bundled dataset has one) a “Fixed time effects” checkbox appears with a period value to optimize at, matchinglago_optimization()’sinclude_time_effectsandtime_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 setsinclude_interaction_terms = TRUEandmain_components, appends thea:bterm tointervention_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()’scenter_characteristicsandcenter_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 frontierlago_optimization()traces out and returns the most ambitious reachable goal whose recommended cost fits the budget (the lowest reachable outcome within budget foroutcome_goal_intention = "minimize"), withprint()andplot()methods and afrontierof the cost-vs-outcome points searched. Likelago_sensitivity(), it reuses a fittedlagoresult’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_datais thepre_postpre/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_datauses thepp3_oxytocin_motheroutcome with thecoaching_updtandlaunch_durationcomponents;mtcarsusesmpgwithgearandqsec), 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 plainvisualize_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 ascost_list_of_vectorsfor 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 bydefault_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 onecost_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 ofprint()andsummary(), now displays the actual model formula instead of the literal wordformula. 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 trylago_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 usesjsonlite(a new Suggests).Added an MCP (Model Context Protocol) server to the Python package (
python -m lago.mcp_server) that exposesoptimizeandsensitivityas tools any MCP-aware AI agent can call, plus asensitivity()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, withprint()andplot()methods.The package is now installed and loaded as
LAGOtrials(calllibrary(LAGOtrials)); the previousLAGOidentifier clashed with an archived CRAN package. Function names, thelagoresult class, and the LAGO method name are unchanged.visualize_cost()now stores the returned cost list in thelago_cost_listoption instead of assigning it to the global environment; retrieve it withgetOption("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.cffso 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 aslago) that calls LAGOtrials throughrpy2. (#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
Rcppis a new dependency. (#79)lago_optimization()now refuses an additional covariate whose column is entirelyNA, 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_goalmust 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"andlink = "log"are no longer accepted, since onlylogitandidentitywere ever implemented. (#70)Fixed
$est_outcome_cisometimes 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_percentageunderstating 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 returnsrec_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
datawere reordered. (#68)Fixed passing more than one center characteristic to the confidence set failing or duplicating a column. (#68)
Added runnable
@examplesto every exported function that lacked them. (#67)Restyled the
print()andsummary()console output with boxedclisections. (#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 withprint(),summary(), andplot()methods. (#61)Added an “Optimizing an intervention with LAGO” vignette. (#61)
Added a hex logo and refreshed the README header. (#56, #61)
Added a
quietargument tolago_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
LICENSEfile. (#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_sizenow switches the optimization method to grid search automatically. (#32)Added an
iccargument 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. Underoutcome_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 asest_outcome_goalandest_outcome_ci, are computed at the recommended intervention and are direction independent, so they are unaffected.