diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 27bd9cec..3d272557 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -231,3 +231,36 @@ After `runAnalysis()`, check: - Use `createJaspTable()`, `createJaspPlot()`, `createJaspHtml()` for output elements - Always set `$dependOn()` for proper caching and state management - Use containers for grouping related elements, state objects for reusing computed results + +## Container Environment (overrides Session Setup section above) + +This is a **headless Docker container**. There is no interactive user. + +### MANDATORY FIRST ACTION — R Session Connection + +Before doing ANYTHING else (before reading code, before exploring the repo), +you MUST connect to the pre-started R session: + +1. Call `list_r_sessions` to discover available sessions. +2. Call `select_r_session` to connect to the listed session. +3. Only then proceed with the workflow. + +If `list_r_sessions` returns empty, the background R session failed to start. +Fall back to Bash for R execution. Do NOT spend more than 2 turns debugging. + +This step is NOT optional. Without it, `btw_tool_run_r` will fail. + +### Other container rules + +- `session_startup.R` is NOT relevant here — ignore references to it. +- Do NOT run any git commands (the outer orchestrator handles git). + +## Compact Instructions + +When context is compacted, preserve: +- Current workflow stage (from /workspace/.openclaw-run/current_stage) +- Implementation plan (from /workspace/.openclaw-run/PLAN.md) +- The module name and original task description +- What git changes have been made so far + +After compaction, re-read /workspace/.openclaw-run/RECOVERY.md to re-orient. diff --git a/R/TimeWeightedCharts.R b/R/TimeWeightedCharts.R index 153f9a00..22ae8c1e 100644 --- a/R/TimeWeightedCharts.R +++ b/R/TimeWeightedCharts.R @@ -194,10 +194,21 @@ timeWeightedCharts <- function(jaspResults, dataset, options) { columnsToPass <- c(measurements, stages) columnsToPass <- columnsToPass[columnsToPass != ""] phase2 <- (options[["cumulativeSumChartSdSource"]] == "historical") + movingRangeLength <- options[["cumulativeSumChartAverageMovingRangeLength"]] + if (!phase2 && .stageHasTooFewObservationsForMovingRange(dataset, stages, movingRangeLength)) { + plot$setError(.timeWeightedStagesMovingRangeErrorMessage( + chartTitle = gettext("Cumulative sum chart"), + dataset = dataset, + stages = stages, + movingRangeLength = movingRangeLength + )) + return(list("plot" = plot)) + } + cusumChart <- .controlChart(dataset[columnsToPass], plotType = "cusum", stages = stages, xBarSdType = options[["cumulativeSumChartSdMethod"]], nSigmasControlLimits = options[["cumulativeSumChartNumberSd"]], xAxisLabels = axisLabels, cusumShiftSize = options[["cumulativeSumChartShiftSize"]], cusumTarget = options[["cumulativeSumChartTarget"]], - movingRangeLength = options[["cumulativeSumChartAverageMovingRangeLength"]], phase2 = phase2, + movingRangeLength = movingRangeLength, phase2 = phase2, phase2Sd = options[["cumulativeSumChartSdValue"]], tableLabels = axisLabels, ruleList = ruleList) table <- cusumChart$table plot$plotObject <- cusumChart$plotObject @@ -221,9 +232,20 @@ timeWeightedCharts <- function(jaspResults, dataset, options) { columnsToPass <- c(measurements, stages) columnsToPass <- columnsToPass[columnsToPass != ""] phase2 <- (options[["exponentiallyWeightedMovingAverageChartSdSource"]] == "historical") + movingRangeLength <- options[["exponentiallyWeightedMovingAverageChartMovingRangeLength"]] + if (!phase2 && .stageHasTooFewObservationsForMovingRange(dataset, stages, movingRangeLength)) { + plot$setError(.timeWeightedStagesMovingRangeErrorMessage( + chartTitle = gettext("Exponentially weighted moving average chart"), + dataset = dataset, + stages = stages, + movingRangeLength = movingRangeLength + )) + return(list("plot" = plot)) + } + ewmaChart <- .controlChart(dataset[columnsToPass], plotType = "ewma", stages = stages, xBarSdType = options[["exponentiallyWeightedMovingAverageChartSdMethod"]], nSigmasControlLimits = options[["exponentiallyWeightedMovingAverageChartSigmaControlLimits"]], - xAxisLabels = axisLabels, movingRangeLength = options[["exponentiallyWeightedMovingAverageChartMovingRangeLength"]], + xAxisLabels = axisLabels, movingRangeLength = movingRangeLength, ewmaLambda = options[["exponentiallyWeightedMovingAverageChartLambda"]], phase2 = phase2, phase2Sd = options[["exponentiallyWeightedMovingAverageChartSdValue"]], tableLabels = axisLabels, ruleList = ruleList) @@ -247,3 +269,20 @@ timeWeightedCharts <- function(jaspResults, dataset, options) { return(ruleList) } +.stageHasTooFewObservationsForMovingRange <- function(dataset, stages, movingRangeLength) { + if (identical(stages, "") || !stages %in% colnames(dataset)) + return(FALSE) + + stageCounts <- table(dataset[[stages]]) + any(stageCounts < movingRangeLength) +} + +.timeWeightedStagesMovingRangeErrorMessage <- function(chartTitle, dataset, stages, movingRangeLength) { + stageCounts <- table(dataset[[stages]]) + minObservations <- min(stageCounts) + gettextf(paste0( + "At least one stage contains only %1$s observation(s). %2$s requires at least %3$s observations per stage ", + "for the selected moving range length. This can happen when too many stages are defined (for example one point ", + "per stage). Reduce the number of stages or lower the moving range length." + ), minObservations, chartTitle, movingRangeLength) +} diff --git a/tests/testthat/_snaps/example-Type1InstrumentCapability/analysis-1-figure-1-bias-histogram.new.svg b/tests/testthat/_snaps/example-Type1InstrumentCapability/analysis-1-figure-1-bias-histogram.new.svg new file mode 100644 index 00000000..0b696f60 --- /dev/null +++ b/tests/testthat/_snaps/example-Type1InstrumentCapability/analysis-1-figure-1-bias-histogram.new.svg @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +5 +10 +15 + + + + + + + + + + + +-5.5 +-5.0 +-4.5 +-4.0 +-3.5 +-3.0 +jaspColumn1 +Count + + + + + + + + + + + + + + +Mean +Mean - 3s +Mean + 3s +Reference +Ref. - 0.10 * tol. +Ref. + 0.10 * tol. +analysis-1_figure-1_bias-histogram + + diff --git a/tests/testthat/_snaps/msaType1Gauge/1-bias-histogram.new.svg b/tests/testthat/_snaps/msaType1Gauge/1-bias-histogram.new.svg new file mode 100644 index 00000000..f28037c6 --- /dev/null +++ b/tests/testthat/_snaps/msaType1Gauge/1-bias-histogram.new.svg @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +5 +10 +15 + + + + + + + + + + + +-5.5 +-5.0 +-4.5 +-4.0 +-3.5 +-3.0 +dm +Count + + + + + + + + + + + + + + +Mean +Mean - 3s +Mean + 3s +Reference +Ref. - 0.10 * tol. +Ref. + 0.10 * tol. +1_bias-histogram + + diff --git a/tests/testthat/_snaps/msaType1Gauge/2-bias-histogram.new.svg b/tests/testthat/_snaps/msaType1Gauge/2-bias-histogram.new.svg new file mode 100644 index 00000000..0e215eaf --- /dev/null +++ b/tests/testthat/_snaps/msaType1Gauge/2-bias-histogram.new.svg @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +5 +10 +15 + + + + + + + + + + +-5.0 +-4.5 +-4.0 +-3.5 +-3.0 +dm +Count + + + + + + + + + + + + + + +Mean +Mean - 2s +Mean + 2s +Reference +Ref. - 0.07 * tol. +Ref. + 0.07 * tol. +2_bias-histogram + + diff --git a/tests/testthat/_snaps/msaType1Gauge/3-bias-histogram.new.svg b/tests/testthat/_snaps/msaType1Gauge/3-bias-histogram.new.svg new file mode 100644 index 00000000..e07d4ebb --- /dev/null +++ b/tests/testthat/_snaps/msaType1Gauge/3-bias-histogram.new.svg @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +5 +10 + + + + + + + + + + +-5.5 +-5.0 +-4.5 +-4.0 +-3.5 +-3.0 +dmMissing1 +Count + + + + + + + + + + + + + + +Mean +Mean - 3s +Mean + 3s +Reference +Ref. - 0.10 * tol. +Ref. + 0.10 * tol. +3_bias-histogram + + diff --git a/tests/testthat/_snaps/msaType1Gauge/4-bias-histogram.new.svg b/tests/testthat/_snaps/msaType1Gauge/4-bias-histogram.new.svg new file mode 100644 index 00000000..3c9b9602 --- /dev/null +++ b/tests/testthat/_snaps/msaType1Gauge/4-bias-histogram.new.svg @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +5 +10 + + + + + + + + + + +-4.6 +-4.4 +-4.2 +-4.0 +-3.8 +-3.6 +dmMissing25 +Count + + + + + + + + + + + + + + +Mean +Mean - 3s +Mean + 3s +Reference +Ref. - 0.10 * tol. +Ref. + 0.10 * tol. +4_bias-histogram + +