From 6799a6f9ea25799a441f2b989ea98b05153dd5b8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 13:17:58 +0000 Subject: [PATCH 1/2] chore(letsplot): add metadata for timeseries-forecast-uncertainty --- .../implementations/python/letsplot.py | 113 ++++----- .../metadata/python/letsplot.yaml | 231 +----------------- 2 files changed, 60 insertions(+), 284 deletions(-) diff --git a/plots/timeseries-forecast-uncertainty/implementations/python/letsplot.py b/plots/timeseries-forecast-uncertainty/implementations/python/letsplot.py index 6b91742812..b3cc6eea00 100644 --- a/plots/timeseries-forecast-uncertainty/implementations/python/letsplot.py +++ b/plots/timeseries-forecast-uncertainty/implementations/python/letsplot.py @@ -1,7 +1,7 @@ -""" anyplot.ai +"""anyplot.ai timeseries-forecast-uncertainty: Time Series Forecast with Uncertainty Band -Library: letsplot 4.9.0 | Python 3.13.13 -Quality: 88/100 | Updated: 2026-05-16 +Library: letsplot | Python 3.13 +Quality: pending | Updated: 2026-05-19 """ # ruff: noqa: F405 @@ -14,41 +14,34 @@ LetsPlot.setup_html() -# Theme tokens (see prompts/default-style-guide.md) +# Theme tokens THEME = os.getenv("ANYPLOT_THEME", "light") PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" INK = "#1A1A17" if THEME == "light" else "#F0EFE8" INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" +INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" INK_GRID = "rgba(26,26,23,0.10)" if THEME == "light" else "rgba(240,239,232,0.10)" -# Okabe-Ito palette for categorical data OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00", "#56B4E9", "#F0E442"] -# Data - Stock price with 36 months history + 12 month forecast +# Monthly energy demand: 36 months history + 12 month forecast np.random.seed(42) -# Historical period (36 months) dates_hist = pd.date_range("2023-01-01", periods=36, freq="MS") -# Trend + volatility + noise -trend = np.linspace(120, 185, 36) -volatility = 8 * np.sin(np.linspace(0, 4 * np.pi, 36)) -noise = np.random.normal(0, 6, 36) -actual = trend + volatility + noise +trend = np.linspace(420, 510, 36) +seasonal = 40 * np.sin(np.linspace(0, 6 * np.pi, 36)) +noise = np.random.normal(0, 12, 36) +actual = trend + seasonal + noise -# Forecast period (12 months) dates_forecast = pd.date_range("2026-01-01", periods=12, freq="MS") -trend_fc = np.linspace(185, 210, 12) -volatility_fc = 8 * np.sin(np.linspace(4 * np.pi, 5 * np.pi, 12)) -forecast = trend_fc + volatility_fc +trend_fc = np.linspace(510, 545, 12) +seasonal_fc = 40 * np.sin(np.linspace(6 * np.pi, 8 * np.pi, 12)) +forecast = trend_fc + seasonal_fc +uncertainty_80 = np.linspace(18, 45, 12) +uncertainty_95 = np.linspace(28, 68, 12) -# Uncertainty grows with forecast horizon (realistic for financial predictions) -uncertainty_80 = np.linspace(12, 35, 12) -uncertainty_95 = np.linspace(18, 55, 12) - -# Build DataFrames df_hist = pd.DataFrame({"date": dates_hist, "value": actual, "series": "Historical"}) - df_fc = pd.DataFrame( { "date": dates_forecast, @@ -61,54 +54,50 @@ } ) -# Forecast start date for vertical line forecast_start = dates_forecast[0] -# Combine line data for legend -df_lines = pd.concat([df_hist[["date", "value", "series"]], df_fc[["date", "value", "series"]]], ignore_index=True) - -# Theme-adaptive theme -anyplot_theme = theme( - plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), - panel_background=element_rect(fill=PAGE_BG), - panel_grid_major=element_line(color=INK_GRID, size=0.3), - axis_title=element_text(color=INK, size=20), - axis_text=element_text(color=INK_SOFT, size=16), - axis_line=element_line(color=INK_SOFT, size=0.5), - plot_title=element_text(color=INK, size=24), - legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT), - legend_text=element_text(color=INK_SOFT, size=16), - legend_title=element_text(color=INK, size=18), - plot_caption=element_text(color=INK_SOFT, size=14), - legend_position="right", -) - -# Plot +# Plot — theme_classic gives L-shaped spines; theme() overrides specific elements plot = ( ggplot() - # 95% confidence band (lighter, using position 5 - orange) - + geom_ribbon(aes(x="date", ymin="lower_95", ymax="upper_95"), data=df_fc, fill=OKABE_ITO[4], alpha=0.2) - # 80% confidence band (darker, using position 5 - orange) - + geom_ribbon(aes(x="date", ymin="lower_80", ymax="upper_80"), data=df_fc, fill=OKABE_ITO[4], alpha=0.35) - # Historical and Forecast lines with legend - + geom_line(aes(x="date", y="value", color="series"), data=df_lines, size=1.5) - # Vertical line at forecast start - + geom_vline(xintercept=forecast_start.timestamp() * 1000, color=INK_SOFT, size=0.8, linetype="dotted") - # Manual color scale: historical using brand green, forecast using orange - + scale_color_manual(values={"Historical": OKABE_ITO[0], "Forecast": OKABE_ITO[4]}, name="Series") - # Labels + # 95% CI (outer, lighter) + + geom_ribbon(aes(x="date", ymin="lower_95", ymax="upper_95"), data=df_fc, fill=OKABE_ITO[4], alpha=0.18) + # 80% CI (inner, darker) + + geom_ribbon(aes(x="date", ymin="lower_80", ymax="upper_80"), data=df_fc, fill=OKABE_ITO[4], alpha=0.38) + # Historical solid line (brand green) + + geom_line( + aes(x="date", y="value", color="series"), data=df_hist[["date", "value", "series"]], size=1.2, linetype="solid" + ) + # Forecast dashed line (orange) + + geom_line( + aes(x="date", y="value", color="series"), data=df_fc[["date", "value", "series"]], size=1.2, linetype="dashed" + ) + # Vertical marker at forecast boundary + + geom_vline(xintercept=forecast_start.timestamp() * 1000, color=INK_MUTED, size=0.6, linetype="dotted") + + scale_color_manual(values={"Historical": OKABE_ITO[0], "Forecast": OKABE_ITO[4]}, name="") + labs( x="Date", - y="Stock Price ($)", - title="timeseries-forecast-uncertainty · letsplot · anyplot.ai", - caption="Shaded bands: 80% confidence interval (darker) and 95% CI (lighter)", + y="Energy Demand (MWh)", + title="timeseries-forecast-uncertainty · python · letsplot · anyplot.ai", + caption="Bands: 80% CI (darker) · 95% CI (lighter)", + ) + + ggsize(800, 450) + + theme_classic() + + theme( + plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), + panel_background=element_rect(fill=PAGE_BG), + panel_grid_major_y=element_line(color=INK_GRID, size=0.5), + axis_title=element_text(color=INK, size=14), + axis_text=element_text(color=INK_SOFT, size=12), + axis_line=element_line(color=INK_SOFT, size=0.5), + plot_title=element_text(color=INK, size=18), + legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT), + legend_text=element_text(color=INK_SOFT, size=12), + legend_title=element_blank(), + plot_caption=element_text(color=INK_MUTED, size=11), + legend_position="bottom", ) - # Base size scaled 3x on export = 4800 × 2700 px - + ggsize(1600, 900) - # Apply custom theme - + anyplot_theme ) # Save PNG and HTML with theme suffix -ggsave(plot, f"plot-{THEME}.png", path=".", scale=3) +ggsave(plot, f"plot-{THEME}.png", path=".", scale=4) ggsave(plot, f"plot-{THEME}.html", path=".") diff --git a/plots/timeseries-forecast-uncertainty/metadata/python/letsplot.yaml b/plots/timeseries-forecast-uncertainty/metadata/python/letsplot.yaml index 4d22c1cf52..d711cb7419 100644 --- a/plots/timeseries-forecast-uncertainty/metadata/python/letsplot.yaml +++ b/plots/timeseries-forecast-uncertainty/metadata/python/letsplot.yaml @@ -1,10 +1,13 @@ +# Per-library metadata for letsplot implementation of timeseries-forecast-uncertainty +# Auto-generated by impl-generate.yml + library: letsplot language: python specification_id: timeseries-forecast-uncertainty created: '2026-01-07T16:34:36Z' -updated: '2026-05-16T22:45:57Z' -generated_by: claude-haiku -workflow_run: 25974733360 +updated: '2026-05-19T13:17:58Z' +generated_by: claude-sonnet +workflow_run: 26099465079 issue: 3188 language_version: 3.13.13 library_version: 4.9.0 @@ -12,223 +15,7 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/timeserie preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/timeseries-forecast-uncertainty/python/letsplot/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/timeseries-forecast-uncertainty/python/letsplot/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/timeseries-forecast-uncertainty/python/letsplot/plot-dark.html -quality_score: 88 +quality_score: null review: - strengths: - - Proper theme-adaptive implementation with correct chrome flipping in both light - and dark renders - - Accurate Okabe-Ito palette usage with correct brand color (#009E73) for historical - series - - Effective nested confidence bands with well-chosen alpha transparency (0.35 for - 80%, 0.2 for 95%) - - Clean, reproducible code with realistic synthetic data and proper seeding - - All spec requirements met with visual clarity and correct styling - weaknesses: - - 'Generic design defaults: could benefit from explicit spine removal (top/right) - per style guide' - - Grid styling uses defaults; could be refined to y-axis-only with lower opacity - - Legend frame styling and positioning could be more refined for stronger visual - hierarchy - image_description: |- - Light render (plot-light.png): - Background: Warm off-white #FAF8F1 - correct color, not pure white - Chrome: Title, axis labels, tick labels all rendered in dark ink (#1A1A17) - fully readable against light background - Data: Green solid line (#009E73) for historical, orange dashed line (#E69F00) for forecast, two nested orange bands (alpha 0.35 and 0.2) - Elements: Vertical dotted line at forecast start, legend on right identifying series - Legibility verdict: PASS - All text clear and readable, no light-on-light issues - - Dark render (plot-dark.png): - Background: Warm near-black #1A1A17 - correct color, not pure black - Chrome: Title, axis labels, tick labels rendered in light tones (#F0EFE8 for title, #B8B7B0 for ticks) - fully readable against dark background - Data: Green (#009E73) and orange (#E69F00) - identical to light render, confirming chrome-only adaptation - Elements: Vertical dotted line clear, legend readable - Legibility verdict: PASS - All text clear and readable, no dark-on-dark failures, axis text has proper contrast - criteria_checklist: - visual_quality: - score: 30 - max: 30 - items: - - id: VQ-01 - name: Text Legibility - score: 8 - max: 8 - passed: true - comment: All text readable in both themes; font sizes appropriately scaled - for 4800×2700 canvas - - id: VQ-02 - name: No Overlap - score: 6 - max: 6 - passed: true - comment: Date labels well-spaced, legend positioned without collision - - id: VQ-03 - name: Element Visibility - score: 6 - max: 6 - passed: true - comment: Lines sized appropriately (1.5pt), bands transparent enough to see - through - - id: VQ-04 - name: Color Accessibility - score: 2 - max: 2 - passed: true - comment: Okabe-Ito palette is colorblind-safe; green/orange have adequate - contrast - - id: VQ-05 - name: Layout & Canvas - score: 4 - max: 4 - passed: true - comment: Good proportions, nothing cut off, generous margins - - id: VQ-06 - name: Axis Labels & Title - score: 2 - max: 2 - passed: true - comment: Descriptive labels with units, correct title format - - id: VQ-07 - name: Palette Compliance - score: 2 - max: 2 - passed: true - comment: 'First series #009E73, Okabe-Ito order correct, backgrounds correct - for both themes' - design_excellence: - score: 10 - max: 20 - items: - - id: DE-01 - name: Aesthetic Sophistication - score: 4 - max: 8 - passed: false - comment: Follows style guide defaults; professional but generic styling - - id: DE-02 - name: Visual Refinement - score: 2 - max: 6 - passed: false - comment: Standard letsplot defaults; minimal spine customization or grid refinement - - id: DE-03 - name: Data Storytelling - score: 4 - max: 6 - passed: true - comment: Nested bands create visual hierarchy; distinct line styles and vertical - marker guide viewer effectively - spec_compliance: - score: 15 - max: 15 - items: - - id: SC-01 - name: Plot Type - score: 5 - max: 5 - passed: true - comment: Correct time series with confidence bands - - id: SC-02 - name: Required Features - score: 4 - max: 4 - passed: true - comment: 'All elements present: historical line, forecast, bands, marker, - legend' - - id: SC-03 - name: Data Mapping - score: 3 - max: 3 - passed: true - comment: Date axis spans both periods, stock price axis shows all values - - id: SC-04 - name: Title & Legend - score: 3 - max: 3 - passed: true - comment: Title correct format, legend identifies series - data_quality: - score: 15 - max: 15 - items: - - id: DQ-01 - name: Feature Coverage - score: 6 - max: 6 - passed: true - comment: 'Shows all aspects: historical, forecast, both CIs, horizon marker' - - id: DQ-02 - name: Realistic Context - score: 5 - max: 5 - passed: true - comment: Stock price scenario is neutral and realistic - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 4 - passed: true - comment: Values plausible for stock price; uncertainty grows with horizon - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: Simple, straightforward code - - id: CQ-02 - name: Reproducibility - score: 2 - max: 2 - passed: true - comment: Uses np.random.seed(42) - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: Only imports used - - id: CQ-04 - name: Code Elegance - score: 2 - max: 2 - passed: true - comment: Appropriate complexity; no fake UI - - id: CQ-05 - name: Output & API - score: 1 - max: 1 - passed: true - comment: Saves as plot-{THEME}.png and .html - library_mastery: - score: 8 - max: 10 - items: - - id: LM-01 - name: Idiomatic Usage - score: 5 - max: 5 - passed: true - comment: ggplot-style API correctly used; proper aes() and manual scales - - id: LM-02 - name: Distinctive Features - score: 3 - max: 5 - passed: false - comment: Uses letsplot-specific ggsize() and ggsave(scale=); LetsPlot.setup_html(); - not extraordinary - verdict: APPROVED -impl_tags: - dependencies: [] - techniques: - - layer-composition - - html-export - patterns: - - data-generation - - explicit-figure - dataprep: - - time-series - styling: - - alpha-blending + strengths: [] + weaknesses: [] From 394cbbce0e08017121dd4d8c623a6c67b5eddd4f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 13:24:07 +0000 Subject: [PATCH 2/2] chore(letsplot): update quality score 90 and review feedback for timeseries-forecast-uncertainty --- .../implementations/python/letsplot.py | 6 +- .../metadata/python/letsplot.yaml | 227 +++++++++++++++++- 2 files changed, 223 insertions(+), 10 deletions(-) diff --git a/plots/timeseries-forecast-uncertainty/implementations/python/letsplot.py b/plots/timeseries-forecast-uncertainty/implementations/python/letsplot.py index b3cc6eea00..070b61a41d 100644 --- a/plots/timeseries-forecast-uncertainty/implementations/python/letsplot.py +++ b/plots/timeseries-forecast-uncertainty/implementations/python/letsplot.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai timeseries-forecast-uncertainty: Time Series Forecast with Uncertainty Band -Library: letsplot | Python 3.13 -Quality: pending | Updated: 2026-05-19 +Library: letsplot 4.9.0 | Python 3.13.13 +Quality: 90/100 | Updated: 2026-05-19 """ # ruff: noqa: F405 diff --git a/plots/timeseries-forecast-uncertainty/metadata/python/letsplot.yaml b/plots/timeseries-forecast-uncertainty/metadata/python/letsplot.yaml index d711cb7419..df72a69f9c 100644 --- a/plots/timeseries-forecast-uncertainty/metadata/python/letsplot.yaml +++ b/plots/timeseries-forecast-uncertainty/metadata/python/letsplot.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for letsplot implementation of timeseries-forecast-uncertainty -# Auto-generated by impl-generate.yml - library: letsplot language: python specification_id: timeseries-forecast-uncertainty created: '2026-01-07T16:34:36Z' -updated: '2026-05-19T13:17:58Z' +updated: '2026-05-19T13:24:07Z' generated_by: claude-sonnet workflow_run: 26099465079 issue: 3188 @@ -15,7 +12,223 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/timeserie preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/timeseries-forecast-uncertainty/python/letsplot/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/timeseries-forecast-uncertainty/python/letsplot/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/timeseries-forecast-uncertainty/python/letsplot/plot-dark.html -quality_score: null +quality_score: 90 review: - strengths: [] - weaknesses: [] + strengths: + - 'Full spec compliance: all required elements (solid/dashed lines, nested CI bands, + vline marker, legend, caption) correctly implemented' + - 'Excellent theme adaptation: all chrome tokens flip correctly between light and + dark without any dark-on-dark failures' + - 'Clean data story: green-to-orange color contrast plus solid-to-dashed linetype + creates immediate visual clarity of past vs. future' + - 'Perfect code quality: reproducible, KISS structure, idiomatic lets-plot API usage' + weaknesses: + - 95% CI band (alpha=0.18) is very subtle in dark render — consider increasing to + 0.22-0.25 or adding a thin boundary line to the outer ribbon for better dark-mode + visibility + - 'LM-02 could be higher: no use of lets-plot-exclusive interactive features (e.g., + tooltips in the HTML output, geom_errorbar alternatives, or lets-plot built-in + theming beyond basics)' + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct theme surface + Chrome: Title "timeseries-forecast-uncertainty · python · letsplot · anyplot.ai" in dark ink, clearly readable. Axis labels "Date" and "Energy Demand (MWh)" in dark ink. Tick labels in dark secondary ink. All text readable. + Data: Historical line in #009E73 (brand green, solid). Forecast line in #E69F00 (orange, dashed). Two nested CI bands both in orange: 80% inner (alpha=0.38, darker), 95% outer (alpha=0.18, lighter). Vertical dotted line at forecast start (2026-01). Bottom legend "Historical" / "Forecast". Caption "Bands: 80% CI (darker) · 95% CI (lighter)". + Legibility verdict: PASS — all elements clearly readable and distinguishable + + Dark render (plot-dark.png): + Background: Near-black (#1A1A17) — correct dark surface, warm not pure black + Chrome: Title in light cream text (INK_SOFT token), clearly readable. Axis labels, tick labels, legend text, and caption all in light-colored text. No dark-on-dark failures detected. + Data: Colors identical to light render — #009E73 historical line, #E69F00 forecast line and CI bands. 80% CI band (alpha=0.38) clearly visible as brownish-orange fill. 95% CI band (alpha=0.18) subtle but distinguishable via boundary lines and slight tonal difference from background. + Legibility verdict: PASS — all text readable; 95% CI band slightly subtle but still functional + criteria_checklist: + visual_quality: + score: 29 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 8 + max: 8 + passed: true + comment: All font sizes explicitly set; proportions good in both renders + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No text collisions in either render + - id: VQ-03 + name: Element Visibility + score: 5 + max: 6 + passed: true + comment: Lines clearly visible; 95% CI band subtle in dark render (alpha=0.18 + too low for dark surface) + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: CVD-safe green/orange pair with dual encoding (color + linestyle) + - id: VQ-05 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: 3200x1800 canvas well-utilized; balanced margins + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: Y-axis has units (MWh); title in correct format + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'First series #009E73; Okabe-Ito order; correct backgrounds #FAF8F1/#1A1A17; + all chrome theme-adaptive' + design_excellence: + score: 13 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: 'Above default: warm backgrounds, Okabe-Ito, linetype differentiation. + Not quite strong design.' + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: L-spines via theme_classic, subtle y-only grid, warm backgrounds. + Good refinement. + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Clear past-to-future narrative with color+linestyle contrast, vline + boundary, widening uncertainty bands + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: 'Correct: time series with forecast uncertainty bands and boundary + marker' + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: 'All required: solid/dashed lines, nested CI bands, vline, legend, + caption' + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: 'X: datetime, Y: energy demand; all data visible' + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Correct title format; legend labels Historical/Forecast + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: Seasonal oscillation, trend, noise, growing uncertainty all demonstrated + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Energy demand forecasting — real, neutral, business use case + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: 400-620 MWh plausible; seasonal amplitude and uncertainty growth + realistic + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: 'Linear: imports → tokens → data → plot → save' + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: np.random.seed(42) + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: Only used imports; noqa appropriate for lets_plot wildcard + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Clean grammar-of-graphics composition; well-organized theme tokens + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-{THEME}.png (scale=4) and plot-{THEME}.html correctly + library_mastery: + score: 8 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 5 + max: 5 + passed: true + comment: 'Expert use of lets-plot grammar: geom_ribbon, geom_line, geom_vline, + scale_color_manual, theme_classic, ggsize, ggsave' + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: Uses datetime-as-milliseconds xintercept (lets-plot specific), HTML + export, multi-layer ribbon composition + verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - layer-composition + - html-export + patterns: + - data-generation + dataprep: + - time-series + styling: + - alpha-blending