From 43b86669fa7553d62ab963001552d05a4d06a60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B2=BD=EC=A2=85?= Date: Thu, 21 May 2026 17:03:51 +0900 Subject: [PATCH] initial commit FESurrogateModelTutorial --- .../.agents/skills/harness-review/SKILL.md | 42 + .../skills/harness-review/agents/openai.yaml | 4 + .../.agents/skills/harness-workflow/SKILL.md | 124 + .../harness-workflow/agents/openai.yaml | 4 + FESurrogateModelTutorial/.codex/config.toml | 4 + FESurrogateModelTutorial/.codex/hooks.json | 28 + .../.codex/hooks/pre_commit_checks.py | 111 + .../.codex/hooks/tdd-guard.py | 189 ++ FESurrogateModelTutorial/.gitignore | 19 + FESurrogateModelTutorial/AGENTS.md | 168 ++ .../BeamExamples/CantileverBeam.txt | 29 + .../CantileverBeam_Displacements.txt | 7 + FESurrogateModelTutorial/PROGRESS.md | 91 + FESurrogateModelTutorial/WORKNOTES.md | 16 + .../data/processed/.gitkeep | 1 + .../data/reference/.gitkeep | 1 + .../data/reference/beam2d_lhs_300.csv | 301 +++ .../reference/beam2d_lhs_300_metadata.json | 36 + FESurrogateModelTutorial/docs/ADR.md | 76 + FESurrogateModelTutorial/docs/ARCHITECTURE.md | 226 ++ FESurrogateModelTutorial/docs/PRD.md | 60 + .../theory/00_surrogate_modeling_for_fem.md | 98 + .../docs/theory/01_doe_sampling_validation.md | 114 + .../theory/02_response_surface_methodology.md | 77 + .../theory/03_gaussian_process_kriging.md | 86 + .../docs/theory/04_random_forest.md | 76 + .../docs/theory/05_gradient_boosting.md | 77 + .../docs/theory/06_mlp_neural_network.md | 90 + FESurrogateModelTutorial/notebooks/.gitkeep | 1 + .../notebooks/00_beam2d_fea_dataset.ipynb | 173 ++ .../01_response_surface_surrogate.ipynb | 168 ++ ...2_gaussian_process_kriging_surrogate.ipynb | 168 ++ .../03_random_forest_surrogate.ipynb | 168 ++ .../04_gradient_boosting_surrogate.ipynb | 168 ++ .../notebooks/05_mlp_surrogate.ipynb | 168 ++ .../06_compare_surrogate_models.ipynb | 115 + .../phases/0-project-foundation/index.json | 18 + .../phases/0-project-foundation/step0.md | 40 + .../phases/0-project-foundation/step1.md | 36 + .../phases/1-beam2d-solver/index.json | 30 + .../phases/1-beam2d-solver/step0.md | 32 + .../phases/1-beam2d-solver/step1.md | 28 + .../phases/1-beam2d-solver/step2.md | 31 + .../phases/1-beam2d-solver/step3.md | 30 + .../2-dataset-and-surrogates/index.json | 30 + .../phases/2-dataset-and-surrogates/step0.md | 28 + .../phases/2-dataset-and-surrogates/step1.md | 26 + .../phases/2-dataset-and-surrogates/step2.md | 30 + .../phases/2-dataset-and-surrogates/step3.md | 26 + .../index.json | 30 + .../step0.md | 23 + .../step1.md | 39 + .../step2.md | 24 + .../step3.md | 37 + FESurrogateModelTutorial/phases/index.json | 20 + FESurrogateModelTutorial/pyproject.toml | 46 + .../reports/figures/.gitkeep | 1 + .../reports/figures/comparison_fit_time_s.png | Bin 0 -> 24138 bytes .../reports/figures/comparison_mae.png | Bin 0 -> 25303 bytes .../figures/comparison_predict_time_s.png | Bin 0 -> 26399 bytes .../reports/figures/comparison_r2.png | Bin 0 -> 20450 bytes .../reports/figures/comparison_rmse.png | Bin 0 -> 25572 bytes .../reports/figures/gpr_parity.png | Bin 0 -> 40436 bytes .../reports/figures/gpr_residuals.png | Bin 0 -> 38685 bytes .../figures/gradient_boosting_parity.png | Bin 0 -> 41489 bytes .../figures/gradient_boosting_residuals.png | Bin 0 -> 36048 bytes .../reports/figures/mlp_parity.png | Bin 0 -> 39882 bytes .../reports/figures/mlp_residuals.png | Bin 0 -> 38616 bytes .../reports/figures/random_forest_parity.png | Bin 0 -> 41000 bytes .../figures/random_forest_residuals.png | Bin 0 -> 39038 bytes .../reports/figures/rsm_parity.png | Bin 0 -> 41090 bytes .../reports/figures/rsm_residuals.png | Bin 0 -> 37915 bytes .../reports/predictions/.gitkeep | 1 + .../reports/predictions/gpr_predictions.csv | 61 + .../gradient_boosting_predictions.csv | 61 + .../reports/predictions/mlp_predictions.csv | 61 + .../predictions/random_forest_predictions.csv | 61 + .../reports/predictions/rsm_predictions.csv | 61 + .../reports/results/.gitkeep | 1 + .../reports/results/gpr_metrics.json | 9 + .../results/gradient_boosting_metrics.json | 9 + .../reports/results/mlp_metrics.json | 9 + .../reports/results/model_comparison.csv | 6 + .../results/random_forest_metrics.json | 9 + .../reports/results/rsm_metrics.json | 9 + FESurrogateModelTutorial/scripts/execute.py | 417 ++++ .../src/femsurrogate/__init__.py | 3 + .../src/femsurrogate/data/__init__.py | 1 + .../src/femsurrogate/data/bounds.py | 16 + .../src/femsurrogate/data/dataset.py | 106 + .../src/femsurrogate/data/sampling.py | 18 + .../src/femsurrogate/data/schema.py | 24 + .../src/femsurrogate/fea/__init__.py | 1 + .../src/femsurrogate/fea/assembly.py | 60 + .../src/femsurrogate/fea/benchmark.py | 2 + .../src/femsurrogate/fea/element.py | 46 + .../src/femsurrogate/fea/io.py | 70 + .../src/femsurrogate/fea/model.py | 40 + .../src/femsurrogate/fea/solver.py | 33 + .../src/femsurrogate/plotting/__init__.py | 1 + .../src/femsurrogate/plotting/comparison.py | 27 + .../src/femsurrogate/plotting/diagnostics.py | 30 + .../src/femsurrogate/surrogates/__init__.py | 1 + .../src/femsurrogate/surrogates/boosting.py | 21 + .../src/femsurrogate/surrogates/common.py | 96 + .../src/femsurrogate/surrogates/gpr.py | 34 + .../src/femsurrogate/surrogates/mlp.py | 39 + .../femsurrogate/surrogates/random_forest.py | 20 + .../src/femsurrogate/surrogates/registry.py | 28 + .../src/femsurrogate/surrogates/rsm.py | 20 + FESurrogateModelTutorial/tests/.gitkeep | 1 + .../tests/test_beam_solver.py | 31 + .../tests/test_beamexamples_io.py | 47 + .../test_cantilever_fixture_regression.py | 42 + .../tests/test_dataset_builder.py | 27 + .../tests/test_frame_element.py | 42 + .../tests/test_plotting_and_results.py | 41 + .../tests/test_project_structure.py | 18 + .../tests/test_sampling.py | 19 + .../tests/test_surrogate_common.py | 67 + .../tests/test_surrogate_models.py | 47 + FESurrogateModelTutorial/uv.lock | 2146 +++++++++++++++++ 122 files changed, 7929 insertions(+) create mode 100644 FESurrogateModelTutorial/.agents/skills/harness-review/SKILL.md create mode 100644 FESurrogateModelTutorial/.agents/skills/harness-review/agents/openai.yaml create mode 100644 FESurrogateModelTutorial/.agents/skills/harness-workflow/SKILL.md create mode 100644 FESurrogateModelTutorial/.agents/skills/harness-workflow/agents/openai.yaml create mode 100644 FESurrogateModelTutorial/.codex/config.toml create mode 100644 FESurrogateModelTutorial/.codex/hooks.json create mode 100644 FESurrogateModelTutorial/.codex/hooks/pre_commit_checks.py create mode 100644 FESurrogateModelTutorial/.codex/hooks/tdd-guard.py create mode 100644 FESurrogateModelTutorial/.gitignore create mode 100644 FESurrogateModelTutorial/AGENTS.md create mode 100644 FESurrogateModelTutorial/BeamExamples/CantileverBeam.txt create mode 100644 FESurrogateModelTutorial/BeamExamples/CantileverBeam_Displacements.txt create mode 100644 FESurrogateModelTutorial/PROGRESS.md create mode 100644 FESurrogateModelTutorial/WORKNOTES.md create mode 100644 FESurrogateModelTutorial/data/processed/.gitkeep create mode 100644 FESurrogateModelTutorial/data/reference/.gitkeep create mode 100644 FESurrogateModelTutorial/data/reference/beam2d_lhs_300.csv create mode 100644 FESurrogateModelTutorial/data/reference/beam2d_lhs_300_metadata.json create mode 100644 FESurrogateModelTutorial/docs/ADR.md create mode 100644 FESurrogateModelTutorial/docs/ARCHITECTURE.md create mode 100644 FESurrogateModelTutorial/docs/PRD.md create mode 100644 FESurrogateModelTutorial/docs/theory/00_surrogate_modeling_for_fem.md create mode 100644 FESurrogateModelTutorial/docs/theory/01_doe_sampling_validation.md create mode 100644 FESurrogateModelTutorial/docs/theory/02_response_surface_methodology.md create mode 100644 FESurrogateModelTutorial/docs/theory/03_gaussian_process_kriging.md create mode 100644 FESurrogateModelTutorial/docs/theory/04_random_forest.md create mode 100644 FESurrogateModelTutorial/docs/theory/05_gradient_boosting.md create mode 100644 FESurrogateModelTutorial/docs/theory/06_mlp_neural_network.md create mode 100644 FESurrogateModelTutorial/notebooks/.gitkeep create mode 100644 FESurrogateModelTutorial/notebooks/00_beam2d_fea_dataset.ipynb create mode 100644 FESurrogateModelTutorial/notebooks/01_response_surface_surrogate.ipynb create mode 100644 FESurrogateModelTutorial/notebooks/02_gaussian_process_kriging_surrogate.ipynb create mode 100644 FESurrogateModelTutorial/notebooks/03_random_forest_surrogate.ipynb create mode 100644 FESurrogateModelTutorial/notebooks/04_gradient_boosting_surrogate.ipynb create mode 100644 FESurrogateModelTutorial/notebooks/05_mlp_surrogate.ipynb create mode 100644 FESurrogateModelTutorial/notebooks/06_compare_surrogate_models.ipynb create mode 100644 FESurrogateModelTutorial/phases/0-project-foundation/index.json create mode 100644 FESurrogateModelTutorial/phases/0-project-foundation/step0.md create mode 100644 FESurrogateModelTutorial/phases/0-project-foundation/step1.md create mode 100644 FESurrogateModelTutorial/phases/1-beam2d-solver/index.json create mode 100644 FESurrogateModelTutorial/phases/1-beam2d-solver/step0.md create mode 100644 FESurrogateModelTutorial/phases/1-beam2d-solver/step1.md create mode 100644 FESurrogateModelTutorial/phases/1-beam2d-solver/step2.md create mode 100644 FESurrogateModelTutorial/phases/1-beam2d-solver/step3.md create mode 100644 FESurrogateModelTutorial/phases/2-dataset-and-surrogates/index.json create mode 100644 FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step0.md create mode 100644 FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step1.md create mode 100644 FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step2.md create mode 100644 FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step3.md create mode 100644 FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/index.json create mode 100644 FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step0.md create mode 100644 FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step1.md create mode 100644 FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step2.md create mode 100644 FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step3.md create mode 100644 FESurrogateModelTutorial/phases/index.json create mode 100644 FESurrogateModelTutorial/pyproject.toml create mode 100644 FESurrogateModelTutorial/reports/figures/.gitkeep create mode 100644 FESurrogateModelTutorial/reports/figures/comparison_fit_time_s.png create mode 100644 FESurrogateModelTutorial/reports/figures/comparison_mae.png create mode 100644 FESurrogateModelTutorial/reports/figures/comparison_predict_time_s.png create mode 100644 FESurrogateModelTutorial/reports/figures/comparison_r2.png create mode 100644 FESurrogateModelTutorial/reports/figures/comparison_rmse.png create mode 100644 FESurrogateModelTutorial/reports/figures/gpr_parity.png create mode 100644 FESurrogateModelTutorial/reports/figures/gpr_residuals.png create mode 100644 FESurrogateModelTutorial/reports/figures/gradient_boosting_parity.png create mode 100644 FESurrogateModelTutorial/reports/figures/gradient_boosting_residuals.png create mode 100644 FESurrogateModelTutorial/reports/figures/mlp_parity.png create mode 100644 FESurrogateModelTutorial/reports/figures/mlp_residuals.png create mode 100644 FESurrogateModelTutorial/reports/figures/random_forest_parity.png create mode 100644 FESurrogateModelTutorial/reports/figures/random_forest_residuals.png create mode 100644 FESurrogateModelTutorial/reports/figures/rsm_parity.png create mode 100644 FESurrogateModelTutorial/reports/figures/rsm_residuals.png create mode 100644 FESurrogateModelTutorial/reports/predictions/.gitkeep create mode 100644 FESurrogateModelTutorial/reports/predictions/gpr_predictions.csv create mode 100644 FESurrogateModelTutorial/reports/predictions/gradient_boosting_predictions.csv create mode 100644 FESurrogateModelTutorial/reports/predictions/mlp_predictions.csv create mode 100644 FESurrogateModelTutorial/reports/predictions/random_forest_predictions.csv create mode 100644 FESurrogateModelTutorial/reports/predictions/rsm_predictions.csv create mode 100644 FESurrogateModelTutorial/reports/results/.gitkeep create mode 100644 FESurrogateModelTutorial/reports/results/gpr_metrics.json create mode 100644 FESurrogateModelTutorial/reports/results/gradient_boosting_metrics.json create mode 100644 FESurrogateModelTutorial/reports/results/mlp_metrics.json create mode 100644 FESurrogateModelTutorial/reports/results/model_comparison.csv create mode 100644 FESurrogateModelTutorial/reports/results/random_forest_metrics.json create mode 100644 FESurrogateModelTutorial/reports/results/rsm_metrics.json create mode 100644 FESurrogateModelTutorial/scripts/execute.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/__init__.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/data/__init__.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/data/bounds.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/data/dataset.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/data/sampling.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/data/schema.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/fea/__init__.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/fea/assembly.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/fea/benchmark.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/fea/element.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/fea/io.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/fea/model.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/fea/solver.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/plotting/__init__.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/plotting/comparison.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/plotting/diagnostics.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/surrogates/__init__.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/surrogates/boosting.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/surrogates/common.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/surrogates/gpr.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/surrogates/mlp.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/surrogates/random_forest.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/surrogates/registry.py create mode 100644 FESurrogateModelTutorial/src/femsurrogate/surrogates/rsm.py create mode 100644 FESurrogateModelTutorial/tests/.gitkeep create mode 100644 FESurrogateModelTutorial/tests/test_beam_solver.py create mode 100644 FESurrogateModelTutorial/tests/test_beamexamples_io.py create mode 100644 FESurrogateModelTutorial/tests/test_cantilever_fixture_regression.py create mode 100644 FESurrogateModelTutorial/tests/test_dataset_builder.py create mode 100644 FESurrogateModelTutorial/tests/test_frame_element.py create mode 100644 FESurrogateModelTutorial/tests/test_plotting_and_results.py create mode 100644 FESurrogateModelTutorial/tests/test_project_structure.py create mode 100644 FESurrogateModelTutorial/tests/test_sampling.py create mode 100644 FESurrogateModelTutorial/tests/test_surrogate_common.py create mode 100644 FESurrogateModelTutorial/tests/test_surrogate_models.py create mode 100644 FESurrogateModelTutorial/uv.lock diff --git a/FESurrogateModelTutorial/.agents/skills/harness-review/SKILL.md b/FESurrogateModelTutorial/.agents/skills/harness-review/SKILL.md new file mode 100644 index 0000000..4d3d784 --- /dev/null +++ b/FESurrogateModelTutorial/.agents/skills/harness-review/SKILL.md @@ -0,0 +1,42 @@ +--- +name: harness-review +description: "Use when reviewing this Harness repository: local changes, generated phase files, step outputs, implementation diffs, missing tests, build readiness, or compliance with AGENTS.md, docs/ARCHITECTURE.md, docs/ADR.md, and Harness acceptance criteria." +--- + +# Harness Review + +## Overview + +Use this skill to review Harness work against the repository's persistent rules, architecture docs, and executable verification requirements. Prioritize bugs, regressions, missing tests, and rule violations. + +## Review Process + +1. Read `/AGENTS.md`, `/docs/ARCHITECTURE.md`, and `/docs/ADR.md`. +2. Inspect the changed files with `git status --short` and `git diff`. +3. Check architecture, stack choices, tests, critical rules, and build readiness. +4. Run relevant verification commands when feasible. If a command cannot be run, report that as residual risk. +5. Lead with actionable findings. Keep summaries secondary. + +## Checklist + +| Item | Question | +| --- | --- | +| Architecture | Does the change follow `docs/ARCHITECTURE.md` directory and module boundaries? | +| Stack | Does the change stay within choices documented in `docs/ADR.md`? | +| Tests | Are new or changed behaviors covered by tests? | +| Critical Rules | Does the change violate any `AGENTS.md` CRITICAL rule? | +| Build | Do relevant build/test/lint commands pass? | + +## Output Format + +If there are findings, list them first in severity order with file and line references when possible. Then include this table: + +| 항목 | 결과 | 비고 | +| --- | --- | --- | +| 아키텍처 준수 | PASS/FAIL | {상세} | +| 기술 스택 준수 | PASS/FAIL | {상세} | +| 테스트 존재 | PASS/FAIL | {상세} | +| CRITICAL 규칙 | PASS/FAIL | {상세} | +| 빌드 가능 | PASS/FAIL | {상세} | + +When there are no findings, say that clearly, then mention any commands not run or remaining risk. diff --git a/FESurrogateModelTutorial/.agents/skills/harness-review/agents/openai.yaml b/FESurrogateModelTutorial/.agents/skills/harness-review/agents/openai.yaml new file mode 100644 index 0000000..9af296a --- /dev/null +++ b/FESurrogateModelTutorial/.agents/skills/harness-review/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Harness Review" + short_description: "Review Harness changes safely" + default_prompt: "Use $harness-review to review Harness repository changes." diff --git a/FESurrogateModelTutorial/.agents/skills/harness-workflow/SKILL.md b/FESurrogateModelTutorial/.agents/skills/harness-workflow/SKILL.md new file mode 100644 index 0000000..72519ba --- /dev/null +++ b/FESurrogateModelTutorial/.agents/skills/harness-workflow/SKILL.md @@ -0,0 +1,124 @@ +--- +name: harness-workflow +description: "Use when planning or running this Harness framework: reading AGENTS.md and docs/*.md, discussing implementation scope, creating or updating phases/index.json, phases/{task}/index.json, phases/{task}/stepN.md, or invoking scripts/execute.py for staged Codex execution." +--- + +# Harness Workflow + +## Overview + +Use this skill to turn a user-approved task into small, self-contained Harness steps that another Codex session can execute reliably. Keep the workflow grounded in repository docs and executable acceptance criteria. + +## Workflow + +1. Read `AGENTS.md` and relevant files under `docs/`, especially `docs/PRD.md`, `docs/ARCHITECTURE.md`, and `docs/ADR.md`. +2. Discuss unresolved product or technical decisions with the user before writing phase files. +3. When the user asks for an implementation plan, draft steps and get approval before creating files. +4. Create or update `phases/index.json`, `phases/{task-name}/index.json`, and one `phases/{task-name}/stepN.md` per step. +5. Run the phase with `python scripts/execute.py {task-name}` when asked to execute it. Use `--push` only when the user asks to push. + +## Step Design Rules + +- Scope each step to one layer or module. Split steps when multiple modules would otherwise change together. +- Make every step self-contained. Do not rely on prior conversation; include all required context and file paths. +- Force context gathering. Each step must tell Codex which docs and previous outputs to read before editing. +- Specify interfaces and signatures, not full implementations, unless exact code is required for a constraint. +- Put core invariants directly in the step: idempotency, security, data integrity, API contracts, or other non-negotiables. +- Use executable acceptance criteria such as `npm run build && npm test`, not abstract statements. +- Write cautions concretely: "Do not do X. Reason: Y." +- Name steps with kebab-case slugs such as `project-setup`, `api-layer`, or `auth-flow`. + +## Phase Files + +Create or update `phases/index.json`: + +```json +{ + "phases": [ + { + "dir": "0-mvp", + "status": "pending" + } + ] +} +``` + +Create `phases/{task-name}/index.json`: + +```json +{ + "project": "", + "phase": "", + "steps": [ + { "step": 0, "name": "project-setup", "status": "pending" }, + { "step": 1, "name": "core-types", "status": "pending" }, + { "step": 2, "name": "api-layer", "status": "pending" } + ] +} +``` + +Rules: + +- `project` comes from `AGENTS.md`. +- `phase` matches the task directory name. +- `steps[].step` starts at `0`. +- Initial status is always `pending`. +- Do not add timestamps when creating files. `scripts/execute.py` records `created_at`, `started_at`, `completed_at`, `failed_at`, and `blocked_at`. + +## Step Template + +```markdown +# Step {N}: {name} + +## 읽어야 할 파일 + +먼저 아래 파일들을 읽고 프로젝트의 아키텍처와 설계 의도를 파악하라: + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- {previously created or modified files} + +이전 step에서 만들어진 코드를 꼼꼼히 읽고, 설계 의도를 이해한 뒤 작업하라. + +## 작업 + +{Concrete instructions with file paths, interfaces, signatures, and rules.} + +## Acceptance Criteria + +```bash +npm run build +npm test +``` + +## 검증 절차 + +1. 위 AC 커맨드를 실행한다. +2. 아키텍처 체크리스트를 확인한다: + - ARCHITECTURE.md 디렉토리 구조를 따르는가? + - ADR 기술 스택을 벗어나지 않았는가? + - AGENTS.md CRITICAL 규칙을 위반하지 않았는가? +3. 결과에 따라 `phases/{task-name}/index.json`의 해당 step을 업데이트한다: + - 성공: `"status": "completed"`, `"summary": "산출물 한 줄 요약"` + - 3회 수정 시도 후 실패: `"status": "error"`, `"error_message": "구체적 에러 내용"` + - 사용자 개입 필요: `"status": "blocked"`, `"blocked_reason": "구체적 사유"` 후 중단 + +## 금지사항 + +- {Do not do X. Reason: Y.} +- 기존 테스트를 깨뜨리지 마라. +``` + +## Execution And Recovery + +Run: + +```bash +python scripts/execute.py {task-name} +python scripts/execute.py {task-name} --push +``` + +`scripts/execute.py` creates or checks out `feat-{task-name}`, injects `AGENTS.md` and `docs/*.md` into each prompt, carries completed step summaries forward, retries failed steps up to three times, separates code and metadata commits, and records timestamps. + +If a step is `error`, set it back to `pending` and remove `error_message` after fixing the cause. If a step is `blocked`, resolve `blocked_reason`, set it back to `pending`, remove `blocked_reason`, and rerun. diff --git a/FESurrogateModelTutorial/.agents/skills/harness-workflow/agents/openai.yaml b/FESurrogateModelTutorial/.agents/skills/harness-workflow/agents/openai.yaml new file mode 100644 index 0000000..3a671bf --- /dev/null +++ b/FESurrogateModelTutorial/.agents/skills/harness-workflow/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Harness Workflow" + short_description: "Plan staged Harness workflow steps" + default_prompt: "Use $harness-workflow to plan Harness phases and step files." diff --git a/FESurrogateModelTutorial/.codex/config.toml b/FESurrogateModelTutorial/.codex/config.toml new file mode 100644 index 0000000..b75aa36 --- /dev/null +++ b/FESurrogateModelTutorial/.codex/config.toml @@ -0,0 +1,4 @@ +#:schema https://developers.openai.com/codex/config-schema.json + +[features] +codex_hooks = true diff --git a/FESurrogateModelTutorial/.codex/hooks.json b/FESurrogateModelTutorial/.codex/hooks.json new file mode 100644 index 0000000..0229d62 --- /dev/null +++ b/FESurrogateModelTutorial/.codex/hooks.json @@ -0,0 +1,28 @@ +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "^Bash$", + "hooks": [ + { + "type": "command", + "command": "python -c \"import pathlib, runpy, subprocess; root = pathlib.Path(subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], text=True).strip()); runpy.run_path(str(root / '.codex' / 'hooks' / 'pre_commit_checks.py'), run_name='__main__')\"", + "timeout": 600, + "statusMessage": "Running pre-commit checks" + } + ] + }, + { + "matcher": "^(apply_patch|Edit|Write)$", + "hooks": [ + { + "type": "command", + "command": "python -c \"import pathlib, runpy, subprocess; root = pathlib.Path(subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], text=True).strip()); runpy.run_path(str(root / '.codex' / 'hooks' / 'tdd-guard.py'), run_name='__main__')\"", + "timeout": 30, + "statusMessage": "Checking TDD guard" + } + ] + } + ] + } +} diff --git a/FESurrogateModelTutorial/.codex/hooks/pre_commit_checks.py b/FESurrogateModelTutorial/.codex/hooks/pre_commit_checks.py new file mode 100644 index 0000000..1cca8d8 --- /dev/null +++ b/FESurrogateModelTutorial/.codex/hooks/pre_commit_checks.py @@ -0,0 +1,111 @@ +import json +import re +import shutil +import subprocess +import sys +from pathlib import Path + + +CHECKS = ("lint", "build", "test") + + +def _repo_root(cwd: Path) -> Path: + try: + root = subprocess.check_output( + ["git", "rev-parse", "--show-toplevel"], + cwd=cwd, + text=True, + stderr=subprocess.DEVNULL, + ).strip() + except (subprocess.CalledProcessError, FileNotFoundError): + return cwd + return Path(root) + + +def _load_scripts(root: Path) -> dict[str, str]: + package_json = root / "package.json" + if not package_json.exists(): + return {} + + try: + package = json.loads(package_json.read_text(encoding="utf-8")) + except json.JSONDecodeError as exc: + _deny(f"Invalid package.json: {exc}") + raise SystemExit(0) from exc + + scripts = package.get("scripts", {}) + if not isinstance(scripts, dict): + return {} + return {str(name): str(command) for name, command in scripts.items()} + + +def _is_git_commit(command: str) -> bool: + return re.search(r"\bgit(?:\s+(?:-[A-Za-z]\s+\S+|--[A-Za-z0-9-]+(?:=\S+)?))*\s+commit\b", command) is not None + + +def _deny(reason: str) -> None: + print( + json.dumps( + { + "hookSpecificOutput": { + "hookEventName": "PreToolUse", + "permissionDecision": "deny", + "permissionDecisionReason": reason, + } + } + ) + ) + + +def _tail(text: str, limit: int = 1200) -> str: + text = text.strip() + if len(text) <= limit: + return text + return text[-limit:] + + +def _run_checks(root: Path, scripts: dict[str, str]) -> str | None: + npm = shutil.which("npm") or shutil.which("npm.cmd") + if npm is None: + return "npm was not found, so pre-commit checks could not run." + + for check in CHECKS: + if check not in scripts: + continue + result = subprocess.run( + [npm, "run", check], + cwd=root, + capture_output=True, + text=True, + ) + + if result.returncode != 0: + details = _tail(result.stdout + "\n" + result.stderr) + if details: + return f"npm run {check} failed:\n{details}" + return f"npm run {check} failed with exit code {result.returncode}." + + return None + + +def main() -> int: + try: + payload = json.load(sys.stdin) + except json.JSONDecodeError: + return 0 + + command = payload.get("tool_input", {}).get("command", "") + if not isinstance(command, str) or not _is_git_commit(command): + return 0 + + cwd = Path(payload.get("cwd") or Path.cwd()) + root = _repo_root(cwd) + failure = _run_checks(root, _load_scripts(root)) + if failure: + _deny(f"PRE-COMMIT CHECKS: {failure}") + + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/FESurrogateModelTutorial/.codex/hooks/tdd-guard.py b/FESurrogateModelTutorial/.codex/hooks/tdd-guard.py new file mode 100644 index 0000000..8f7e23c --- /dev/null +++ b/FESurrogateModelTutorial/.codex/hooks/tdd-guard.py @@ -0,0 +1,189 @@ +import json +import subprocess +import sys +from pathlib import Path + + +SOURCE_SUFFIXES = {".ts", ".tsx", ".js", ".jsx"} +TEST_SUFFIXES = ("ts", "tsx", "js", "jsx") +CONFIG_SUFFIXES = {".json", ".css", ".scss", ".md", ".yml", ".yaml"} +NEXT_SPECIAL_FILES = { + "layout.ts", + "layout.tsx", + "page.ts", + "page.tsx", + "loading.tsx", + "error.tsx", + "not-found.tsx", + "globals.css", +} + + +def _repo_root(cwd: Path) -> Path: + try: + root = subprocess.check_output( + ["git", "rev-parse", "--show-toplevel"], + cwd=cwd, + text=True, + stderr=subprocess.DEVNULL, + ).strip() + except (subprocess.CalledProcessError, FileNotFoundError): + return cwd + return Path(root) + + +def _extract_patch_paths(command: str) -> list[str]: + prefixes = ( + "*** Add File: ", + "*** Update File: ", + "*** Delete File: ", + "*** Move to: ", + ) + paths: list[str] = [] + for raw_line in command.splitlines(): + line = raw_line.strip() + for prefix in prefixes: + if line.startswith(prefix): + paths.append(line[len(prefix) :].strip()) + break + return paths + + +def _touched_paths(payload: dict) -> list[str]: + tool_input = payload.get("tool_input", {}) + if not isinstance(tool_input, dict): + return [] + + file_path = tool_input.get("file_path") + if isinstance(file_path, str) and file_path: + return [file_path] + + command = tool_input.get("command") + if isinstance(command, str): + return _extract_patch_paths(command) + + return [] + + +def _normalize(path_text: str) -> str: + return path_text.replace("\\", "/").lower() + + +def _is_test_path(path_text: str) -> bool: + normalized = _normalize(path_text) + name = normalized.rsplit("/", 1)[-1] + return ( + "__tests__/" in normalized + or ".test." in name + or ".spec." in name + or "test" in name + or "spec" in name + ) + + +def _is_exempt(path_text: str) -> bool: + normalized = _normalize(path_text) + path = Path(path_text) + name = path.name.lower() + + if _is_test_path(path_text): + return True + if name in NEXT_SPECIAL_FILES: + return True + if path.suffix.lower() in CONFIG_SUFFIXES: + return True + if ".env" in name or ".config." in name: + return True + if any(token in name for token in ("tailwind", "postcss", "next.config", "tsconfig")): + return True + if "/types/" in normalized or name in {"types.ts", "types.d.ts"}: + return True + + return False + + +def _resolve_path(path_text: str, cwd: Path) -> Path: + path = Path(path_text) + if path.is_absolute(): + return path + return (cwd / path).resolve() + + +def _base_name(path: Path) -> str: + for suffix in (".tsx", ".ts", ".jsx", ".js"): + if path.name.endswith(suffix): + return path.name[: -len(suffix)] + return path.stem + + +def _has_existing_test(path: Path, root: Path) -> bool: + directory = path.parent + parent = directory.parent + base = _base_name(path) + + for ext in TEST_SUFFIXES: + if (directory / f"{base}.test.{ext}").exists(): + return True + if (directory / f"{base}.spec.{ext}").exists(): + return True + + for ext in TEST_SUFFIXES: + if (parent / "__tests__" / f"{base}.test.{ext}").exists(): + return True + if (directory / "__tests__" / f"{base}.test.{ext}").exists(): + return True + + for ext in TEST_SUFFIXES: + if (root / "src" / "__tests__" / f"{base}.test.{ext}").exists(): + return True + + return False + + +def _guarded_paths(paths: list[str], cwd: Path, root: Path) -> list[str]: + missing_tests: list[str] = [] + for path_text in paths: + if _is_exempt(path_text): + continue + + path = _resolve_path(path_text, cwd) + if path.suffix.lower() not in SOURCE_SUFFIXES: + continue + if not _has_existing_test(path, root): + missing_tests.append(_base_name(path)) + + return missing_tests + + +def main() -> int: + try: + payload = json.load(sys.stdin) + except json.JSONDecodeError: + return 0 + + cwd = Path(payload.get("cwd") or Path.cwd()) + root = _repo_root(cwd) + missing_tests = _guarded_paths(_touched_paths(payload), cwd, root) + if not missing_tests: + return 0 + + names = ", ".join(sorted(set(missing_tests))) + print( + json.dumps( + { + "hookSpecificOutput": { + "hookEventName": "PreToolUse", + "permissionDecision": "deny", + "permissionDecisionReason": ( + "TDD GUARD: missing test file for " + f"{names}. Write or add the test first." + ), + } + } + ) + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/FESurrogateModelTutorial/.gitignore b/FESurrogateModelTutorial/.gitignore new file mode 100644 index 0000000..93deae3 --- /dev/null +++ b/FESurrogateModelTutorial/.gitignore @@ -0,0 +1,19 @@ +node_modules/ +.next/ +out/ +next-env.d.ts +tsconfig.tsbuildinfo + +# Python +__pycache__/ +*.py[cod] +.pytest_cache/ +.ruff_cache/ +.venv/ +*.egg-info/ +.ipynb_checkpoints/ +*.nbconvert.ipynb + +# phase execution outputs +phases/**/phase*-output.json +phases/**/step*-output.json diff --git a/FESurrogateModelTutorial/AGENTS.md b/FESurrogateModelTutorial/AGENTS.md new file mode 100644 index 0000000..3e59373 --- /dev/null +++ b/FESurrogateModelTutorial/AGENTS.md @@ -0,0 +1,168 @@ +# FEMSurrogateTutorial Agent Instructions + +## Project Purpose +This repository is a Korean tutorial project for studying surrogate models in finite element method (FEM) structural analysis. The tutorial combines: +- Theory documents on surrogate modeling methods. +- NumPy/SciPy implementation of a 2D Euler-Bernoulli beam/frame element. +- Jupyter notebooks that build, validate, and compare surrogate models from generated FEM data. + +The primary audience is graduate students and researchers who already know basic FEM and Python. + +## Tech Stack +- Python `>=3.12,<3.15` +- Environment and dependency management: `uv`, `pyproject.toml`, `uv.lock` +- Numerical computing: NumPy, SciPy +- Machine learning: scikit-learn +- Data and plotting: pandas, matplotlib +- Notebook workflow: JupyterLab, ipykernel, nbconvert +- Testing and quality: pytest, ruff +- Model/result persistence: joblib, CSV, JSON + +## Architecture Rules +- CRITICAL: At the start of every new task or session, read `AGENTS.md`, `PROGRESS.md`, and `WORKNOTES.md` before planning or editing. Use them to understand current scope, completed work, open tasks, and known pitfalls. +- CRITICAL: Keep `PROGRESS.md` current while working. Update it whenever the task state materially changes, including completed milestones, in-progress work, blockers, verification status, and next actions. +- CRITICAL: Record meaningful trial-and-error, mistakes, false starts, debugging discoveries, and corrective decisions in `WORKNOTES.md`. Do not log routine command output; log lessons future agents need. +- CRITICAL: Core calculation logic must live under `src/femsurrogate/`; notebooks should explain and orchestrate, not hide reusable implementation in cells. +- CRITICAL: FEM data for the tutorial must be generated with the in-repository 2D beam/frame implementation using NumPy/SciPy. Do not introduce Abaqus, ANSYS, OpenSeesPy, CalculiX, or other external solvers for v1. +- CRITICAL: Keep the structural model linear static and Euler-Bernoulli based for v1. Do not add Timoshenko shear deformation, geometric nonlinearity, material nonlinearity, dynamics, contact, or shell/solid elements unless explicitly requested. +- CRITICAL: Use `BeamExamples/CantileverBeam.txt` and `BeamExamples/CantileverBeam_Displacements.txt` as the canonical solver verification fixture. The solver must reproduce the listed `Ux`, `Uy`, and `Rz` values within documented floating-point tolerance before it is used to generate surrogate training data. +- CRITICAL: All random sampling, train/test splits, and model training examples must use fixed seeds for reproducibility. +- CRITICAL: Keep the project document and Python notebook based. Do not add browser app or design-system work. +- Keep public helper interfaces small and stable: + - `run_beam2d_case(params)` + - `generate_lhs_samples(bounds, n, seed)` + - `build_dataset(samples)` + - `make_model(model_name, random_state)` + - `evaluate_model(...)` + +## Expected Repository Shape +```text +docs/ + PRD.md + ARCHITECTURE.md + ADR.md + theory/ + 00_surrogate_modeling_for_fem.md + 01_doe_sampling_validation.md + 02_response_surface_methodology.md + 03_gaussian_process_kriging.md + 04_random_forest.md + 05_gradient_boosting.md + 06_mlp_neural_network.md + +PROGRESS.md +WORKNOTES.md + +BeamExamples/ + CantileverBeam.txt + CantileverBeam_Displacements.txt + +notebooks/ + 00_beam2d_fea_dataset.ipynb + 01_response_surface_surrogate.ipynb + 02_gaussian_process_kriging_surrogate.ipynb + 03_random_forest_surrogate.ipynb + 04_gradient_boosting_surrogate.ipynb + 05_mlp_surrogate.ipynb + 06_compare_surrogate_models.ipynb + +src/femsurrogate/ + fea/ + io.py + data/ + surrogates/ + plotting/ + +tests/ +``` + +## Development Process +- Start each session by reading `PROGRESS.md` and `WORKNOTES.md` after `AGENTS.md`. +- Before making changes, update `PROGRESS.md` with the current task, intended scope, and success criteria when they are not already recorded. +- During longer tasks, update `PROGRESS.md` after each meaningful milestone instead of waiting until the end. +- When you encounter an implementation mistake, incorrect assumption, failed approach, non-obvious parser/detail issue, or verification problem, add a concise note to `WORKNOTES.md` with the date and lesson learned. +- At the end of a task, update `PROGRESS.md` with completed work, verification commands/results, remaining risks, and recommended next step. +- Use TDD for code changes: write a failing pytest first, implement the smallest passing change, then refactor only if needed. +- For documentation changes, verify that links, filenames, and referenced commands match the repository. +- Prefer simple educational implementations over production abstractions. +- Keep every change traceable to the tutorial goal. Do not add speculative tooling, dashboards, APIs, or deployment layers. +- Commit messages should follow Conventional Commits, for example `docs: define tutorial architecture` or `feat: add beam2d solver`. + +## Commands +Use these commands once the Python project files exist: + +```powershell +uv sync +uv run pytest +uv run ruff check . +uv run jupyter nbconvert --to notebook --execute notebooks/00_beam2d_fea_dataset.ipynb +``` + +For full notebook verification: + +```powershell +uv run jupyter nbconvert --to notebook --execute notebooks/00_beam2d_fea_dataset.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/01_response_surface_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/02_gaussian_process_kriging_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/03_random_forest_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/04_gradient_boosting_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/05_mlp_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/06_compare_surrogate_models.ipynb +``` + +## Documentation Standards +- Write tutorial content in Korean. +- Keep technical terms such as surrogate model, response surface, Gaussian process, Kriging, Random Forest, Gradient Boosting, MLP, DOE, LHS, RMSE, MAE, and R2 in English when that is clearer. +- Theory documents must include citations and links to primary or official sources where possible. +- Avoid long quotations. Summarize sources in your own words. +- When adding equations, define symbols and units near the equation. +- Each model-specific theory document should explain: + - Core idea and assumptions. + - Mathematical form. + - FEM structural-analysis use case. + - Strengths, weaknesses, and failure modes. + - Hyperparameters used in the matching notebook. + - References. + +## Progress And Work Notes +`PROGRESS.md` and `WORKNOTES.md` are mandatory handoff files for future agents. + +`PROGRESS.md` should answer: +- What is the current project/task state? +- What has been completed? +- What is in progress? +- What is blocked or intentionally deferred? +- What verification has been run, with command names and results? +- What should the next agent do first? + +`WORKNOTES.md` should answer: +- What assumptions turned out to be wrong? +- What approaches were tried and rejected? +- What parsing, numerical, notebook, or tooling pitfalls were discovered? +- What should future agents avoid repeating? + +Keep both files concise and factual. Do not use them as a full chat transcript. + +## Data And Result Conventions +- Treat files under `BeamExamples/` as checked-in verification fixtures, not generated data. +- `BeamExamples/CantileverBeam.txt` defines a six-node, five-element cantilever beam with fixed node 1 and a downward nodal load at node 6. +- `BeamExamples/CantileverBeam_Displacements.txt` defines expected nodal `Ux`, `Uy`, and `Rz` values for that example. +- The BeamExamples fixture uses clockwise-positive `Rz`; keep element stiffness, solver output, and regression comparisons in that convention. +- For the 2D in-plane beam/frame solver, use `Area`, `ElasticModulus`, and `Izz` from the example input. Preserve `J`, `Iyy`, and `Poisson'sRatio` when parsing metadata, but do not use them in the v1 Euler-Bernoulli in-plane solve. +- Store generated reference data under `data/reference/`. +- Store derived or regenerated data under `data/processed/`. +- Store metrics under `reports/results/`. +- Store predictions under `reports/predictions/`. +- Store generated figures under `reports/figures/`. +- Use SI units in data columns and encode units in column names where practical, for example `tip_uy_m`, `max_abs_bending_stress_pa`, `mass_kg`, `compliance_j`. +- Include metadata JSON for generated datasets with seed, sample count, bounds, and code version notes. + +## Review Checklist +- Does the change keep notebooks thin and reusable code in `src/femsurrogate/`? +- Does the FEM implementation remain a linear static 2D Euler-Bernoulli beam/frame model? +- Does the solver pass the `BeamExamples/CantileverBeam.txt` displacement regression check? +- Are random seeds fixed? +- Are tests added or updated for new code behavior? +- Do docs and notebooks refer to the same paths and artifact names? +- Are citations present for theory claims? +- Has browser-app and design-system work been avoided? diff --git a/FESurrogateModelTutorial/BeamExamples/CantileverBeam.txt b/FESurrogateModelTutorial/BeamExamples/CantileverBeam.txt new file mode 100644 index 0000000..4b1d10b --- /dev/null +++ b/FESurrogateModelTutorial/BeamExamples/CantileverBeam.txt @@ -0,0 +1,29 @@ +Area, 1.0 +J, 0.140625 +Iyy, 0.0833333 +Izz, 0.0833333 + +ElasticModulus, 2.05e+011 +Poisson'sRatio, 0.3 + +# Node, NodeID, X, Y +Node, 1, 0.0, 0.0, +Node, 2, 1.0, 0.0, +Node, 3, 2.0, 0.0, +Node, 4, 3.0, 0.0, +Node, 5, 4.0, 0.0, +Node, 6, 5.0, 0.0, + +# Beam, BeamID, NodeID1, NodeID2 +Beam, 1, 1, 2, +Beam, 2, 2, 3, +Beam, 3, 3, 4, +Beam, 4, 4, 5, +Beam, 5, 5, 6, + +# Fix, NodeID +Fix, 1, + +# NodalLoad, NodeID, Fx, Fy, Mz +NodeLoad, 6, 0.0, -100000.0, 0.0, + diff --git a/FESurrogateModelTutorial/BeamExamples/CantileverBeam_Displacements.txt b/FESurrogateModelTutorial/BeamExamples/CantileverBeam_Displacements.txt new file mode 100644 index 0000000..0348a8c --- /dev/null +++ b/FESurrogateModelTutorial/BeamExamples/CantileverBeam_Displacements.txt @@ -0,0 +1,7 @@ +# NodeID, Ux, Uy, Rz +1 0.000000, 0.000000, 0.000000 +2 0.000000, -0.000014, 0.000026 +3 0.000000, -0.000051, 0.000047 +4 0.000000, -0.000105, 0.000061 +5 0.000000, -0.000172, 0.000070 +6 0.000000, -0.000244, 0.000073 \ No newline at end of file diff --git a/FESurrogateModelTutorial/PROGRESS.md b/FESurrogateModelTutorial/PROGRESS.md new file mode 100644 index 0000000..7ba1a4a --- /dev/null +++ b/FESurrogateModelTutorial/PROGRESS.md @@ -0,0 +1,91 @@ +# Progress + +## Current State +- Project direction is defined as a Korean FEM surrogate tutorial using NumPy/SciPy 2D Euler-Bernoulli beam/frame analysis and scikit-learn surrogate models. +- Documentation files have been populated for PRD, architecture, ADR, and model-specific theory. +- `BeamExamples/CantileverBeam.txt` and `BeamExamples/CantileverBeam_Displacements.txt` are designated as canonical solver verification fixtures. +- Implementation work is active on branch `codex/harness-implementation`. + +## Completed +- Replaced template project instructions in `AGENTS.md`. +- Removed UI-oriented documentation from the planned scope. +- Added theory document structure under `docs/theory/`. +- Updated PRD and architecture to require BeamExamples-based solver regression verification. +- Added `PROGRESS.md` and `WORKNOTES.md` as mandatory handoff files and documented their workflow in `AGENTS.md`. +- Created Harness phase files under `phases/`. +- Completed phase `0-project-foundation` step 0: `pyproject.toml`, package skeleton, artifact directories, and lint configuration. +- Completed phase `0-project-foundation` step 1 with TDD: package import smoke tests and `femsurrogate.__version__`. +- Completed phase `1-beam2d-solver` step 0 with TDD: BeamExamples input and displacement parser. +- Completed phase `1-beam2d-solver` step 1 with TDD: frame local stiffness and transformation matrix. +- Completed phase `1-beam2d-solver` step 2 with TDD: sparse global assembly, constrained DOF handling, load vector assembly, and linear static solve. +- Completed phase `1-beam2d-solver` step 3 with TDD: BeamExamples displacement regression and analytical cantilever tip check. +- Completed phase `2-dataset-and-surrogates` step 0 with TDD: LHS sampling, dataset schema, Beam2D case runner, and dataset builder. +- Completed phase `2-dataset-and-surrogates` step 1 with TDD: common split/evaluate utilities, metrics, timings, and prediction table. +- Completed phase `2-dataset-and-surrogates` step 2 with TDD: scikit-learn model builders and registry for RSM, GPR, Random Forest, Gradient Boosting, and MLP. +- Completed phase `2-dataset-and-surrogates` step 3 with TDD: plotting diagnostics and metric comparison helpers. +- Completed phase `3-notebooks-and-final-verification` step 0: dataset notebook, reference CSV, and metadata JSON. +- Completed phase `3-notebooks-and-final-verification` step 1: five surrogate model notebooks with metrics, predictions, and diagnostic figures. +- Completed phase `3-notebooks-and-final-verification` step 2: comparison notebook and model comparison outputs. +- Completed phase `3-notebooks-and-final-verification` step 3: full pytest, ruff, and all notebook execution checks. + +## In Progress +- None. + +## Blockers +- None recorded. + +## Verification +- Documentation checks were run manually with PowerShell/`rg` to confirm required BeamExamples references and absence of stale template terms. +- Verified that `AGENTS.md` references `PROGRESS.md` and `WORKNOTES.md`, both files exist, and stale template terms are absent. +- `uv sync` passed. +- `uv run python -c "import femsurrogate; print(femsurrogate.__name__)"` printed `femsurrogate`. +- `uv run ruff check .` passed after excluding existing local harness infrastructure from ruff scope. +- RED: `uv run pytest tests/test_project_structure.py -q` failed because `femsurrogate.__version__` was missing. +- GREEN: `uv run pytest tests/test_project_structure.py -q` passed with 2 tests. +- `uv run ruff check .` passed. +- RED: `uv run pytest tests/test_beamexamples_io.py -q` failed because `femsurrogate.fea.io` did not exist. +- GREEN: `uv run pytest tests/test_beamexamples_io.py tests/test_project_structure.py -q` passed with 4 tests. +- `uv run ruff check .` passed. +- RED: `uv run pytest tests/test_frame_element.py -q` failed because `femsurrogate.fea.element` did not exist. +- GREEN: `uv run pytest tests/test_frame_element.py tests/test_beamexamples_io.py tests/test_project_structure.py -q` passed with 8 tests. +- `uv run ruff check .` passed. +- RED: `uv run pytest tests/test_beam_solver.py -q` failed because `femsurrogate.fea.assembly` did not exist. +- GREEN: `uv run pytest tests/test_beam_solver.py tests/test_frame_element.py tests/test_beamexamples_io.py -q` passed with 9 tests. +- `uv run ruff check .` passed after solver import formatting was corrected. +- RED: `uv run pytest tests/test_cantilever_fixture_regression.py -q` failed because `femsurrogate.fea.benchmark` did not exist. +- Regression discovery: fixture comparison then exposed an `Rz` sign convention mismatch; the element convention was aligned to BeamExamples clockwise-positive `Rz`. +- GREEN: `uv run pytest tests/test_cantilever_fixture_regression.py tests/test_beam_solver.py tests/test_frame_element.py tests/test_beamexamples_io.py -q` passed with 11 tests. +- `uv run ruff check .` passed. +- GREEN: `uv run pytest -q` passed with 13 tests after completing phase 1. +- RED: `uv run pytest tests/test_sampling.py tests/test_dataset_builder.py -q` failed because `femsurrogate.data.bounds` did not exist. +- GREEN: `uv run pytest tests/test_sampling.py tests/test_dataset_builder.py -q` passed with 4 tests. +- `uv run ruff check .` passed. +- GREEN: `uv run pytest -q` passed with 17 tests after completing dataset builder work. +- RED: `uv run pytest tests/test_surrogate_common.py -q` failed because `femsurrogate.surrogates.common` did not exist. +- GREEN: `uv run pytest tests/test_surrogate_common.py -q` passed with 2 tests. +- `uv run ruff check .` passed. +- GREEN: `uv run pytest -q` passed with 19 tests after completing surrogate common utilities. +- RED: `uv run pytest tests/test_surrogate_models.py -q` failed because `femsurrogate.surrogates.registry` did not exist. +- GREEN: `uv run pytest tests/test_surrogate_models.py -q` passed with 2 tests. +- `uv run ruff check .` passed. +- GREEN: `uv run pytest -q` passed with 21 tests after completing surrogate model builders. +- RED: `uv run pytest tests/test_plotting_and_results.py -q` failed because `femsurrogate.plotting.comparison` did not exist. +- GREEN: `uv run pytest tests/test_plotting_and_results.py -q` passed with 2 tests. +- `uv run ruff check .` passed. +- Initial `uv run jupyter nbconvert --to notebook --execute notebooks/00_beam2d_fea_dataset.ipynb` failed because nbconvert executed with `notebooks/` as the working directory; notebooks now locate the repository root by checking for `pyproject.toml`. +- `uv run jupyter nbconvert --to notebook --execute notebooks/00_beam2d_fea_dataset.ipynb` passed. +- `uv run jupyter nbconvert --to notebook --execute` passed for notebooks 01 through 05. +- `uv run jupyter nbconvert --to notebook --execute notebooks/06_compare_surrogate_models.ipynb` exited 0 and wrote comparison output; Windows/Jupyter emitted a transient zmq connection-reset message after execution. +- `uv run ruff check .` passed after notebook cell style fixes. +- FINAL: `uv run pytest` passed with 23 tests. +- FINAL: `uv run ruff check .` passed. +- FINAL: `uv run jupyter nbconvert --to notebook --execute notebooks/00_beam2d_fea_dataset.ipynb` passed. +- FINAL: `uv run jupyter nbconvert --to notebook --execute notebooks/01_response_surface_surrogate.ipynb` passed. +- FINAL: `uv run jupyter nbconvert --to notebook --execute notebooks/02_gaussian_process_kriging_surrogate.ipynb` passed. +- FINAL: `uv run jupyter nbconvert --to notebook --execute notebooks/03_random_forest_surrogate.ipynb` passed. +- FINAL: `uv run jupyter nbconvert --to notebook --execute notebooks/04_gradient_boosting_surrogate.ipynb` passed. +- FINAL: `uv run jupyter nbconvert --to notebook --execute notebooks/05_mlp_surrogate.ipynb` passed. +- FINAL: `uv run jupyter nbconvert --to notebook --execute notebooks/06_compare_surrogate_models.ipynb` passed and `reports/results/model_comparison.csv` exists. + +## Next Actions +- Review generated tutorial outputs and continue with documentation polish or additional explanatory notebook text if desired. diff --git a/FESurrogateModelTutorial/WORKNOTES.md b/FESurrogateModelTutorial/WORKNOTES.md new file mode 100644 index 0000000..707aa4b --- /dev/null +++ b/FESurrogateModelTutorial/WORKNOTES.md @@ -0,0 +1,16 @@ +# Work Notes + +## 2026-05-21 +- Initial repository documents were generic templates for a web project. They were replaced with FEM surrogate tutorial-specific instructions before implementation work. +- The previous design-guide document was removed from the active scope because the project is notebook based. +- BeamExamples fixture files use a simple comma/space text format rather than JSON/CSV. Future parser work should handle comments, trailing commas, and labels such as `Poisson'sRatio`. +- For the v1 in-plane Euler-Bernoulli frame solver, use `Area`, `ElasticModulus`, and `Izz` from `BeamExamples/CantileverBeam.txt`; preserve `J`, `Iyy`, and `Poisson'sRatio` as metadata but do not use them in the in-plane solve. +- Avoid writing removed/stale file names into handoff notes when the project uses simple `rg` checks for stale terms; describe the lesson without preserving obsolete filenames unless the exact name matters. +- `scripts/execute.py` expects `git rev-parse --abbrev-ref HEAD` to succeed. On an unborn repository with no initial commit, it returns `HEAD` plus a fatal stderr and nonzero exit code, so create an initial commit before running Harness execution. +- `ruff check .` should exclude existing local agent/harness infrastructure (`.agents`, `.codex`, `scripts/execute.py`) so linting focuses on tutorial package code and future project scripts. +- Use `Izz` as the code parameter name for the in-plane bending inertia instead of bare `I`; ruff flags `I` as an ambiguous variable name and the fixture also uses `Izz`. +- The BeamExamples displacement fixture reports downward cantilever rotations as positive `Rz`, so this project treats `Rz` as clockwise-positive. A textbook counterclockwise-positive Euler-Bernoulli matrix reproduces `Uy` but flips every `Rz`; keep the element stiffness convention aligned instead of flipping only solver output. +- `jupyter nbconvert --execute notebooks/*.ipynb` can run cells with `Path.cwd()` equal to `notebooks/` on Windows. Notebook code should discover the repository root by walking/checking for `pyproject.toml`, not by assuming the shell working directory. +- `ruff check .` lints notebook code cells too. Generated notebooks must keep imports sorted and line lengths under the configured limit. +- nbconvert writes `*.nbconvert.ipynb` output files by default; keep them ignored because they are verification artifacts, not source notebooks. +- On Windows, nbconvert may emit a zmq Proactor event loop warning, and comparison execution once printed a libzmq connection-reset assertion after finishing with exit code 0. Treat this as an environment warning only when the command exit code is 0 and expected output files exist. diff --git a/FESurrogateModelTutorial/data/processed/.gitkeep b/FESurrogateModelTutorial/data/processed/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/FESurrogateModelTutorial/data/processed/.gitkeep @@ -0,0 +1 @@ + diff --git a/FESurrogateModelTutorial/data/reference/.gitkeep b/FESurrogateModelTutorial/data/reference/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/FESurrogateModelTutorial/data/reference/.gitkeep @@ -0,0 +1 @@ + diff --git a/FESurrogateModelTutorial/data/reference/beam2d_lhs_300.csv b/FESurrogateModelTutorial/data/reference/beam2d_lhs_300.csv new file mode 100644 index 0000000..04c1618 --- /dev/null +++ b/FESurrogateModelTutorial/data/reference/beam2d_lhs_300.csv @@ -0,0 +1,301 @@ +L_m,b_m,h_m,E_pa,P_n,A_m2,I_m4,tip_uy_m,max_abs_bending_stress_pa,mass_kg,compliance_j +1.8314998429486489,0.02288848310526338,0.0815229398597667,172594545239.26154,1204.4650264605164,0.0018659364316716727,1.0334161957807233e-06,-0.013829015619417438,87011299.20020096,26.827078910236825,16.656565663964518 +1.485780501096186,0.0703451958583708,0.15227975734470864,134603011411.74176,430.61187485571196,0.01071214935567871,2.070044708657494e-05,-0.00016896401045085464,2353277.332637697,124.93983570435536,0.07275790932338262 +1.912481924636748,0.047325586440789394,0.13412538162234836,137384268072.70396,1491.016058175157,0.006347562341872312,9.51585181099103e-06,-0.0026593065863062455,20096154.678896487,95.29584621803525,3.965068823793571 +1.9005563087063533,0.03892541267357975,0.07695136609138858,204751900490.29495,1095.028618079069,0.002995363680903012,1.4780903506148138e-06,-0.008279755549199318,54174082.80724987,44.68893012378931,9.066569277072231 +1.5947212929865011,0.028377670567845643,0.060651928533480566,143550315733.9896,285.4873970880711,0.0017211604472276289,5.27629829547462e-07,-0.005095497266108835,26167185.46189781,21.54645402864454,1.4547002513707934 +1.07237473124558,0.060835540739851784,0.1272283305923341,194807902395.3725,841.5626396886561,0.0077400042890132725,1.0440651813465087e-05,-0.00017008684513586912,5498690.043104498,65.15645240127142,0.14313873436885768 +1.719404317170917,0.05385550434598768,0.12141457596271288,180228444125.88403,780.2860073349921,0.006538843223426135,8.03269604288166e-06,-0.0009132337131101088,10139378.371577015,88.25688485115214,0.7125834877663964 +1.8443936254162967,0.06781937032695569,0.0906637700929121,206850241685.69434,664.8332582220359,0.0061487597991691754,4.2118590646042665e-06,-0.0015959616691765433,13197640.606252536,89.02475701575838,1.0610483965161202 +1.1133087091552474,0.07276333760631655,0.08972554699620917,109961391102.16035,527.9000060948273,0.00652873026799659,4.380056467488244e-06,-0.0005041471272986309,6019683.850035296,57.057664296625695,0.2661392715736369 +1.7653262594338854,0.05980665036951069,0.10875237157317413,126953548532.28677,896.458597440227,0.006504115063531939,6.410389856402397e-06,-0.0020200152084294265,13423924.977437384,90.13279816085453,1.8108600005565714 +2.4184005785926237,0.046583251237609244,0.1568083429212308,150170594507.19855,1012.1064382265317,0.007304642434452879,1.4967733662081683e-05,-0.00212299367486471,12821461.97409473,138.67457919566064,2.148695566644777 +1.0122542173163664,0.0257631638203873,0.05996802707039356,122101793297.94275,196.1163789614812,0.0015449661053999694,4.629959923088148e-07,-0.0011993946892279361,12856299.886894634,12.276602878045393,0.23522094339701388 +2.99885756490169,0.034208042406339394,0.06827291867439919,212556641451.73248,222.15212458178422,0.0023354828972184083,9.071777376802585e-07,-0.010356897291806043,25068733.85015985,54.979677349072226,2.30080673745004 +2.5090373124694736,0.0644222822855815,0.06190015136572917,213676707662.4631,1509.0204900058407,0.003987749024803228,1.2732978139795645e-06,-0.029201695277680767,92030965.56296098,78.54247710356118,44.06595651692707 +1.8803275265391401,0.03546362707534823,0.141638741145562,188165807683.9365,370.8129344289211,0.005023023495407992,8.39746263160384e-06,-0.0005200502893437317,5880203.563159812,74.14269535721769,0.19284137384215863 +2.2767602373665152,0.05078719396396178,0.1319282799922206,113377538465.96469,502.63221905928657,0.006700267145296765,9.718218816358546e-06,-0.001794598357182278,7767635.770409364,119.75097925673768,0.9020229545906786 +1.8387426022120184,0.03598261817712693,0.042756728124461955,139276750527.0553,693.7486407804699,0.0015384990226057391,2.3438235152907022e-07,-0.04403927624425049,116351676.43422394,22.20689401616478,30.552188035404416 +1.3011131084669427,0.05481935324204158,0.08484687238436737,115209362593.83258,1734.3755729455568,0.004651250668721058,2.7903596005967974e-06,-0.003961130049810408,34308668.80130053,47.50665524433302,6.870087199651787 +2.6198549887683336,0.07887793897606994,0.13647070121249977,207909603351.69885,1561.5862492494184,0.01076452764226103,1.670677321550229e-05,-0.0026946933734432015,16709370.142657414,221.38178634570068,4.2079961179124314 +1.9163836401280836,0.0692936197063689,0.09353918410176623,173905530654.12637,1950.663751507745,0.006481668650791817,4.725989305697665e-06,-0.005568040616383383,36994376.79622444,97.50770554040177,10.861374997301908 +2.460080176958872,0.03952084747455992,0.0688781284182868,107735300872.5662,974.7000408118613,0.002722122007552264,1.0761901586120548e-06,-0.041720592641427086,76733069.55438615,52.56861136183609,40.66506335029402 +2.7755844200326263,0.05125709604641546,0.05692408518502546,175283604103.8452,1997.850111329783,0.0029177633016831852,7.878815513196515e-07,-0.10311046485275611,200319153.39364558,63.57321213773421,205.99925368534448 +1.4102930025734708,0.022265414249600112,0.08705755680218691,186941727856.41827,117.79790590776206,0.0019383725657587836,1.2242467456018725e-06,-0.00048124824409759455,5906829.594940002,21.45933513707948,0.05669003537648415 +2.7187095888004675,0.04325268945427481,0.08898072117551989,134150937902.88864,326.1913240502886,0.0038486555004221762,2.53933287372463e-06,-0.0064139601803737635,15537513.364638543,82.13750641195135,2.092178163641946 +1.5015451743314063,0.0280474634849621,0.11212059965520282,163640968179.4723,1011.4454299974409,0.0031446984247413554,3.294341222963827e-06,-0.002117267779164323,25844473.813744865,37.06696794352397,2.1415008193165854 +1.5613872984144939,0.039382290755115124,0.11412904353427888,149887803869.72943,1234.6779455652597,0.004494663176070163,4.878746594076833e-06,-0.002142346946215878,22548738.685472872,55.09059345107331,2.6451085262418284 +2.2823683011586327,0.021672540627220464,0.05066818292659669,184397309151.04816,1023.8895143480386,0.001098108252984105,2.3492788514504826e-07,-0.09366986044671798,252005249.36306617,19.674356622635106,95.90758792183861 +2.6010016269455036,0.06835079352389664,0.1545043674209379,186248249676.83844,589.1393859193188,0.01056049611612879,2.100799452968336e-05,-0.0008831650596319473,5634882.319220892,215.62276049831084,0.520307320896964 +2.6988235184899976,0.050858874149295734,0.14880865969476118,102787761774.47253,1136.1743909684308,0.007568240895741235,1.396593804751516e-05,-0.005186037815692381,16336069.803628998,160.33897020574037,5.892243356783542 +1.601688330241449,0.03963062111434279,0.1144439338431775,113729873278.4416,1702.5081209908894,0.004535484180973879,4.950259498266031e-06,-0.004141898486083398,31521147.53931131,57.02579186458539,7.051615808876856 +1.9382531257107587,0.03620970064654632,0.15745742612342728,141534717182.76892,1897.3497040557022,0.005701486264504984,1.1779670221306714e-05,-0.0027622405372338702,24578642.735462748,86.74975005098388,5.240936265851348 +1.5591287409274512,0.049392939146356715,0.06940672689731209,100163372270.41394,1158.927649116863,0.0034282022379867358,1.376221431308448e-06,-0.01062144848682015,45563969.61218766,41.9583178158119,12.309490325046339 +1.0169440865973296,0.05593646414679583,0.07417492434149953,100476764002.75151,160.82272485226002,0.004149082996019581,1.902326686036506e-06,-0.0002949623926723835,3188500.632999652,33.122175528188606,0.04743665571851501 +1.2608420992915117,0.021894964398804215,0.040383667280905984,106701680904.53453,680.973354795578,0.0008841989574085911,1.2016562860306466e-07,-0.035484561670924356,144273416.82930407,8.751456866755749,24.16404100449994 +1.1681065315811268,0.03651047386470185,0.06101704401387274,172176203613.8894,1116.1525285212006,0.0022277611907698634,6.911776980931584e-07,-0.004982953168829409,57548956.32287725,20.427759822268623,5.5617357788916735 +2.613091893660169,0.0428529520046492,0.08746146285403349,188757426541.5191,1856.724475458743,0.0037479818699403056,2.3891846138442986e-06,-0.02448705173017026,88805359.56713,76.8814951791214,45.46570827923148 +1.957399449788186,0.02352144812631788,0.13224525759397504,144858300254.10114,1813.4632198003533,0.0031105999664482295,4.533390505297857e-06,-0.0069033416455300395,51774414.247427806,47.79619030326978,12.518956167884774 +1.0754425740145133,0.05632837492058661,0.10197971033879796,127852674408.22131,1402.1610993072868,0.0057443513582566335,4.978371458644394e-06,-0.0009133583838071284,15444776.195958031,48.49510208452314,1.28067559550053 +2.748190193991543,0.029189783685797673,0.13914471791153568,194550648608.6056,1991.810225336548,0.004061604216859064,6.553145407482807e-06,-0.010808976488024223,58114120.24030992,87.62217791307721,21.529429894268976 +2.737376665709003,0.059793119208386175,0.15846534399138273,197171418728.4136,1360.1770486512287,0.009475137203674669,1.982772363055239e-05,-0.0023788171016291743,14878578.766606314,203.60560296298277,3.23561242457504 +2.127996843275138,0.07648227551987294,0.065583255277641,210719969283.56403,1765.8392275775352,0.0050159565996347,1.7978707338303775e-06,-0.014971960976924529,68537246.1786959,83.79042750871774,26.438076006813407 +2.339542531006592,0.05110218729810469,0.11375155805330195,217519353948.91022,1324.3401998970633,0.005812953425091065,6.268019011143268e-06,-0.0041461301601332,28114318.46768957,106.75726638477374,5.490886845070045 +2.4807541533989843,0.07280280445677859,0.1434690996526244,188989500502.69434,1030.2910044573773,0.010444952807600093,1.791603828409672e-05,-0.0015484963132998005,10233637.532757176,203.40417646715596,1.5954018220281971 +1.611259544606639,0.020965647782533448,0.0793032577437884,132195515076.3166,301.11512726835883,0.0016626441698637357,8.713650254441947e-07,-0.003644945025297345,22077962.1869384,21.02976761062358,1.0975480851785815 +1.1380693108621813,0.054688929246585666,0.1302823502190609,172923054616.7614,1611.8077500652946,0.007125002233209116,1.0078013308574489e-05,-0.0004544334545482174,11856666.740908664,63.65365909430245,0.7324593639297616 +1.1970560162717296,0.07686991602122166,0.07875653775878153,161018911947.34885,236.11945674620944,0.006054008443639709,3.129212149325244e-06,-0.00026794277217479195,3556868.926398274,56.88884975564729,0.06326650180498523 +2.2366756486113366,0.032494419533240844,0.04880067870206303,133425120710.35454,1317.3621792082665,0.0015857497272517274,3.1470607277950625e-07,-0.11701734408260855,228454093.01701942,27.842441227927658,154.15422340582876 +1.5799282239183674,0.07445087941133813,0.07008585625845357,190051464709.8472,885.9142139521327,0.005217953632738504,2.135894201675166e-06,-0.0028690064822059374,22964113.163278602,64.71533889136836,2.5416936225070463 +2.875760889847622,0.027160509123923204,0.11772326594936802,198436241667.45178,1085.3627463884377,0.0031974238389158483,3.6926960907836247e-06,-0.011742144368100255,49752673.59576146,72.18095743013201,12.744486059850818 +2.43133244952272,0.07060028264520024,0.10016988958032483,196552139300.14716,467.0925737092751,0.007072022516909432,5.913393489384802e-06,-0.001925307900863989,9618729.896012884,134.97633695857036,0.8992970225973624 +2.454532752038515,0.060416097529133087,0.09619491473650338,212976693312.94727,472.14750470019595,0.005811721350527229,4.481545039166519e-06,-0.0024383895768227836,12437723.079946205,111.98072414463617,1.151279554183844 +2.2659447659220726,0.028952339083094296,0.04094356756849021,124497478994.26439,1125.413412036063,0.0011854120515145112,1.6559966563004738e-07,-0.21169898568446774,315251844.6210834,21.08571413368349,238.2488778037305 +2.8870356750940136,0.07720109864779011,0.07803697159449194,118508819724.02277,1241.3343766667094,0.006024539942241167,3.057338015981658e-06,-0.027480830284222508,45737022.472930476,136.53553465334076,34.11289933114898 +1.1291014037948819,0.03573057699007314,0.052549547438675834,183667874579.9599,1353.1837966588705,0.0018776256505511077,4.320815517243893e-07,-0.008181547419697236,92910114.81121816,16.642233599032494,11.07113739993049 +2.2414313057299413,0.06872856088386628,0.12359238421025875,146548487465.68164,812.8953468340021,0.008494326702976963,1.0812624845355039e-05,-0.0019256493507311863,10413354.435320249,149.45968087623032,1.5653513968432986 +1.4065306561811344,0.020273390641434193,0.1040998919792323,135341893943.94872,397.70883693499695,0.0021104577758260788,1.90588187213665e-06,-0.0014300899817837975,15277023.517729312,23.30212494816057,0.5687594233676251 +1.826249320085565,0.04697611579152199,0.11924746491239926,144621923926.2337,1653.5705281560415,0.005601782719570324,6.638092864183832e-06,-0.0034970690839348415,27124305.438361306,80.30747728062661,5.7826503721203 +2.2246456016622407,0.05005609518099281,0.15198244049392126,197936724240.38977,142.72425932125824,0.007607647507203299,1.4643873337184473e-05,-0.00018070772012295034,1647654.2683857938,132.85590859228773,0.025791375508181322 +1.042833035705912,0.058779886893946726,0.14493211466677136,126379582748.83847,1972.5755796896055,0.008519093307413338,1.4912188568033188e-05,-0.00039567484010969616,9996355.198026434,69.73933669156939,0.7804985270979758 +2.899760811553612,0.0318220486590499,0.13490142046062267,194336063708.38275,1659.3238440922435,0.004292839566072884,6.510231879122651e-06,-0.010659738945541567,49852093.38463715,97.71843236028197,17.68795900413583 +1.780938884510343,0.03761604152904589,0.11829859744482052,216411005745.66534,307.6507833259193,0.004449924954312251,5.189561130770031e-06,-0.0005157910996826229,6244907.491086512,62.21159841665765,0.15868353584989625 +2.4755986030522696,0.07137351869202158,0.05303918024990824,138485060383.08636,688.5633491549236,0.0037855929229763273,8.874548585343163e-07,-0.028334407686754395,50938325.87525222,73.56712713198132,19.510034653112616 +2.9282979381162413,0.07048741960062826,0.06795280784918846,205214703573.28278,479.0341318296734,0.004789818079906613,1.8431156484791915e-06,-0.010600587323396578,25858691.500124387,110.10421309763807,5.078043145347921 +2.102098815519008,0.026402623716520364,0.12228369270545006,151914192477.86105,253.96104698542044,0.003228610325168604,4.023198635307189e-06,-0.0012865758997511547,8113108.99264617,53.276834831428495,0.3267401625270126 +1.438691137842491,0.053003422601885564,0.06601178728785918,110575643852.93709,942.6032728618675,0.0034988506583241777,1.2705364910413264e-06,-0.006659839671566904,35229044.54530091,39.51505866290807,6.2775866711542685 +1.414403183805858,0.04882944216761645,0.14845767749078817,149309506519.0759,610.60676382933,0.007249105577375095,1.3313998479414166e-05,-0.00028971038864845423,4815030.022969181,80.48729036581547,0.1768991228603701 +2.0353686403612703,0.02332481098639935,0.15539943358306796,179856019927.0757,1945.7396345704922,0.0036246624157185796,7.29432621084417e-06,-0.004168526314270902,42185389.05134458,57.91356507087033,8.110866867426946 +2.885249561289233,0.07502641998074575,0.05528161931795067,147988357964.81046,606.4353783401605,0.004147581988164274,1.0562707308145347e-06,-0.031060656337359775,45787130.56863121,93.93945152733245,18.836280877440476 +2.351414219740206,0.02986481013474012,0.09828716313145244,214871839997.58304,505.5376364361669,0.0029353274656030563,2.3630282440532682e-06,-0.0043149050563687525,24721824.882794213,54.18204032637211,2.181346903643125 +1.4311801416075802,0.02434680593601473,0.1293718902803398,191379545728.0371,1304.2210211934942,0.0031497923062308235,4.393195391237984e-06,-0.001515782214629715,27483681.44445964,35.387173561097285,1.976915027871303 +1.8605504351019462,0.042054043274588296,0.14538206538300838,155548354819.96948,404.43763353660887,0.006113903668966059,1.0768594273778364e-05,-0.0005183584838648528,5079428.273869284,89.29552513200956,0.20964367853792554 +2.838279252077004,0.06353785559677937,0.15836925718719325,157717901217.78394,355.8809369288714,0.010062442994129098,2.1031194818127544e-05,-0.0008177186490437612,3803091.596639364,224.19618192723718,0.2910104789659047 +2.0111673108402313,0.06485092449088713,0.12682787158977285,111271833012.24095,1986.3541833732334,0.008224904723808288,1.1025011173054024e-05,-0.004390517963427739,22977911.960835844,129.85202719509425,8.721123723830017 +1.8574788390230883,0.0685463759352212,0.0947230269330848,105468411318.24774,613.2931684395832,0.0064929202138773135,4.854784488659686e-06,-0.0025587398737420674,11113417.203661704,94.67462592082764,1.5692576843799715 +2.6392631901607957,0.050586520941824586,0.07477415415586579,205756877676.9475,1792.692131769722,0.0037825643151129244,1.7624146452234193e-06,-0.030294940628359013,100369516.79162282,78.36798467615259,54.30950169689008 +2.111956910778975,0.04150066578872504,0.15400899877518737,152541561771.2149,316.0008881453181,0.006391475986625215,1.263316331472268e-05,-0.0005148988350637654,4067966.312636845,105.96339675824329,0.1627084891851395 +1.0014264214742683,0.061764448541219166,0.11708875672061811,125718315392.91345,1376.2922971645733,0.007231922489225947,8.262337020810443e-06,-0.00044355257253967935,9765894.263652556,56.85157033130386,0.6104579889738913 +1.6856494847041383,0.0663499842356854,0.1189675311235549,108626234296.58911,263.5662911187316,0.00789349381460628,9.309898043819937e-06,-0.0004160933527119218,2838642.271951645,104.44946068168507,0.10966818173343947 +1.1458396446677404,0.026891163534892886,0.08406813850038895,178256591425.2339,1547.380576946341,0.002260690060487984,1.331443190666247e-06,-0.003269483729673584,55975731.78183147,20.33454812056554,5.059135619938985 +1.6712647923371784,0.04365954073872256,0.12457052002277555,128972751590.80008,1905.650002103744,0.005438691693778223,7.03305071686388e-06,-0.003269007846047917,28205248.893309005,71.35252746187737,6.229584808698369 +2.1384126500867273,0.05709307593456131,0.055745934746160644,215490403396.62256,970.0232332545547,0.0031827068855056493,8.242174439925595e-07,-0.0178018726648786,70147961.63245386,53.42663422404477,17.268230080371417 +1.2557271906680043,0.044839093908410316,0.12255691330320925,160243710423.25885,1111.453854069051,0.0054953409447275016,6.878425296936459e-06,-0.0006655582310943875,12433847.260623487,54.17009501334135,0.739737261057237 +2.588034071579322,0.021174945313894144,0.15511863778583707,207517772888.27136,1141.6966984823966,0.0032846286722808538,6.586170934589154e-06,-0.004826709522544038,34795391.17509136,66.73073769334123,5.510638326422073 +2.807867229176492,0.0666381271839097,0.10374811733425016,113085413208.90451,1067.323026027182,0.0069135802380109485,6.201292416114119e-06,-0.011230925047518122,25069199.434559733,152.38746078475626,11.987024906801516 +1.227061247834137,0.029723238153739916,0.1029526971865092,177496282147.6928,1883.8957752126732,0.0030600875370444826,2.7028880727597e-06,-0.0024183380949151356,44025346.65861299,29.476081428746827,4.5558969200464885 +2.9710431244066564,0.060186340327272714,0.13692333426772887,166872332657.3057,729.6871195986578,0.008240914394982451,1.2875054890388292e-05,-0.0029689908975776454,11527735.869587757,192.20027960848614,2.1664344161680655 +2.210021847705903,0.051760835238663316,0.13811991091366066,176150450348.11322,1826.625937519196,0.007149201951980845,1.1365509212876897e-05,-0.003282807450351345,24529211.211943835,124.02915618418395,5.996461236693027 +2.4487914057713125,0.053673046310513686,0.14252070565784486,213317360550.77258,191.55717833418424,0.0076495204349805975,1.2948184857742409e-05,-0.00033946692094041287,2581602.071297701,147.04682721070228,0.0650273255131391 +2.045876965049992,0.04954726517142617,0.0833183854162591,117833768369.22206,1959.1727057772932,0.004128198135874477,2.3881465726731752e-06,-0.019872809059518277,69920110.49397166,66.29941596578111,38.93426509653193 +1.3947201725217278,0.07977939782851484,0.1589662855852927,142043082185.1145,332.6222866889177,0.01268223453903037,2.6706968102347878e-05,-7.929515677140202e-05,1380666.7640673867,138.852121502264,0.026375336368659956 +2.727914991379722,0.07249126009796847,0.07971050709530414,120733477883.6434,265.75679548591074,0.005778315102386654,3.0595046598209796e-06,-0.004868293923976997,9443862.782197664,123.73760628282379,1.2937821927196567 +1.5080205001189793,0.07929796780301963,0.059519692129124196,104269368673.55035,1047.7877266045866,0.004719790630100931,1.3933583994093103e-06,-0.008244307928712086,33748027.387947045,55.87269705772418,8.638284662053405 +2.7117035361833945,0.06135319406939463,0.12096633619886818,108056962302.81097,583.7158701538976,0.007421671100672796,9.050019442820886e-06,-0.00396738732995687,10578612.956230627,157.98416837946354,2.315826947543323 +1.0939706323345735,0.06893894354764854,0.1361355202715921,157283226091.914,536.4549517916284,0.009385038946833051,1.4494316622265394e-05,-0.00010269489179134353,2756021.731196738,80.59561238053969,0.055091183225171696 +1.1622913272795432,0.05786893010930312,0.0460773074504991,157178725492.1706,1425.8497974086044,0.0026664444844778047,4.717647482754067e-07,-0.010064177004606168,80932021.23996015,24.32860459700026,14.35000474310204 +2.7716878936706366,0.04312541237999208,0.12480506453875065,156706246149.03607,1682.697094517661,0.005382269875345148,6.9863227093708594e-06,-0.010908944065388938,41658520.38609861,117.10608219360417,18.356448483085646 +2.5389745767420147,0.05546185075884183,0.1291954309889122,169475506176.02783,1536.9320110250876,0.007165417712231298,9.966773228725662e-06,-0.0049641733799332816,25291558.42784295,142.81358521427373,7.629596975898065 +2.691255638827559,0.06297069741791503,0.0765125118485241,182849657583.16687,1188.249760943137,0.00481804623229805,2.3504695887419873e-06,-0.017963979523115015,52048775.4075278,101.7877636128114,21.345694373928826 +2.471636471146515,0.05778734751839677,0.08634307603146052,201290879335.22626,314.4498614731415,0.004989537340437364,3.099802786616029e-06,-0.002536446909736171,10824291.000963096,96.80873134846313,0.7975853794005168 +1.1749551739564756,0.07225278999907067,0.06712687228516774,217670736453.52356,165.16932008621438,0.004850103806514662,1.821220843370476e-06,-0.00022527311363690155,3576469.151747768,44.734438309269635,0.03720820701311154 +2.3809623473625416,0.04852277304787561,0.06134584352093114,140821987726.1037,1039.775234610213,0.0029766704425966324,9.335117613737227e-07,-0.03558652100852212,81344341.81955363,55.635620917987154,37.00198323059736 +2.0875962313292424,0.03274970697390237,0.04426037959548125,190994540317.8186,1457.9021947833785,0.0014495144623056986,2.3663096529928056e-07,-0.09782596018411872,284635101.82364684,23.754107290817885,142.6206820592181 +1.7941800678946425,0.045497545343850115,0.10729594440554388,103020088720.08171,995.1496827382779,0.0048817020958024536,4.683350275692161e-06,-0.003970879214337942,20452721.60720234,68.75542289185287,3.9516191903404247 +2.0574912934882548,0.034019059204692954,0.14686011359844534,189703355518.88113,498.1916558730003,0.004996042899313445,8.979509875556454e-06,-0.0008491053312872404,8382154.9957609605,80.69262092276516,0.4230171910045828 +2.5323886742521076,0.071607908391047,0.07490476862260115,137178636631.16434,622.871006540016,0.005363773809579794,2.507888032320121e-06,-0.009801066218384816,23555905.66826902,106.6278063660451,6.104799980610698 +2.3301750347380024,0.05527413751107069,0.09549247389991775,123981563453.13733,1556.5889191219576,0.005278264133616382,4.010958444788195e-06,-0.01320118883679208,43177099.64580963,96.54934259061136,20.548824262587036 +1.677122085801654,0.07462903940988234,0.11497922397710428,206518586292.924,1232.4381175880685,0.008580789037505004,9.453327962571316e-06,-0.0009926451687196605,12569976.11805454,112.96959184597424,1.2233737431697491 +2.0323791598945036,0.04277015701138904,0.09154170388539487,140161625063.5206,554.0170695932885,0.003915253048268421,2.7341137178513925e-06,-0.004045483107103573,18849520.242546406,62.46463780296122,2.2412666960866736 +2.8062624068569506,0.07985373881967696,0.11337690514066068,200031319360.05948,205.79991536540234,0.009053569771285607,9.698125558017938e-06,-0.0007814891818280886,3375827.68091437,199.44253610156997,0.16083040747919816 +2.2717225155456804,0.04716473377826938,0.0949863969839479,127466196746.35666,1090.6494644510033,0.0044800081263049124,3.3683746050520937e-06,-0.009926916544691682,34934256.698401086,79.89208234328272,10.826786213117787 +1.7378500598700533,0.0738777679130561,0.14607640565505262,219006087605.34467,1760.7324236745358,0.010791798794557413,1.9189901333882387e-05,-0.0007329596853289192,11646166.685165578,147.2230462226333,1.290545883204913 +1.5137154358328395,0.05407141725293492,0.10531225799488872,198347582797.3896,491.23308203901007,0.005694383043890359,5.262877731885171e-06,-0.0005440626066401296,7439735.481965973,67.66445276199077,0.26726155108200844 +1.4492631580499715,0.025535568028259188,0.10835483609802105,181044649435.6347,962.4982454017294,0.002766902288371891,2.7071303983189564e-06,-0.0019926250153884852,27916201.656973228,31.47826095542309,1.917898081055011 +1.2689404943203408,0.06687857997010405,0.058791498763259065,123206849125.83661,272.9127958972913,0.003931891951600894,1.132529158521066e-06,-0.0013321163869399325,8988770.643501224,39.16629479592707,0.3635516076203749 +1.4258128606535507,0.0758595259575483,0.06400342688102204,202271809950.72742,1362.0811610946794,0.004855269622852936,1.6574428459527883e-06,-0.003925503713462117,37497316.15409862,54.34324108110321,5.346854655913956 +1.0313069010984408,0.03073462810610016,0.143667461943138,203435921628.17838,653.2340954951508,0.004415566013769644,7.594898511996559e-06,-0.0001545830051510399,6371815.872576612,35.74735906271248,0.10097888954876179 +2.904521170293873,0.03156970614678105,0.14293141312972282,121103625103.24872,1964.0599277206998,0.004512302711649512,7.681965562248249e-06,-0.017243587282486036,53070675.69776106,102.8827182091696,33.8674387916851 +1.4573945036854046,0.06471900711662265,0.14999607121470343,145928435034.80405,104.33495908973752,0.00970759680040983,1.820079053666575e-05,-4.0533098182527294e-05,626565.6961965796,111.06021603415373,0.0042290191406542995 +2.3995696313896944,0.03826366264328562,0.08648192895824242,106970536155.77838,1569.0855127466498,0.0033091153543987816,2.0624403488417235e-06,-0.032755170141048756,78939422.57360174,62.332553782768194,51.39566293587124 +1.5831564779291536,0.06158952125377512,0.14651519020975837,134859695898.89427,1524.898180279426,0.009023800421424817,1.6142602099109667e-05,-0.0009264786171953522,10955792.648574464,112.14579152784042,1.4127855574289916 +2.763846605279553,0.07855458480595,0.14787570706278394,135672389234.38428,649.6311811736562,0.011616314771203281,2.11680471453804e-05,-0.0015918976721288796,6271433.8012254285,252.029840348054,1.0341463650526777 +1.3259034621897743,0.023928018494800956,0.1309319860687389,139710905166.88168,1446.3098788607458,0.0031329429842138056,4.475718424778278e-06,-0.0017971434688577397,28049573.410042908,32.60874260445615,2.599226352739018 +1.4630438878749488,0.0753596491752525,0.12043197556765828,203664306156.47577,1650.7582276289302,0.009075711428261307,1.0969404555335327e-05,-0.0007713230369176848,13257742.691050088,104.23358844589103,1.2732678493516012 +1.054406551847298,0.027783601365745487,0.05215405511524665,147170484989.8246,1287.711424834247,0.0014490274769291323,3.284517181024652e-07,-0.010409486893534211,107798617.8929205,11.993732914024568,13.404415199466358 +2.7894324144038096,0.07145804127893124,0.08227478525214643,148956404054.46942,849.1079141955836,0.0058791950007630826,3.3164246451966493e-06,-0.012435402609648991,29379564.91368695,128.7369942799756,10.558998772061372 +2.2539066242101127,0.0380942901797728,0.11154464927677643,115056077385.51292,826.4707556456384,0.004249214237550506,4.405800892019677e-06,-0.006222710058892296,23580732.457847882,75.1820571239686,5.142887884536431 +2.402994457545718,0.024450172665569057,0.07333284694924996,119617979556.28087,1486.8203416185795,0.0017930007699669106,8.035193158826713e-07,-0.0715488673316161,163035992.62936315,33.822281663954676,106.38031136841587 +2.742828039600342,0.023609133476818346,0.09170812089936714,159918493491.65118,395.0861585155586,0.002165149267221353,1.5174772399310487e-06,-0.011198127962772995,32745076.440472394,46.61826214243065,4.424225359377641 +1.5697906829164001,0.07549512638840895,0.07604579502760658,181453987934.30493,1258.2507780822061,0.0057410869069162,2.7667077354952207e-06,-0.0032317770495882414,27145064.58942552,70.74659217987953,4.066385987232621 +1.0361433009419025,0.06182983510372808,0.04805833918607037,111760346401.94025,706.8580808633781,0.0029714391872337647,5.719039774627004e-07,-0.0041007149991116746,30772848.329627056,24.168868942866858,2.8986235344397473 +1.1891332822946319,0.0527875598961165,0.08766354684184721,139024803572.45477,1499.9087014354996,0.004627544729620024,2.963517222398649e-06,-0.0020404944982919558,26380130.898834437,43.196724508391526,3.0605554532193686 +2.544032769922248,0.06594414947234263,0.05742754543697271,120109802061.00427,156.39458008854078,0.0037870106401254764,1.0407724496932926e-06,-0.006866482356673922,10976878.837448228,75.62909147290901,1.073880624857392 +2.4113491041746977,0.06806925253289528,0.15637898691304603,165932504055.44736,1719.6287239408757,0.010644600751022457,2.1692266004892448e-05,-0.0022328385307194484,14946457.070863962,201.4926106094112,3.8396532733471047 +1.5923443831004058,0.04005190618973452,0.05773069148673035,151035260497.287,1282.6360973889136,0.0023122242396950293,6.421880539337018e-07,-0.017797239006710864,91802603.88603026,28.90257965229384,22.82738118386537 +2.14854194002951,0.05439898896951202,0.11195997362774329,147207832368.7976,1631.9826419816247,0.006090509370402464,6.362062696420984e-06,-0.005760987394660233,30852774.00784508,102.7228613248515,9.401831428760444 +2.9217862660688345,0.032843445417127595,0.048757074670193176,195326934051.26315,761.0501315585215,0.001601350320629304,3.1723448179120516e-07,-0.10211624123203614,170879107.52690297,36.72860648574005,77.71557882390282 +2.650969177806023,0.033149857480434794,0.07285282237491812,112263045235.50276,562.2891172867971,0.002415060678775967,1.0681680006457648e-06,-0.029118974501895014,50832465.96639513,50.25767366243609,16.3732824689673 +2.645330657566194,0.05809176556486251,0.062398521644742064,192519600897.1284,1836.6219985253722,0.0036248402909803547,1.176132446739775e-06,-0.05005036379772565,128880680.4817552,75.27287403151523,91.92359918510083 +1.7116485574723677,0.04607224077507914,0.05080289837571628,133938373623.35886,414.7005979668885,0.0023406033660378772,5.034119949422421e-07,-0.01028084050401299,35816586.66371313,31.44937944448555,4.263470704616394 +2.3179594419089993,0.0698117402640165,0.12983737616156665,109203043249.62506,1619.773916426538,0.009064173181152699,1.273345944268063e-05,-0.004835812948398948,19141834.59741644,164.93152859555715,7.832923678534328 +2.2170807507995125,0.06206830874195027,0.09726977055680387,219837925483.5011,1265.2639654958202,0.0060373701501783665,4.760168652730884e-06,-0.00439217324060257,28660793.27513042,105.07489659148435,5.557258531549435 +1.5294680246631351,0.04242086202547611,0.1352559504127669,140463337062.4261,856.1338645748704,0.0057376740105846225,8.747166327492526e-06,-0.0008310195877148452,10123742.215554321,68.88837314076949,0.711464011167726 +2.2316117653477456,0.07494208675424054,0.09992226275683394,208295443337.3362,956.7772193039224,0.007488382884202668,6.230620737223157e-06,-0.0027310799449712883,17121050.84331536,131.18263228035056,2.6130350754463385 +1.2445404504507112,0.020747849981456956,0.10212715532645167,196038222403.36148,1775.016121825097,0.002118918897746172,1.8416858803310756e-06,-0.0031590156914121205,61250127.86547549,20.701080193835935,5.607303781354969 +2.595558640536703,0.07828353095980646,0.04130940703342244,116560683003.23747,124.8123838731956,0.0032338462444321723,4.5987102109595957e-07,-0.013571905660408055,14550283.171452533,65.89005486093926,1.6939418991776465 +1.316696947387901,0.04519978117597574,0.15359480367917966,136273168756.41151,1435.5960470836774,0.006942451516065875,1.364849156707118e-05,-0.0005873182212224315,10636039.812315397,71.75767204095068,0.8431517167671394 +1.626844127395485,0.05282349110856836,0.047938376313797666,167988424833.00262,793.6237756270751,0.0025322723949710952,4.849487175130852e-07,-0.013981574273287148,63814316.719322376,32.338957926586744,11.096109763976525 +1.0617097056098412,0.05157370872018972,0.12594127202734143,132787328876.609,1712.9943483542802,0.0064952584793882846,8.585218314452442e-06,-0.000599437708845018,13339773.44982657,54.13421989888761,1.0268334074419545 +1.690444257651822,0.021496426584195448,0.0818724117236866,121600668008.59973,1672.1450161760738,0.0017599642878892516,9.83100182416688e-07,-0.022522754868352028,117702206.53730504,23.35470396445711,37.66131230367025 +2.197356544114635,0.0249116415865122,0.15997594369687082,183594002331.03647,1251.4457206043853,0.003985263371840501,8.499338833351692e-06,-0.0028362775317182136,25879274.133217223,68.74279971855255,3.549447379515127 +1.4693122091591027,0.059152260883236454,0.1331021331716896,191936918720.63373,1417.963699048954,0.007873292105487064,1.1623720270335684e-05,-0.0006720203919551751,11928588.864011742,90.81134510241475,0.952900520813088 +2.8602167128648457,0.07186473302707089,0.09702997350637749,143986230123.234,698.2192085353996,0.006973033141659579,5.470818525639466e-06,-0.006913438243374578,17709827.89240488,156.56342955941122,4.827095378547361 +2.2941834394689877,0.037284593794104204,0.11294452893614798,144254417101.51257,1604.7796995369506,0.004211090882650726,4.476553355336487e-06,-0.010002434203830587,46444575.73239496,75.83896747584768,16.051703356261367 +2.0844917675866554,0.05949897487368812,0.14722733877245786,202799760420.5213,1572.01388989613,0.008759875730342438,1.5823174704596453e-05,-0.0014790219398015017,15244788.603835296,143.3401274331005,2.3250430328290785 +2.304222089828586,0.03906286972043847,0.12026734480875395,107303479831.53624,230.63138968017876,0.004697987621887408,5.662732780013312e-06,-0.0015478550699345377,5643316.537703733,84.97787382033972,0.3569839658025127 +2.288668294374408,0.07636508084636587,0.13870445205023224,115956690685.08931,1784.523748927207,0.010592176694566862,1.6981841100838293e-05,-0.0036213379155577586,16679415.125940835,190.29953490874354,6.4623635132033685 +1.619280685381442,0.06031216365010704,0.12285413804816706,208559810329.4909,1179.1318813706505,0.007409598879053893,9.319508963432962e-06,-0.000858586154413993,12584943.811277138,94.18602975751622,1.0123863075729633 +1.9764133743797743,0.04862186406220104,0.04718223796736001,209818554532.6043,914.5179335817894,0.002294088360599399,4.255846630641964e-07,-0.026355694473561814,100191893.13257454,35.592425305496334,24.102755248074736 +2.5811156078482758,0.04791637475969256,0.07180650089040813,162818322054.708,1394.271398804625,0.0034407072068469934,1.4784069635400225e-06,-0.0332009996887741,87396601.42829902,69.71477512798624,46.29120427777899 +2.4240966074345485,0.0550835490300282,0.1164652314828088,137726245762.51544,291.74655046003613,0.006415318288676882,7.251528374280895e-06,-0.0013870368085180226,5679268.500204659,122.07810769867636,0.40466320424623076 +1.8119409846568342,0.03615284614821878,0.043978129880797225,168655136048.6181,1384.97239798188,0.0015899345634668451,2.562545111832703e-07,-0.06354493181927395,215337868.01679626,22.61481064797419,88.00797660133492 +1.5203382549442104,0.0661720352183438,0.13349617672348985,153446858345.07272,1758.8207431663848,0.008833713707661018,1.3118969722462246e-05,-0.0010234420659766342,13605073.890493095,105.42732813140951,1.8000511350687638 +1.119274932276804,0.03118191689650051,0.15397494615710128,130820606053.8404,1267.9718041324911,0.004801233975213873,9.48575157053905e-06,-0.00047758510126295325,11518467.262977421,42.185121534752895,0.6055644424751853 +2.8264732580246443,0.03711519596359855,0.04504328364823122,210362584278.08685,1195.6522622459536,0.001671790299448056,2.826575829108088e-07,-0.1513523398706324,269270748.2849036,37.0933740091573,180.96476756254006 +1.9700378017525204,0.02010190573151893,0.06320283381208486,176721792183.19147,378.1281448349977,0.001270497407255387,4.229272215427543e-07,-0.012893941091676782,55661445.40198045,19.64798416667518,4.875562024607487 +2.3540189868785317,0.05728838900570228,0.10253006432107029,166687539871.52856,860.9030418047646,0.005873782209605151,5.145635904998451e-06,-0.004364361156086619,20190467.95615102,108.5419095426689,3.7572917948095292 +2.681783428693869,0.06279757642523184,0.0903787048143618,131752029800.08102,579.2534526212464,0.005675563622793355,3.863313725592832e-06,-0.007316463209146168,18170566.797023073,119.48196490602393,4.2380865748742425 +1.1228746478704057,0.03003018546318814,0.10893177537958146,164989127617.54022,1929.469855839357,0.003271241417483183,3.2347484534134203e-06,-0.0017061402656593592,36479875.439676814,28.8345733298308,3.291946212423486 +2.3452421725929256,0.06721105485541519,0.08017800091707836,171857774746.8822,798.8693930488431,0.005388848017835283,2.8868561032027542e-06,-0.006923461670399869,26017380.52327449,99.20950602000063,5.530941622429273 +2.1921406572154005,0.04161487558830651,0.11868647536109089,125111735826.98828,1697.0981515337937,0.004939122906166404,5.7979044364939595e-06,-0.008215270238589898,38078125.56060209,84.99392924869139,13.942119936261504 +1.6538092114275944,0.023076624935595744,0.15312730231001884,170280287585.6021,1465.4676397641606,0.0035336613228078885,6.90476560049627e-06,-0.0018793076552264289,26874187.02850412,45.87541291894207,2.7540645538953936 +2.572389637442625,0.06310861419853078,0.15585331463983307,117112596843.1493,989.0783852809141,0.009835686705167455,1.99092787415357e-05,-0.0024069139974230015,9958592.990530154,198.61456567641395,2.3806266100811726 +1.9501819587052847,0.06965944772581867,0.05461591488166573,102058969811.37593,756.6883347626233,0.0038045144676971555,9.45706599929415e-07,-0.019382669354814672,42611318.31850184,58.24303949080942,14.666639797349244 +2.169380236533605,0.07309913637665019,0.14042989389535024,185356904469.80307,1328.859299956813,0.010265303965214724,1.686979103822627e-05,-0.0014462597918054655,11998709.765359618,174.81437822155294,1.921875774494297 +1.9210801752994098,0.03752749610171206,0.09940157815533544,105927512798.03633,675.2751286959088,0.003730292336728378,3.0714834610985046e-06,-0.004905000029512263,20991397.246766213,56.25459665085755,3.31222452618233 +1.8672525327673226,0.06439535012713746,0.14110818184384483,161447928371.44077,871.9607816125334,0.009086710775638168,1.5077517842054512e-05,-0.0007773606289221339,7618901.494090041,133.19239212612575,0.6778279815897544 +2.5139736529173735,0.0523306246636633,0.08575743461063907,158554436079.10913,1902.691856398136,0.004487740122728002,2.7503629902673907e-06,-0.023107925436530653,74572886.04475248,88.56417437297526,43.967261546342215 +2.8287887582563256,0.0655810217625155,0.1502194765651921,185857541823.98007,132.24380229654287,0.00985154676177555,1.8525744315176733e-05,-0.00028980092717855843,1516688.6192816324,218.7633661395054,0.0383243765191561 +1.1491168951070976,0.043562541919502956,0.13726800646592155,214735079097.06833,1303.003086355074,0.005979743285878311,9.38944552879265e-06,-0.0003268691068341117,10944830.456825476,53.940678699917086,0.42591145503897393 +1.816452532974277,0.031336992307416156,0.053829698863246477,169898635912.34576,1175.1395559848966,0.001686860859188083,4.073257968145525e-07,-0.03392411627878146,141046897.41507798,24.05320604151176,39.865570941027244 +1.7201861883903216,0.05216015809158496,0.08834191964205884,124165131519.08154,1368.5047738109579,0.004607928494643884,2.9968026860878492e-06,-0.006240129876809475,34697681.819949664,62.22298538557642,8.539647525614152 +1.4466566045237335,0.027334226317785183,0.07884479362491571,159208365270.32013,739.752259166604,0.0021551614329225126,1.1164636867654345e-06,-0.004200015783817907,37787675.500095166,24.47456138790466,3.1069711646146914 +1.8527855752852664,0.03493335622852884,0.14129445290853324,116134563701.037,335.50969196930976,0.004935889456568885,8.211725114663548e-06,-0.000745870451627361,5347994.409986015,71.78938657271767,0.25024676547450586 +2.7971497624395587,0.024165381669526993,0.09574930693548259,118806388105.07796,1437.322937855852,0.0023138185466886245,1.7677438297101707e-06,-0.049925352234107614,108882075.16564503,50.805961435856894,71.75885394661577 +1.2963080909812095,0.04750360625822915,0.09387910852407244,145324504696.18393,752.151047413974,0.0044595962072011015,3.2753084462676986e-06,-0.001147406876847494,13973334.399871632,45.38093357034563,0.8630232842308393 +1.9936770076287835,0.03342559856298535,0.07239437329396463,180532790604.77344,953.707162368382,0.0024198252599429686,1.0568476488097286e-06,-0.013203519451001034,65122681.703268915,37.871147368336985,12.592291068889933 +1.3869643241945444,0.058219887610593324,0.13360766982317238,104935850950.06586,547.9444957150688,0.007778623521018357,1.157135682245887e-05,-0.0004013312796635827,4387518.563440152,84.69108552269515,0.21990726564994506 +2.5564017033384347,0.03856683579322107,0.1511509527738792,164293231268.08487,627.6901227004914,0.005829413975619112,1.1098529223897001e-05,-0.0019170181887193482,10926721.058913376,116.98324196138995,1.2032933820963216 +1.3502967241920518,0.07867742122415634,0.049844588613273774,148097496367.31027,983.0855480332484,0.003921643694071328,8.11938095415363e-07,-0.006709452211138715,40746060.66989111,41.56875367339051,6.595965503990194 +2.8669274755305993,0.04082263006107567,0.08536535809262197,174577218859.83533,1923.2652766415831,0.0034848384334463588,2.116239102299512e-06,-0.04088987199949751,111209742.10429634,78.42761556316417,78.64207098295249 +2.321092882149906,0.0624418907370763,0.11083112427626327,156235495722.25974,790.1308036373971,0.006920504952325756,7.084023859237722e-06,-0.002975744043477069,14346410.090740222,126.09560806795292,2.351227032491734 +1.6420849752535778,0.05664594997241158,0.1006076067015132,203193406480.75067,1199.838353027825,0.005699013456057977,4.807065859132985e-06,-0.0018130036740156116,20617647.849358328,73.46237530419205,2.175311342264287 +2.6727701007027393,0.06108791293093188,0.0710279279220952,103940414216.20375,454.08890509393973,0.004338947876569457,1.8241539064487798e-06,-0.015242581589106612,23628718.435804565,91.0365297010695,6.921487184602466 +1.7744739384736667,0.06564742067871134,0.1216052643240628,123074084192.20244,511.90463757274773,0.007983071943827637,9.837699424928616e-06,-0.0007874382793362332,5614195.354110834,111.2011619392673,0.40309330699452256 +2.960533583025227,0.07947322771835542,0.15159347388603736,178840793298.61615,1346.2324845207952,0.012047622670761614,2.307178104636529e-05,-0.0028220264349158876,13093611.348032258,279.9890233723858,3.7991036588601776 +1.2157155733362761,0.06378382198624324,0.06471442790537063,109114310589.13678,149.76433221439063,0.0041277335494577325,1.4405642793286307e-06,-0.0005706485592192375,4089581.3660352468,39.39247717546836,0.08546280040057326 +2.389810404232901,0.05241290466780049,0.13599722167844264,162288211966.3734,1937.3023089560381,0.007128009414917944,1.0986189627661704e-05,-0.004943475859068718,28655882.859444786,133.72153983074168,9.577007196042262 +2.0263533456094995,0.051833773855205115,0.12841653159329114,215618442447.67346,1634.7370694283527,0.006656313457876456,9.147330929693026e-06,-0.002298750802032596,23251963.77338491,105.88113790162892,3.757853149460842 +2.1801583211376006,0.0544373241338348,0.08478722391231747,182444307143.85284,1227.1349606572255,0.004615589590522854,2.765074079163017e-06,-0.008402298097986923,41017955.65846277,78.99232101396575,10.310753745903463 +2.14563415133425,0.04819637311475541,0.08252572251278449,205188393280.99457,596.2179361203249,0.003977440513790931,2.2573615199825473e-06,-0.0042383507360532644,23384006.977611676,66.9929377801286,2.5269807284037373 +1.7926478098633127,0.04021839785799433,0.0836200901763734,167578973472.24176,659.5016413182734,0.0033630660556347486,1.959636024754766e-06,-0.003856422518740346,25224123.077278662,47.32602504261536,2.543316980726008 +2.3756280674227153,0.0483290729257396,0.09665149195898387,200871859581.95782,130.53595113399155,0.004671077003267266,3.636243060911639e-06,-0.0007986789177711991,4121300.169104623,87.10942182732785,0.1042563121819305 +1.6958661415634104,0.06526374561339524,0.062458407865225524,168178476222.96375,1870.3868278064733,0.004076269642333763,1.3251452289488016e-06,-0.013644291790094198,74751591.11529726,54.265540211985474,25.520103638940196 +2.4433997055693606,0.04408042722693588,0.09428494243490745,131315942784.47629,1341.246356802283,0.004156120543597776,3.078871543997218e-06,-0.016131019880204368,50179213.1978636,79.71725014341997,21.635671645829305 +1.1028063868576052,0.06406947408643922,0.046615887590654936,190473321972.5782,1310.082184245514,0.00298665540200583,5.408437141121633e-07,-0.005685506510251672,62262992.35227599,25.855565823497166,7.448480787492602 +2.0518223806710534,0.05934782620461518,0.04929105853191075,161709968680.2527,1056.1085577582949,0.0029253171751933535,5.922812776066097e-07,-0.03174985874842365,90169252.42114542,47.11751531739171,33.53129753182728 +1.0223759978198008,0.03397969986648991,0.12554263886747186,142541733129.8655,523.4450425052518,0.004265901189163824,5.602889429367168e-06,-0.00023346817289116728,5995576.4022467835,34.23663663124551,0.12220775768264053 +1.5385843620956283,0.0569991138377577,0.14001589228789396,146082075158.87045,877.2234445545054,0.00798078178361289,1.3038236515113336e-05,-0.0005591613347830274,7247029.445275793,96.39098248908093,0.49050943216006226 +2.5662646359499606,0.028666054976278867,0.04563183452125549,129906583615.10869,175.8268955552439,0.0013080846770547698,2.2698150440767e-07,-0.033592841401824065,45355944.012306854,26.351597863296394,5.9065250165623935 +2.5475806232002713,0.026145266709118133,0.060181120434581035,141646259842.15485,456.35486046361933,0.0015734514446156804,4.7488957685110224e-07,-0.03739103507369861,73666197.535083,31.46668113301765,17.063580593648027 +1.8023601030541823,0.04529786577896972,0.04061234069047676,199529001178.22357,1584.56457706168,0.0018396523575670068,2.528544241506192e-07,-0.061296658313751695,229355403.64641982,26.028370700231466,97.12851345622427 +2.0785411776654135,0.030505920460044238,0.11257009285054553,184566302940.21112,1074.432761558658,0.0034340542986785365,3.6263687238748333e-06,-0.004805178356806669,34662425.026948035,56.03191263921675,5.1628410516856835 +1.383765571277426,0.0456377171355702,0.06848166717680429,101575719368.99918,425.77229281039746,0.0031253469555872567,1.221421724284707e-06,-0.003031015502007379,16516522.223900557,33.94926799619116,1.2905224198335397 +1.8869495499350393,0.02206603407158994,0.13149700401976216,176890774227.61542,917.97242336677,0.0029016173710120713,4.181100558450406e-06,-0.002779671352508547,27238624.543780982,42.98036389967212,2.5516616476254583 +2.9070650191280567,0.07764107771594184,0.05129676553297728,201713576323.0376,1684.3832381599352,0.0039827361593223354,8.733337723868289e-07,-0.07830121620547195,143805463.9610624,90.88787280808175,131.88925610403405 +1.7054965108590037,0.0670474566809185,0.11559254638985875,154576172017.00507,1878.5585276090378,0.007750186246711116,8.629597801067986e-06,-0.002328750055407863,21457782.839533187,103.76063747784498,4.37469327525646 +1.184295505330851,0.027483044815957383,0.045438835799037305,104640068317.19223,716.4567217412143,0.001248797560649871,2.1486475721748903e-07,-0.017643540894781685,89718510.65179947,11.609720904444318,12.640833469382338 +2.6278699871233693,0.02582792346346185,0.09088122248710997,197355116711.1208,738.0035598900417,0.0023472732586629244,1.615588397802971e-06,-0.01400134349726241,54547615.502999134,48.421382241937906,10.333041344222945 +2.7024519568205987,0.03539519932942396,0.04210185934832423,133110101253.87187,248.86983309758128,0.0014902037037733077,2.2012377114750704e-07,-0.055878789497748604,64318302.56899091,31.613550735289312,13.906545015999573 +1.3297143707186265,0.020598701447028227,0.08283703529892925,204128818615.94937,1890.6208917107308,0.0017063353588795823,9.757357983043522e-07,-0.007439122734166268,106714916.20655371,17.81116838654492,14.064560857215 +2.493970388921495,0.029519715390018526,0.12384489925720596,211627243968.80576,772.5088228459828,0.0036558661785782366,4.67267195611426e-06,-0.004039421782807421,25531573.26245612,71.57333266258458,3.1204889664149817 +1.2376104313828369,0.07799389912769801,0.15785801418451584,152877308824.47632,1841.6809879495952,0.01231196203480585,2.5566971772605712e-05,-0.00029773007909170217,7036484.147785957,119.61368926376164,0.5483238262039172 +1.4771859313584725,0.040513737564428005,0.10497583568425264,189411673010.8775,632.8111067480272,0.004252963457518328,3.905611909384729e-06,-0.0009190994374579616,12562599.497313634,49.31697962031793,0.5816163322292619 +2.819157854789256,0.05351171996944851,0.14819831316475116,155105351085.70502,184.8837000512838,0.007930346634016799,1.4514345119172876e-05,-0.0006133541746896295,2660932.375508624,175.50165718524644,0.11339918925852019 +1.3369512392761456,0.053296070850150104,0.11593498395800672,103501600362.37758,1152.4278222710052,0.006178879119036942,6.920818587591752e-06,-0.0012815473411189504,12904950.645225698,64.84775174994141,1.4768908114629091 +2.8501593284628433,0.02277771271481304,0.0532787527568028,138339274506.69586,1866.5618870210176,0.0012135681240980074,2.8707211811440863e-07,-0.36273715876780366,493678907.641683,27.152070700541252,677.071355562274 +2.0951792560264026,0.07406533974700003,0.07146009099466157,110929048849.82607,1740.7797644535306,0.005292715917871146,2.25229082633491e-06,-0.02136074396510656,57859425.41469475,87.05013050344027,37.18435084813037 +1.0836687756578331,0.04222388045854136,0.041856923487206044,193639384841.11835,726.7213463140549,0.0017673617336861002,2.5803511413136545e-07,-0.006169697030512495,63873832.58763539,15.034592599791754,4.483650532363868 +2.7546212839409696,0.04461943357315988,0.12642371509089032,192860071445.43384,767.1257728362566,0.005640954557570071,7.513260584185761e-06,-0.0036885887754046563,17778641.534867678,121.97874386530671,2.8296115150074383 +1.5467854062971749,0.049870594991660216,0.04470165073126904,218740964751.01474,640.2836832422215,0.00222929791907777,3.712222395568458e-07,-0.009726963089415511,59629625.15415055,27.068727077017517,6.228015753652102 +2.173910077761913,0.06642213976014666,0.13974731270509982,211435093105.7926,417.4666239245434,0.00928231553560306,1.5106435890405407e-05,-0.0004475959511004225,4197732.824075782,158.40451640933568,0.1868563705881884 +2.9881608632106027,0.06226482992396756,0.06380558300294158,187433213647.60504,446.12442249273533,0.003972843773877753,1.3478377128018105e-06,-0.015705888459199183,31553755.344870836,93.1912458038986,7.006780418595552 +1.928995177822485,0.021303088247859245,0.11962160800408958,130279639299.75061,485.0840592149928,0.002548309671661946,3.0387168120254663e-06,-0.0029317193820578113,18417791.69843448,38.58806498563921,1.4221303383278734 +1.6519785274161694,0.0302512897817867,0.10102083746353827,110336460642.15823,1386.2454826876135,0.00305601062810827,2.5989357504399295e-06,-0.007264696769490036,44507168.68080702,39.63044190694513,10.070653079800861 +1.7318884807611248,0.07204950073348351,0.15261615406608325,154159461726.3519,708.8711369355949,0.010995917704325698,2.134279264448713e-05,-0.00037306489081996894,4389413.364616604,149.49307017902404,0.264454933306305 +1.660836317721548,0.029259975287818117,0.06563276847501871,216087586514.02155,1599.6674590351797,0.0019204131836501354,6.893739688650444e-07,-0.01639850496561314,126471418.98158444,25.037511889433635,26.232154770318147 +1.3605777007928852,0.05032300096904793,0.10614835262365957,106246645726.0461,1625.703309806559,0.005341703651943262,5.01562503462157e-06,-0.0025612371482731057,23405764.992079355,57.05225255366169,4.1638117091471 +2.9558431518635926,0.07374489336359635,0.12823646225845173,206271115408.20898,901.4139582943543,0.009456784234574371,1.295941182037301e-05,-0.0029028424886419295,13182625.226640377,219.4292517095832,2.616662737991756 +2.249765552000813,0.03329480317374009,0.12404159838985881,148666125744.9088,1060.8610296626157,0.004129940603746465,5.295381665986321e-06,-0.005114930511678461,27953477.905458976,72.93747510162815,5.426230449271942 +1.7725347730110497,0.04188773776384526,0.08091372269812258,192280991525.7248,1538.9560461677734,0.0033892927978754527,1.8491502826542483e-06,-0.008034903989242845,59681668.88542053,47.15996882017868,12.365364074622839 +2.940011731978143,0.07566834988588603,0.059190285389112834,162741747361.5662,1126.6770492461765,0.004478831224668837,1.3076283241468332e-06,-0.04484789766891998,74969502.74749662,103.36735831669986,50.52909701051324 +2.624776066505209,0.043805932405658055,0.08922955060496712,174865528976.846,881.0331896034272,0.003908783662388435,2.5934495239728607e-06,-0.011710239589151218,39781892.249888845,80.53850217854237,10.317109736250226 +2.7240323279965777,0.05656983266985362,0.10595797521122305,174184264326.22763,211.23376340607712,0.005994024927735386,5.607956031341586e-06,-0.001457019403494844,5435939.931264098,128.17415377205305,0.3077716919558935 +1.4930080857952328,0.05746940956810506,0.08857761921629925,181986546190.57208,1726.7551338255507,0.0050905034773091554,3.328338577228582e-06,-0.0031624902764392274,34305158.0410692,59.66127839127186,5.460846320514821 +1.4978591215046884,0.030966805920008115,0.10651328394486723,101910433057.51341,381.2722785189818,0.0032983761918234196,3.1183617195054307e-06,-0.0013439457646466806,9753342.762155218,38.78294749085136,0.5124092638927752 +2.4904040188857453,0.04111838637386729,0.11614233792704334,125431018377.34157,927.0671449994952,0.0047755855252484295,5.368173072711737e-06,-0.007088721321710404,24975549.821073905,93.36112846919856,6.571720637415113 +1.6202029806615617,0.07332331449794896,0.0674029628912004,218117586637.73328,1645.1576020070886,0.00494220864616507,1.8711034749810364e-06,-0.005714865914334549,48009603.80757185,62.85794225960871,9.401855103418674 +1.5406629516324877,0.04120566430531498,0.07240269404633617,119564303692.352,1748.06148661587,0.002983401105673756,1.303286368322009e-06,-0.013674673808985646,74808202.8299052,36.081862093962,23.90417062752255 +1.960630680308092,0.03506576023661653,0.08072497564950115,118234799547.0885,215.9390093583068,0.0028306826412321153,1.5371837366101303e-06,-0.002984874888866303,11116780.867309257,43.566897376029544,0.6445509265602756 +2.4397064110239333,0.02535178025825994,0.1106155953071023,160769926256.55527,1799.7399897197276,0.0028043022653622667,2.8594091243021e-06,-0.018950475123467307,84929271.86628518,53.707142589738105,34.105927903893004 +2.0647253922351423,0.046344053185831235,0.11735671690144217,163550742253.26984,815.8856469688461,0.005438785929794975,6.242184805680148e-06,-0.002344799933806798,15835541.745614268,88.15235538560438,1.9130886110064667 +1.0523732677245807,0.032248275964980415,0.05625056779683694,158803880645.26825,278.6476441083222,0.0018139838334992379,4.783061746560689e-07,-0.0014252020732370275,17243130.329282057,14.985556541504364,0.3971292000857942 +1.7401156422876118,0.04582209130992622,0.05172123384202792,173440774897.3228,1694.7117816808484,0.002369975099771449,5.283239400985305e-07,-0.03248309717520949,144348591.41050282,32.37364133211387,55.04948748831141 +1.206060508769472,0.0735780027774754,0.06659308000994577,166028251316.1757,1498.1950736613505,0.00489978582593243,1.810731492584172e-06,-0.002914193282266561,33226340.64116436,46.38908976077129,4.366030019188764 +1.7583912519298883,0.025094062051144405,0.07049933995135561,150585897268.83624,1576.7306984844304,0.0017691148113040415,7.327315204746838e-07,-0.025897249241152977,133377698.35273038,24.41974866167448,40.83298788482852 +1.9922434745333981,0.07701808187849038,0.07756755245216204,219344889732.8167,387.5516471728011,0.0059741041058747136,2.995378556826978e-06,-0.0015547348521333635,9997015.741973927,93.42967888072982,0.6025400528612463 +2.9755934765842085,0.03475764166615617,0.05659374519233602,170948948382.8667,905.0359449688766,0.001967065115940964,5.25018202556666e-07,-0.08855734201116047,145145476.28413817,45.94751109703079,80.14757771100261 +1.3094892725297502,0.07093992867841134,0.09238199660591137,195849893830.10547,1852.1065781860923,0.006553572250392591,4.660918768946262e-06,-0.0015186429556610496,24035531.69588962,67.36738558530635,2.8126886080958 +1.8981167520140687,0.038721206016067364,0.13766089031344603,121475057997.73196,1454.1325339922068,0.005330395694182196,8.417814504873018e-06,-0.003241641893466258,22568782.972723186,79.42404989162846,4.713776940841385 +1.3574827743366096,0.03447660181414077,0.1421915841094498,114059411442.89397,1911.9193096375288,0.004902282626663407,8.25971162199173e-06,-0.0016922139691061726,22339986.12159546,52.23989913190785,3.2353765635724563 +2.3614452255990823,0.056194595351063276,0.15040608205209757,170741500984.13037,1146.7202174889098,0.008452008919256444,1.593343809830657e-05,-0.0018502109703872754,12780894.536866957,156.67780545642705,2.1216743263628635 +1.2835769902090703,0.03370516955796104,0.06515841870363565,117335088497.90169,1786.1736193459988,0.0021961755505346594,7.770104836812091e-07,-0.013810627192923274,96130069.42665954,22.128839164539308,24.668177958622035 +2.844162452744898,0.07675297437317298,0.09281253990843882,128746469431.01382,1804.5579421198604,0.0071236384971014996,5.113684640101157e-06,-0.02102052230264616,46576617.9910677,159.04716335201582,37.932750468747784 +1.7485215564374665,0.028478863066171697,0.1012479627143423,153814855172.39337,1078.618158304916,0.002883426865870612,2.4632034319057656e-06,-0.005072953519384799,38760978.732904285,39.57761214637765,5.471779782245274 +1.6367506690640443,0.031673975209392455,0.10710018393981813,126460361692.25813,804.6497488754809,0.0033922885710311714,3.2425895336681313e-06,-0.002868050609130363,21749919.389263835,43.585795118104606,2.3077762023989163 +2.8593012729562552,0.039935660012452856,0.06986382492509467,187784073528.28076,1274.6650253987286,0.0027900579593781107,1.134845387465724e-06,-0.04660785489340355,112186772.41173568,62.624287757741776,59.409402541480496 +1.2894122392511047,0.07003745071138104,0.07587294613660116,182345905342.1501,1666.9298081007958,0.005313947725369472,2.549235324139676e-06,-0.0025625094730750667,31985719.588014014,53.787173501280925,4.271523424209492 +2.5007519169881003,0.02472886936083557,0.10324005577111053,198895061932.1864,1528.157161891395,0.0025530098519691707,2.2676065649571843e-06,-0.017663098512832365,86993972.04948102,50.11788760900107,26.991990493578026 +2.575713827835502,0.06074189800573748,0.13939833856790468,178616507363.1539,571.5920948948395,0.008467319663460928,1.3711340152901193e-05,-0.0013294018832493678,7483961.0802418385,171.20372988375613,0.759875607403651 +2.3127451009760245,0.03796653861409344,0.12617502498012312,193413776489.3423,1101.938323212827,0.004790428958042049,6.355357079950439e-06,-0.003696510805289008,25298134.89069752,86.97047266864062,4.073326918518267 +1.0867103616976994,0.058812886692577795,0.07546259379684746,112590649803.91116,1594.1365388368088,0.004438172978502014,2.106136119624612e-06,-0.0028757883752170105,31035205.190956067,37.8606172175473,4.584399326895575 +2.1545894431208374,0.04435398512393907,0.13450475818736907,114782616266.9025,1729.1938392131376,0.00596582204374159,8.99423736084342e-06,-0.0055843874647924854,27858101.40911099,100.9030929806182,9.656488399898238 +2.9161579355363765,0.047608153993703106,0.06288634706975409,185042648477.68683,564.93738666509,0.0029939028953983125,9.866638140493067e-07,-0.025578268905592966,52501115.328370355,68.53594544013282,14.450120390942622 +2.000970817284346,0.03692262640850094,0.10948735191872908,155690935171.92496,1166.5925641960014,0.004042560591351303,4.038342930675903e-06,-0.004955114455666087,31643952.152809307,63.49900929762199,5.780599678720175 +2.5257575434441066,0.049619483679336954,0.15926963098288882,128319429680.0518,347.56102305797657,0.007902876855169471,1.670590149549538e-05,-0.0008708080825570729,4184617.698189847,156.69189403005493,0.30265894806069116 +1.8742592357417815,0.06944088769281627,0.0986166055119026,165387780700.4831,1036.5394879150635,0.006848024627998794,5.549887332477966e-06,-0.002478369121151686,17260421.557063296,100.75454123406925,2.5689274597030747 +1.2481383635438636,0.07808945345119186,0.04746855694708957,209349288623.42667,1479.3639341378,0.003706793668115001,6.96032029338957e-07,-0.006580232727711145,62962877.45763502,36.318742355889135,9.734558975609067 +1.275326027497872,0.0321316650017885,0.1304934908462004,175661232869.35196,1412.3338300614255,0.004192973132784065,5.950021456310129e-06,-0.0009342977827756744,19751446.500165913,41.97715098538465,1.3195403659654659 +2.9333622363830667,0.07107695027394666,0.05409851593936968,158363799031.54465,1518.188155176256,0.0038451575273168895,9.377856727866733e-07,-0.08600860998612192,128452646.89814313,88.54203308606732,130.57725292410456 +1.3703702447732584,0.027947534902596813,0.07398694652962075,179263668998.52936,109.23131917603185,0.00206775277047314,9.432516503091359e-07,-0.0005541404200699495,5870601.936981746,22.243656931100304,0.060529489093001015 +1.1567270365111966,0.06386407424978399,0.10457363801910008,171509667256.70508,1405.6795964765386,0.0066784985830218415,6.086141230807372e-06,-0.0006947476967621571,13969067.724642783,60.64281901312218,0.9765926620376335 +2.950898911344147,0.0774297823386892,0.05496187934167775,211191670593.61926,178.12924338747985,0.004255686354351407,1.0713010128343616e-06,-0.006743551272841987,13483716.681648755,98.58108680611,1.20122368597602 +1.2245838548143226,0.046656130713799045,0.14458165377891735,214231300322.82773,1931.3916143840818,0.006745620537526405,1.175078924724582e-05,-0.00046963960449313805,14550403.131653015,64.84553730752617,0.9070579939007035 +2.654042778904257,0.06908777372321699,0.15664819627399507,177931027615.85968,1216.535491985191,0.010822475138327854,2.2130750799585856e-05,-0.0019252159470979626,11426992.90055299,225.47799912738665,2.342093529380555 +1.341647441716586,0.06518563156775864,0.1276817747379519,199710785525.73175,1296.2575257759631,0.008323017125985684,1.1307259608286994e-05,-0.00046208979063604963,9819090.191774791,87.65745388036989,0.5989873686962185 +2.119507188432695,0.0445034505665908,0.10768973330179513,169075513542.73682,441.7098327760789,0.004792564722525787,4.63164583863495e-06,-0.0017902118817806182,10883809.28827098,79.73932173631543,0.7907541909350664 +1.9833354161451644,0.026723614080772236,0.09760623526288784,164792672870.41846,1005.0305193964633,0.002608391363042477,2.070840412147525e-06,-0.007658821840670438,46976034.399680264,40.61052251049103,7.6973496924939875 +2.9830555649770574,0.07432930167586123,0.043372498172153065,186610332176.64044,933.5025178522313,0.003223847501073705,5.053847335008139e-07,-0.08758313029815197,119492090.63789581,75.49279239541507,81.75907265470491 +2.2059194362242263,0.06750011366567416,0.05817678090920038,209145047096.00708,1830.4582337522565,0.003926939324074048,1.1075728938136135e-06,-0.028274023080775923,106046623.13896349,68.00071747180812,51.75441834950763 +2.372138401379674,0.04908727021159006,0.13277350189106182,216988375018.40353,834.7645356514713,0.006517488764265615,9.574627017102846e-06,-0.0017877404859739238,13729779.534080055,121.36402521945894,1.492342356639358 +2.12015487262597,0.03674782348618326,0.14563549833092412,129541030934.79411,1470.121780419921,0.005351787585987137,9.45915003841848e-06,-0.003811319465878837,23994186.74255478,89.07095544236498,5.603103758926898 +2.016354373847353,0.06773755385580861,0.0776701506922517,136685689093.0688,542.9227248488031,0.005261186015505169,2.644908830182127e-06,-0.004103775526658433,16073791.377157208,83.27606115680874,2.2280329911012284 +2.6656097913052337,0.040681731393672725,0.04307193176899242,143020562662.46283,1208.9931467032854,0.0017522407588327486,2.7089515186277925e-07,-0.19701196119820402,256202601.8744024,36.66570246922919,238.18611090720225 +2.7834542390347785,0.026360463582715998,0.14929065592923285,152346166625.45764,240.32891356571506,0.003935370898862327,7.30919714808926e-06,-0.001551442980384774,6831609.964977957,85.98830976330774,0.3728566059350277 +1.2116712982771045,0.07911760326114853,0.11039028427685474,122653054422.75237,942.102232455435,0.008733814715301595,8.86919966074582e-06,-0.0005135330986130388,7103939.887531149,83.07272402775914,0.4838006786431009 +1.3743417983180422,0.07603784896307911,0.05026209108819763,130676803187.83884,1976.5708030753901,0.003821821290732896,8.045818570399575e-07,-0.016266969392967665,84849141.58795275,41.23203665261483,32.15281675666089 +2.0690065573514795,0.02248557684543056,0.14406425226894867,151244101150.64072,341.9052137577071,0.003239367815072939,5.602623980454012e-06,-0.0011912424166293971,9094992.56856866,52.61284502081509,0.4072919930949216 +2.6751069756974353,0.06320983032140148,0.09257444072869406,100880770512.19016,362.8125614439693,0.00585161469055939,4.1790413614801725e-06,-0.00549160714740934,10749986.04889828,122.88150793080075,1.992424055595592 +2.161070148505975,0.05567257776565458,0.09899735765114717,200734643086.90546,831.3373741828162,0.005511438092427811,4.5012267733521605e-06,-0.0030953475561482768,19756448.814332534,93.49824404454299,2.573278109511506 +1.9431887660878542,0.058471811981890304,0.10969641005462585,212336367484.17975,1817.640943138909,0.006414147863802424,6.431948395661203e-06,-0.0032551040880256102,30119166.95645154,97.84161557279313,5.916610464574188 diff --git a/FESurrogateModelTutorial/data/reference/beam2d_lhs_300_metadata.json b/FESurrogateModelTutorial/data/reference/beam2d_lhs_300_metadata.json new file mode 100644 index 0000000..5a6da1b --- /dev/null +++ b/FESurrogateModelTutorial/data/reference/beam2d_lhs_300_metadata.json @@ -0,0 +1,36 @@ +{ + "dataset_name": "beam2d_lhs_300", + "sample_count": 300, + "random_seed": 20260521, + "unit_system": "SI", + "fea_model": "2D Euler-Bernoulli beam/frame, linear static", + "target_columns": [ + "tip_uy_m", + "max_abs_bending_stress_pa", + "mass_kg", + "compliance_j" + ], + "parameter_bounds": { + "L_m": { + "lower": 1.0, + "upper": 3.0 + }, + "b_m": { + "lower": 0.02, + "upper": 0.08 + }, + "h_m": { + "lower": 0.04, + "upper": 0.16 + }, + "E_pa": { + "lower": 100000000000.0, + "upper": 220000000000.0 + }, + "P_n": { + "lower": 100.0, + "upper": 2000.0 + } + }, + "notes": "Generated by notebooks/00_beam2d_fea_dataset.ipynb using src/femsurrogate." +} \ No newline at end of file diff --git a/FESurrogateModelTutorial/docs/ADR.md b/FESurrogateModelTutorial/docs/ADR.md new file mode 100644 index 0000000..189f810 --- /dev/null +++ b/FESurrogateModelTutorial/docs/ADR.md @@ -0,0 +1,76 @@ +# Architecture Decision Records + +## 철학 +이 프로젝트는 연구용 개념 전달과 재현성을 우선한다. 구현은 작고 명시적이어야 하며, notebook 교육 흐름과 테스트 가능한 Python 모듈 사이의 경계를 분명히 둔다. + +--- + +## ADR-001: Python tutorial project로 구성 +**결정**: Python `>=3.12,<3.15` 기반의 문서 + notebook + src package 구조를 사용한다. + +**이유**: 대상 사용자는 FEM/CAE 연구자이며 Python scientific stack에 익숙하다. NumPy, SciPy, scikit-learn, pandas, matplotlib로 FEM 데이터 생성과 surrogate 모델링을 모두 재현할 수 있다. + +**트레이드오프**: 브라우저 대시보드 기반 상호작용은 제공하지 않는다. 시각적 결과는 notebook과 저장된 figure로 제한한다. + +--- + +## ADR-002: `uv`와 `pyproject.toml` 사용 +**결정**: 의존성 관리는 `uv`, 프로젝트 설정은 `pyproject.toml`, lock은 `uv.lock`으로 관리한다. + +**이유**: 튜토리얼 재현성을 높이고, pytest/ruff/jupyter 실행 명령을 하나의 환경에서 고정하기 쉽다. + +**트레이드오프**: conda 기반 연구실 환경보다 초기 학습 비용이 있을 수 있다. 대신 repository-local workflow가 단순해진다. + +--- + +## ADR-003: 자체 2D Euler-Bernoulli beam/frame solver 사용 +**결정**: FEM 데이터는 NumPy/SciPy로 구현한 2-node 2D Euler-Bernoulli beam/frame element에서 생성한다. + +**이유**: 외부 CAE solver 없이 해석 데이터 생성 과정을 완전히 설명할 수 있다. 요소 강성, 조립, 경계조건, 응답 계산이 surrogate 학습 데이터와 직접 연결된다. + +**트레이드오프**: 산업용 고충실도 해석과 차이가 있다. v1은 선형 정적, slender beam 가정에 제한된다. + +--- + +## ADR-004: Notebook은 orchestration layer로 제한 +**결정**: 핵심 계산과 학습 helper는 `src/femsurrogate/`에 두고 notebook은 설명, 호출, 시각화, 해석을 담당한다. + +**이유**: notebook hidden state 문제를 줄이고, pytest로 핵심 로직을 검증할 수 있다. 모델별 notebook도 같은 helper를 사용하므로 비교 조건이 일관된다. + +**트레이드오프**: 독자가 처음 볼 파일 수는 늘어난다. 대신 코드 재사용성과 검증 가능성이 높아진다. + +--- + +## ADR-005: scikit-learn 중심 surrogate 모델 +**결정**: Response Surface, Gaussian Process/Kriging, Random Forest, Gradient Boosting, MLP를 모두 scikit-learn API로 구현한다. + +**이유**: 공통 `fit/predict` 인터페이스를 사용하면 모델별 비교가 단순하다. 연구자에게 익숙하고 설치 부담이 낮다. + +**트레이드오프**: PyTorch 기반 deep learning, GPU 학습, 복잡한 Bayesian optimization framework는 제외한다. + +--- + +## ADR-006: 기준 데이터셋은 CSV + metadata JSON +**결정**: 기준 FEM 데이터는 CSV로 저장하고, 생성 조건은 JSON metadata로 별도 저장한다. + +**이유**: CSV는 notebook, pandas, spreadsheet, 다른 ML 도구에서 쉽게 읽을 수 있다. Metadata JSON은 seed, bounds, 단위, target 정보를 명확히 남긴다. + +**트레이드오프**: 대용량/버전관리형 데이터셋에는 Parquet, DVC, database가 더 적합할 수 있다. v1에서는 단순성과 가독성을 우선한다. + +--- + +## ADR-007: 모델별 이론 문서와 모델별 notebook 분리 +**결정**: 각 surrogate 모델은 별도 이론 문서와 별도 실습 notebook으로 구성한다. 최종 비교는 별도 notebook에서 수행한다. + +**이유**: 모델별 가정, 장점, 실패 모드, hyperparameter가 다르므로 독립적으로 학습하는 편이 좋다. 최종 비교 notebook은 같은 입력 데이터와 metric을 기준으로 모델 선택을 돕는다. + +**트레이드오프**: notebook 수가 늘어난다. 대신 각 notebook의 목표가 분명하고 실행 실패 범위가 작아진다. + +--- + +## ADR-008: Notebook 중심 범위 고정 +**결정**: 브라우저 앱과 디자인 시스템 계획을 프로젝트 범위에서 제외한다. + +**이유**: 튜토리얼은 notebook 기반이다. 브라우저 앱 설계 지침은 현재 목표에 직접 기여하지 않으며 미래 agent에게 잘못된 구현 방향을 줄 수 있다. + +**트레이드오프**: 웹 기반 인터랙티브 학습 환경은 제공하지 않는다. diff --git a/FESurrogateModelTutorial/docs/ARCHITECTURE.md b/FESurrogateModelTutorial/docs/ARCHITECTURE.md new file mode 100644 index 0000000..dbabc69 --- /dev/null +++ b/FESurrogateModelTutorial/docs/ARCHITECTURE.md @@ -0,0 +1,226 @@ +# 아키텍처 + +## 개요 +이 프로젝트는 문서와 Jupyter notebook이 중심인 교육용 Python 프로젝트다. 재사용 가능한 계산 로직은 `src/femsurrogate/`에 모듈화하고, notebook은 설명, 시각화, 실행 순서, 결과 해석을 담당한다. + +## 기술 스택 +- Python `>=3.12,<3.15` +- `uv` + `pyproject.toml` + `uv.lock` +- NumPy, SciPy +- pandas, matplotlib +- scikit-learn +- JupyterLab, ipykernel, nbconvert +- pytest, ruff +- joblib, CSV, JSON + +## 디렉토리 구조 +```text +docs/ + PRD.md + ARCHITECTURE.md + ADR.md + theory/ + 00_surrogate_modeling_for_fem.md + 01_doe_sampling_validation.md + 02_response_surface_methodology.md + 03_gaussian_process_kriging.md + 04_random_forest.md + 05_gradient_boosting.md + 06_mlp_neural_network.md + +BeamExamples/ + CantileverBeam.txt + CantileverBeam_Displacements.txt + +notebooks/ + 00_beam2d_fea_dataset.ipynb + 01_response_surface_surrogate.ipynb + 02_gaussian_process_kriging_surrogate.ipynb + 03_random_forest_surrogate.ipynb + 04_gradient_boosting_surrogate.ipynb + 05_mlp_surrogate.ipynb + 06_compare_surrogate_models.ipynb + +src/femsurrogate/ + fea/ + element.py + model.py + io.py + assembly.py + solver.py + responses.py + benchmark.py + data/ + bounds.py + sampling.py + dataset.py + schema.py + surrogates/ + common.py + rsm.py + gpr.py + random_forest.py + boosting.py + mlp.py + registry.py + plotting/ + diagnostics.py + comparison.py + +tests/ +data/ + reference/ + processed/ +reports/ + results/ + predictions/ + figures/ +``` + +## 핵심 모듈 책임 +### `femsurrogate.fea` +2D Euler-Bernoulli beam/frame 요소 기반 선형 정적 해석을 담당한다. + +- `element.py`: local 6x6 stiffness matrix와 좌표 변환 행렬. +- `model.py`: node, element, support, load, material, section, parameter dataclass. +- `io.py`: `BeamExamples/*.txt`의 간단한 텍스트 fixture parser. +- `assembly.py`: global sparse stiffness matrix 조립. +- `solver.py`: 경계조건 적용과 `K u = f` 풀이. +- `responses.py`: tip displacement, bending stress, mass, compliance 계산. +- `benchmark.py`: cantilever analytical solution 등 검증 helper. + +### `femsurrogate.data` +입력 공간 정의, 샘플링, batch 해석, dataset schema를 담당한다. + +- `bounds.py`: 설계변수 범위와 단위. +- `sampling.py`: Latin Hypercube Sampling. +- `dataset.py`: 샘플별 FEM 실행과 CSV/metadata 저장. +- `schema.py`: 컬럼명, target명, 단위, split seed. + +### `femsurrogate.surrogates` +scikit-learn 기반 모델 생성, 학습, 평가를 담당한다. + +- `common.py`: train/test split, scaling, metric, timing, JSON 저장. +- `rsm.py`: `PolynomialFeatures` + `Ridge`. +- `gpr.py`: `GaussianProcessRegressor`. +- `random_forest.py`: `RandomForestRegressor`. +- `boosting.py`: `GradientBoostingRegressor`. +- `mlp.py`: `MLPRegressor`. +- `registry.py`: notebook에서 모델명을 통해 builder를 가져오는 작은 registry. + +### `femsurrogate.plotting` +모델 진단과 최종 비교 그림을 담당한다. + +- `diagnostics.py`: parity plot, residual plot, error histogram. +- `comparison.py`: 모델별 metric table, bar plot, prediction-time comparison. + +## 주요 인터페이스 +```python +def run_beam2d_case(params: BeamParameters) -> AnalysisResult: + ... + +def generate_lhs_samples(bounds: ParameterBounds, n: int, seed: int) -> pd.DataFrame: + ... + +def build_dataset(samples: pd.DataFrame) -> pd.DataFrame: + ... + +def make_model(model_name: str, random_state: int): + ... + +def evaluate_model(model, X_train, X_test, y_train, y_test) -> MetricsReport: + ... +``` + +## 데이터 흐름 +```text +Parameter bounds + -> Latin Hypercube samples + -> Beam2D FEM batch analysis + -> data/reference/beam2d_lhs_300.csv + -> model-specific notebooks + -> reports/results/_metrics.json + -> reports/predictions/_predictions.csv + -> notebooks/06_compare_surrogate_models.ipynb +``` + +## FEM 해석 설계 +- 요소: 2-node 2D Euler-Bernoulli frame element. +- 노드 DOF: `[ux, uy, rz]`. +- Local stiffness matrix: axial `EA/L` 항과 bending `EI` 항을 포함한 6x6 matrix. +- Global assembly: sparse matrix 기반. +- Solver: constrained DOF 제거 후 `scipy.sparse.linalg.spsolve`. +- 기준 검증: cantilever tip displacement `P L^3 / (3 E I)`. + +## Solver Verification Fixture +`BeamExamples/`의 cantilever 예제는 solver 구현의 canonical regression fixture다. + +```text +BeamExamples/CantileverBeam.txt +BeamExamples/CantileverBeam_Displacements.txt +``` + +입력 파일은 다음 항목을 포함한다. + +- Section/material metadata: `Area`, `J`, `Iyy`, `Izz`, `ElasticModulus`, `Poisson'sRatio`. +- Geometry: `Node, NodeID, X, Y`. +- Connectivity: `Beam, BeamID, NodeID1, NodeID2`. +- Boundary condition: `Fix, NodeID`. +- Load: `NodeLoad, NodeID, Fx, Fy, Mz`. + +2D in-plane Euler-Bernoulli frame solver는 `Area`, `Izz`, `ElasticModulus`, node coordinates, beam connectivity, fixed nodes, nodal loads를 사용한다. `J`, `Iyy`, `Poisson'sRatio`는 fixture metadata로 보존하되 v1 해석에는 사용하지 않는다. + +기준 변위 파일은 다음 형식을 가진다. + +```text +# NodeID, Ux, Uy, Rz +1 0.000000, 0.000000, 0.000000 +... +``` + +검증 test는 solver 결과의 모든 node별 `[Ux, Uy, Rz]`를 기준 파일과 비교한다. 기준 파일 값은 소수점 6자리로 반올림되어 있으므로 기본 허용오차는 `atol=5e-7`, `rtol=1e-6`로 둔다. Tip displacement는 별도로 해석해 `P L^3 / (3 E I)`와 비교해 부호와 크기를 확인한다. + +## Dataset Schema +기본 dataset은 SI 단위 컬럼을 사용한다. + +```text +L_m +b_m +h_m +E_pa +P_n +A_m2 +I_m4 +tip_uy_m +max_abs_bending_stress_pa +mass_kg +compliance_j +``` + +Metadata JSON에는 다음을 포함한다. + +```text +dataset_name +created_by +sample_count +random_seed +parameter_bounds +target_columns +unit_system +fea_model +notes +``` + +## Notebook 책임 +- Notebook은 한 번에 위에서 아래로 실행 가능해야 한다. +- Notebook 셀에 핵심 FEM 또는 ML helper 구현을 길게 두지 않는다. +- 각 모델별 notebook은 같은 dataset, target, split seed를 사용한다. +- 각 모델별 notebook은 metric JSON과 prediction CSV를 저장한다. +- 최종 비교 notebook은 이전 notebook 결과물을 읽어 비교만 수행한다. + +## 검증 전략 +- Unit tests: FEM element, solver, dataset generation, model factory. +- Regression tests: `BeamExamples/CantileverBeam.txt`를 해석하고 `BeamExamples/CantileverBeam_Displacements.txt`와 비교. +- Integration tests: 작은 sample count로 dataset 생성과 모든 surrogate smoke test. +- Notebook tests: `nbconvert --execute`로 순차 실행. +- Documentation checks: 문서의 경로와 notebook/file 이름이 실제 구조와 일치하는지 검토. diff --git a/FESurrogateModelTutorial/docs/PRD.md b/FESurrogateModelTutorial/docs/PRD.md new file mode 100644 index 0000000..ff23e8f --- /dev/null +++ b/FESurrogateModelTutorial/docs/PRD.md @@ -0,0 +1,60 @@ +# PRD: FEM Surrogate Tutorial + +## 목표 +FEM 기반 구조해석 데이터로 surrogate model을 구축하고 검증하는 전체 절차를 학습할 수 있는 한국어 튜토리얼을 만든다. 독자는 2D beam 요소로 해석 데이터를 직접 생성하고, 여러 surrogate 모델을 같은 데이터셋에서 학습, 평가, 비교한다. + +## 사용자 +- FEM과 선형 정적 구조해석의 기본 개념을 아는 대학원생. +- CAE 해석 결과를 기계학습 모델로 근사하고 싶은 연구자. +- surrogate 기반 설계 탐색, 민감도 분석, 최적화의 입문 파이프라인을 재현하고 싶은 엔지니어. + +## 사용자 문제 +고정밀 구조해석은 반복 설계, 불확실성 분석, 최적화에서 계산 비용이 커진다. Surrogate model은 해석 데이터에서 입력 변수와 응답의 관계를 학습하여 빠른 근사 예측을 제공하지만, 모델별 가정, 데이터 설계, 검증 방법, 외삽 위험을 함께 이해해야 실무적으로 사용할 수 있다. + +## 학습 성과 +튜토리얼을 완료한 독자는 다음을 할 수 있어야 한다. + +1. 2D Euler-Bernoulli beam/frame 요소를 이용해 선형 정적 FEM 해석 데이터를 생성한다. +2. DOE와 Latin Hypercube Sampling으로 입력 공간을 정의하고 해석 케이스를 만든다. +3. Response Surface, Gaussian Process/Kriging, Random Forest, Gradient Boosting, MLP를 같은 데이터셋에 적용한다. +4. RMSE, MAE, R2, residual, parity plot, uncertainty 또는 feature importance로 모델을 진단한다. +5. 최종 비교표를 통해 구조해석 surrogate 문제에 맞는 모델을 선택하는 기준을 설명한다. + +## 핵심 산출물 +- `docs/theory/`: surrogate 모델별 이론 문서와 출처. +- `notebooks/`: 데이터 생성, 모델별 학습, 최종 비교 notebook. +- `src/femsurrogate/`: notebook에서 재사용하는 FEM, 데이터, 모델, plotting helper. +- `tests/`: FEM 공식 검증, dataset schema, surrogate pipeline smoke test. +- `BeamExamples/`: 2D beam solver 검증용 cantilever 예제와 기준 변위 파일. +- `data/reference/`: 재현 가능한 기준 해석 데이터. +- `reports/`: 모델별 metric, 예측값, 그림. + +## MVP 범위 +- 선형 정적 2D Euler-Bernoulli beam/frame 요소. +- 기준 구조: fixed-free cantilever beam 또는 간단한 planar frame. +- Solver 검증 기준 fixture: `BeamExamples/CantileverBeam.txt`와 `BeamExamples/CantileverBeam_Displacements.txt`. +- 입력 변수: `L`, `b`, `h`, `E`, `P`. +- 응답 변수: `tip_uy_m`, `max_abs_bending_stress_pa`, `mass_kg`, `compliance_j`. +- Surrogate 모델: + - Response Surface Methodology: polynomial features + Ridge regression. + - Gaussian Process Regression/Kriging. + - Random Forest Regressor. + - Gradient Boosting Regressor. + - Multi-layer Perceptron Regressor. + +## MVP 제외 사항 +- 상용 CAE 연동. +- 3D beam, shell, solid element. +- Timoshenko beam, geometric nonlinearity, material nonlinearity, contact, buckling, modal, transient analysis. +- PyTorch/TensorFlow 기반 deep learning framework. +- Bayesian optimization, active learning, MLflow, DVC, browser dashboard. +- 배포용 Python package publishing. + +## 성공 기준 +- 이론 문서가 모델별로 분리되어 있고 각 문서에 출처가 있다. +- FEM solver가 `BeamExamples/CantileverBeam.txt`를 해석했을 때 `BeamExamples/CantileverBeam_Displacements.txt`의 모든 노드 `Ux`, `Uy`, `Rz` 기준값과 허용오차 내에서 일치한다. +- `00_beam2d_fea_dataset.ipynb`가 데이터셋을 생성하고, 생성 데이터가 동일 seed에서 재현된다. +- 모든 모델별 notebook이 같은 dataset과 split을 사용한다. +- 최종 비교 notebook이 모든 모델의 metric JSON을 읽어 하나의 비교표와 그림을 만든다. +- FEM solver는 cantilever beam 해석해와 BeamExamples regression fixture를 모두 비교하는 pytest를 통과한다. +- 전체 notebook은 `nbconvert --execute`로 순서대로 실행 가능하다. diff --git a/FESurrogateModelTutorial/docs/theory/00_surrogate_modeling_for_fem.md b/FESurrogateModelTutorial/docs/theory/00_surrogate_modeling_for_fem.md new file mode 100644 index 0000000..34d7c52 --- /dev/null +++ b/FESurrogateModelTutorial/docs/theory/00_surrogate_modeling_for_fem.md @@ -0,0 +1,98 @@ +# FEM 구조해석을 위한 Surrogate Modeling 개요 + +## 목적 +Surrogate model은 계산 비용이 큰 해석 모델을 반복 호출하기 어려울 때, 입력 변수와 출력 응답 사이의 관계를 데이터 기반으로 근사하는 모델이다. FEM 구조해석에서는 설계변수 변화에 따른 변위, 응력, 질량, compliance 같은 응답을 빠르게 예측하기 위해 사용한다. + +이 튜토리얼의 surrogate는 고충실도 산업용 solver를 대체하는 범용 도구가 아니라, 제한된 입력 범위 안에서 반복 설계 탐색과 모델 비교를 학습하기 위한 교육용 근사 모델이다. + +## 문제 정의 +FEM 해석 모델을 다음 함수로 본다. + +```text +y = f(x) +``` + +- `x`: 설계변수 벡터. 예: beam 길이 `L`, 폭 `b`, 높이 `h`, 탄성계수 `E`, 하중 `P`. +- `f`: FEM solver. 이 튜토리얼에서는 2D Euler-Bernoulli beam/frame solver. +- `y`: 응답. 예: tip displacement, maximum bending stress, mass, compliance. + +Surrogate model은 해석 데이터 `{x_i, y_i}`를 이용해 `f`를 근사하는 `\hat{f}`를 만든다. + +```text +\hat{y} = \hat{f}(x) +``` + +좋은 surrogate는 빠른 예측뿐 아니라, 어떤 영역에서 믿을 수 있고 어떤 영역에서 위험한지도 설명할 수 있어야 한다. + +## 왜 FEM에서 필요한가 +구조해석에서는 다음 작업이 반복 평가를 요구한다. + +- 설계변수 sweep. +- 민감도 분석. +- 최적화. +- 불확실성 전파. +- 신뢰성 분석. +- inverse problem 또는 model calibration. + +Queipo et al.은 surrogate-based analysis and optimization이 비싼 high-fidelity model의 계산 부담을 줄이고 민감도/최적화 연구를 가능하게 한다고 정리한다. Forrester와 Keane도 긴 계산 시간이 필요한 aerospace design evaluation에서 surrogate 기반 방법이 효율적 최적화를 가능하게 하는 배경을 설명한다. + +## 전체 workflow +```text +1. 해석 문제 정의 +2. 입력 변수와 범위 설정 +3. DOE로 샘플 생성 +4. FEM batch 해석 +5. 데이터 정리와 train/test split +6. surrogate 모델 학습 +7. 검증과 진단 +8. 모델 비교 +9. 설계 탐색 또는 최적화에 활용 +``` + +이 workflow에서 가장 중요한 판단은 데이터의 범위다. Surrogate는 학습한 입력 영역 안에서만 신뢰할 수 있다. 학습 범위를 벗어난 외삽은 모델별로 다르게 실패하며, 예측값이 그럴듯해 보여도 구조적으로 틀릴 수 있다. + +## 이 튜토리얼의 FEM 모델 +기준 해석 모델은 2D Euler-Bernoulli beam/frame element이다. + +- 노드당 자유도: `ux`, `uy`, `rz`. +- 요소: 축방향 변형과 굽힘 변형을 포함한 2-node frame element. +- 해석: 선형 정적 해석. +- solver: sparse global stiffness matrix를 조립하고 `scipy.sparse.linalg.spsolve`로 선형 시스템을 푼다. +- 검증: cantilever beam tip displacement 해석해 `P L^3 / (3 E I)`와 비교한다. + +이 선택은 학습 목적에 맞다. Beam 요소는 수식이 충분히 작아 직접 구현할 수 있고, 단면 형상과 하중 변화가 변위/응력에 비선형적인 영향을 주므로 surrogate 비교에도 적합하다. + +## 모델 비교 관점 +이 튜토리얼은 다음 질문에 답하도록 설계한다. + +| 모델 | 핵심 질문 | +| --- | --- | +| Response Surface | 낮은 차수 다항식으로 구조 응답을 충분히 설명할 수 있는가? | +| Gaussian Process/Kriging | 적은 데이터에서 예측 불확실성을 함께 얻을 수 있는가? | +| Random Forest | 비선형성과 변수 상호작용을 튼튼하게 포착하는가? | +| Gradient Boosting | 작은 tree를 순차적으로 더해 높은 정확도를 얻는가? | +| MLP | scaling과 충분한 데이터가 있을 때 매끄러운 비선형 근사가 가능한가? | + +## 검증 원칙 +Surrogate 검증은 단순히 test R2 하나로 끝내지 않는다. + +- Train/test split은 고정 seed로 재현한다. +- K-fold cross validation으로 표본 의존성을 확인한다. +- RMSE, MAE, R2를 함께 본다. +- Parity plot으로 편향과 outlier를 본다. +- Residual plot으로 입력 영역별 오류 구조를 본다. +- 모델별 uncertainty 또는 feature importance를 해석한다. +- 해석 데이터의 물리 단위와 target 정의를 metadata에 남긴다. + +## 실패 모드 +- 학습 영역 밖에서 외삽한다. +- 입력 변수 범위가 물리적으로 의미 없는 조합을 포함한다. +- 응력처럼 국소적이고 비선형적인 응답을 너무 단순한 모델로 근사한다. +- train/test split이 샘플링 편향을 숨긴다. +- feature scaling을 하지 않아 MLP나 GPR 학습이 불안정하다. +- 예측 정확도만 보고 물리 제약을 확인하지 않는다. + +## References +- Queipo, N. V. et al. (2005), "Surrogate-based analysis and optimization", Progress in Aerospace Sciences. https://doi.org/10.1016/j.paerosci.2005.02.001 +- Forrester, A. I. J. and Keane, A. J. (2009), "Recent advances in surrogate-based optimization", Progress in Aerospace Sciences. https://doi.org/10.1016/j.paerosci.2008.11.001 +- SciPy `spsolve` documentation. https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.linalg.spsolve.html diff --git a/FESurrogateModelTutorial/docs/theory/01_doe_sampling_validation.md b/FESurrogateModelTutorial/docs/theory/01_doe_sampling_validation.md new file mode 100644 index 0000000..9ec8560 --- /dev/null +++ b/FESurrogateModelTutorial/docs/theory/01_doe_sampling_validation.md @@ -0,0 +1,114 @@ +# DOE, Sampling, Validation + +## 목적 +Surrogate model의 품질은 모델 종류만큼이나 데이터 설계에 좌우된다. FEM surrogate에서는 입력 변수 범위, 샘플링 방법, train/test split, 검증 지표가 모두 모델 해석에 영향을 준다. + +## 입력 공간 정의 +이 튜토리얼의 기본 입력 변수는 다음과 같다. + +| 변수 | 의미 | 단위 | 예시 범위 | +| --- | --- | --- | --- | +| `L_m` | beam length | m | 1.0-3.0 | +| `b_m` | rectangular section width | m | 0.02-0.08 | +| `h_m` | rectangular section height | m | 0.04-0.16 | +| `E_pa` | Young's modulus | Pa | 100e9-220e9 | +| `P_n` | tip point load magnitude | N | 100-2000 | + +파생 변수는 FEM 해석 직전에 계산한다. + +```text +A = b h +I = b h^3 / 12 +``` + +`h`는 bending stiffness에 세제곱으로 들어가므로, tip displacement와 bending stress에 큰 영향을 준다. 이런 구조적 비선형성 때문에 단순 선형 회귀보다 다양한 surrogate 비교가 의미를 가진다. + +## Latin Hypercube Sampling +Latin Hypercube Sampling(LHS)은 각 입력 변수의 marginal distribution을 층화하여, 적은 샘플에서도 각 변수 범위를 비교적 고르게 덮도록 설계한다. McKay, Beckman, Conover의 1979년 논문은 computer code output 분석에서 sampling plan을 비교한 고전적 출처다. + +SciPy의 `scipy.stats.qmc.LatinHypercube`는 `[0, 1)^d` 단위 hypercube에 샘플을 만들고, 이후 사용자가 물리 범위로 scaling한다. + +```text +u ~ LHS([0,1)^d) +x_j = lower_j + u_j (upper_j - lower_j) +``` + +이 튜토리얼은 다음을 기본값으로 사용한다. + +- `n_samples = 300` +- `seed = 20260521` +- `target = tip_uy_m` +- 동일 dataset과 동일 split을 모든 model notebook에서 사용 + +## Train/Test Split +단일 test set만으로 모델을 판단하면 샘플 배치에 민감할 수 있다. 따라서 다음 두 가지를 함께 사용한다. + +- Hold-out test set: 최종 성능 비교용. +- K-fold cross validation: 학습 데이터 안에서 모델 안정성 확인용. + +추천 기본값: + +```text +test_size = 0.2 +cv_folds = 5 +random_state = 20260521 +``` + +## 평가 지표 +### RMSE +큰 오차에 민감하다. 구조해석 surrogate에서 위험한 outlier를 확인하는 데 유용하다. + +```text +RMSE = sqrt(mean((y - y_hat)^2)) +``` + +### MAE +평균적인 절대 오차를 직관적으로 보여준다. + +```text +MAE = mean(abs(y - y_hat)) +``` + +### R2 +분산 설명력을 나타낸다. 다만 target scale이나 test set 분포에 따라 해석이 왜곡될 수 있으므로 RMSE/MAE와 함께 본다. + +```text +R2 = 1 - sum((y - y_hat)^2) / sum((y - mean(y))^2) +``` + +## Plot 기반 진단 +- Parity plot: 예측값과 실제값이 `y=x` 선 주변에 있는지 확인. +- Residual plot: 예측값 또는 주요 입력 변수에 따른 오차 패턴 확인. +- Error histogram: 오차 분포와 outlier 확인. +- Model comparison bar plot: RMSE, MAE, R2, 학습 시간, 예측 시간 비교. + +## Dataset Metadata +CSV만으로는 dataset의 생성 조건을 알기 어렵다. 따라서 metadata JSON을 함께 저장한다. + +```json +{ + "dataset_name": "beam2d_lhs_300", + "sample_count": 300, + "random_seed": 20260521, + "unit_system": "SI", + "fea_model": "2D Euler-Bernoulli beam/frame, linear static", + "target_columns": [ + "tip_uy_m", + "max_abs_bending_stress_pa", + "mass_kg", + "compliance_j" + ] +} +``` + +## 주의점 +- DOE 범위는 surrogate의 유효 영역이다. 범위 밖 예측은 별도 경고를 둔다. +- 물리적으로 불가능한 조합을 허용하지 않는다. +- FEM solver 실패 케이스는 조용히 버리지 말고 metadata에 기록한다. +- 단위가 섞이면 모델 비교가 무의미해진다. +- 동일 데이터셋을 쓰지 않으면 모델별 비교가 공정하지 않다. + +## References +- McKay, M. D., Beckman, R. J., and Conover, W. J. (1979), "Comparison of Three Methods for Selecting Values of Input Variables in the Analysis of Output from a Computer Code", Technometrics. https://doi.org/10.1080/00401706.1979.10489755 +- OSTI bibliographic record for McKay et al. https://www.osti.gov/biblio/5236110 +- SciPy `LatinHypercube` documentation. https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.qmc.LatinHypercube.html diff --git a/FESurrogateModelTutorial/docs/theory/02_response_surface_methodology.md b/FESurrogateModelTutorial/docs/theory/02_response_surface_methodology.md new file mode 100644 index 0000000..387a050 --- /dev/null +++ b/FESurrogateModelTutorial/docs/theory/02_response_surface_methodology.md @@ -0,0 +1,77 @@ +# Response Surface Methodology + +## 핵심 아이디어 +Response Surface Methodology(RSM)는 입력 변수와 응답 사이의 관계를 낮은 차수 다항식으로 근사한다. 구조해석 surrogate에서는 물리 응답이 충분히 매끄럽고 입력 범위가 좁을 때 강력한 기준선이 된다. + +기본 2차 response surface는 다음 형태다. + +```text +y = beta_0 + sum beta_i x_i + sum beta_ii x_i^2 + sum beta_ij x_i x_j + epsilon +``` + +- `x_i`: scaling된 설계변수. +- `beta`: 회귀 계수. +- `x_i x_j`: 변수 상호작용. +- `epsilon`: 모델이 설명하지 못한 잔차. + +## FEM surrogate에서의 의미 +Beam 문제에서는 `I = b h^3 / 12` 때문에 응답이 입력 변수에 대해 비선형이다. 낮은 차수 다항식은 이 관계를 완벽히 재현하지 못할 수 있지만, 다음 장점이 있다. + +- 빠르다. +- 계수 해석이 가능하다. +- 적은 데이터에서도 안정적이다. +- 복잡한 모델의 baseline으로 적합하다. + +RSM은 특히 설계변수 범위가 좁고 응답이 단조롭고 매끄러울 때 유용하다. + +## 구현 선택 +이 튜토리얼에서는 scikit-learn의 `PolynomialFeatures`와 `Ridge`를 조합한다. + +```text +StandardScaler + -> PolynomialFeatures(degree=2, include_bias=False) + -> Ridge(alpha=...) +``` + +`PolynomialFeatures`는 입력 변수의 다항 조합을 만들고, `Ridge`는 L2 regularization으로 계수 크기를 제어한다. 일반 선형회귀 대신 Ridge를 쓰는 이유는 다항 feature가 늘어나면 feature 간 상관성이 커지고 계수가 불안정해질 수 있기 때문이다. + +## Notebook 실습 포인트 +`notebooks/01_response_surface_surrogate.ipynb`는 다음을 보여준다. + +1. 동일 FEM dataset 로드. +2. target `tip_uy_m` 선택. +3. degree 1, 2, 3 비교. +4. Ridge `alpha` 변화에 따른 train/test error 비교. +5. parity plot과 residual plot. +6. 다항 feature 이름과 계수 크기 해석. + +## 장점 +- 학습과 예측이 매우 빠르다. +- 작은 데이터에서 baseline으로 좋다. +- 변수 간 interaction을 명시적으로 볼 수 있다. +- extrapolation이 tree model보다 연속적이다. + +## 한계와 실패 모드 +- 실제 응답이 강하게 비선형이면 낮은 차수 다항식으로 부족하다. +- 높은 차수는 과적합과 수치 불안정을 만든다. +- 입력 scaling 없이 다항 feature를 만들면 큰 단위의 변수가 학습을 지배할 수 있다. +- 설계공간 경계 밖에서는 다항식이 물리적으로 말이 안 되는 큰 값을 낼 수 있다. + +## 구조해석 해석 기준 +RSM이 좋은 선택인 경우: + +- 설계변수 수가 적다. +- 입력 범위가 좁다. +- 응답이 매끄럽고 단조적이다. +- 설명 가능한 surrogate가 중요하다. + +RSM을 피해야 하는 경우: + +- 응답에 threshold, discontinuity, contact-like behavior가 있다. +- 입력 범위가 넓고 상호작용이 복잡하다. +- 국소 응력 peak처럼 고차 비선형성이 크다. + +## References +- Box, G. E. P. and Wilson, K. B. (1951), "On the Experimental Attainment of Optimum Conditions", Journal of the Royal Statistical Society Series B. https://doi.org/10.1111/j.2517-6161.1951.tb00067.x +- scikit-learn `PolynomialFeatures` documentation. https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html +- scikit-learn `Ridge` documentation. https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html diff --git a/FESurrogateModelTutorial/docs/theory/03_gaussian_process_kriging.md b/FESurrogateModelTutorial/docs/theory/03_gaussian_process_kriging.md new file mode 100644 index 0000000..7579346 --- /dev/null +++ b/FESurrogateModelTutorial/docs/theory/03_gaussian_process_kriging.md @@ -0,0 +1,86 @@ +# Gaussian Process Regression and Kriging + +## 핵심 아이디어 +Gaussian Process Regression(GPR)은 함수값을 확률변수로 보고, 입력 위치 사이의 상관관계를 kernel로 정의한다. Engineering design 분야에서는 Kriging이라는 이름으로 널리 사용된다. + +GPR은 예측 평균뿐 아니라 예측 표준편차를 제공한다. + +```text +y(x) ~ GP(m(x), k(x, x')) +``` + +- `m(x)`: mean function. +- `k(x, x')`: covariance function 또는 kernel. +- 예측 결과: `mean`, `standard deviation`. + +## FEM surrogate에서의 의미 +FEM 해석 데이터는 deterministic한 computer experiment인 경우가 많다. 같은 입력을 넣으면 같은 출력이 나온다. 이런 상황에서 GPR/Kriging은 적은 해석점으로 매끄러운 응답면을 만들고, 학습점에서 먼 영역의 불확실성을 크게 줄 수 있어 surrogate 신뢰도 설명에 유리하다. + +Sacks et al.의 computer experiment 연구는 계산 모델 입력과 출력 사이의 응답을 stochastic process로 모델링하는 관점을 제시했다. Rasmussen과 Williams의 GPML은 Gaussian process의 수학적 기반과 kernel 관점을 체계적으로 설명한다. + +## 구현 선택 +이 튜토리얼에서는 다음 kernel을 기본으로 사용한다. + +```text +ConstantKernel * RBF + WhiteKernel +``` + +- `ConstantKernel`: 응답 scale. +- `RBF`: 입력 공간에서 가까운 점은 비슷한 응답을 가진다는 smoothness 가정. +- `WhiteKernel`: 수치 noise 또는 모델 불일치 허용. + +Notebook pipeline: + +```text +StandardScaler + -> GaussianProcessRegressor(kernel=..., normalize_y=True) +``` + +## Hyperparameter 의미 +- `length_scale`: 각 입력 방향에서 함수가 얼마나 빨리 변하는지 나타낸다. +- `noise_level`: 해석 데이터의 noise 또는 모델 불일치 허용량이다. +- `alpha`: numerical stability를 위한 diagonal jitter로 사용할 수 있다. +- `n_restarts_optimizer`: kernel hyperparameter 최적화의 local optimum 위험을 줄인다. + +## Notebook 실습 포인트 +`notebooks/02_gaussian_process_kriging_surrogate.ipynb`는 다음을 보여준다. + +1. 동일 dataset과 split 로드. +2. RBF kernel 기반 GPR 학습. +3. 예측 평균과 표준편차 계산. +4. parity plot에 uncertainty band 또는 error coloring 추가. +5. 입력 공간에서 학습점과 먼 샘플의 uncertainty 확인. +6. 학습 sample 수 증가에 따른 RMSE와 예측 표준편차 변화. + +## 장점 +- 작은 데이터에서 강력하다. +- 예측 uncertainty를 제공한다. +- Smooth response surface에 적합하다. +- Bayesian optimization과 active learning으로 확장하기 좋다. + +## 한계와 실패 모드 +- 기본 exact GPR은 학습 데이터 수가 커지면 계산 비용이 급격히 증가한다. +- Kernel 선택이 성능을 크게 좌우한다. +- 입력 scaling이 중요하다. +- 고차원 입력에서는 length scale 학습이 불안정할 수 있다. +- 예측 표준편차는 모델 가정 하의 불확실성이지, 모든 물리 오류를 보장하지 않는다. + +## 구조해석 해석 기준 +GPR/Kriging이 좋은 선택인 경우: + +- FEM 해석이 비싸고 sample 수가 작다. +- 응답이 매끄럽다. +- uncertainty 기반 추가 샘플링을 설명하고 싶다. +- 설계공간 탐색에서 신뢰도 경고가 필요하다. + +주의할 경우: + +- sample 수가 수천 개 이상이다. +- 응답이 불연속적이다. +- 입력 차원이 많고 상호작용이 복잡하다. + +## References +- Sacks, J., Welch, W. J., Mitchell, T. J., and Wynn, H. P. (1989), "Design and Analysis of Computer Experiments", Statistical Science. https://doi.org/10.1214/ss/1177012413 +- Sacks, J., Schiller, S. B., and Welch, W. J. (1989), "Designs for Computer Experiments", Technometrics. https://doi.org/10.1080/00401706.1989.10488474 +- Rasmussen, C. E. and Williams, C. K. I. (2006), Gaussian Processes for Machine Learning. https://gaussianprocess.org/gpml/chapters/RW.pdf +- scikit-learn Gaussian Process documentation. https://scikit-learn.org/stable/modules/gaussian_process.html diff --git a/FESurrogateModelTutorial/docs/theory/04_random_forest.md b/FESurrogateModelTutorial/docs/theory/04_random_forest.md new file mode 100644 index 0000000..3792caa --- /dev/null +++ b/FESurrogateModelTutorial/docs/theory/04_random_forest.md @@ -0,0 +1,76 @@ +# Random Forest Surrogate + +## 핵심 아이디어 +Random Forest는 여러 decision tree를 bootstrap sample로 학습하고 평균하여 예측하는 ensemble 모델이다. 각 tree는 입력 공간을 여러 영역으로 나누고, 회귀 문제에서는 leaf의 평균값을 예측한다. + +```text +\hat{f}(x) = (1 / T) sum_{t=1}^{T} h_t(x) +``` + +- `T`: tree 개수. +- `h_t`: 개별 regression tree. + +Breiman의 2001년 Random Forest 논문은 bagging과 random feature selection을 결합한 ensemble 방법을 제시했다. + +## FEM surrogate에서의 의미 +Random Forest는 비선형성과 변수 상호작용을 명시적 feature engineering 없이 포착할 수 있다. Beam surrogate에서는 `h`, `b`, `L`, `P`, `E`의 비선형 영향과 interaction을 빠르게 잡는 비교 모델로 좋다. + +## 구현 선택 +이 튜토리얼에서는 scikit-learn의 `RandomForestRegressor`를 사용한다. + +기본 설정 예: + +```text +RandomForestRegressor( + n_estimators=300, + max_depth=None, + min_samples_leaf=2, + random_state=20260521, + n_jobs=-1 +) +``` + +Tree model은 feature scaling이 필수는 아니지만, 다른 모델과 공통 전처리 구조를 설명하기 위해 입력 column 관리는 동일하게 유지한다. + +## Notebook 실습 포인트 +`notebooks/03_random_forest_surrogate.ipynb`는 다음을 보여준다. + +1. 동일 dataset과 split 로드. +2. `n_estimators`, `max_depth`, `min_samples_leaf` 영향 비교. +3. test metric 계산. +4. parity plot과 residual plot. +5. permutation importance로 입력 변수 영향 확인. +6. feature importance와 beam 물리 관계 비교. + +## 장점 +- scaling에 덜 민감하다. +- 비선형성과 interaction을 잘 포착한다. +- outlier에 비교적 튼튼하다. +- feature importance를 계산하기 쉽다. +- 학습이 안정적이고 baseline으로 좋다. + +## 한계와 실패 모드 +- 예측이 piecewise constant라 매끄러운 응답면이 필요한 경우 부자연스러울 수 있다. +- 학습 데이터 범위 밖으로 외삽하지 못한다. +- 물리적으로 단조여야 하는 관계를 자동으로 보장하지 않는다. +- uncertainty는 GPR처럼 원래 제공되는 개념이 아니다. +- feature importance는 correlated feature에서 오해될 수 있다. + +## 구조해석 해석 기준 +Random Forest가 좋은 선택인 경우: + +- 빠르고 안정적인 비선형 baseline이 필요하다. +- 변수 중요도 분석을 보고 싶다. +- 데이터가 중간 규모 이상이다. +- target이 매끄러운 global response다. + +주의할 경우: + +- 설계 최적화에서 매끄러운 gradient-like response가 필요하다. +- 외삽이 필요하다. +- 응답면의 국소 smoothness가 중요하다. + +## References +- Breiman, L. (2001), "Random Forests", Machine Learning, 45, 5-32. https://doi.org/10.1023/A:1010933404324 +- CiNii bibliographic record for Breiman (2001). https://cir.nii.ac.jp/crid/1360574092892023168 +- scikit-learn `RandomForestRegressor` documentation. https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html diff --git a/FESurrogateModelTutorial/docs/theory/05_gradient_boosting.md b/FESurrogateModelTutorial/docs/theory/05_gradient_boosting.md new file mode 100644 index 0000000..9205cf8 --- /dev/null +++ b/FESurrogateModelTutorial/docs/theory/05_gradient_boosting.md @@ -0,0 +1,77 @@ +# Gradient Boosting Surrogate + +## 핵심 아이디어 +Gradient Boosting은 약한 예측기, 보통 shallow decision tree를 순차적으로 더해 손실함수를 줄이는 additive model이다. 각 단계의 tree는 이전 모델의 오차를 보정하는 방향으로 학습된다. + +```text +F_M(x) = F_0(x) + sum_{m=1}^{M} nu h_m(x) +``` + +- `F_M`: 최종 모델. +- `h_m`: m번째 weak learner. +- `nu`: learning rate. + +Friedman의 2001년 논문은 gradient boosting machine을 함수공간에서의 greedy approximation으로 설명한다. + +## FEM surrogate에서의 의미 +Gradient Boosting은 Random Forest보다 bias를 더 적극적으로 줄이는 경우가 많다. Beam surrogate에서 낮은 차수 RSM이 놓치는 비선형성을 tree ensemble이 순차적으로 보정할 수 있다. + +## 구현 선택 +이 튜토리얼에서는 scikit-learn의 `GradientBoostingRegressor`를 사용한다. + +기본 설정 예: + +```text +GradientBoostingRegressor( + loss="squared_error", + learning_rate=0.05, + n_estimators=300, + max_depth=3, + subsample=0.9, + random_state=20260521 +) +``` + +`learning_rate`와 `n_estimators`는 함께 조정해야 한다. 작은 learning rate는 더 많은 tree를 요구하지만 과적합을 완화할 수 있다. + +## Notebook 실습 포인트 +`notebooks/04_gradient_boosting_surrogate.ipynb`는 다음을 보여준다. + +1. 동일 dataset과 split 로드. +2. `learning_rate`와 `n_estimators` tradeoff. +3. staged prediction으로 train/test error curve 확인. +4. parity plot과 residual plot. +5. permutation importance 또는 built-in feature importance 비교. +6. Random Forest와 오차 패턴 비교. + +## 장점 +- tabular regression에서 높은 성능을 내기 쉽다. +- 비선형성과 interaction을 잘 포착한다. +- model size와 성능의 tradeoff를 조절하기 쉽다. +- staged prediction으로 과적합 진행을 관찰할 수 있다. + +## 한계와 실패 모드 +- hyperparameter에 Random Forest보다 민감하다. +- noise가 큰 데이터에서는 오차를 과도하게 따라갈 수 있다. +- tree 기반 모델이므로 외삽은 약하다. +- 학습 순서가 sequential하므로 Random Forest보다 병렬화 이점이 작다. +- 너무 복잡한 설정은 교육용 notebook을 흐리게 만들 수 있다. + +## 구조해석 해석 기준 +Gradient Boosting이 좋은 선택인 경우: + +- 정확도가 중요한 tabular surrogate가 필요하다. +- 입력 변수 수가 적거나 중간 규모다. +- 해석 응답이 비선형이지만 불연속은 아니다. +- 최종 비교에서 강한 classical ML baseline이 필요하다. + +주의할 경우: + +- uncertainty가 핵심 요구사항이다. +- 모델 해석성이 RSM 수준으로 필요하다. +- 데이터 수가 매우 적다. + +## References +- Friedman, J. H. (2001), "Greedy Function Approximation: A Gradient Boosting Machine", The Annals of Statistics. https://doi.org/10.1214/aos/1013203451 +- CiNii bibliographic record for Friedman (2001). https://cir.nii.ac.jp/crid/1360292617909870720 +- scikit-learn `GradientBoostingRegressor` documentation. https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingRegressor.html diff --git a/FESurrogateModelTutorial/docs/theory/06_mlp_neural_network.md b/FESurrogateModelTutorial/docs/theory/06_mlp_neural_network.md new file mode 100644 index 0000000..b2a99a2 --- /dev/null +++ b/FESurrogateModelTutorial/docs/theory/06_mlp_neural_network.md @@ -0,0 +1,90 @@ +# MLP Neural Network Surrogate + +## 핵심 아이디어 +Multi-layer Perceptron(MLP)은 affine transform과 nonlinear activation을 여러 층으로 쌓아 입력과 출력의 비선형 관계를 학습한다. + +단일 hidden layer MLP는 다음처럼 표현할 수 있다. + +```text +\hat{y} = W_2 phi(W_1 x + b_1) + b_2 +``` + +- `x`: scaling된 입력. +- `phi`: activation function. +- `W`, `b`: 학습되는 weight와 bias. + +Cybenko의 universal approximation theorem은 충분한 hidden unit을 가진 신경망이 넓은 함수군을 근사할 수 있음을 보인 고전적 결과다. 다만 "근사 가능하다"는 말이 적은 데이터에서 항상 잘 학습된다는 뜻은 아니다. + +## FEM surrogate에서의 의미 +MLP는 beam 응답처럼 매끄러운 비선형 함수를 학습할 수 있다. 그러나 데이터 수, scaling, regularization, optimization 설정에 민감하다. 이 튜토리얼에서는 deep learning framework를 도입하지 않고 scikit-learn의 `MLPRegressor`로 작은 neural surrogate의 특성을 보여준다. + +## 구현 선택 +기본 pipeline: + +```text +StandardScaler + -> TransformedTargetRegressor( + regressor=MLPRegressor(...), + transformer=StandardScaler() + ) +``` + +추천 기본 설정: + +```text +MLPRegressor( + hidden_layer_sizes=(64, 32), + activation="relu", + solver="adam", + alpha=1e-4, + learning_rate_init=1e-3, + early_stopping=True, + max_iter=2000, + random_state=20260521 +) +``` + +입력뿐 아니라 target scaling도 중요하다. FEM 응답은 단위와 scale이 크게 다를 수 있기 때문이다. + +## Notebook 실습 포인트 +`notebooks/05_mlp_surrogate.ipynb`는 다음을 보여준다. + +1. 동일 dataset과 split 로드. +2. 입력 scaling과 target scaling의 효과. +3. hidden layer 크기 비교. +4. train/test learning curve. +5. parity plot과 residual plot. +6. RSM, GPR, tree ensemble 대비 MLP의 장단점 정리. + +## 장점 +- 매끄러운 비선형 함수 근사에 적합하다. +- 다중 출력 surrogate로 확장하기 쉽다. +- 충분한 데이터와 tuning이 있으면 복잡한 관계를 학습할 수 있다. +- 동일 pipeline 구조로 다른 neural framework로 확장 가능하다. + +## 한계와 실패 모드 +- 작은 데이터에서는 과적합하거나 불안정할 수 있다. +- scaling 없이 학습하면 convergence가 나빠질 수 있다. +- hyperparameter 선택이 성능에 큰 영향을 준다. +- GPR처럼 기본 uncertainty를 제공하지 않는다. +- 모델 해석성이 낮다. + +## 구조해석 해석 기준 +MLP가 좋은 선택인 경우: + +- 데이터 수가 충분하다. +- 응답이 매끄럽지만 단순 다항식으로 부족하다. +- 다중 출력 또는 복잡한 feature representation 확장을 고려한다. +- 최종 정확도가 중요하고 해석성 요구가 낮다. + +주의할 경우: + +- sample 수가 매우 작다. +- 예측 불확실성이 중요하다. +- 실험자가 scaling과 validation을 엄격히 관리하기 어렵다. + +## References +- Cybenko, G. (1989), "Approximation by Superpositions of a Sigmoidal Function", Mathematics of Control, Signals, and Systems. https://doi.org/10.1007/BF02551274 +- CiNii bibliographic record for Cybenko (1989). https://cir.nii.ac.jp/crid/1361981471344652032 +- Glorot, X. and Bengio, Y. (2010), "Understanding the difficulty of training deep feedforward neural networks", AISTATS. https://proceedings.mlr.press/v9/glorot10a.html +- scikit-learn `MLPRegressor` documentation. https://scikit-learn.org/stable/modules/generated/sklearn.neural_network.MLPRegressor.html diff --git a/FESurrogateModelTutorial/notebooks/.gitkeep b/FESurrogateModelTutorial/notebooks/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/FESurrogateModelTutorial/notebooks/.gitkeep @@ -0,0 +1 @@ + diff --git a/FESurrogateModelTutorial/notebooks/00_beam2d_fea_dataset.ipynb b/FESurrogateModelTutorial/notebooks/00_beam2d_fea_dataset.ipynb new file mode 100644 index 0000000..41ef2de --- /dev/null +++ b/FESurrogateModelTutorial/notebooks/00_beam2d_fea_dataset.ipynb @@ -0,0 +1,173 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7e3ade70", + "metadata": {}, + "source": [ + "# 00 Beam2D FEM Dataset\n", + "\n", + "BeamExamples ?? ??? ?? ??? ? LHS sample? ???, repository solver? FEM surrogate ??? dataset? ????." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "71929240", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from pathlib import Path\n", + "\n", + "import numpy as np\n", + "\n", + "from femsurrogate.data.bounds import DEFAULT_PARAMETER_BOUNDS\n", + "from femsurrogate.data.dataset import build_dataset\n", + "from femsurrogate.data.sampling import generate_lhs_samples\n", + "from femsurrogate.data.schema import DEFAULT_RANDOM_SEED, TARGET_COLUMNS\n", + "from femsurrogate.fea.io import read_beam_example, read_expected_displacements\n", + "from femsurrogate.fea.solver import solve_linear_static\n", + "\n", + "ROOT = Path.cwd().resolve()\n", + "if not (ROOT / \"pyproject.toml\").exists():\n", + " ROOT = ROOT.parent\n", + "assert (ROOT / \"pyproject.toml\").exists(), ROOT\n", + "REFERENCE_DIR = ROOT / \"data\" / \"reference\"\n", + "REFERENCE_DIR.mkdir(parents=True, exist_ok=True)" + ] + }, + { + "cell_type": "markdown", + "id": "df256ebc", + "metadata": {}, + "source": [ + "## BeamExamples ?? ??\n", + "\n", + "Fixture? ?? node? ?? `Ux`, `Uy`, `Rz`? ???? ???? ?? ????? ????." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0a8c947c", + "metadata": {}, + "outputs": [], + "source": [ + "model = read_beam_example(ROOT / \"BeamExamples\" / \"CantileverBeam.txt\")\n", + "expected = read_expected_displacements(ROOT / \"BeamExamples\" / \"CantileverBeam_Displacements.txt\")\n", + "actual = solve_linear_static(model)\n", + "\n", + "max_abs_error = 0.0\n", + "for node_id, expected_displacement in expected.items():\n", + " actual_displacement = actual[node_id]\n", + " actual_values = np.array(\n", + " [actual_displacement.ux, actual_displacement.uy, actual_displacement.rz]\n", + " )\n", + " expected_values = np.array(\n", + " [expected_displacement.ux, expected_displacement.uy, expected_displacement.rz]\n", + " )\n", + " error = float(np.max(np.abs(actual_values - expected_values)))\n", + " max_abs_error = max(max_abs_error, error)\n", + "\n", + "assert max_abs_error <= 5e-7\n", + "max_abs_error" + ] + }, + { + "cell_type": "markdown", + "id": "6620d0ee", + "metadata": {}, + "source": [ + "## LHS sampling? FEM batch ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9923fd04", + "metadata": {}, + "outputs": [], + "source": [ + "N_SAMPLES = 300\n", + "\n", + "samples = generate_lhs_samples(DEFAULT_PARAMETER_BOUNDS, n=N_SAMPLES, seed=DEFAULT_RANDOM_SEED)\n", + "dataset = build_dataset(samples)\n", + "\n", + "assert len(dataset) == N_SAMPLES\n", + "assert set(TARGET_COLUMNS).issubset(dataset.columns)\n", + "dataset.head()" + ] + }, + { + "cell_type": "markdown", + "id": "c0efee15", + "metadata": {}, + "source": [ + "## Dataset ??\n", + "\n", + "?? notebook? ?? CSV? metadata? ??? `data/reference/`? ????." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d80890bd", + "metadata": {}, + "outputs": [], + "source": [ + "dataset_path = REFERENCE_DIR / \"beam2d_lhs_300.csv\"\n", + "metadata_path = REFERENCE_DIR / \"beam2d_lhs_300_metadata.json\"\n", + "\n", + "dataset.to_csv(dataset_path, index=False)\n", + "metadata = {\n", + " \"dataset_name\": \"beam2d_lhs_300\",\n", + " \"sample_count\": N_SAMPLES,\n", + " \"random_seed\": DEFAULT_RANDOM_SEED,\n", + " \"unit_system\": \"SI\",\n", + " \"fea_model\": \"2D Euler-Bernoulli beam/frame, linear static\",\n", + " \"target_columns\": list(TARGET_COLUMNS),\n", + " \"parameter_bounds\": {\n", + " name: {\"lower\": bound.lower, \"upper\": bound.upper}\n", + " for name, bound in DEFAULT_PARAMETER_BOUNDS.items()\n", + " },\n", + " \"notes\": \"Generated by notebooks/00_beam2d_fea_dataset.ipynb using src/femsurrogate.\",\n", + "}\n", + "metadata_path.write_text(json.dumps(metadata, indent=2), encoding=\"utf-8\")\n", + "\n", + "{\"dataset_path\": str(dataset_path), \"metadata_path\": str(metadata_path)}" + ] + }, + { + "cell_type": "markdown", + "id": "d56bcddb", + "metadata": {}, + "source": [ + "## ?? sanity check" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e560e50c", + "metadata": {}, + "outputs": [], + "source": [ + "dataset.describe().T.loc[[\"L_m\", \"b_m\", \"h_m\", \"E_pa\", \"P_n\", *TARGET_COLUMNS]]" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/FESurrogateModelTutorial/notebooks/01_response_surface_surrogate.ipynb b/FESurrogateModelTutorial/notebooks/01_response_surface_surrogate.ipynb new file mode 100644 index 0000000..3f90dc3 --- /dev/null +++ b/FESurrogateModelTutorial/notebooks/01_response_surface_surrogate.ipynb @@ -0,0 +1,168 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "260fc3ce", + "metadata": {}, + "source": [ + "# Response Surface Surrogate\n", + "\n", + "Response Surface? polynomial feature? Ridge regression?? ?? baseline? ???.\n", + "\n", + "?? ?? notebook? ?? dataset, target, train/test split seed? ????." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "56528a9c", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import warnings\n", + "from pathlib import Path\n", + "\n", + "import pandas as pd\n", + "from sklearn.exceptions import ConvergenceWarning\n", + "\n", + "from femsurrogate.data.schema import DEFAULT_RANDOM_SEED, PARAMETER_COLUMNS\n", + "from femsurrogate.plotting.diagnostics import plot_parity, plot_residuals\n", + "from femsurrogate.surrogates.common import evaluate_model, metrics_to_dict, split_dataset\n", + "from femsurrogate.surrogates.registry import make_model\n", + "\n", + "ROOT = Path.cwd().resolve()\n", + "if not (ROOT / \"pyproject.toml\").exists():\n", + " ROOT = ROOT.parent\n", + "assert (ROOT / \"pyproject.toml\").exists(), ROOT\n", + "DATASET_PATH = ROOT / \"data\" / \"reference\" / \"beam2d_lhs_300.csv\"\n", + "RESULTS_DIR = ROOT / \"reports\" / \"results\"\n", + "PREDICTIONS_DIR = ROOT / \"reports\" / \"predictions\"\n", + "FIGURES_DIR = ROOT / \"reports\" / \"figures\"\n", + "for directory in [RESULTS_DIR, PREDICTIONS_DIR, FIGURES_DIR]:\n", + " directory.mkdir(parents=True, exist_ok=True)" + ] + }, + { + "cell_type": "markdown", + "id": "7cd36ad9", + "metadata": {}, + "source": [ + "## Dataset? split" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "50689a07", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = pd.read_csv(DATASET_PATH)\n", + "target_column = \"tip_uy_m\"\n", + "split = split_dataset(\n", + " dataset,\n", + " feature_columns=list(PARAMETER_COLUMNS),\n", + " target_column=target_column,\n", + " test_size=0.2,\n", + " random_state=DEFAULT_RANDOM_SEED,\n", + ")\n", + "\n", + "len(split.X_train), len(split.X_test)" + ] + }, + { + "cell_type": "markdown", + "id": "0473847f", + "metadata": {}, + "source": [ + "## ?? ??? ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "539ffb4d", + "metadata": {}, + "outputs": [], + "source": [ + "MODEL_NAME = \"rsm\"\n", + "model = make_model(MODEL_NAME, random_state=DEFAULT_RANDOM_SEED, **{})\n", + "\n", + "with warnings.catch_warnings():\n", + " warnings.filterwarnings(\"ignore\", category=ConvergenceWarning)\n", + " result = evaluate_model(\n", + " model,\n", + " split.X_train,\n", + " split.X_test,\n", + " split.y_train,\n", + " split.y_test,\n", + " model_name=MODEL_NAME,\n", + " target_column=target_column,\n", + " )\n", + "\n", + "metrics = metrics_to_dict(result.metrics)\n", + "metrics" + ] + }, + { + "cell_type": "markdown", + "id": "78c34610", + "metadata": {}, + "source": [ + "## ?? ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e15bf80d", + "metadata": {}, + "outputs": [], + "source": [ + "metrics_path = RESULTS_DIR / f\"{MODEL_NAME}_metrics.json\"\n", + "predictions_path = PREDICTIONS_DIR / f\"{MODEL_NAME}_predictions.csv\"\n", + "\n", + "metrics_path.write_text(json.dumps(metrics, indent=2), encoding=\"utf-8\")\n", + "result.predictions.to_csv(predictions_path, index=False)\n", + "\n", + "{\"metrics_path\": str(metrics_path), \"predictions_path\": str(predictions_path)}" + ] + }, + { + "cell_type": "markdown", + "id": "2142e40b", + "metadata": {}, + "source": [ + "## ?? plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14b89510", + "metadata": {}, + "outputs": [], + "source": [ + "parity_fig = plot_parity(result.predictions, title=f\"{MODEL_NAME} parity\")\n", + "residual_fig = plot_residuals(result.predictions, title=f\"{MODEL_NAME} residuals\")\n", + "parity_fig.savefig(FIGURES_DIR / f\"{MODEL_NAME}_parity.png\", dpi=150, bbox_inches=\"tight\")\n", + "residual_fig.savefig(FIGURES_DIR / f\"{MODEL_NAME}_residuals.png\", dpi=150, bbox_inches=\"tight\")\n", + "parity_fig" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/FESurrogateModelTutorial/notebooks/02_gaussian_process_kriging_surrogate.ipynb b/FESurrogateModelTutorial/notebooks/02_gaussian_process_kriging_surrogate.ipynb new file mode 100644 index 0000000..e316b84 --- /dev/null +++ b/FESurrogateModelTutorial/notebooks/02_gaussian_process_kriging_surrogate.ipynb @@ -0,0 +1,168 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "144f56e0", + "metadata": {}, + "source": [ + "# Gaussian Process / Kriging Surrogate\n", + "\n", + "GPR? smooth response? ?? ???? ??? ???? ????.\n", + "\n", + "?? ?? notebook? ?? dataset, target, train/test split seed? ????." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a5a2974", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import warnings\n", + "from pathlib import Path\n", + "\n", + "import pandas as pd\n", + "from sklearn.exceptions import ConvergenceWarning\n", + "\n", + "from femsurrogate.data.schema import DEFAULT_RANDOM_SEED, PARAMETER_COLUMNS\n", + "from femsurrogate.plotting.diagnostics import plot_parity, plot_residuals\n", + "from femsurrogate.surrogates.common import evaluate_model, metrics_to_dict, split_dataset\n", + "from femsurrogate.surrogates.registry import make_model\n", + "\n", + "ROOT = Path.cwd().resolve()\n", + "if not (ROOT / \"pyproject.toml\").exists():\n", + " ROOT = ROOT.parent\n", + "assert (ROOT / \"pyproject.toml\").exists(), ROOT\n", + "DATASET_PATH = ROOT / \"data\" / \"reference\" / \"beam2d_lhs_300.csv\"\n", + "RESULTS_DIR = ROOT / \"reports\" / \"results\"\n", + "PREDICTIONS_DIR = ROOT / \"reports\" / \"predictions\"\n", + "FIGURES_DIR = ROOT / \"reports\" / \"figures\"\n", + "for directory in [RESULTS_DIR, PREDICTIONS_DIR, FIGURES_DIR]:\n", + " directory.mkdir(parents=True, exist_ok=True)" + ] + }, + { + "cell_type": "markdown", + "id": "a2c2b3fe", + "metadata": {}, + "source": [ + "## Dataset? split" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ef13216f", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = pd.read_csv(DATASET_PATH)\n", + "target_column = \"tip_uy_m\"\n", + "split = split_dataset(\n", + " dataset,\n", + " feature_columns=list(PARAMETER_COLUMNS),\n", + " target_column=target_column,\n", + " test_size=0.2,\n", + " random_state=DEFAULT_RANDOM_SEED,\n", + ")\n", + "\n", + "len(split.X_train), len(split.X_test)" + ] + }, + { + "cell_type": "markdown", + "id": "6c3be3f4", + "metadata": {}, + "source": [ + "## ?? ??? ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d5e09c8a", + "metadata": {}, + "outputs": [], + "source": [ + "MODEL_NAME = \"gpr\"\n", + "model = make_model(MODEL_NAME, random_state=DEFAULT_RANDOM_SEED, **{})\n", + "\n", + "with warnings.catch_warnings():\n", + " warnings.filterwarnings(\"ignore\", category=ConvergenceWarning)\n", + " result = evaluate_model(\n", + " model,\n", + " split.X_train,\n", + " split.X_test,\n", + " split.y_train,\n", + " split.y_test,\n", + " model_name=MODEL_NAME,\n", + " target_column=target_column,\n", + " )\n", + "\n", + "metrics = metrics_to_dict(result.metrics)\n", + "metrics" + ] + }, + { + "cell_type": "markdown", + "id": "4b9e74af", + "metadata": {}, + "source": [ + "## ?? ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5af40658", + "metadata": {}, + "outputs": [], + "source": [ + "metrics_path = RESULTS_DIR / f\"{MODEL_NAME}_metrics.json\"\n", + "predictions_path = PREDICTIONS_DIR / f\"{MODEL_NAME}_predictions.csv\"\n", + "\n", + "metrics_path.write_text(json.dumps(metrics, indent=2), encoding=\"utf-8\")\n", + "result.predictions.to_csv(predictions_path, index=False)\n", + "\n", + "{\"metrics_path\": str(metrics_path), \"predictions_path\": str(predictions_path)}" + ] + }, + { + "cell_type": "markdown", + "id": "37a881b4", + "metadata": {}, + "source": [ + "## ?? plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d156a54d", + "metadata": {}, + "outputs": [], + "source": [ + "parity_fig = plot_parity(result.predictions, title=f\"{MODEL_NAME} parity\")\n", + "residual_fig = plot_residuals(result.predictions, title=f\"{MODEL_NAME} residuals\")\n", + "parity_fig.savefig(FIGURES_DIR / f\"{MODEL_NAME}_parity.png\", dpi=150, bbox_inches=\"tight\")\n", + "residual_fig.savefig(FIGURES_DIR / f\"{MODEL_NAME}_residuals.png\", dpi=150, bbox_inches=\"tight\")\n", + "parity_fig" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/FESurrogateModelTutorial/notebooks/03_random_forest_surrogate.ipynb b/FESurrogateModelTutorial/notebooks/03_random_forest_surrogate.ipynb new file mode 100644 index 0000000..921bd8f --- /dev/null +++ b/FESurrogateModelTutorial/notebooks/03_random_forest_surrogate.ipynb @@ -0,0 +1,168 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1638813f", + "metadata": {}, + "source": [ + "# Random Forest Surrogate\n", + "\n", + "Random Forest? feature scaling ??? ????? interaction? ??? ???? tree ensemble??.\n", + "\n", + "?? ?? notebook? ?? dataset, target, train/test split seed? ????." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8bdcff3", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import warnings\n", + "from pathlib import Path\n", + "\n", + "import pandas as pd\n", + "from sklearn.exceptions import ConvergenceWarning\n", + "\n", + "from femsurrogate.data.schema import DEFAULT_RANDOM_SEED, PARAMETER_COLUMNS\n", + "from femsurrogate.plotting.diagnostics import plot_parity, plot_residuals\n", + "from femsurrogate.surrogates.common import evaluate_model, metrics_to_dict, split_dataset\n", + "from femsurrogate.surrogates.registry import make_model\n", + "\n", + "ROOT = Path.cwd().resolve()\n", + "if not (ROOT / \"pyproject.toml\").exists():\n", + " ROOT = ROOT.parent\n", + "assert (ROOT / \"pyproject.toml\").exists(), ROOT\n", + "DATASET_PATH = ROOT / \"data\" / \"reference\" / \"beam2d_lhs_300.csv\"\n", + "RESULTS_DIR = ROOT / \"reports\" / \"results\"\n", + "PREDICTIONS_DIR = ROOT / \"reports\" / \"predictions\"\n", + "FIGURES_DIR = ROOT / \"reports\" / \"figures\"\n", + "for directory in [RESULTS_DIR, PREDICTIONS_DIR, FIGURES_DIR]:\n", + " directory.mkdir(parents=True, exist_ok=True)" + ] + }, + { + "cell_type": "markdown", + "id": "6957e06b", + "metadata": {}, + "source": [ + "## Dataset? split" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "209f40be", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = pd.read_csv(DATASET_PATH)\n", + "target_column = \"tip_uy_m\"\n", + "split = split_dataset(\n", + " dataset,\n", + " feature_columns=list(PARAMETER_COLUMNS),\n", + " target_column=target_column,\n", + " test_size=0.2,\n", + " random_state=DEFAULT_RANDOM_SEED,\n", + ")\n", + "\n", + "len(split.X_train), len(split.X_test)" + ] + }, + { + "cell_type": "markdown", + "id": "fdc2fbed", + "metadata": {}, + "source": [ + "## ?? ??? ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "63ed6060", + "metadata": {}, + "outputs": [], + "source": [ + "MODEL_NAME = \"random_forest\"\n", + "model = make_model(MODEL_NAME, random_state=DEFAULT_RANDOM_SEED, **{})\n", + "\n", + "with warnings.catch_warnings():\n", + " warnings.filterwarnings(\"ignore\", category=ConvergenceWarning)\n", + " result = evaluate_model(\n", + " model,\n", + " split.X_train,\n", + " split.X_test,\n", + " split.y_train,\n", + " split.y_test,\n", + " model_name=MODEL_NAME,\n", + " target_column=target_column,\n", + " )\n", + "\n", + "metrics = metrics_to_dict(result.metrics)\n", + "metrics" + ] + }, + { + "cell_type": "markdown", + "id": "25dafcbf", + "metadata": {}, + "source": [ + "## ?? ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8357de5d", + "metadata": {}, + "outputs": [], + "source": [ + "metrics_path = RESULTS_DIR / f\"{MODEL_NAME}_metrics.json\"\n", + "predictions_path = PREDICTIONS_DIR / f\"{MODEL_NAME}_predictions.csv\"\n", + "\n", + "metrics_path.write_text(json.dumps(metrics, indent=2), encoding=\"utf-8\")\n", + "result.predictions.to_csv(predictions_path, index=False)\n", + "\n", + "{\"metrics_path\": str(metrics_path), \"predictions_path\": str(predictions_path)}" + ] + }, + { + "cell_type": "markdown", + "id": "069f56dd", + "metadata": {}, + "source": [ + "## ?? plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00159cc2", + "metadata": {}, + "outputs": [], + "source": [ + "parity_fig = plot_parity(result.predictions, title=f\"{MODEL_NAME} parity\")\n", + "residual_fig = plot_residuals(result.predictions, title=f\"{MODEL_NAME} residuals\")\n", + "parity_fig.savefig(FIGURES_DIR / f\"{MODEL_NAME}_parity.png\", dpi=150, bbox_inches=\"tight\")\n", + "residual_fig.savefig(FIGURES_DIR / f\"{MODEL_NAME}_residuals.png\", dpi=150, bbox_inches=\"tight\")\n", + "parity_fig" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/FESurrogateModelTutorial/notebooks/04_gradient_boosting_surrogate.ipynb b/FESurrogateModelTutorial/notebooks/04_gradient_boosting_surrogate.ipynb new file mode 100644 index 0000000..76a6577 --- /dev/null +++ b/FESurrogateModelTutorial/notebooks/04_gradient_boosting_surrogate.ipynb @@ -0,0 +1,168 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ad3ce4ad", + "metadata": {}, + "source": [ + "# Gradient Boosting Surrogate\n", + "\n", + "Gradient Boosting? shallow tree? ????? ?? residual pattern? ??? ensemble??.\n", + "\n", + "?? ?? notebook? ?? dataset, target, train/test split seed? ????." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0fec75b1", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import warnings\n", + "from pathlib import Path\n", + "\n", + "import pandas as pd\n", + "from sklearn.exceptions import ConvergenceWarning\n", + "\n", + "from femsurrogate.data.schema import DEFAULT_RANDOM_SEED, PARAMETER_COLUMNS\n", + "from femsurrogate.plotting.diagnostics import plot_parity, plot_residuals\n", + "from femsurrogate.surrogates.common import evaluate_model, metrics_to_dict, split_dataset\n", + "from femsurrogate.surrogates.registry import make_model\n", + "\n", + "ROOT = Path.cwd().resolve()\n", + "if not (ROOT / \"pyproject.toml\").exists():\n", + " ROOT = ROOT.parent\n", + "assert (ROOT / \"pyproject.toml\").exists(), ROOT\n", + "DATASET_PATH = ROOT / \"data\" / \"reference\" / \"beam2d_lhs_300.csv\"\n", + "RESULTS_DIR = ROOT / \"reports\" / \"results\"\n", + "PREDICTIONS_DIR = ROOT / \"reports\" / \"predictions\"\n", + "FIGURES_DIR = ROOT / \"reports\" / \"figures\"\n", + "for directory in [RESULTS_DIR, PREDICTIONS_DIR, FIGURES_DIR]:\n", + " directory.mkdir(parents=True, exist_ok=True)" + ] + }, + { + "cell_type": "markdown", + "id": "1d93d9fb", + "metadata": {}, + "source": [ + "## Dataset? split" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c905b0aa", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = pd.read_csv(DATASET_PATH)\n", + "target_column = \"tip_uy_m\"\n", + "split = split_dataset(\n", + " dataset,\n", + " feature_columns=list(PARAMETER_COLUMNS),\n", + " target_column=target_column,\n", + " test_size=0.2,\n", + " random_state=DEFAULT_RANDOM_SEED,\n", + ")\n", + "\n", + "len(split.X_train), len(split.X_test)" + ] + }, + { + "cell_type": "markdown", + "id": "c5e7af1a", + "metadata": {}, + "source": [ + "## ?? ??? ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f5168f3e", + "metadata": {}, + "outputs": [], + "source": [ + "MODEL_NAME = \"gradient_boosting\"\n", + "model = make_model(MODEL_NAME, random_state=DEFAULT_RANDOM_SEED, **{})\n", + "\n", + "with warnings.catch_warnings():\n", + " warnings.filterwarnings(\"ignore\", category=ConvergenceWarning)\n", + " result = evaluate_model(\n", + " model,\n", + " split.X_train,\n", + " split.X_test,\n", + " split.y_train,\n", + " split.y_test,\n", + " model_name=MODEL_NAME,\n", + " target_column=target_column,\n", + " )\n", + "\n", + "metrics = metrics_to_dict(result.metrics)\n", + "metrics" + ] + }, + { + "cell_type": "markdown", + "id": "f02aead6", + "metadata": {}, + "source": [ + "## ?? ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1daaf0f6", + "metadata": {}, + "outputs": [], + "source": [ + "metrics_path = RESULTS_DIR / f\"{MODEL_NAME}_metrics.json\"\n", + "predictions_path = PREDICTIONS_DIR / f\"{MODEL_NAME}_predictions.csv\"\n", + "\n", + "metrics_path.write_text(json.dumps(metrics, indent=2), encoding=\"utf-8\")\n", + "result.predictions.to_csv(predictions_path, index=False)\n", + "\n", + "{\"metrics_path\": str(metrics_path), \"predictions_path\": str(predictions_path)}" + ] + }, + { + "cell_type": "markdown", + "id": "14f71882", + "metadata": {}, + "source": [ + "## ?? plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "807c1025", + "metadata": {}, + "outputs": [], + "source": [ + "parity_fig = plot_parity(result.predictions, title=f\"{MODEL_NAME} parity\")\n", + "residual_fig = plot_residuals(result.predictions, title=f\"{MODEL_NAME} residuals\")\n", + "parity_fig.savefig(FIGURES_DIR / f\"{MODEL_NAME}_parity.png\", dpi=150, bbox_inches=\"tight\")\n", + "residual_fig.savefig(FIGURES_DIR / f\"{MODEL_NAME}_residuals.png\", dpi=150, bbox_inches=\"tight\")\n", + "parity_fig" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/FESurrogateModelTutorial/notebooks/05_mlp_surrogate.ipynb b/FESurrogateModelTutorial/notebooks/05_mlp_surrogate.ipynb new file mode 100644 index 0000000..9ec7f35 --- /dev/null +++ b/FESurrogateModelTutorial/notebooks/05_mlp_surrogate.ipynb @@ -0,0 +1,168 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "69c9cc92", + "metadata": {}, + "source": [ + "# MLP Neural Network Surrogate\n", + "\n", + "MLP? scaled input? target? ??? ???? ??? ??? ????.\n", + "\n", + "?? ?? notebook? ?? dataset, target, train/test split seed? ????." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eed089f5", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import warnings\n", + "from pathlib import Path\n", + "\n", + "import pandas as pd\n", + "from sklearn.exceptions import ConvergenceWarning\n", + "\n", + "from femsurrogate.data.schema import DEFAULT_RANDOM_SEED, PARAMETER_COLUMNS\n", + "from femsurrogate.plotting.diagnostics import plot_parity, plot_residuals\n", + "from femsurrogate.surrogates.common import evaluate_model, metrics_to_dict, split_dataset\n", + "from femsurrogate.surrogates.registry import make_model\n", + "\n", + "ROOT = Path.cwd().resolve()\n", + "if not (ROOT / \"pyproject.toml\").exists():\n", + " ROOT = ROOT.parent\n", + "assert (ROOT / \"pyproject.toml\").exists(), ROOT\n", + "DATASET_PATH = ROOT / \"data\" / \"reference\" / \"beam2d_lhs_300.csv\"\n", + "RESULTS_DIR = ROOT / \"reports\" / \"results\"\n", + "PREDICTIONS_DIR = ROOT / \"reports\" / \"predictions\"\n", + "FIGURES_DIR = ROOT / \"reports\" / \"figures\"\n", + "for directory in [RESULTS_DIR, PREDICTIONS_DIR, FIGURES_DIR]:\n", + " directory.mkdir(parents=True, exist_ok=True)" + ] + }, + { + "cell_type": "markdown", + "id": "b2547495", + "metadata": {}, + "source": [ + "## Dataset? split" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "039279d4", + "metadata": {}, + "outputs": [], + "source": [ + "dataset = pd.read_csv(DATASET_PATH)\n", + "target_column = \"tip_uy_m\"\n", + "split = split_dataset(\n", + " dataset,\n", + " feature_columns=list(PARAMETER_COLUMNS),\n", + " target_column=target_column,\n", + " test_size=0.2,\n", + " random_state=DEFAULT_RANDOM_SEED,\n", + ")\n", + "\n", + "len(split.X_train), len(split.X_test)" + ] + }, + { + "cell_type": "markdown", + "id": "71b3323f", + "metadata": {}, + "source": [ + "## ?? ??? ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "605253ef", + "metadata": {}, + "outputs": [], + "source": [ + "MODEL_NAME = \"mlp\"\n", + "model = make_model(MODEL_NAME, random_state=DEFAULT_RANDOM_SEED, **{'max_iter': 500})\n", + "\n", + "with warnings.catch_warnings():\n", + " warnings.filterwarnings(\"ignore\", category=ConvergenceWarning)\n", + " result = evaluate_model(\n", + " model,\n", + " split.X_train,\n", + " split.X_test,\n", + " split.y_train,\n", + " split.y_test,\n", + " model_name=MODEL_NAME,\n", + " target_column=target_column,\n", + " )\n", + "\n", + "metrics = metrics_to_dict(result.metrics)\n", + "metrics" + ] + }, + { + "cell_type": "markdown", + "id": "f70ad9fd", + "metadata": {}, + "source": [ + "## ?? ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb08797b", + "metadata": {}, + "outputs": [], + "source": [ + "metrics_path = RESULTS_DIR / f\"{MODEL_NAME}_metrics.json\"\n", + "predictions_path = PREDICTIONS_DIR / f\"{MODEL_NAME}_predictions.csv\"\n", + "\n", + "metrics_path.write_text(json.dumps(metrics, indent=2), encoding=\"utf-8\")\n", + "result.predictions.to_csv(predictions_path, index=False)\n", + "\n", + "{\"metrics_path\": str(metrics_path), \"predictions_path\": str(predictions_path)}" + ] + }, + { + "cell_type": "markdown", + "id": "39a34166", + "metadata": {}, + "source": [ + "## ?? plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "694a1081", + "metadata": {}, + "outputs": [], + "source": [ + "parity_fig = plot_parity(result.predictions, title=f\"{MODEL_NAME} parity\")\n", + "residual_fig = plot_residuals(result.predictions, title=f\"{MODEL_NAME} residuals\")\n", + "parity_fig.savefig(FIGURES_DIR / f\"{MODEL_NAME}_parity.png\", dpi=150, bbox_inches=\"tight\")\n", + "residual_fig.savefig(FIGURES_DIR / f\"{MODEL_NAME}_residuals.png\", dpi=150, bbox_inches=\"tight\")\n", + "parity_fig" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/FESurrogateModelTutorial/notebooks/06_compare_surrogate_models.ipynb b/FESurrogateModelTutorial/notebooks/06_compare_surrogate_models.ipynb new file mode 100644 index 0000000..411e0bf --- /dev/null +++ b/FESurrogateModelTutorial/notebooks/06_compare_surrogate_models.ipynb @@ -0,0 +1,115 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "741ede83", + "metadata": {}, + "source": [ + "# 06 Compare Surrogate Models\n", + "\n", + "? notebook? ?? model notebook?? ??? metrics JSON? ?? ??? ????. ??? ?? ???? ???." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10f43a71", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from pathlib import Path\n", + "\n", + "import pandas as pd\n", + "\n", + "from femsurrogate.plotting.comparison import plot_metric_comparison\n", + "\n", + "ROOT = Path.cwd().resolve()\n", + "if not (ROOT / \"pyproject.toml\").exists():\n", + " ROOT = ROOT.parent\n", + "assert (ROOT / \"pyproject.toml\").exists(), ROOT\n", + "RESULTS_DIR = ROOT / \"reports\" / \"results\"\n", + "FIGURES_DIR = ROOT / \"reports\" / \"figures\"\n", + "FIGURES_DIR.mkdir(parents=True, exist_ok=True)\n", + "MODEL_NAMES = [\"rsm\", \"gpr\", \"random_forest\", \"gradient_boosting\", \"mlp\"]" + ] + }, + { + "cell_type": "markdown", + "id": "9798e3bb", + "metadata": {}, + "source": [ + "## Metrics ??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55d2447d", + "metadata": {}, + "outputs": [], + "source": [ + "records = []\n", + "for model_name in MODEL_NAMES:\n", + " metrics_path = RESULTS_DIR / f\"{model_name}_metrics.json\"\n", + " assert metrics_path.exists(), metrics_path\n", + " records.append(json.loads(metrics_path.read_text(encoding=\"utf-8\")))\n", + "\n", + "comparison = pd.DataFrame(records).sort_values(\"rmse\").reset_index(drop=True)\n", + "comparison_path = RESULTS_DIR / \"model_comparison.csv\"\n", + "comparison.to_csv(comparison_path, index=False)\n", + "comparison" + ] + }, + { + "cell_type": "markdown", + "id": "731bb2f7", + "metadata": {}, + "source": [ + "## Metric ?? plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "64657b84", + "metadata": {}, + "outputs": [], + "source": [ + "figures = {}\n", + "for metric in [\"rmse\", \"mae\", \"r2\", \"fit_time_s\", \"predict_time_s\"]:\n", + " figure = plot_metric_comparison(comparison, metric=metric, title=f\"Surrogate {metric}\")\n", + " figure.savefig(FIGURES_DIR / f\"comparison_{metric}.png\", dpi=150, bbox_inches=\"tight\")\n", + " figures[metric] = figure\n", + "\n", + "figures[\"rmse\"]" + ] + }, + { + "cell_type": "markdown", + "id": "63cb5b8d", + "metadata": {}, + "source": [ + "## ?? ???\n", + "\n", + "- `rmse`? `mae`? ?? ??? ?? ????.\n", + "- `r2`? ??? residual plot?? ?? ?? ??? bias? ??? ????? ????.\n", + "- `fit_time_s`, `predict_time_s`? ?? ??? ??? loop?? ????.\n", + "- GPR? ?? dataset?? ???? sample ?? ??? ?? ??? ??? ?? ? ??." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/FESurrogateModelTutorial/phases/0-project-foundation/index.json b/FESurrogateModelTutorial/phases/0-project-foundation/index.json new file mode 100644 index 0000000..f6062c0 --- /dev/null +++ b/FESurrogateModelTutorial/phases/0-project-foundation/index.json @@ -0,0 +1,18 @@ +{ + "project": "FEMSurrogateTutorial", + "phase": "0-project-foundation", + "steps": [ + { + "step": 0, + "name": "python-project-skeleton", + "status": "completed", + "summary": "Created uv/pyproject foundation, src package skeleton, artifact directories, and ruff configuration." + }, + { + "step": 1, + "name": "import-smoke-test", + "status": "completed", + "summary": "Added package import smoke tests and exposed femsurrogate.__version__." + } + ] +} diff --git a/FESurrogateModelTutorial/phases/0-project-foundation/step0.md b/FESurrogateModelTutorial/phases/0-project-foundation/step0.md new file mode 100644 index 0000000..e82853a --- /dev/null +++ b/FESurrogateModelTutorial/phases/0-project-foundation/step0.md @@ -0,0 +1,40 @@ +# Step 0: python-project-skeleton + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/PROGRESS.md` +- `/WORKNOTES.md` +- `/docs/PRD.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` + +## 작업 + +Python tutorial project의 최소 기반을 만든다. + +- `/pyproject.toml` 생성: Python `>=3.12,<3.15`, setuptools src layout, pytest `pythonpath = ["src"]`, ruff target `py312`. +- runtime dependencies: `numpy`, `scipy`, `pandas`, `scikit-learn`, `matplotlib`, `joblib`. +- dev dependencies: `pytest`, `ruff`, `jupyterlab`, `ipykernel`, `nbconvert`. +- Python package directories: `/src/femsurrogate/`, `/src/femsurrogate/fea/`, `/src/femsurrogate/data/`, `/src/femsurrogate/surrogates/`, `/src/femsurrogate/plotting/`. +- artifact directories: `/tests/`, `/data/reference/`, `/data/processed/`, `/reports/results/`, `/reports/predictions/`, `/reports/figures/`, `/notebooks/`. +- 빈 artifact directory에는 `.gitkeep`을 둔다. +- Python cache, virtualenv, notebook checkpoint를 `.gitignore`에 추가한다. +- `/PROGRESS.md`에 phase 0 시작 상태를 기록한다. + +## Acceptance Criteria + +```powershell +uv sync +uv run python -c "import femsurrogate; print(femsurrogate.__name__)" +uv run ruff check . +``` + +## 검증 절차 + +AC 커맨드를 실행하고 성공하면 `phases/0-project-foundation/index.json`의 step 0을 `completed`로 갱신한다. + +## 금지사항 + +- Beam solver, parser, dataset, surrogate 모델 구현을 이 step에서 만들지 마라. +- Notebook 내용을 만들지 마라. diff --git a/FESurrogateModelTutorial/phases/0-project-foundation/step1.md b/FESurrogateModelTutorial/phases/0-project-foundation/step1.md new file mode 100644 index 0000000..51ba7ee --- /dev/null +++ b/FESurrogateModelTutorial/phases/0-project-foundation/step1.md @@ -0,0 +1,36 @@ +# Step 1: import-smoke-test + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/PROGRESS.md` +- `/WORKNOTES.md` +- `/docs/ARCHITECTURE.md` +- `/pyproject.toml` +- `/src/femsurrogate/__init__.py` + +## 작업 + +TDD로 package import smoke test를 추가한다. + +- 먼저 `/tests/test_project_structure.py`를 작성한다. +- 테스트는 `femsurrogate.__version__`이 문자열인지 확인한다. +- 테스트는 `femsurrogate.fea`, `femsurrogate.data`, `femsurrogate.surrogates`, `femsurrogate.plotting` import 가능성을 확인한다. +- 테스트 실패를 먼저 확인한 뒤 최소 구현으로 통과시킨다. +- `/PROGRESS.md`에 검증 결과를 기록한다. + +## Acceptance Criteria + +```powershell +uv run pytest tests/test_project_structure.py -q +uv run ruff check . +``` + +## 검증 절차 + +테스트가 먼저 실패한 기록을 확인하고, 구현 후 AC가 통과하면 `phases/0-project-foundation/index.json`의 step 1을 `completed`로 갱신한다. + +## 금지사항 + +- solver API를 만들지 마라. +- 테스트를 구현 후에만 작성하지 마라. diff --git a/FESurrogateModelTutorial/phases/1-beam2d-solver/index.json b/FESurrogateModelTutorial/phases/1-beam2d-solver/index.json new file mode 100644 index 0000000..18f03ca --- /dev/null +++ b/FESurrogateModelTutorial/phases/1-beam2d-solver/index.json @@ -0,0 +1,30 @@ +{ + "project": "FEMSurrogateTutorial", + "phase": "1-beam2d-solver", + "steps": [ + { + "step": 0, + "name": "beamexamples-parser", + "status": "completed", + "summary": "Added BeamExamples parser dataclasses and tests for cantilever input and displacement fixtures." + }, + { + "step": 1, + "name": "frame-element", + "status": "completed", + "summary": "Added 2D Euler-Bernoulli frame local stiffness and transformation matrix tests and implementation." + }, + { + "step": 2, + "name": "assembly-and-solver", + "status": "completed", + "summary": "Added sparse global stiffness assembly, load vector assembly, constrained DOF handling, and linear static solve." + }, + { + "step": 3, + "name": "fixture-regression", + "status": "completed", + "summary": "Added BeamExamples displacement regression, analytical cantilever tip check, and clockwise-positive Rz convention alignment." + } + ] +} diff --git a/FESurrogateModelTutorial/phases/1-beam2d-solver/step0.md b/FESurrogateModelTutorial/phases/1-beam2d-solver/step0.md new file mode 100644 index 0000000..99284b4 --- /dev/null +++ b/FESurrogateModelTutorial/phases/1-beam2d-solver/step0.md @@ -0,0 +1,32 @@ +# Step 0: beamexamples-parser + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/PROGRESS.md` +- `/WORKNOTES.md` +- `/docs/ARCHITECTURE.md` +- `/BeamExamples/CantileverBeam.txt` +- `/BeamExamples/CantileverBeam_Displacements.txt` + +## 작업 + +TDD로 `BeamExamples` parser를 구현한다. + +- `/tests/test_beamexamples_io.py`를 먼저 작성한다. +- `read_beam_example()`은 metadata, 6 nodes, 5 beams, fixed node 1, node 6 load를 읽는다. +- `read_expected_displacements()`는 node별 `Ux`, `Uy`, `Rz` 기준값을 읽는다. +- parser는 comment, blank line, trailing comma, `Poisson'sRatio` label을 처리한다. +- 구현 파일: `/src/femsurrogate/fea/model.py`, `/src/femsurrogate/fea/io.py`. + +## Acceptance Criteria + +```powershell +uv run pytest tests/test_beamexamples_io.py -q +uv run ruff check . +``` + +## 금지사항 + +- solver 구현을 이 step에 넣지 마라. +- fixture 파일을 수정하지 마라. diff --git a/FESurrogateModelTutorial/phases/1-beam2d-solver/step1.md b/FESurrogateModelTutorial/phases/1-beam2d-solver/step1.md new file mode 100644 index 0000000..dce1ae6 --- /dev/null +++ b/FESurrogateModelTutorial/phases/1-beam2d-solver/step1.md @@ -0,0 +1,28 @@ +# Step 1: frame-element + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/src/femsurrogate/fea/model.py` +- `/src/femsurrogate/fea/io.py` + +## 작업 + +TDD로 2-node 2D Euler-Bernoulli frame element 행렬을 구현한다. + +- `/tests/test_frame_element.py`를 먼저 작성한다. +- `local_frame_stiffness(E, A, I, L)`의 shape, symmetry, axial/bending 계수를 검증한다. +- `transformation_matrix(x1, y1, x2, y2)`의 shape와 orthogonality를 검증한다. +- 구현 파일: `/src/femsurrogate/fea/element.py`. + +## Acceptance Criteria + +```powershell +uv run pytest tests/test_frame_element.py tests/test_beamexamples_io.py -q +uv run ruff check . +``` + +## 금지사항 + +- Timoshenko beam, 3D beam DOF를 추가하지 마라. diff --git a/FESurrogateModelTutorial/phases/1-beam2d-solver/step2.md b/FESurrogateModelTutorial/phases/1-beam2d-solver/step2.md new file mode 100644 index 0000000..52bde88 --- /dev/null +++ b/FESurrogateModelTutorial/phases/1-beam2d-solver/step2.md @@ -0,0 +1,31 @@ +# Step 2: assembly-and-solver + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/src/femsurrogate/fea/model.py` +- `/src/femsurrogate/fea/io.py` +- `/src/femsurrogate/fea/element.py` + +## 작업 + +TDD로 global assembly와 constrained linear static solver를 구현한다. + +- `/tests/test_beam_solver.py`를 먼저 작성한다. +- BeamExamples model의 global stiffness shape `(18, 18)`을 검증한다. +- fixed node 1의 3 DOF가 constrained 처리되는지 검증한다. +- `solve_linear_static(model)`이 모든 node displacement를 finite 값으로 반환하는지 검증한다. +- 구현 파일: `/src/femsurrogate/fea/assembly.py`, `/src/femsurrogate/fea/solver.py`. +- solver는 `scipy.sparse`와 `scipy.sparse.linalg.spsolve`를 사용한다. + +## Acceptance Criteria + +```powershell +uv run pytest tests/test_beam_solver.py tests/test_frame_element.py tests/test_beamexamples_io.py -q +uv run ruff check . +``` + +## 금지사항 + +- expected displacement 값을 solver에 hard-code하지 마라. diff --git a/FESurrogateModelTutorial/phases/1-beam2d-solver/step3.md b/FESurrogateModelTutorial/phases/1-beam2d-solver/step3.md new file mode 100644 index 0000000..82c03d7 --- /dev/null +++ b/FESurrogateModelTutorial/phases/1-beam2d-solver/step3.md @@ -0,0 +1,30 @@ +# Step 3: fixture-regression + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/PRD.md` +- `/docs/ARCHITECTURE.md` +- `/BeamExamples/CantileverBeam.txt` +- `/BeamExamples/CantileverBeam_Displacements.txt` +- `/src/femsurrogate/fea/` + +## 작업 + +TDD로 BeamExamples displacement regression을 완성한다. + +- `/tests/test_cantilever_fixture_regression.py`를 먼저 작성한다. +- solver 결과의 모든 node별 `Ux`, `Uy`, `Rz`를 기준 displacement file과 `atol=5e-7`, `rtol=1e-6`으로 비교한다. +- tip displacement 부호와 해석해 `P L^3 / (3 E I)` 대비 크기를 검증한다. +- 필요한 helper는 `/src/femsurrogate/fea/benchmark.py`, `/src/femsurrogate/fea/responses.py`에 둔다. + +## Acceptance Criteria + +```powershell +uv run pytest tests/test_cantilever_fixture_regression.py tests/test_beam_solver.py tests/test_frame_element.py tests/test_beamexamples_io.py -q +uv run ruff check . +``` + +## 금지사항 + +- 허용오차를 문서 기준보다 느슨하게 키우지 마라. diff --git a/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/index.json b/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/index.json new file mode 100644 index 0000000..348eb5f --- /dev/null +++ b/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/index.json @@ -0,0 +1,30 @@ +{ + "project": "FEMSurrogateTutorial", + "phase": "2-dataset-and-surrogates", + "steps": [ + { + "step": 0, + "name": "sampling-and-dataset", + "status": "completed", + "summary": "Added reproducible LHS sampling, BeamParameters/AnalysisResult schema, and Beam2D dataset builder using the in-repository solver." + }, + { + "step": 1, + "name": "surrogate-common", + "status": "completed", + "summary": "Added reproducible dataset split helper, evaluation result dataclasses, regression metrics, fit/predict timing, and prediction table generation." + }, + { + "step": 2, + "name": "surrogate-models", + "status": "completed", + "summary": "Added scikit-learn builders and registry for RSM, GPR, Random Forest, Gradient Boosting, and MLP models." + }, + { + "step": 3, + "name": "plotting-and-results", + "status": "completed", + "summary": "Added parity and residual diagnostic plots, metrics table creation, and metric comparison plot helpers returning matplotlib figures." + } + ] +} diff --git a/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step0.md b/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step0.md new file mode 100644 index 0000000..554d167 --- /dev/null +++ b/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step0.md @@ -0,0 +1,28 @@ +# Step 0: sampling-and-dataset + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/theory/01_doe_sampling_validation.md` +- `/src/femsurrogate/fea/` + +## 작업 + +TDD로 LHS sampling과 Beam2D dataset builder를 구현한다. + +- 테스트: `/tests/test_sampling.py`, `/tests/test_dataset_builder.py`. +- 구현: `/src/femsurrogate/data/bounds.py`, `schema.py`, `sampling.py`, `dataset.py`. +- 기본 seed는 `20260521`. +- dataset schema는 문서의 SI 단위 컬럼을 따른다. + +## Acceptance Criteria + +```powershell +uv run pytest tests/test_sampling.py tests/test_dataset_builder.py -q +uv run ruff check . +``` + +## 금지사항 + +- surrogate 학습을 이 step에 넣지 마라. diff --git a/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step1.md b/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step1.md new file mode 100644 index 0000000..0fa5ff4 --- /dev/null +++ b/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step1.md @@ -0,0 +1,26 @@ +# Step 1: surrogate-common + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/src/femsurrogate/data/` + +## 작업 + +TDD로 surrogate 공통 split/evaluate/result helper를 구현한다. + +- 테스트: `/tests/test_surrogate_common.py`. +- 구현: `/src/femsurrogate/surrogates/common.py`. +- metrics는 `rmse`, `mae`, `r2`, `fit_time_s`, `predict_time_s`를 포함한다. + +## Acceptance Criteria + +```powershell +uv run pytest tests/test_surrogate_common.py -q +uv run ruff check . +``` + +## 금지사항 + +- 개별 모델 builder를 이 step에 섞지 마라. diff --git a/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step2.md b/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step2.md new file mode 100644 index 0000000..9feb8d5 --- /dev/null +++ b/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step2.md @@ -0,0 +1,30 @@ +# Step 2: surrogate-models + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/theory/02_response_surface_methodology.md` +- `/docs/theory/03_gaussian_process_kriging.md` +- `/docs/theory/04_random_forest.md` +- `/docs/theory/05_gradient_boosting.md` +- `/docs/theory/06_mlp_neural_network.md` +- `/src/femsurrogate/surrogates/common.py` + +## 작업 + +TDD로 모델별 scikit-learn pipeline builder와 registry를 구현한다. + +- 테스트: `/tests/test_surrogate_models.py`. +- 구현: `rsm.py`, `gpr.py`, `random_forest.py`, `boosting.py`, `mlp.py`, `registry.py`. +- 모델명: `rsm`, `gpr`, `random_forest`, `gradient_boosting`, `mlp`. + +## Acceptance Criteria + +```powershell +uv run pytest tests/test_surrogate_models.py -q +uv run ruff check . +``` + +## 금지사항 + +- PyTorch/TensorFlow, AutoML, MLflow를 추가하지 마라. diff --git a/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step3.md b/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step3.md new file mode 100644 index 0000000..9a07828 --- /dev/null +++ b/FESurrogateModelTutorial/phases/2-dataset-and-surrogates/step3.md @@ -0,0 +1,26 @@ +# Step 3: plotting-and-results + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/src/femsurrogate/surrogates/` + +## 작업 + +TDD로 diagnostics plotting과 result comparison helper를 구현한다. + +- 테스트: `/tests/test_plotting_and_results.py`. +- 구현: `/src/femsurrogate/plotting/diagnostics.py`, `/src/femsurrogate/plotting/comparison.py`. +- plotting 함수는 matplotlib Figure를 반환한다. + +## Acceptance Criteria + +```powershell +uv run pytest tests/test_plotting_and_results.py -q +uv run ruff check . +``` + +## 금지사항 + +- browser dashboard를 만들지 마라. diff --git a/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/index.json b/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/index.json new file mode 100644 index 0000000..f8edac3 --- /dev/null +++ b/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/index.json @@ -0,0 +1,30 @@ +{ + "project": "FEMSurrogateTutorial", + "phase": "3-notebooks-and-final-verification", + "steps": [ + { + "step": 0, + "name": "dataset-notebook", + "status": "completed", + "summary": "Added and executed dataset notebook that validates BeamExamples, generates LHS samples, builds FEM dataset, and writes reference CSV/metadata." + }, + { + "step": 1, + "name": "model-notebooks", + "status": "completed", + "summary": "Added and executed five model notebooks sharing the same dataset, target, and split seed while saving metrics, predictions, and diagnostic figures." + }, + { + "step": 2, + "name": "comparison-notebook", + "status": "completed", + "summary": "Added and executed comparison notebook that reads saved metrics and writes model comparison CSV and figures without retraining." + }, + { + "step": 3, + "name": "final-verification", + "status": "completed", + "summary": "Ran full pytest, ruff, all seven nbconvert executions, and verified comparison outputs exist." + } + ] +} diff --git a/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step0.md b/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step0.md new file mode 100644 index 0000000..a54531f --- /dev/null +++ b/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step0.md @@ -0,0 +1,23 @@ +# Step 0: dataset-notebook + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/PRD.md` +- `/docs/ARCHITECTURE.md` +- `/src/femsurrogate/` + +## 작업 + +`notebooks/00_beam2d_fea_dataset.ipynb`를 만든다. Notebook은 BeamExamples regression 검증, LHS sampling, FEM batch run, dataset 저장을 설명하고 실행한다. + +## Acceptance Criteria + +```powershell +uv run jupyter nbconvert --to notebook --execute notebooks/00_beam2d_fea_dataset.ipynb +uv run ruff check . +``` + +## 금지사항 + +- 핵심 solver 구현을 notebook cell에 넣지 마라. diff --git a/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step1.md b/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step1.md new file mode 100644 index 0000000..a93d66d --- /dev/null +++ b/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step1.md @@ -0,0 +1,39 @@ +# Step 1: model-notebooks + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/theory/02_response_surface_methodology.md` +- `/docs/theory/03_gaussian_process_kriging.md` +- `/docs/theory/04_random_forest.md` +- `/docs/theory/05_gradient_boosting.md` +- `/docs/theory/06_mlp_neural_network.md` +- `/src/femsurrogate/surrogates/` +- `/src/femsurrogate/plotting/` + +## 작업 + +모델별 notebook 5개를 만든다. + +- `notebooks/01_response_surface_surrogate.ipynb` +- `notebooks/02_gaussian_process_kriging_surrogate.ipynb` +- `notebooks/03_random_forest_surrogate.ipynb` +- `notebooks/04_gradient_boosting_surrogate.ipynb` +- `notebooks/05_mlp_surrogate.ipynb` + +각 notebook은 같은 dataset, target, split seed를 쓰고 metric JSON과 prediction CSV를 저장한다. + +## Acceptance Criteria + +```powershell +uv run jupyter nbconvert --to notebook --execute notebooks/01_response_surface_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/02_gaussian_process_kriging_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/03_random_forest_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/04_gradient_boosting_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/05_mlp_surrogate.ipynb +uv run ruff check . +``` + +## 금지사항 + +- 모델별로 다른 split을 쓰지 마라. diff --git a/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step2.md b/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step2.md new file mode 100644 index 0000000..166ebdd --- /dev/null +++ b/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step2.md @@ -0,0 +1,24 @@ +# Step 2: comparison-notebook + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/PRD.md` +- `/reports/results/` +- `/reports/predictions/` +- `/src/femsurrogate/plotting/comparison.py` + +## 작업 + +`notebooks/06_compare_surrogate_models.ipynb`를 만든다. 이전 notebook 결과물을 읽어 RMSE, MAE, R2, 학습 시간, 예측 시간을 비교하고 모델 선택 가이드를 정리한다. + +## Acceptance Criteria + +```powershell +uv run jupyter nbconvert --to notebook --execute notebooks/06_compare_surrogate_models.ipynb +uv run ruff check . +``` + +## 금지사항 + +- 비교 notebook에서 모델을 다시 학습하지 마라. diff --git a/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step3.md b/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step3.md new file mode 100644 index 0000000..4e308dd --- /dev/null +++ b/FESurrogateModelTutorial/phases/3-notebooks-and-final-verification/step3.md @@ -0,0 +1,37 @@ +# Step 3: final-verification + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/PROGRESS.md` +- `/WORKNOTES.md` +- `/docs/PRD.md` +- `/docs/ARCHITECTURE.md` + +## 작업 + +전체 검증과 handoff 문서 정리를 수행한다. + +- `uv run pytest` +- `uv run ruff check .` +- 모든 notebook 순차 `nbconvert --execute` +- `/PROGRESS.md` 최종 업데이트 +- `/WORKNOTES.md`에 남은 주의점 기록 + +## Acceptance Criteria + +```powershell +uv run pytest +uv run ruff check . +uv run jupyter nbconvert --to notebook --execute notebooks/00_beam2d_fea_dataset.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/01_response_surface_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/02_gaussian_process_kriging_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/03_random_forest_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/04_gradient_boosting_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/05_mlp_surrogate.ipynb +uv run jupyter nbconvert --to notebook --execute notebooks/06_compare_surrogate_models.ipynb +``` + +## 금지사항 + +- 실패한 검증을 성공으로 기록하지 마라. diff --git a/FESurrogateModelTutorial/phases/index.json b/FESurrogateModelTutorial/phases/index.json new file mode 100644 index 0000000..a86aa12 --- /dev/null +++ b/FESurrogateModelTutorial/phases/index.json @@ -0,0 +1,20 @@ +{ + "phases": [ + { + "dir": "0-project-foundation", + "status": "completed" + }, + { + "dir": "1-beam2d-solver", + "status": "completed" + }, + { + "dir": "2-dataset-and-surrogates", + "status": "completed" + }, + { + "dir": "3-notebooks-and-final-verification", + "status": "completed" + } + ] +} diff --git a/FESurrogateModelTutorial/pyproject.toml b/FESurrogateModelTutorial/pyproject.toml new file mode 100644 index 0000000..cbc84fa --- /dev/null +++ b/FESurrogateModelTutorial/pyproject.toml @@ -0,0 +1,46 @@ +[project] +name = "femsurrogate-tutorial" +version = "0.1.0" +description = "Korean tutorial for FEM structural-analysis surrogate models." +readme = "docs/PRD.md" +requires-python = ">=3.12,<3.15" +dependencies = [ + "joblib", + "matplotlib", + "numpy", + "pandas", + "scikit-learn", + "scipy", +] + +[dependency-groups] +dev = [ + "ipykernel", + "jupyterlab", + "nbconvert", + "pytest", + "ruff", +] + +[build-system] +requires = ["setuptools>=69", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.pytest.ini_options] +pythonpath = ["src"] +testpaths = ["tests"] + +[tool.ruff] +target-version = "py312" +line-length = 100 +extend-exclude = [ + ".agents", + ".codex", + "scripts/execute.py", +] + +[tool.ruff.lint] +select = ["E", "F", "I", "UP", "B"] diff --git a/FESurrogateModelTutorial/reports/figures/.gitkeep b/FESurrogateModelTutorial/reports/figures/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/FESurrogateModelTutorial/reports/figures/.gitkeep @@ -0,0 +1 @@ + diff --git a/FESurrogateModelTutorial/reports/figures/comparison_fit_time_s.png b/FESurrogateModelTutorial/reports/figures/comparison_fit_time_s.png new file mode 100644 index 0000000000000000000000000000000000000000..d79208b1a5daf0cb9e23892834fdd32e50f6b95b GIT binary patch literal 24138 zcmeFZcT|*Fw>OAwx1nuNM8zhGwtyheNJfG!0!oyeDTS6CBxlf8i9#7jf&@WQkwkJV zl~5{4D3S$&f>2O|l1!0m_Mz|Fw{Li7zFF&jYu;HifAq3Zs_LodIcM)*+9%?wmMY_q zY(FwEFfd-Zd`XvqVRs1w!*})j_Q2mP#81b=AF`gx#-4hvHl9A$-ES~xUiZA|o94WDIEaplr)`o2$RKkctF@Tynb7P<45pXqb>{Xdej{;&w!r}O>`MWRQ%RHJK; zSlD5Y_kNSOJblYDvuwNU8&+1iH>|>W)dYCdB4tio%)M!#e}Q=jPhQ-juTH)CxR>ea zZt~fV>1DZ%kK}^#6;sFJ@|ADHBYDbs`U0ondiZa}N7wI$|G8>(@htptkEiK7_~H2f z;18|FHJq8D_HTFgWOWA3dD!1! zl(d`qWWl%fl~3^swQf;McJ1>WV#j&vkln_7JvB%qnnUIs{ZqDPav(iDPpTjPa@ zk4~$1D{jwYmvR)h&LnidbP3p|k%_9@L9uj&FLzlSz90COkJ%ECF!=MPT|9e1Y!$9S zESmGYBt2*AOFC zogCPo{v^sf^oCLxlf~4+EU7$Sv~Xy?Q|X|5nJMR-en?TPFUQ0{e%6+Y-J~Q(37Z1+_jhE0axI+*K&##M>pJvno_;KGo_sh$!TK`c$D1j zz2y`txKn;f37D(4AFlJ0;9_YdtY@&fNUsc7=chW-4ByqS4ktIPHH%~yR*(d^??g+I z_-CuhsZ+L!8z!c8zHX*R=gqCoyQRLzx#HKC)X45$X^rojB$%<$xF(*t1dQwQw2N}T z$@1c{>+Y#NS@$+Qn*qNNN? zPj4)=if9MSl&F$?$D$XjKl)D>5)<&7<4Xh9*sM@b`qpX=+(B`#={})KOpIfp4|Ujn zBxqIB$imA2ez%g%Gk`(!_9J5kTw9WaU`U?pS&@b{tL+SK9v)d{Q`h=s0bwb((I)e8 z+Sckw=dRyrxZLafg5RFTuY1!{EI%$ z8RBxdTdJz&H|7)f&0*yhE;lHblQ!mRMfMKXgwHlBTw06XVjO2mxp=qas7WvRs?m5% z)@XImx7T}ViQaQV)h*}pPxh6=3v%G5@fM5xG5b`;qq{g{YdX+nbUl*%jn)~W5Jr*? zn-4KhkQ%zFVvZxX76r^g; z*e;KI4?0(NvuMldl*cT%QyVs1@{Ect{i{3Ojo=p%KkN=uJDoW|fR4tq?oXgFOdEdG`_o>zs7EJs^XIfg0 zh-q1_=jtaP@{}n3^PPjjg*fT3@v%Bt^2?&m>js=2ZK8hlZupa4A1fK9hFC+gx zfHPd9-}bXGE>r)7cYKRuZ`fVybY!8nsuh}5b}UkBri=VJu|JF1#F|z(J?WPST>I8N z^RYC4qJFXCe3mMg-}9vuY9JqV_p2I}@E_8b+FgT71*$Hk&q5Q}{*HrZ?ul*cnV`*i zg5&8Xmlv=1Wc6DH6poJNhYjpI1-IFznEELsnyZBcWWUNlXxyEraLWQYYGzjjW&S%MitDrzuEGaQY0n`3)O2EX0|v zx;BL~`#nkVCgtgKGv`{%Z>=xq_xm$MUQRY)!?Y_j3JiVNu-weV9 z-sqH<&BUCa%XK(U>n#p0Z?Vp-oUrS!sj*7i3u~6X4Ns)TbUK_;z_TJkGBG?%_!W04 zVNl~`L9R+eyX0Vx^jRpYnBI}DVgJXPl6hWF>>hJE=d@{QK?bN6ti2Cq-~ z*QZJj-E73IRQ9g!PM0}kwd<|?A=QnVkEOObW-isIeJo3fTIUVQCGLA?h^jcEjurZ>D;wWLDZz(7jWB z_4%n7>61P$SQLNKr{3i!T?%zierIrWY&pKsX|w9;pz~0bn_sp2hWWO0zlBesuQaZ5 z*EW{EhK&*D^fC|4^P8p^?+l8n?r^gA*IQ?haQeOORjGoVFQ%z|}apNe?nB_-1H- z`~;gNtu8hIThv;e=UV)FeE4xDAH_GQ<&f_DsVkeGj~Fak8|UO&?0QkeY_%)*vE3K+C?B>Ie#j*?5c)2~ds)GiYS)ro6oi=f7X* zRm~;X{8~7l=SK`2@&&QV>m+%B!xqiZi%Y4?DGK zXa26x3iBIsY8Tnn^)s`NefL;Tm@xyK9Us^HS?hV}X{+|A@wgvaRzD+f)w6HWG$W?jUE$fopfzIQR4#p5*Ej!W}8TTvi+1QPh`RBNvuk zHXM4EIeI0JNA03*$J6RJ6qi6wY6HYsOZwwoNuhZs9HNi@9*s=Ra^vVHu>^gTdeKcmnJ* zWZeHUJLTq^{X0!-gubXq7dx2A!YO56e1+@Rt^8t~ie(?pTr`6wL2&j#VzuqioG1sMl*4Y>~Uf44U1 zinnlkay)~tLsfddiDl6r6HFV&(Ms@G#cf~V=;^LZ!Z}W(LPjq?rezaX4*KN1$}^GN z(iwU$s^(S!B@GdMmbry8#$K#FBR^1L%JXk8DBAblEr=kAGs0pQx#h26{Kn&GbYF|z z1s-ex>81>9{ixmNrd78UY9>o&MN17=^<*eV-N-%&ZBsm8Wrl6q_~q|c?4f-WnF@1N zcB!zBZ&X>pyJWq-vzP40YJT&#XhH(FRPg4S>FQ#fk!7B#@V4bcxHZ{jy@qB6LLmF-s%~eh z{GwX~K}Dpj%W)pI8NKKx-r6o!I;LydsX#E)Awuhqcq%`CjBD&lOGPLndwiPFQVhF6 zR%Rw{z;Y>u!+N5~F87(lGlYkfYp0=bN*l3a$w$cPb;C!!_$w-!r}<(w5MK-2BHYx_ z5#w2K^ISSwT*99vf@Q6%$uRXR;8XJ)^T+l(IPt~k_3*E~(+++_kS`kka^zJ_hVm~T zTZZ>D@JH_31TfGVqFPHRtQ@W>@!8LibQJ3Piywt+XI=)^PYv6sg$LYsWMLQl$}0HU}RvsO=)7d+8%pGFaBq;L}+_NY7DEexv|7- zte)08=kQ&(%C*CPxaE+sBq7`Ovy_W@l0uL_SBA~IN2jYBpC6YzE!#sIA}f#+3qz@Z zm=Tb}WD%OMKd5rJHOU6lakAVp==Yc4+RZRspp_z<1?^pE#Ll=Y^X8Iaod9scGOe^d zgzvBQo{9K@fg$}@&zbKT7%p7j2l@xYkUhoMC<*xmivvS=hdwGGxojU4qECW4gCVIeth@||I03l?%~>Faq8D{G?ObNrQlsZ z{66!dk!jh#4mc14!;ebgJD+~{U-5@bFKa4%5s$9Lf&lgaR=Z!sgcU!Ogzd@r1-}2S zHvpnQNBN28pZ#$EP1t~P)Um9^PDRD#>3)%N&>x(u$K$7}#$wa~p<5O%w`fR+}!y2UEJU)JfJ@`EDpuA3tv}!N-gJSi&9n?Kie_zhAET`bfPSN_1K%6K7Jz zu>UmDCVKE8^d(@W#og=MYXrq?PVWJptx;C|g3s_h~OX^;@ z>0U(HqXSt9mPuS8oAc(n>rgCYyr2+ibAwnTJ6lF{kC*`xtDoZ~Pv2aWDf6cEoRRT_BBgAAzM3m;qg@XshG>`&Sg4(eP#-*-Ue!4p;)ukp&)uY*{nTbi%MQO_Kt=M(-Pc!MnNr!gRx)T~==~#g##C@1bwdLk7 z)y&mQcOMK{Ym6&$1*R!@_E~g^?XFuBSzX0UsQ@PL z38+n^vlp9NoOw{^hw^s$n}j6ipzr$?g(k(367;<)qMizaEYNnli+3j!)}p z;yTDw1m9@4>wqs~YrJQZTE@1lQi8Q&|r^5H^t?gwZ$3=HBT|ASiX|E%)+|G(S+eJx#Q?NF^shd#vV|&#&LLI8er4ukepxE$&e=%J^+%#`{{Ywt4CyYWIp1x7BGe7iX*VqMR3ws% zdrp23w{E$Q+Jh&o_ODYQN?T@mae+>BG{*-tyW1;l(86qfwi2md>gLc#xP0lKw1G0U z={nd&eIJJ5OMP(4XA!ZilitzQgJ#S74SyK;6(pcCK+M_uS$Lo4r26BSSHb1D6{$e$Nb!1?@^&L(s;`QL+z+J0tkj;Q%kw5!Qxp_x@}r!}kubX4|F(NmdqaK>;O7 zHOxmNRZi;jFuJA!H7jksHD`2NUl1^qCUYTKS< z05{Da%OwxL882iu!S$dKN*ASE7*@xBQ>CY;L1MMcPC?~4I`ajO_vcr)^E}8M)r65V zdf7dRivCNJfgvA$+uQ4SzN=64?YyL?|$9`ilrwg?tRD81l0@@TnE=H@moR`NQu~T z($|a8?N7i2%NSj;1l|YALVfpm0;VB8jT64rw8j-DyTJ-)HpSpTq+7aw;}EmaU@B=0 zWo+G5270`gX=m`pYy!w`Rb{XDus;WPMcha^c)ppH2nNDOPk^)J^dVSk65E0Be#Rxo zvT_AmO?9~VDk|K5-*wB&th02^87-i;s?7@oE;fGFqcuB_a6t=&~}O#xM;pOj`so1=)ZDHlgTXLqIylvwxHA(#YhMN~8K zS01Fe=9dji4f~!-0YGh^7PN8&MEu|HP!U>c|Fua0oJxDJ_wqm^ucmxkU^+kZB2dwL zX28Id>Vx0-G}N(zfY6H|gvy_U4dkQ+%Z?ynW^{952~^`gzZ9sDn4(9UcepoCIG46d zGM43_?-kpZmu}PX^a-`rYuXSMeq@Z~EF+Q`L_R-q1(`Imi)~`l<*x9NO3hQys&pxE zmy@JiE$jOZUf6OjeNAAp7VAw+YXlRebyab#65)NrLenf8R;x^@(GO6}BNxwmPClTH zfQ}(sNCok+{kG5M+I$`;NsLv0UI?Jg(50`BwX+?Is(CqqjMxK@!L6=Cv8#A{ zPXIeZPiGYMScNjS^`(ug^S@F8}Arln2)c5R@6Gy90NIkuz~B1q2rPzfKH$xqqeZCoZo)3x-XUx zQRvKJ0!$#)_S5uDDLr7`FS;sbYaAQc7HjT!3H^^(T+`y{Xt~uP4|`x!_JG#4YJs1T z20+MQm`>j#7*W5qGDt)i>-m+(@lO!-%=wE~rqSALyMeqtiWjyZT}|Ghr}i%nZGdYa ztNG;I>1FB&-htEO`Yz-Nfi zoDz|PC@~Ap^c4_mF2h!%y5B@(NEavrQ6z-c8cIURjrPlT?hQzd1d2JA_ZqfputVD; zA(y>jV=kFK0xmT%HDK8KImG%vpdYQ0?xG-JRuBQ04k$)E<7vT z^fgskD7Hl4!$jb%$sN*T_i=tm|3s!0$_B*yX`Gev{q{L@_$a)nPqdKT{RXh!%eEJe0$!9J`>a-FiLt&y_OdewceY=GC5hr8&+MHBXR09aA8OG&r_tz7oEVuZ+s2uipl-*h)5@FZv?64gC zd<#2z-0v$BxldQ{rFiQ8^@@u#D(ud&Ez#@=s7HAcIDMXjp-!F(Stq6~2!#&Pn)nnR zw%q?&FQ=juuH!}Bp4sbXNHtopLs5JN31l6;QHl`9=>e;|tW#m*IWj@=K)q+IzVhdl zQ+caEy|SPD@Qj8cVwx|(f&>xJ{L0Lmdk0Xa;mJhXlgG$~HcdDWos-=kRoa3v*heY^ zO>$aD@H$eJ@61HTJ9cH<+gVX#_XeUw8l<_nb)=Gt3@On1k zrs127j41AO87seHOalDMiIkEg7lPK}M7#Q(y$6q7LmPITr^0ol!A}FpsdfuID|cD6 zE`xrdEoReZmumnk`&H8Z5@hTVVc{=}+kHrfQXz$~i&PH|-XQ(Dl9MzFBq7BnaTdf2 zhhCgPv)ObXqk0WWAe=^F^7K1INz39eaf&lh6V5TKmueu@31|dj}2(SDi=! z66RNh0J+^Go)u~cJpjok9ta@c;{C*1p_ikDgfzx-S@;!W51y4{tc;KcU_eAs56@Pi%IC24&j-O%)-rQ0H(;u0 zjT(+}1vnH+5=U2z7GttYO&*2HAAwRUjuwVHFkMG!W^I0q-N68U>4lBb%;(p4{_(?k zZ}^;B5}N4uu6-)j8UnI4^c%6tZA`b=5|V3PN3jT$8Tz27E3TK%X=U4%_>igyPyELA zUi1xFtfY&NI+b385{&aRaXS4CYu^aK0gKR#QDXJ9J>GRz`onS_)VtV znLR~nCNuVYoIrV$(4T&OBwYRV(bDz?H3yW)Z15~(quC?`peHG!o9kt%JwpUT>gi6n z4hV1#G&&I>*w)B$REG<(MmZ4n-%;!5zv?xL5LUbpyG?0=rN6yD*@Hc5COA0xcb*U^{YR5i`LFqlDGGxbao(Dk>;%LJ1DZgI72x}|Hux3Z|yS;nw z#0JH*+#ycg@6^{8e`p#Q>K1IybY_1(rq%>c6?+@!thBBSHS zGDYMw;ddvLB`q}4)!deZ5mt!AT zg1ea4fT9(Fiq~GizfV+bH%&!PVSgK;ZoIX37m?5$z!qEJX&% zpngyv{S9(nQ z9xL!JKVyh}9xA3_2iCjb8I*$jEfp5)W(7!Z+C#_E=6ibcqCZlX94+8F#P9R6SQ#0t z&V5?kDljQUdQY({`%p*9`J6jUvivCch3tuCQ&#xpcJZdUGNKkOc;V|iBx9>4_l4rN zMM3oPF9!SRmd$aiy-Xa5>Q^#Zvj1K2;LgfjmH@XRklVT&w*HR5V*NJtzX;HcW0$nw zb)C`s2$X6EfpjQr%-rbng3g;A!NS)!pi)*D9g}jhNu_q+_{Dwjd0y#0qb)Z95M{fK zwTv@>%|0U6q<#Ou`M;?g!li*r(sB^Z5Qmh&jci50;!_z>!fL3TkpLih?585MukJen zFkzF9{61XAbNI4$9QT+?oChm3QH@Wq@HW|T6%s|QyJ7u2MJ_4Y{HUGD7Lq?G9c&+a zrvOk+=7Y*j=l&uK5~OOo=Ly_tS_-tUWzEOT3g*c`8(&41^A}PEBpol@XW2k;Qxuac zY<)l0)F&BpmcdaQ^bfD9N)!SFZtrefE$}ffCEvdyU5%TC+V!lY$n){`+EX zpoa3!h%aW|ydPYW@_Gav`gS=who>O_3ERb{G-^kO;Pxw1kqBq#QN2P#0OMLU@`Izg z`*)x@1PvqTk<_=)iF3OI_ z>QPE}kV>Bay#WfRc)8QZbDY6zU#8%uI)!iTw1$3ONm308hyK;T&|YIK7eG%1ginyW z$Qu?upCrKbtDw+pNT78Y{d>Du1<`6Kj|hL6078P%a)<@oV^1$BRBpt|Njxiw)-mr^ zQ_lNztb#nXBybNk5MxIkNq^q$PWonN8H&8ou~43eO7vpi!zH~+`rz)xEsY$v&Bacm zEhJv%2o_akJX?XUk01p4mcXvlDRih(uJCsszT#M1fsmspWZUVN;6c78?g$fbb7bWk zzzoW-wTItJ%Ijq+8384;d$nP;Ui|mB4{-KCQf(UwH9Q&0!EEdOw9{yN9Kr_lv}8`B z@ardN_V(Z;*#pf(?5@qAJy-`B?uUPI;odVt5aTw|m zLv%jq-1DQ&_FvyVq)|aFmISxE#9{c`m&P5U&8w04AQd1*T+uY*Z79XYRM3kAX$y!p z(Wodb#kkD@?_|fzBZ*t@NCQJ3zysp-Et?QiJUfErJYQis_;JS)1z=t5Ux-kk4Tn|Q z-w^_6L#D;EbpX3)!O-T4AyEqN*}~%uq=D98R_THo79KRcWs=sC7Don=AO4-q=z0KO zFa*mNgPi5}sM>0N0hVVr>%0kJG*>q8I7vVah$glv24uo4L@SQw;QwY)=hp*3xbG~v zHt@_Tn{Cl!z^gwHnZy6?dq8fZ49es$K@hucZ=4$f#lUY9l|T4kb*t8TW)btM7o(d$ z960uM1C~SKLJeqyAI*cL{Vz03Bsn5l_EHU-2CL;qb-P;6sh96JzQ54uKW~8_lQfE^ z$;^Og6G*=klCOQniGPOA*H8NC-}Em)AA-eok5(X8jdX_`lqO0ETzJR$q7p7a{4Qv7 z3m>E&^Jy1Jxx-K`ojF%c^4) zrOQ+LSWg$DoUG*t2&l=y5R{ktQyR42}Oq1uVhDs4O30jUDs0VJS-_3mUV6 z&m?G97l^t8F)43g-6w~=dLr#+MH#GgWrMsO7ppg@MtP3?Mb$=M#%m=Z#Dv%0X;WbVr$3nq_dgA>{PTFrzu3Rr?}K?JaYp#2l_fs6RnCFj&l!LM zMpynfjW_)ZHI6Qbp}~qVE`_W>vC@!6d)4NvvLc1NAiLO7DtRo6d!hoGqLbhp0 zp2-8GVh?m$1C$f8|9fkImdqQr|F3lcFVlWx z7A!%YqIfJxvAk~F$>h*F9@D zfgN_EG+y^IM0pi)>l?sPFiJaIuJmlg-_u6A^zALjHbsb}Eo_0@!hW5K?jsA>tF5y} ze{-b!DZv0pUrZpk`ak>5L{bHcsz2TCRu>uP!jjvQ6Oxjk;#Q$`*nOl})tJ4G3K*Hz zKt}rY#$sQ2e_*@gA0x}47bgL8?cG$ff&rhcKo}SKyI)aWgIHLB%srt9=l2fNpQ_9+ z4gy~7>8V?DxgOG)o|-heywCB@YW+mM=*X(MPrH$I$Z*X{Qn9e+w^~cYwyr-`ua+7G z*V^zY9w=!b8a(*xT^UP2Wa?an;3*DjYrQI#%h3xtPR1Va^?gY8If06P3tthlMM>?y zy=?bhCJh8l<+njQ%WBy~D%%Dyv0P>_+(0&Y21z2YSEeAp^FAcacQnGl`C237m>1Sw zfKa6c4@SLr3G!muC{>yQwLE%<{fm$N8O;%Q8LAS88K@qhN=TuS6P^M2PZ#(K5g@&> z_5J5l#GD*x13kw5NCpo)0Ki120XvRlO56<)2W!NEl1psYp)a#n$qC6Sp!5(yo{mQd zM;t&(8R&>P;67xj3s?UF<+re7Ix;5xqz=^0fooj+Z*R$A#VTU?R0RTf z^oA9ZqaGMi`4h^Yp-ONP@9t;m2G5|p+pGPF7$0(Zt{_nxrhP1gBZO)f-V5rXos2>) zOE4K*^vo714ziq9h+T+>Y;X4DXs4Nb`TB)%dK))z!?-F0Gto3Gni)eXmOU_5Gn-+Q z3u2O;OfQ1~k0)$=iO*uNThl+@{Vxu5QLop()o!2B$p~pr*zCxgM&G@#ND!rwkLDBjWh?`R7n4M&e&P^GeFX8O(^BJ3-ayDt zF+t2z;SBg!Z6V`|YKSq2(IS^+Ymv$ItbwDPJ^lxZPIU(zn#`-mUw=PHsi4vPkv1}NS zN#BK3VTN|zCKaq9@?y3(npm_894gsV?jL_h@Z^;9y-9+qi_6A>l6%nA-Rz1? zI1@yLu;XlWpIMTGJSgpXKs60oF;I?o@Cq8OLfOxFlm0rt#cq(9Q`Nn#bK|tZ463dq zp$r$|cg2nXrd{sZg7|RZi@KH4KRN}PSs?gw{*@b=HO}8V5H|(k?DfHs?Rc~y%ufcu zn$AMuHl%rIvm*b64f9MLrNZqjf3(;^UyD0-;y)X!zreXP^HB^0DXS;;;LyA!TD2`? zM3E15o=(;CIFD_=BDX5NM|l;df}VE`&*tV(ALcm2a%mfv|cF8P1-mp_(ImSxG$687Mgs? zBBurjm%EM(ckzcK?u?)jIH5g_;B<6D1g#t02w~8?35Sz-;L{9=Xe<-l%kzZd3!tYH z2Wl_Kwzq zAp&*R11H8koi@DMkWieDCZa3*NlvBh3+3e~Q-cOQra)vXT&{`iz6WlySmpeVEsiF3 zP?@P40$$TlB@;I(LOXjV3rn;5c~Jn|eNjUAK> zt~RZz#SKu#bT{~~=5E{|Ys7W{n+sGJlUDtV=8U@`bz_vjP66Dqun2)nAzh%Ex{y`u zMv*~tPItfFG&0KnLbOoiIhtRmZh-wngp5Ffi9&_nObKBEk8B*A_w82h{N8yKB|x!f zT4GE2aRUiZ|1I1;qL7Klp;jM=?vIR0(~)1Jo*-PfmPp^g)76ppiYTZ;2Tbs~kpN#3 z(MWJ)D-sx{z!-c>KDTlvegy1~1xG7*m<9xq4l{HZ!a2ezOIt7JL5}`cAS=W{BJg1! zCS?((@;_wQY z-zzA1jER+lXJh~B)-HQchzweXp`+QuSro0skJmP%sh;ymMNtcG*wu}ymeIgwzZh=y z4(J?_#k<*b_V?{lgyG)N$JISAZ?tw>2Fx0)L-x^}(wlE&pBXJFfPzJS!_dib@lcsn zQ@tU|5f6R3z8fqAy>-a=>+h`JC9ud!&+; zY0+`bY-HUqm=O(9cM>LGfbZQRE3ALAD@6IT(BOn$i3Xhhu(%{W*NRl|#h0Rr73}0i zC}L+J)LG;S+0wWg$gYwNYL1P{2~lB_ws-QmxOJd9u{nIWl~Dc-1~IIkjEkT#$JMNX zPVFFyo*y1j61jRHsaa@n&w&P_NP#%CE;*6-2(o?y%BbWAGL6c_R&rC_;P41rg@Zt1 z+lXUHfzUVN{o3Gg4Yj=-H!q~(A@=#T|21SE)FF=Zo;VtK7S#7A1au?=rc+cg#$JxV zqZImeS}{BNxTw{Waj<1fNa(k zd;@Txa0+B|{ni(#N<5b8Am&5 ztpu5v-|8&Kf=(1|8Ha?Aj|IuaPXQ5DI9QUp;1}Nc2ZhYD@@&(5?0E2(1DLnuFK7fP z*g0V&Cs%Q~~&S;xW z8zFLYf*6`w^CIVTVbNyl5{ABvp?Ptv&MSNXNmx##kDVN!{abj}H>3@qqPZ{&g%{`| zR$)EY6O~1&R8j*2Veb$+KSE*)@K!4(+iDnz3z6IdZX2K{*T$!EYSMO>Z$4WGoNLq` z_3a4e!{`A7p6lAiMw0>|TPbL1H2+&5MC0`}L!h6ir)_@aTddO#9A(MMjFH8a0SUy> zpgFpvvhFID!H13=7zHG3W}PxWu%>Iam3R*VSEWk;w`CQ*K_h8xs|8VaacQ3_q%rc7 zwxRo!mW{`o8P2L&T%3Vc)Ljs`qN{4lG#b z)5B?i+P(%w21Rv-zckL~D1x=sccV{-$-TEzvyQvTtE3KshY2Vfw&|xIwAI^r#VKI4 zDZ+qw>Z;0#NWa#w5#-_ftwW{7YkYeO!BnPeaTjMMyD}G-syYxT!%fZacD_qYtPIR` zXj?5>aLif{xENIQZow^vfeyxGuQ3@Nq9dnxkqGH^TsC2O17ZX6o##Q!ha0eAtP#as zJtp?7rphHgL_610bHTM2V>Zt@3kacjo~sI4(^qcpv1L<9h)r<#S_cPq^qg*r$KZPt zu$|Eh5?f>3^npD4lXX`7b!%R7!^Wd`e)nS*e$P#cYha*%-m929p9p^cIHq~btyeMd zJ@j;4;;=C>}^hHtqOd@kqY0)Bq~u)EpH4=t&~?E*qN2#CUfa<)psR zkKB$Yn}jhAI>W)==T*UEt|!gf8*q2OZyO4V;6xH`%s0OAgtXBtE;`*u#4Ubuc%tv8*jJ2zIl|lcecxss}mPKTJL!mr4O+q7{b=CxV0H)mR zv*Yos&S4ph>SeaHjS;$~b#R&9okO!6iZHJ%;_+*Sym48;QxN!Fj8-K2BV=@SBn6t8Hi_&2|mvN{&7(+Qx_b@dipD1MXyDm*hJ-BVV+utTNzE-n3M^yGJ+ULThU6skj~nk` zD36F}kFCPulc5%Ozb;|1qAtjc*HSi>2RC6#BpXG}k#kYGD+g|Z1Fc3RYK)_JFwP<> z-@V?z|KR=Af~t6wJ@Fd#@UckuvHG!i)8=sWrr;Dr!V0lM_;~~W%=-tYfyHC;%M_9l zNJaOM_!_cL#r9XXsOht^6A|`wS{mJCUbJiK-9pBx2c(HOa`6F73}un6$l21fjrq$7 zS*yHuz$8Y?KD2Vn!GMc_^D!cLuc;=XhHovb+lNwQ3Y|WVH)Bu4T~Zb6y55;ok+IrL zAvoM1oRz&2;pf(tp_dDD$#oRbaxYW8RLgpnJZUWR=Fa&+C>Y{Xw!lrF=ccKT1B^@P zAG~VlInxO0T~+sVMWCi|h_ecx26G0=@W@&`791>A+bDbKp*vMY2)JBlnITp_`BP2> zp*h%yGL(O&-lwobqWb0P<4Jw~OJp-a_ErhY&iPZ9zb{;ypFytSjz11VDzi%v@H+?X zF0HlSW0U_C&a7)$e-KWzp%gzp8j)@q>?|Zwl(JTGvZ!>eB(mjn(;IECK^1kB;|F~MUn)k^Sr#`0u*9IwByvqa8X>|{o{-EFGaSzOceZAQHI&0Jrt$owqOYL zUA=;;{VWX5q++af)cOvwjSlpCYpN9YFn>Rm1iq@+g2Zu5ymc}JdPUsdIXU7n3Km{9%Ad(A=lTm>&+_AOebA${Nb|{Qh&5B|4BQ2Q^mOcJ0WP zOMR-UN7>8iyfc=r1u_@U-ebjwHXk|wNqf_xAM5H8Et4nv6dJx7CUIH$erL=ndZ`(m z#1nWx$3g_hxswux)R;QJw_Cdh8H&GWRNrnwJ4z&vT+Su#AoqT)At7qR==C=HN$I?4Bb9&B%%I>9omO9oa)R?Um z1>;(ZChNpc=X+=tX;dGPYq?|D`z${rb{j?sIx3H^kYP1AyYwAWwBmp&CxJ61u4O!z zaJZx|5G`~tdZP9^@iX56*jKG~ckhfhOM8_^pFf`APg+O?KgK*xT21G@wbsQTW%g?K z06Yj5eY>2~`@cmtg!dRSmUd4o;3Aq?JB}02wQQMN2GR=h!3i{q=HYO*?tkv?HNN)8 z&{YA>wA>aBGS7E@v_R$F)+!KJDn}O)rdad~KV0Bm-hTX!_@ycPEbbqy0!b9-P@|<& zI`?1yyrH+XT*ezipqN*7tw^-U7X@>wMp)i$8{h3zc14Ijsf+276eHQG3=XKhuIl#U zC}$bn%B!Hc1!jI~<*`uR6zO1}FOPNjUpYUp>)bDNC zz&xefS?3G55l=Mf`p)Ou1TtJQXoubD`$U9UCncvsQiW%aQt_~#-cQC{_(YYsB4gLU zpKlp3<9k|)m)(R6SW~)U&%5Ro&f0nyr1jr)exDM8EOF{NVy1wPQ_dq6Eoq(+f@FS( zN%XHbLANjNUg-n~Zhn{@j%j%;B0_2#hQ?malDf{Hu5MwZvemGDfBg~AZS|? zx;1u0llo8B>M)_8eUd+4J(e=@6p96nO6lbtI{>L^uEb7z4J?BZoYR6G*Qz}ERT)lE zLqpol+`-#0i$AeSp%mxv|A2*;7B?-I@+!ASPNws#87CYJ*@;iWxn;O*EK}pjea(yf zKKqVZad$#C(7d^x=hBD!+^tsiZZ0?s2BqiOWZZvmCd74G$GR9D#Jib@ zx-N|51=3y~hcmIoDHN)vxNvX8nYzi_qNFzh)~P)sJv4RdiRvMUexeP;-N2Hd875B+&%?X*gv&_>mj?WYn8f@=uNS#&%7+>U%MvQGKSbZXB6~j!uedUq+Me zb4!h`$BZ4>C7s#`vdqH~kx_s9eL5F82@**{O`=hY$Fs0*sVBn?Ngbfe7?$JR3R||7 zsU$b8(V-@<3Y_9s@%Y|qUL)RN)r@$w!=G>2Nx;rQHSI2CH zTRzJ4l*2g@-0m+PF5cKj>dk+yQv6m_WY~6e>m<&TaPVB$L~^-c@bf5-pGS6&1vUkE zn``TM{L;~WCgd~}@OKx>i~$Myn8L}unTAj;bu=&3 zSE{_AH*#-32!?R@1OsQMNX&Il(<9f~Te#izGPq%tawHQPpsMx2XPryH5`l zQwKU1N(3;KqL;2NnR8(tjD5YOc^9I}bP>Yt1skGFpC2F{3HqVjZE$@mIB}Q3<_c z6303KP;NFFd{0{A0c*vcMkw?(pE2`dzHde2zk;Q?wHK+e>|xWY>m*1VR>Ua)g)*QL z=XdMZ^|u5Z(^QH&ezu~-=exexH3P+lUoS1EOdhTu+QS=qApA3BAF7%gDQz;*n1tzK zr3H4S?3FcZEm93S5*jQY>g-t#Fia;-e$FeZpH~rzKW_R1o055e=<_QU_aPw9$S&y= zO=bD8wExc&abi-y>G(f6?d6}ilIhGK?`Kd@hv=;t+DYz?`>)JYx2y_QFc0F2!D-_! zwjFqJo$)1x0i7Ad;sz>DpDY#4XPACsWw67+**JE;7n+u02Z8 zEX0bCUK#x|gyBOhOf7x*J`i|;CYlOCv59CuW*0P;;0Y~Q;(f!e3wq#4TwwWzj;X8U zEYx?F&PGSSFoJz`Z@LPdPyuS>V@Z--W)Fmqb`G+I6J-U_;f_ZWFlbl-&WhX_f>;2i zcLg1-1t+e~|5%C6bsLu~0zK2q6f{R7Imwg7;3a4I0TA`eFI%N4efw~F#6bC>Nw{@odeF@@pEn$bu>Bt^!fwtXWWn_dIL zS{6DfN()9qIx3z`kq8b&{mhNpdcX%+O31Ql#B-HJV8Oq zK|^zhShmVd5EQrF{2?~!eqswoexJ<2gd;k3;WE6&0N635E#4>^xoQp4iuysh zZx_~q+opo;8iSl!vhHX1IC5Ov*Y7R_p=WsM(tbPr&cb1Jx6OKpWj{yqS-FA>x10E*qb>6d8CRPHj1knNs&2HzBJiNGtP7!t6PXF!B z!WNo2l9k6W7;_dHP3thcVq@-g%anD~-y4iDP{eSGq`ns>HWy}_DUizz#UwW^c zd5gwbUht92(^tnWm1K~b1ybv=CAs(9jCH{N`k(*63U1S-<2k_7n08+I2CU_M=l?jO zo^>XEAB*X&8*LH$CV@6bKH6Y&cULL!yyGuHy=7Y%Hkg4*4Bs=?fqi@#p=6HPUTr{>{;JxT6!eAl> zoJgBBgJbE%btX(1xo^W(cRwr!ou#^N=d)R$ZOCE1{R{IJ9e)Je?DzEC45b~@T>TF{ z1kOi!gNEgd9$x~bK+)~Or``OIgVO7CNwyVlfIE16K+9->i+Q4+KIdU5U20{>AaVzo z9%g}d0F(d+pO=7U|3MR|J4MW^l=~F(L5JV01Ew3PMw7NfovBF?b3tR?0#dfh#|!K( zN`Ly4eDqjR;H}@FqM{Z!dUNK#`|P`XvQ|(07OMdl+_pdH{FuD>l_A3#POl`!1X+}5d14N5B-I+YX;2fi>kf2O z#7p22QNExB(%pe^7hPul>;k1cuJuRZ~F=l{Md-@p2Xo;ZV)S2u7o wbJm8fz?s$qQcH+CjSENlOlp}PBJ!XA>r7>1ky+omffWLSr>mdKI;Vst00c2gPXGV_ literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/comparison_mae.png b/FESurrogateModelTutorial/reports/figures/comparison_mae.png new file mode 100644 index 0000000000000000000000000000000000000000..625f9eeb4a294da19a961f4c65f1dc40f80fcf86 GIT binary patch literal 25303 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 z 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 literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/comparison_predict_time_s.png b/FESurrogateModelTutorial/reports/figures/comparison_predict_time_s.png new file mode 100644 index 0000000000000000000000000000000000000000..3331a614315ecbf2840bc67e98fa02f6c7c2ebae GIT binary patch literal 26399 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 V75!}GWO#bQF4sLfZfy@p{tq;4#m4{u literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/comparison_r2.png b/FESurrogateModelTutorial/reports/figures/comparison_r2.png new file mode 100644 index 0000000000000000000000000000000000000000..5d8db5d2319be2d621d335faae872e50e9e0dc8b GIT binary patch literal 20450 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 literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/comparison_rmse.png b/FESurrogateModelTutorial/reports/figures/comparison_rmse.png new file mode 100644 index 0000000000000000000000000000000000000000..25efe96f529c3af14dc466a1c596f1f9cd163a49 GIT binary patch literal 25572 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 RR7p%W6DSn>Rct$W=^s*0pFjWr literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/gpr_parity.png b/FESurrogateModelTutorial/reports/figures/gpr_parity.png new file mode 100644 index 0000000000000000000000000000000000000000..00cead6303d429607bb2ebbdc7a3972bf9b614e7 GIT binary patch literal 40436 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 literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/gradient_boosting_parity.png b/FESurrogateModelTutorial/reports/figures/gradient_boosting_parity.png new file mode 100644 index 0000000000000000000000000000000000000000..02141bd8fd9c6fb9d41300d8fd3c4b7ff950e278 GIT binary patch literal 41489 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 z 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

kC&gKg4+||Ly(?$Y1 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 U5!R|86`SU6-Ce0Wj-LC!0F9?-djJ3c literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/rsm_residuals.png b/FESurrogateModelTutorial/reports/figures/rsm_residuals.png new file mode 100644 index 0000000000000000000000000000000000000000..c38127a95f256d6a26584e21b504371cd456d509 GIT binary patch literal 37915 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 MB;_U2uix?fAD(JctN;K2 literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/predictions/.gitkeep b/FESurrogateModelTutorial/reports/predictions/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/FESurrogateModelTutorial/reports/predictions/.gitkeep @@ -0,0 +1 @@ + diff --git a/FESurrogateModelTutorial/reports/predictions/gpr_predictions.csv b/FESurrogateModelTutorial/reports/predictions/gpr_predictions.csv new file mode 100644 index 0000000..ba028c4 --- /dev/null +++ b/FESurrogateModelTutorial/reports/predictions/gpr_predictions.csv @@ -0,0 +1,61 @@ +y_true,y_pred,residual +-0.0098010662183848,-0.015250421684545492,0.005449355466160691 +-0.0038113194658788,-0.0017486039076851003,-0.0020627155581936997 +-0.0027310799449712,-0.00530647071310256,0.0025753907681313605 +-0.0100024342038305,-0.010316738327277896,0.00031430412344739603 +-0.0499253522341076,-0.04382392281863989,-0.006101429415467707 +-0.001425202073237,0.005078412534373628,-0.006503614607610628 +-0.0082152702385898,-0.009571524248486946,0.0013562540098971468 +-0.030294940628359,-0.02508246148372859,-0.005212479144630411 +-0.0003394669209404,-0.0023962303315858673,0.0020567634106454674 +-0.0104094868935342,-0.017755890098581213,0.007346403205047012 +-0.0007458704516273,-0.001982076369748365,0.0012362059181210648 +-0.0019926250153884,-0.003373505311388497,0.0013808802960000974 +-0.0067094522111387,-0.005789165245259511,-0.0009202869658791885 +-0.0007713230369176,0.0012402266579821346,-0.0020115496948997346 +-0.0009264786171953,0.0010793023104413834,-0.002005780927636683 +-0.0048682939239769,-0.010842246768661199,0.0059739528446842985 +-0.0015514429803847,-0.005987417572614714,0.004435974592230015 +-0.0082797555491993,-0.006796396801820442,-0.0014833587473788582 +-0.0067435512728419,0.00680790397400651,-0.01355145524684841 +-0.0002679427721747,0.0006763820975785838,-0.0009443248697532838 +-0.0117102395891512,0.0006489142032870647,-0.012359153792438266 +-0.0038564225187403,-0.0035722131493459413,-0.00028420936939435853 +-0.0043643611560866,-0.002491745084681229,-0.0018726160714053709 +-0.00690334164553,0.00027024498753304947,-0.007173586633063049 +-0.0032694837296735,-0.003198392657812337,-7.109107186116298e-05 +-0.0065802327277111,-0.006997526861566011,0.000417294133854911 +-0.0057609873946602,-0.008005191210867332,0.0022442038162071324 +-0.0978259601841187,-0.10476466176020587,0.0069387015760871695 +-0.0012815473411189,0.005795482786457884,-0.007077030127576784 +-0.2116989856844677,-0.1421513721299082,-0.06954761355455952 +-0.0005873182212224,0.003556659925605549,-0.004143978146827949 +-0.0102808405040129,-0.013683666669211234,0.0034028261651983336 +-0.0274808302842225,-0.023811924704933395,-0.0036689055792891064 +-0.0055843874647924,-0.004446019039931307,-0.0011383684248610932 +-0.0936698604467179,-0.08476905261398741,-0.008900807832730492 +-0.0042383507360532,-0.0028395908107003084,-0.0013987599253528918 +-0.0064139601803737,-0.002776365124053777,-0.003637595056319923 +-0.0500503637977256,-0.04468561411923253,-0.005364749678493069 +-0.0032551040880256,-0.007385900526260484,0.004130796438234884 +-0.0006720203919551,-0.0017365014801694594,0.0010644810882143594 +-0.0140013434972624,-0.018657807128895445,0.004656463631633044 +-0.0136746738089856,-0.01026732343038411,-0.0034073503786014904 +-0.0029028424886419,-0.006199045083251903,0.003296202594610003 +-0.0002977300790917,-0.003466576745293704,0.003168846666202004 +-0.0004013312796635,0.006938137232452899,-0.0073394685121164 +-0.001387036808518,-0.002671626354811536,0.0012845895462935358 +-0.0032416418934662,-2.721371817649039e-05,-0.0032144281752897095 +-0.0012865758997511,-0.004382274888399403,0.003095698988648303 +-0.000781489181828,0.014354677949252189,-0.015136167131080189 +-0.0282740230807759,-0.024446790443019183,-0.0038272326377567153 +-0.0014462597918054,-0.0025761975119785365,0.0011299377201731365 +-0.0009190994374579,-0.0015752616401020422,0.0006561622026441422 +-0.0024183380949151,0.001816942808085446,-0.004235280903000546 +-0.0080349039892428,-0.008306703776443457,0.00027179978720065674 +-0.0317498587484236,-0.026193372689921272,-0.005556486058502327 +-0.0028680506091303,-0.006249707444856041,0.003381656835725741 +-0.0327551701410487,-0.032500451863128575,-0.0002547182779201254 +-0.0002898009271785,-0.004854942238588591,0.00456514131141009 +-0.0049641733799332,-0.008914425892218376,0.003950252512285176 +-0.0005541404200699,0.0025102185642642497,-0.00306435898433415 diff --git a/FESurrogateModelTutorial/reports/predictions/gradient_boosting_predictions.csv b/FESurrogateModelTutorial/reports/predictions/gradient_boosting_predictions.csv new file mode 100644 index 0000000..a9e3487 --- /dev/null +++ b/FESurrogateModelTutorial/reports/predictions/gradient_boosting_predictions.csv @@ -0,0 +1,61 @@ +y_true,y_pred,residual +-0.0098010662183848,-0.011534131293699368,0.0017330650753145677 +-0.0038113194658788,-0.004566781630798601,0.0007554621649198006 +-0.0027310799449712,-0.002569043760932535,-0.0001620361840386649 +-0.0100024342038305,-0.008113001885148158,-0.0018894323186823426 +-0.0499253522341076,-0.05179401032427151,0.0018686580901639063 +-0.001425202073237,-0.0027429307062308422,0.0013177286329938422 +-0.0082152702385898,-0.005244392438185645,-0.002970877800404154 +-0.030294940628359,-0.026941379068354337,-0.003353561560004662 +-0.0003394669209404,0.0011920263930887208,-0.0015314933140291207 +-0.0104094868935342,-0.02009314147825499,0.009683654584720789 +-0.0007458704516273,-0.0006783343667398965,-6.753608488740351e-05 +-0.0019926250153884,-0.0035238050937769078,0.001531180078388508 +-0.0067094522111387,0.0045098371679258165,-0.011219289379064516 +-0.0007713230369176,0.0009525966890204713,-0.0017239197259380713 +-0.0009264786171953,-0.0010291487366641794,0.00010267011946887947 +-0.0048682939239769,-0.008554456850656682,0.003686162926679782 +-0.0015514429803847,-0.003701977800637113,0.002150534820252413 +-0.0082797555491993,-0.010581044499564738,0.0023012889503654377 +-0.0067435512728419,-0.03214833568118499,0.02540478440834309 +-0.0002679427721747,0.0012861204508787876,-0.0015540632230534876 +-0.0117102395891512,-0.011566111843574601,-0.00014412774557659956 +-0.0038564225187403,-0.007016644417818661,0.0031602218990783608 +-0.0043643611560866,-0.0037020847290705405,-0.0006622764270160595 +-0.00690334164553,-0.006957646097004912,5.430445147491282e-05 +-0.0032694837296735,-0.008033853112083723,0.0047643693824102225 +-0.0065802327277111,-0.0029191448483979277,-0.003661087879313172 +-0.0057609873946602,-0.005458264133573717,-0.0003027232610864827 +-0.0978259601841187,-0.07722849901007466,-0.02059746117404404 +-0.0012815473411189,-0.0006360341549186051,-0.0006455131862002948 +-0.2116989856844677,-0.08524519557269143,-0.12645379011177627 +-0.0005873182212224,0.00015120038122322824,-0.0007385186024456282 +-0.0102808405040129,-0.013413515680865662,0.0031326751768527613 +-0.0274808302842225,-0.021333224751441966,-0.006147605532780535 +-0.0055843874647924,-0.004638268193139127,-0.0009461192716532733 +-0.0936698604467179,-0.10583589880087134,0.012166038354153433 +-0.0042383507360532,-0.006994619539973823,0.002756268803920623 +-0.0064139601803737,-0.00721593555420163,0.0008019753738279295 +-0.0500503637977256,-0.029980393421298147,-0.020069970376427455 +-0.0032551040880256,-0.004159641884839451,0.0009045377968138514 +-0.0006720203919551,0.000695861307391559,-0.001367881699346659 +-0.0140013434972624,-0.012330661500693965,-0.0016706819965684357 +-0.0136746738089856,-0.01605569638030974,0.002381022571324139 +-0.0029028424886419,-0.0023341567334053885,-0.0005686857552365115 +-0.0002977300790917,0.0018160654458535613,-0.002113795524945261 +-0.0004013312796635,0.000462792310109772,-0.000864123589773272 +-0.001387036808518,-0.0002553521012893653,-0.0011316847072286348 +-0.0032416418934662,-0.0034662863630390488,0.0002246444695728489 +-0.0012865758997511,-0.001419939312063704,0.00013336341231260382 +-0.000781489181828,0.0004714048460805055,-0.0012528940279085054 +-0.0282740230807759,-0.01656459879962216,-0.011709424281153739 +-0.0014462597918054,-0.001017996892076924,-0.00042826289972847597 +-0.0009190994374579,-0.0030369363287297622,0.0021178368912718624 +-0.0024183380949151,-0.0027257756235102245,0.0003074375285951245 +-0.0080349039892428,-0.013922103226463197,0.005887199237220397 +-0.0317498587484236,-0.04130074037606117,0.009550881627637571 +-0.0028680506091303,-0.004243174200819291,0.0013751235916889906 +-0.0327551701410487,-0.023406512064579634,-0.009348658076469066 +-0.0002898009271785,-0.0003650281642084131,7.522723702991309e-05 +-0.0049641733799332,-0.005214160126186096,0.00024998674625289607 +-0.0005541404200699,0.0014239990341411483,-0.0019781394542110484 diff --git a/FESurrogateModelTutorial/reports/predictions/mlp_predictions.csv b/FESurrogateModelTutorial/reports/predictions/mlp_predictions.csv new file mode 100644 index 0000000..c9fc2b2 --- /dev/null +++ b/FESurrogateModelTutorial/reports/predictions/mlp_predictions.csv @@ -0,0 +1,61 @@ +y_true,y_pred,residual +-0.0098010662183848,-0.012802577507486139,0.0030015112891013385 +-0.0038113194658788,-0.0046515848170360155,0.0008402653511572155 +-0.0027310799449712,-0.010083004760998512,0.007351924816027313 +-0.0100024342038305,-0.020845283706657287,0.010842849502826787 +-0.0499253522341076,-0.040221134519255825,-0.009704217714851776 +-0.001425202073237,-0.009762081791064406,0.008336879717827405 +-0.0082152702385898,-0.016983972468944918,0.008768702230355118 +-0.030294940628359,-0.038763408487603644,0.008468467859244645 +-0.0003394669209404,0.0035130197140065145,-0.0038524866349469145 +-0.0104094868935342,-0.022486601392994278,0.012077114499460077 +-0.0007458704516273,0.008186185488004654,-0.008932055939631955 +-0.0019926250153884,-0.0024680978973060427,0.00047547288191764287 +-0.0067094522111387,-0.00822713371747703,0.0015176815063383305 +-0.0007713230369176,0.00270054572699867,-0.00347186876391627 +-0.0009264786171953,0.010416977768376428,-0.011343456385571727 +-0.0048682939239769,-0.011506092562164864,0.006637798638187964 +-0.0015514429803847,-0.009492646984972703,0.007941204004588002 +-0.0082797555491993,-0.021706863748004304,0.013427108198805004 +-0.0067435512728419,-0.024564514477627017,0.017820963204785118 +-0.0002679427721747,0.003440036938729933,-0.003707979710904633 +-0.0117102395891512,-0.01948773259389725,0.007777493004746051 +-0.0038564225187403,-0.009001834137222772,0.005145411618482472 +-0.0043643611560866,-0.005807071720011332,0.0014427105639247323 +-0.00690334164553,-0.012051489346343392,0.005148147700813392 +-0.0032694837296735,-0.014340233862364537,0.011070750132691036 +-0.0065802327277111,-0.023390501917222473,0.016810269189511375 +-0.0057609873946602,-0.009722949790975566,0.003961962396315366 +-0.0978259601841187,-0.04217063129833486,-0.05565532888578384 +-0.0012815473411189,0.0006427388868981282,-0.001924286228017028 +-0.2116989856844677,-0.03964152265257154,-0.17205746303189617 +-0.0005873182212224,0.013045438142832844,-0.013632756364055244 +-0.0102808405040129,-0.014460966326431212,0.004180125822418312 +-0.0274808302842225,-0.020779704750440366,-0.006701125533782135 +-0.0055843874647924,-0.011569739698444227,0.005985352233651826 +-0.0936698604467179,-0.04673036973556968,-0.046939490711148224 +-0.0042383507360532,-0.015102657835677205,0.010864307099624004 +-0.0064139601803737,-0.021855516256323176,0.015441556075949476 +-0.0500503637977256,-0.04096821507960851,-0.009082148718117092 +-0.0032551040880256,-0.009473373379514092,0.006218269291488492 +-0.0006720203919551,0.008151921529756209,-0.008823941921711308 +-0.0140013434972624,-0.027026365760490362,0.013025022263227961 +-0.0136746738089856,-0.018268174014002526,0.004593500205016926 +-0.0029028424886419,-0.005384453894577489,0.0024816114059355893 +-0.0002977300790917,0.01502494424731751,-0.01532267432640921 +-0.0004013312796635,0.008176262367795053,-0.008577593647458553 +-0.001387036808518,-0.0039136142664811455,0.002526577457963145 +-0.0032416418934662,-0.0005496866955882595,-0.0026919551978779404 +-0.0012865758997511,-0.0015485890387889768,0.00026201313903787666 +-0.000781489181828,0.00021154768682392702,-0.000993036868651927 +-0.0282740230807759,-0.0361710784496896,0.007897055368913702 +-0.0014462597918054,0.0010447393076983297,-0.0024909990995037297 +-0.0009190994374579,0.0005076838393030369,-0.001426783276760937 +-0.0024183380949151,-0.005814615168676113,0.0033962770737610134 +-0.0080349039892428,-0.017259202204240334,0.009224298214997534 +-0.0317498587484236,-0.01979978011856444,-0.01195007862985916 +-0.0028680506091303,-0.0025464659000482004,-0.00032158470908209965 +-0.0327551701410487,-0.02888314308530364,-0.0038720270557450615 +-0.0002898009271785,0.004474162373067482,-0.004763963300245982 +-0.0049641733799332,-0.009564500114358745,0.004600326734425545 +-0.0005541404200699,-0.008223453061769786,0.007669312641699886 diff --git a/FESurrogateModelTutorial/reports/predictions/random_forest_predictions.csv b/FESurrogateModelTutorial/reports/predictions/random_forest_predictions.csv new file mode 100644 index 0000000..5fb6cfb --- /dev/null +++ b/FESurrogateModelTutorial/reports/predictions/random_forest_predictions.csv @@ -0,0 +1,61 @@ +y_true,y_pred,residual +-0.0098010662183848,-0.013052973102582651,0.003251906884197851 +-0.0038113194658788,-0.0030832217758694816,-0.0007280976900093184 +-0.0027310799449712,-0.003443617119201804,0.0007125371742306044 +-0.0100024342038305,-0.006389981087977729,-0.0036124531158527717 +-0.0499253522341076,-0.015352738964269329,-0.03457261326983827 +-0.001425202073237,-0.018459481777023584,0.017034279703786584 +-0.0082152702385898,-0.004456616612166581,-0.003758653626423218 +-0.030294940628359,-0.0233835822329406,-0.006911358395418399 +-0.0003394669209404,-0.001335100166637542,0.000995633245697142 +-0.0104094868935342,-0.029524370191124354,0.019114883297590153 +-0.0007458704516273,-0.0010697310437712045,0.00032386059214390447 +-0.0019926250153884,-0.0020536291218114233,6.1004106423023525e-05 +-0.0067094522111387,-0.014557394629973457,0.007847942418834757 +-0.0007713230369176,-0.0012499540750173254,0.0004786310380997254 +-0.0009264786171953,-0.0012898747386864487,0.0003633961214911487 +-0.0048682939239769,-0.010281716791039721,0.005413422867062821 +-0.0015514429803847,-0.006064928713181127,0.004513485732796427 +-0.0082797555491993,-0.01020851915611972,0.0019287636069204202 +-0.0067435512728419,-0.05887513385526359,0.05213158258242169 +-0.0002679427721747,-0.0014368826831020398,0.0011689399109273398 +-0.0117102395891512,-0.00897904191064286,-0.002731197678508341 +-0.0038564225187403,-0.007064039332542149,0.0032076168138018488 +-0.0043643611560866,-0.0038693413391170145,-0.0004950198169695855 +-0.00690334164553,-0.0038950530678037608,-0.003008288577726239 +-0.0032694837296735,-0.006531726228139853,0.003262242498466353 +-0.0065802327277111,-0.01746332239669454,0.010883089668983442 +-0.0057609873946602,-0.0042079257092469515,-0.0015530616854132484 +-0.0978259601841187,-0.06427351865985945,-0.03355244152425925 +-0.0012815473411189,-0.00131837298277374,3.6825641654840034e-05 +-0.2116989856844677,-0.07299885186088179,-0.13870013382358592 +-0.0005873182212224,-0.0008764204060906751,0.00028910218486827516 +-0.0102808405040129,-0.025656683515613517,0.015375843011600616 +-0.0274808302842225,-0.0233500781934777,-0.004130752090744802 +-0.0055843874647924,-0.00360254423169254,-0.0019818432330998602 +-0.0936698604467179,-0.06835084136803436,-0.025319019078683544 +-0.0042383507360532,-0.008322436707289365,0.004084085971236165 +-0.0064139601803737,-0.007978798272136524,0.0015648380917628237 +-0.0500503637977256,-0.029134230073410976,-0.020916133724314626 +-0.0032551040880256,-0.0038575984824836713,0.0006024943944580715 +-0.0006720203919551,-0.0008321139785327232,0.0001600935865776232 +-0.0140013434972624,-0.009220030597946776,-0.004781312899315625 +-0.0136746738089856,-0.012918969755213044,-0.000755704053772557 +-0.0029028424886419,-0.007061520705634288,0.004158678216992388 +-0.0002977300790917,-0.0008244792974268024,0.0005267492183351024 +-0.0004013312796635,-0.0006335738388530976,0.00023224255918959758 +-0.001387036808518,-0.0022687878733974104,0.0008817510648794103 +-0.0032416418934662,-0.0031708494223524506,-7.079247111374922e-05 +-0.0012865758997511,-0.0020774063656214905,0.0007908304658703904 +-0.000781489181828,-0.004022832924982734,0.003241343743154734 +-0.0282740230807759,-0.023201264759851178,-0.005072758320924721 +-0.0014462597918054,-0.0021273945521054927,0.0006811347603000928 +-0.0009190994374579,-0.0011891624177935518,0.0002700629803356518 +-0.0024183380949151,-0.002935912586886879,0.0005175744919717791 +-0.0080349039892428,-0.012493932904864844,0.004459028915622044 +-0.0317498587484236,-0.02917403551090198,-0.0025758232375216183 +-0.0028680506091303,-0.002477127846164984,-0.00039092276296531607 +-0.0327551701410487,-0.020574378594002435,-0.012180791547046266 +-0.0002898009271785,-0.0030515507112431066,0.0027617497840646066 +-0.0049641733799332,-0.005639149529924011,0.0006749761499908113 +-0.0005541404200699,-0.0033415931535627887,0.0027874527334928885 diff --git a/FESurrogateModelTutorial/reports/predictions/rsm_predictions.csv b/FESurrogateModelTutorial/reports/predictions/rsm_predictions.csv new file mode 100644 index 0000000..404e844 --- /dev/null +++ b/FESurrogateModelTutorial/reports/predictions/rsm_predictions.csv @@ -0,0 +1,61 @@ +y_true,y_pred,residual +-0.0098010662183848,-0.008063708243651395,-0.0017373579747334052 +-0.0038113194658788,-0.0036842415434730005,-0.0001270779224057995 +-0.0027310799449712,0.0015855198478710482,-0.0043165997928422475 +-0.0100024342038305,-0.020768772136692537,0.010766337932862037 +-0.0499253522341076,-0.08634072145899263,0.03641536922488503 +-0.001425202073237,0.009057330651376155,-0.010482532724613155 +-0.0082152702385898,-0.01623359805579585,0.00801832781720605 +-0.030294940628359,-0.05494634739863705,0.024651406770278047 +-0.0003394669209404,0.0003057217392075026,-0.0006451886601479026 +-0.0104094868935342,-0.025186470928988097,0.014776984035453897 +-0.0007458704516273,0.005123479401716775,-0.0058693498533440745 +-0.0019926250153884,0.006483277853635958,-0.008475902869024358 +-0.0067094522111387,-0.004951368629097145,-0.0017580835820415544 +-0.0007713230369176,0.002431470422207911,-0.003202793459125511 +-0.0009264786171953,0.002098379150773981,-0.0030248577679692808 +-0.0048682939239769,0.0023269502345097445,-0.007195244158486645 +-0.0015514429803847,0.0054304376400158855,-0.006981880620400585 +-0.0082797555491993,-0.011235438686456989,0.0029556831372576885 +-0.0067435512728419,-0.01513640141753062,0.00839285014468872 +-0.0002679427721747,0.005023227034898421,-0.005291169807073121 +-0.0117102395891512,-0.021353175562886392,0.009642935973735191 +-0.0038564225187403,0.0024523028133941953,-0.006308725332134495 +-0.0043643611560866,0.0018118523029535282,-0.006176213459040129 +-0.00690334164553,-0.011090572616019383,0.004187230970489383 +-0.0032694837296735,-0.0010327942129321746,-0.0022366895167413255 +-0.0065802327277111,-0.010449659009701765,0.0038694262819906657 +-0.0057609873946602,-0.004202124085317911,-0.0015588633093422885 +-0.0978259601841187,-0.07849009051035474,-0.019335869673763953 +-0.0012815473411189,0.0045897836777313485,-0.005871331018850248 +-0.2116989856844677,-0.11236685970490985,-0.09933212597955786 +-0.0005873182212224,-0.0038346423165307834,0.0032473240953083834 +-0.0102808405040129,-0.011514380677840113,0.001233540173827213 +-0.0274808302842225,-0.03997989882186454,0.01249906853764204 +-0.0055843874647924,-0.007827865894016085,0.0022434784292236845 +-0.0936698604467179,-0.07675546207236617,-0.01691439837435174 +-0.0042383507360532,0.0005673146824279073,-0.004805665418481108 +-0.0064139601803737,-0.011035615882888063,0.004621655702514363 +-0.0500503637977256,-0.07016141645387532,0.020111052656149715 +-0.0032551040880256,0.00548188417318066,-0.008736988261206259 +-0.0006720203919551,0.0009801902763272793,-0.0016522106682823794 +-0.0140013434972624,-0.025223749239703955,0.011222405742441554 +-0.0136746738089856,-0.033649129185114264,0.019974455376128665 +-0.0029028424886419,0.0016175132552921486,-0.004520355743934048 +-0.0002977300790917,-0.012343066428881081,0.012045336349789382 +-0.0004013312796635,-0.0019906728761898054,0.0015893415965263053 +-0.001387036808518,0.014394621344358304,-0.015781658152876302 +-0.0032416418934662,-0.0017551803377404158,-0.001486461555725784 +-0.0012865758997511,0.011086934940341958,-0.012373510840093058 +-0.000781489181828,0.009985914013305923,-0.010767403195133923 +-0.0282740230807759,-0.03956474679869234,0.01129072371791644 +-0.0014462597918054,0.0017128674505823053,-0.0031591272423877052 +-0.0009190994374579,0.008880594747871942,-0.009799694185329841 +-0.0024183380949151,0.006026571466815343,-0.008444909561730444 +-0.0080349039892428,-0.012179467818523977,0.004144563829281177 +-0.0317498587484236,-0.03552887414112901,0.0037790153927054135 +-0.0028680506091303,0.0019507691371565064,-0.004818819746286807 +-0.0327551701410487,-0.06483928482330545,0.03208411468225675 +-0.0002898009271785,0.0050500589361993,-0.0053398598633778 +-0.0049641733799332,-0.001537216194153125,-0.003426957185780075 +-0.0005541404200699,0.015848580403955245,-0.016402720824025146 diff --git a/FESurrogateModelTutorial/reports/results/.gitkeep b/FESurrogateModelTutorial/reports/results/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/FESurrogateModelTutorial/reports/results/.gitkeep @@ -0,0 +1 @@ + diff --git a/FESurrogateModelTutorial/reports/results/gpr_metrics.json b/FESurrogateModelTutorial/reports/results/gpr_metrics.json new file mode 100644 index 0000000..896d16b --- /dev/null +++ b/FESurrogateModelTutorial/reports/results/gpr_metrics.json @@ -0,0 +1,9 @@ +{ + "model_name": "gpr", + "target_column": "tip_uy_m", + "rmse": 0.0102275703149458, + "mae": 0.004887524852501009, + "r2": 0.8984149766904297, + "fit_time_s": 0.15534250007476658, + "predict_time_s": 0.0016494999872520566 +} \ No newline at end of file diff --git a/FESurrogateModelTutorial/reports/results/gradient_boosting_metrics.json b/FESurrogateModelTutorial/reports/results/gradient_boosting_metrics.json new file mode 100644 index 0000000..842f30d --- /dev/null +++ b/FESurrogateModelTutorial/reports/results/gradient_boosting_metrics.json @@ -0,0 +1,9 @@ +{ + "model_name": "gradient_boosting", + "target_column": "tip_uy_m", + "rmse": 0.017503204254034725, + "mae": 0.0056308989929006875, + "r2": 0.7024774700809826, + "fit_time_s": 0.4196564999874681, + "predict_time_s": 0.0021611000411212444 +} \ No newline at end of file diff --git a/FESurrogateModelTutorial/reports/results/mlp_metrics.json b/FESurrogateModelTutorial/reports/results/mlp_metrics.json new file mode 100644 index 0000000..8c0d137 --- /dev/null +++ b/FESurrogateModelTutorial/reports/results/mlp_metrics.json @@ -0,0 +1,9 @@ +{ + "model_name": "mlp", + "target_column": "tip_uy_m", + "rmse": 0.02540606802811113, + "mae": 0.011091159933185777, + "r2": 0.3731557450209999, + "fit_time_s": 0.114232899970375, + "predict_time_s": 0.0020921999821439385 +} \ No newline at end of file diff --git a/FESurrogateModelTutorial/reports/results/model_comparison.csv b/FESurrogateModelTutorial/reports/results/model_comparison.csv new file mode 100644 index 0000000..381ad6e --- /dev/null +++ b/FESurrogateModelTutorial/reports/results/model_comparison.csv @@ -0,0 +1,6 @@ +model_name,target_column,rmse,mae,r2,fit_time_s,predict_time_s +gpr,tip_uy_m,0.0102275703149458,0.004887524852501009,0.8984149766904297,0.15534250007476658,0.0016494999872520566 +rsm,tip_uy_m,0.01692421409745107,0.00986868711451997,0.7218354651088679,0.008010599995031953,0.0015782000264152884 +gradient_boosting,tip_uy_m,0.017503204254034725,0.0056308989929006875,0.7024774700809826,0.4196564999874681,0.0021611000411212444 +random_forest,tip_uy_m,0.021182094831369028,0.008076487480895672,0.5642648925820651,0.6153512999881059,0.08771130000241101 +mlp,tip_uy_m,0.02540606802811113,0.011091159933185777,0.3731557450209999,0.114232899970375,0.0020921999821439385 diff --git a/FESurrogateModelTutorial/reports/results/random_forest_metrics.json b/FESurrogateModelTutorial/reports/results/random_forest_metrics.json new file mode 100644 index 0000000..353edd9 --- /dev/null +++ b/FESurrogateModelTutorial/reports/results/random_forest_metrics.json @@ -0,0 +1,9 @@ +{ + "model_name": "random_forest", + "target_column": "tip_uy_m", + "rmse": 0.021182094831369028, + "mae": 0.008076487480895672, + "r2": 0.5642648925820651, + "fit_time_s": 0.6153512999881059, + "predict_time_s": 0.08771130000241101 +} \ No newline at end of file diff --git a/FESurrogateModelTutorial/reports/results/rsm_metrics.json b/FESurrogateModelTutorial/reports/results/rsm_metrics.json new file mode 100644 index 0000000..fd8be90 --- /dev/null +++ b/FESurrogateModelTutorial/reports/results/rsm_metrics.json @@ -0,0 +1,9 @@ +{ + "model_name": "rsm", + "target_column": "tip_uy_m", + "rmse": 0.01692421409745107, + "mae": 0.00986868711451997, + "r2": 0.7218354651088679, + "fit_time_s": 0.008010599995031953, + "predict_time_s": 0.0015782000264152884 +} \ No newline at end of file diff --git a/FESurrogateModelTutorial/scripts/execute.py b/FESurrogateModelTutorial/scripts/execute.py new file mode 100644 index 0000000..8016252 --- /dev/null +++ b/FESurrogateModelTutorial/scripts/execute.py @@ -0,0 +1,417 @@ +#!/usr/bin/env python3 +""" +Harness Step Executor — phase 내 step을 순차 실행하고 자가 교정한다. + +Usage: + python scripts/execute.py [--push] +""" + +import argparse +import contextlib +import json +import os +import subprocess +import sys +import threading +import time +import types +from datetime import datetime, timezone, timedelta +from pathlib import Path +from typing import Optional + +ROOT = Path(__file__).resolve().parent.parent + + +@contextlib.contextmanager +def progress_indicator(label: str): + """터미널 진행 표시기. with 문으로 사용하며 .elapsed 로 경과 시간을 읽는다.""" + frames = "◐◓◑◒" + stop = threading.Event() + t0 = time.monotonic() + + def _animate(): + idx = 0 + while not stop.wait(0.12): + sec = int(time.monotonic() - t0) + sys.stderr.write(f"\r{frames[idx % len(frames)]} {label} [{sec}s]") + sys.stderr.flush() + idx += 1 + sys.stderr.write("\r" + " " * (len(label) + 20) + "\r") + sys.stderr.flush() + + th = threading.Thread(target=_animate, daemon=True) + th.start() + info = types.SimpleNamespace(elapsed=0.0) + try: + yield info + finally: + stop.set() + th.join() + info.elapsed = time.monotonic() - t0 + + +class StepExecutor: + """Phase 디렉토리 안의 step들을 순차 실행하는 하네스.""" + + MAX_RETRIES = 3 + FEAT_MSG = "feat({phase}): step {num} — {name}" + CHORE_MSG = "chore({phase}): step {num} output" + TZ = timezone(timedelta(hours=9)) + + def __init__(self, phase_dir_name: str, *, auto_push: bool = False): + self._root = str(ROOT) + self._phases_dir = ROOT / "phases" + self._phase_dir = self._phases_dir / phase_dir_name + self._phase_dir_name = phase_dir_name + self._top_index_file = self._phases_dir / "index.json" + self._auto_push = auto_push + + if not self._phase_dir.is_dir(): + print(f"ERROR: {self._phase_dir} not found") + sys.exit(1) + + self._index_file = self._phase_dir / "index.json" + if not self._index_file.exists(): + print(f"ERROR: {self._index_file} not found") + sys.exit(1) + + idx = self._read_json(self._index_file) + self._project = idx.get("project", "project") + self._phase_name = idx.get("phase", phase_dir_name) + self._total = len(idx["steps"]) + + def run(self): + self._print_header() + self._check_blockers() + self._checkout_branch() + guardrails = self._load_guardrails() + self._ensure_created_at() + self._execute_all_steps(guardrails) + self._finalize() + + # --- timestamps --- + + def _stamp(self) -> str: + return datetime.now(self.TZ).strftime("%Y-%m-%dT%H:%M:%S%z") + + # --- JSON I/O --- + + @staticmethod + def _read_json(p: Path) -> dict: + return json.loads(p.read_text(encoding="utf-8")) + + @staticmethod + def _write_json(p: Path, data: dict): + p.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8") + + # --- git --- + + def _run_git(self, *args) -> subprocess.CompletedProcess: + cmd = ["git"] + list(args) + return subprocess.run(cmd, cwd=self._root, capture_output=True, text=True) + + def _checkout_branch(self): + branch = f"feat-{self._phase_name}" + + r = self._run_git("rev-parse", "--abbrev-ref", "HEAD") + if r.returncode != 0: + print(f" ERROR: git을 사용할 수 없거나 git repo가 아닙니다.") + print(f" {r.stderr.strip()}") + sys.exit(1) + + if r.stdout.strip() == branch: + return + + r = self._run_git("rev-parse", "--verify", branch) + r = self._run_git("checkout", branch) if r.returncode == 0 else self._run_git("checkout", "-b", branch) + + if r.returncode != 0: + print(f" ERROR: 브랜치 '{branch}' checkout 실패.") + print(f" {r.stderr.strip()}") + print(f" Hint: 변경사항을 stash하거나 commit한 후 다시 시도하세요.") + sys.exit(1) + + print(f" Branch: {branch}") + + def _commit_step(self, step_num: int, step_name: str): + output_rel = f"phases/{self._phase_dir_name}/step{step_num}-output.json" + index_rel = f"phases/{self._phase_dir_name}/index.json" + + self._run_git("add", "-A") + self._run_git("reset", "HEAD", "--", output_rel) + self._run_git("reset", "HEAD", "--", index_rel) + + if self._run_git("diff", "--cached", "--quiet").returncode != 0: + msg = self.FEAT_MSG.format(phase=self._phase_name, num=step_num, name=step_name) + r = self._run_git("commit", "-m", msg) + if r.returncode == 0: + print(f" Commit: {msg}") + else: + print(f" WARN: 코드 커밋 실패: {r.stderr.strip()}") + + self._run_git("add", "-A") + if self._run_git("diff", "--cached", "--quiet").returncode != 0: + msg = self.CHORE_MSG.format(phase=self._phase_name, num=step_num) + r = self._run_git("commit", "-m", msg) + if r.returncode != 0: + print(f" WARN: housekeeping 커밋 실패: {r.stderr.strip()}") + + # --- top-level index --- + + def _update_top_index(self, status: str): + if not self._top_index_file.exists(): + return + top = self._read_json(self._top_index_file) + ts = self._stamp() + for phase in top.get("phases", []): + if phase.get("dir") == self._phase_dir_name: + phase["status"] = status + ts_key = {"completed": "completed_at", "error": "failed_at", "blocked": "blocked_at"}.get(status) + if ts_key: + phase[ts_key] = ts + break + self._write_json(self._top_index_file, top) + + # --- guardrails & context --- + + def _load_guardrails(self) -> str: + sections = [] + agents_md = ROOT / "AGENTS.md" + if agents_md.exists(): + sections.append(f"## 프로젝트 규칙 (AGENTS.md)\n\n{agents_md.read_text(encoding='utf-8')}") + docs_dir = ROOT / "docs" + if docs_dir.is_dir(): + for doc in sorted(docs_dir.glob("*.md")): + sections.append(f"## {doc.stem}\n\n{doc.read_text(encoding='utf-8')}") + return "\n\n---\n\n".join(sections) if sections else "" + + @staticmethod + def _build_step_context(index: dict) -> str: + lines = [ + f"- Step {s['step']} ({s['name']}): {s['summary']}" + for s in index["steps"] + if s["status"] == "completed" and s.get("summary") + ] + if not lines: + return "" + return "## 이전 Step 산출물\n\n" + "\n".join(lines) + "\n\n" + + def _build_preamble(self, guardrails: str, step_context: str, + prev_error: Optional[str] = None) -> str: + commit_example = self.FEAT_MSG.format( + phase=self._phase_name, num="N", name="" + ) + retry_section = "" + if prev_error: + retry_section = ( + f"\n## ⚠ 이전 시도 실패 — 아래 에러를 반드시 참고하여 수정하라\n\n" + f"{prev_error}\n\n---\n\n" + ) + return ( + f"당신은 {self._project} 프로젝트의 개발자입니다. 아래 step을 수행하세요.\n\n" + f"{guardrails}\n\n---\n\n" + f"{step_context}{retry_section}" + f"## 작업 규칙\n\n" + f"1. 이전 step에서 작성된 코드를 확인하고 일관성을 유지하라.\n" + f"2. 이 step에 명시된 작업만 수행하라. 추가 기능이나 파일을 만들지 마라.\n" + f"3. 기존 테스트를 깨뜨리지 마라.\n" + f"4. AC(Acceptance Criteria) 검증을 직접 실행하라.\n" + f"5. /phases/{self._phase_dir_name}/index.json의 해당 step status를 업데이트하라:\n" + f" - AC 통과 → \"completed\" + \"summary\" 필드에 이 step의 산출물을 한 줄로 요약\n" + f" - {self.MAX_RETRIES}회 수정 시도 후에도 실패 → \"error\" + \"error_message\" 기록\n" + f" - 사용자 개입이 필요한 경우 (API 키, 인증, 수동 설정 등) → \"blocked\" + \"blocked_reason\" 기록 후 즉시 중단\n" + f"6. 모든 변경사항을 커밋하라:\n" + f" {commit_example}\n\n---\n\n" + ) + + # --- Codex 호출 --- + + def _invoke_codex(self, step: dict, preamble: str) -> dict: + step_num, step_name = step["step"], step["name"] + step_file = self._phase_dir / f"step{step_num}.md" + + if not step_file.exists(): + print(f" ERROR: {step_file} not found") + sys.exit(1) + + prompt = preamble + step_file.read_text(encoding="utf-8") + result = subprocess.run( + ["codex", "exec", "--dangerously-bypass-approvals-and-sandbox", "--json", prompt], + cwd=self._root, capture_output=True, text=True, timeout=1800, + ) + + if result.returncode != 0: + print(f"\n WARN: Codex가 비정상 종료됨 (code {result.returncode})") + if result.stderr: + print(f" stderr: {result.stderr[:500]}") + + output = { + "step": step_num, "name": step_name, + "exitCode": result.returncode, + "stdout": result.stdout, "stderr": result.stderr, + } + out_path = self._phase_dir / f"step{step_num}-output.json" + with open(out_path, "w", encoding="utf-8") as f: + json.dump(output, f, indent=2, ensure_ascii=False) + + return output + + # --- 헤더 & 검증 --- + + def _print_header(self): + print(f"\n{'='*60}") + print(f" Harness Step Executor") + print(f" Phase: {self._phase_name} | Steps: {self._total}") + if self._auto_push: + print(f" Auto-push: enabled") + print(f"{'='*60}") + + def _check_blockers(self): + index = self._read_json(self._index_file) + for s in reversed(index["steps"]): + if s["status"] == "error": + print(f"\n ✗ Step {s['step']} ({s['name']}) failed.") + print(f" Error: {s.get('error_message', 'unknown')}") + print(f" Fix and reset status to 'pending' to retry.") + sys.exit(1) + if s["status"] == "blocked": + print(f"\n ⏸ Step {s['step']} ({s['name']}) blocked.") + print(f" Reason: {s.get('blocked_reason', 'unknown')}") + print(f" Resolve and reset status to 'pending' to retry.") + sys.exit(2) + if s["status"] != "pending": + break + + def _ensure_created_at(self): + index = self._read_json(self._index_file) + if "created_at" not in index: + index["created_at"] = self._stamp() + self._write_json(self._index_file, index) + + # --- 실행 루프 --- + + def _execute_single_step(self, step: dict, guardrails: str) -> bool: + """단일 step 실행 (재시도 포함). 완료되면 True, 실패/차단이면 False.""" + step_num, step_name = step["step"], step["name"] + done = sum(1 for s in self._read_json(self._index_file)["steps"] if s["status"] == "completed") + prev_error = None + + for attempt in range(1, self.MAX_RETRIES + 1): + index = self._read_json(self._index_file) + step_context = self._build_step_context(index) + preamble = self._build_preamble(guardrails, step_context, prev_error) + + tag = f"Step {step_num}/{self._total - 1} ({done} done): {step_name}" + if attempt > 1: + tag += f" [retry {attempt}/{self.MAX_RETRIES}]" + + with progress_indicator(tag) as pi: + self._invoke_codex(step, preamble) + elapsed = int(pi.elapsed) + + index = self._read_json(self._index_file) + status = next((s.get("status", "pending") for s in index["steps"] if s["step"] == step_num), "pending") + ts = self._stamp() + + if status == "completed": + for s in index["steps"]: + if s["step"] == step_num: + s["completed_at"] = ts + self._write_json(self._index_file, index) + self._commit_step(step_num, step_name) + print(f" ✓ Step {step_num}: {step_name} [{elapsed}s]") + return True + + if status == "blocked": + for s in index["steps"]: + if s["step"] == step_num: + s["blocked_at"] = ts + self._write_json(self._index_file, index) + reason = next((s.get("blocked_reason", "") for s in index["steps"] if s["step"] == step_num), "") + print(f" ⏸ Step {step_num}: {step_name} blocked [{elapsed}s]") + print(f" Reason: {reason}") + self._update_top_index("blocked") + sys.exit(2) + + err_msg = next( + (s.get("error_message", "Step did not update status") for s in index["steps"] if s["step"] == step_num), + "Step did not update status", + ) + + if attempt < self.MAX_RETRIES: + for s in index["steps"]: + if s["step"] == step_num: + s["status"] = "pending" + s.pop("error_message", None) + self._write_json(self._index_file, index) + prev_error = err_msg + print(f" ↻ Step {step_num}: retry {attempt}/{self.MAX_RETRIES} — {err_msg}") + else: + for s in index["steps"]: + if s["step"] == step_num: + s["status"] = "error" + s["error_message"] = f"[{self.MAX_RETRIES}회 시도 후 실패] {err_msg}" + s["failed_at"] = ts + self._write_json(self._index_file, index) + self._commit_step(step_num, step_name) + print(f" ✗ Step {step_num}: {step_name} failed after {self.MAX_RETRIES} attempts [{elapsed}s]") + print(f" Error: {err_msg}") + self._update_top_index("error") + sys.exit(1) + + return False # unreachable + + def _execute_all_steps(self, guardrails: str): + while True: + index = self._read_json(self._index_file) + pending = next((s for s in index["steps"] if s["status"] == "pending"), None) + if pending is None: + print("\n All steps completed!") + return + + step_num = pending["step"] + for s in index["steps"]: + if s["step"] == step_num and "started_at" not in s: + s["started_at"] = self._stamp() + self._write_json(self._index_file, index) + break + + self._execute_single_step(pending, guardrails) + + def _finalize(self): + index = self._read_json(self._index_file) + index["completed_at"] = self._stamp() + self._write_json(self._index_file, index) + self._update_top_index("completed") + + self._run_git("add", "-A") + if self._run_git("diff", "--cached", "--quiet").returncode != 0: + msg = f"chore({self._phase_name}): mark phase completed" + r = self._run_git("commit", "-m", msg) + if r.returncode == 0: + print(f" ✓ {msg}") + + if self._auto_push: + branch = f"feat-{self._phase_name}" + r = self._run_git("push", "-u", "origin", branch) + if r.returncode != 0: + print(f"\n ERROR: git push 실패: {r.stderr.strip()}") + sys.exit(1) + print(f" ✓ Pushed to origin/{branch}") + + print(f"\n{'='*60}") + print(f" Phase '{self._phase_name}' completed!") + print(f"{'='*60}") + + +def main(): + parser = argparse.ArgumentParser(description="Harness Step Executor") + parser.add_argument("phase_dir", help="Phase directory name (e.g. 0-mvp)") + parser.add_argument("--push", action="store_true", help="Push branch after completion") + args = parser.parse_args() + + StepExecutor(args.phase_dir, auto_push=args.push).run() + + +if __name__ == "__main__": + main() diff --git a/FESurrogateModelTutorial/src/femsurrogate/__init__.py b/FESurrogateModelTutorial/src/femsurrogate/__init__.py new file mode 100644 index 0000000..d665e45 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/__init__.py @@ -0,0 +1,3 @@ +"""FEM surrogate tutorial package.""" + +__version__ = "0.1.0" diff --git a/FESurrogateModelTutorial/src/femsurrogate/data/__init__.py b/FESurrogateModelTutorial/src/femsurrogate/data/__init__.py new file mode 100644 index 0000000..09a6459 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/data/__init__.py @@ -0,0 +1 @@ +"""Dataset generation helpers for FEM surrogate tutorials.""" diff --git a/FESurrogateModelTutorial/src/femsurrogate/data/bounds.py b/FESurrogateModelTutorial/src/femsurrogate/data/bounds.py new file mode 100644 index 0000000..e019d06 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/data/bounds.py @@ -0,0 +1,16 @@ +from dataclasses import dataclass + + +@dataclass(frozen=True) +class ParameterBound: + lower: float + upper: float + + +DEFAULT_PARAMETER_BOUNDS = { + "L_m": ParameterBound(lower=1.0, upper=3.0), + "b_m": ParameterBound(lower=0.02, upper=0.08), + "h_m": ParameterBound(lower=0.04, upper=0.16), + "E_pa": ParameterBound(lower=100e9, upper=220e9), + "P_n": ParameterBound(lower=100.0, upper=2000.0), +} diff --git a/FESurrogateModelTutorial/src/femsurrogate/data/dataset.py b/FESurrogateModelTutorial/src/femsurrogate/data/dataset.py new file mode 100644 index 0000000..01fd17d --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/data/dataset.py @@ -0,0 +1,106 @@ +from collections.abc import Mapping +from dataclasses import asdict + +import pandas as pd + +from femsurrogate.data.schema import ( + DENSITY_KG_M3, + DERIVED_COLUMNS, + PARAMETER_COLUMNS, + TARGET_COLUMNS, + AnalysisResult, + BeamParameters, +) +from femsurrogate.fea.model import Beam, BeamModel, NodalLoad, Node +from femsurrogate.fea.solver import solve_linear_static + +N_CANTILEVER_NODES = 6 + + +def _section_area(params: BeamParameters) -> float: + return params.b_m * params.h_m + + +def _section_izz(params: BeamParameters) -> float: + return params.b_m * params.h_m**3 / 12.0 + + +def _coerce_parameters(params: BeamParameters | Mapping[str, float]) -> BeamParameters: + if isinstance(params, BeamParameters): + return params + return BeamParameters(**{column: float(params[column]) for column in PARAMETER_COLUMNS}) + + +def _make_cantilever_model(params: BeamParameters) -> BeamModel: + area = _section_area(params) + izz = _section_izz(params) + iyy = params.h_m * params.b_m**3 / 12.0 + nodes = { + node_id: Node( + id=node_id, + x=params.L_m * (node_id - 1) / (N_CANTILEVER_NODES - 1), + y=0.0, + ) + for node_id in range(1, N_CANTILEVER_NODES + 1) + } + beams = tuple( + Beam(id=beam_id, node_i=beam_id, node_j=beam_id + 1) + for beam_id in range(1, N_CANTILEVER_NODES) + ) + + return BeamModel( + metadata={ + "Area": area, + "J": iyy + izz, + "Iyy": iyy, + "Izz": izz, + "ElasticModulus": params.E_pa, + "Poisson'sRatio": 0.3, + }, + nodes=nodes, + beams=beams, + fixed_nodes=(1,), + nodal_loads={ + N_CANTILEVER_NODES: NodalLoad( + node_id=N_CANTILEVER_NODES, + fx=0.0, + fy=-params.P_n, + mz=0.0, + ) + }, + ) + + +def run_beam2d_case(params: BeamParameters | Mapping[str, float]) -> AnalysisResult: + beam_params = _coerce_parameters(params) + area = _section_area(beam_params) + izz = _section_izz(beam_params) + model = _make_cantilever_model(beam_params) + solution = solve_linear_static(model) + tip_uy = solution[N_CANTILEVER_NODES].uy + max_moment = abs(beam_params.P_n) * beam_params.L_m + max_abs_bending_stress = max_moment * (beam_params.h_m / 2.0) / izz + mass = DENSITY_KG_M3 * area * beam_params.L_m + compliance = -beam_params.P_n * tip_uy + + return AnalysisResult( + tip_uy_m=tip_uy, + max_abs_bending_stress_pa=max_abs_bending_stress, + mass_kg=mass, + compliance_j=compliance, + ) + + +def build_dataset(samples: pd.DataFrame) -> pd.DataFrame: + rows: list[dict[str, float]] = [] + + for sample in samples.to_dict(orient="records"): + params = _coerce_parameters(sample) + result = run_beam2d_case(params) + row = dict(sample) + row["A_m2"] = _section_area(params) + row["I_m4"] = _section_izz(params) + row.update(asdict(result)) + rows.append(row) + + return pd.DataFrame(rows, columns=[*samples.columns, *DERIVED_COLUMNS, *TARGET_COLUMNS]) diff --git a/FESurrogateModelTutorial/src/femsurrogate/data/sampling.py b/FESurrogateModelTutorial/src/femsurrogate/data/sampling.py new file mode 100644 index 0000000..d48a01a --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/data/sampling.py @@ -0,0 +1,18 @@ +import pandas as pd +from scipy.stats import qmc + +from femsurrogate.data.bounds import ParameterBound + + +def generate_lhs_samples(bounds: dict[str, ParameterBound], n: int, seed: int) -> pd.DataFrame: + if n <= 0: + raise ValueError("n must be positive") + + columns = list(bounds) + sampler = qmc.LatinHypercube(d=len(columns), seed=seed) + unit_samples = sampler.random(n) + lower = [bounds[column].lower for column in columns] + upper = [bounds[column].upper for column in columns] + samples = qmc.scale(unit_samples, lower, upper) + + return pd.DataFrame(samples, columns=columns) diff --git a/FESurrogateModelTutorial/src/femsurrogate/data/schema.py b/FESurrogateModelTutorial/src/femsurrogate/data/schema.py new file mode 100644 index 0000000..d016b2b --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/data/schema.py @@ -0,0 +1,24 @@ +from dataclasses import dataclass + +DEFAULT_RANDOM_SEED = 20260521 +DENSITY_KG_M3 = 7850.0 +PARAMETER_COLUMNS = ("L_m", "b_m", "h_m", "E_pa", "P_n") +DERIVED_COLUMNS = ("A_m2", "I_m4") +TARGET_COLUMNS = ("tip_uy_m", "max_abs_bending_stress_pa", "mass_kg", "compliance_j") + + +@dataclass(frozen=True) +class BeamParameters: + L_m: float + b_m: float + h_m: float + E_pa: float + P_n: float + + +@dataclass(frozen=True) +class AnalysisResult: + tip_uy_m: float + max_abs_bending_stress_pa: float + mass_kg: float + compliance_j: float diff --git a/FESurrogateModelTutorial/src/femsurrogate/fea/__init__.py b/FESurrogateModelTutorial/src/femsurrogate/fea/__init__.py new file mode 100644 index 0000000..bafcc0f --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/fea/__init__.py @@ -0,0 +1 @@ +"""Finite element helpers for 2D beam/frame examples.""" diff --git a/FESurrogateModelTutorial/src/femsurrogate/fea/assembly.py b/FESurrogateModelTutorial/src/femsurrogate/fea/assembly.py new file mode 100644 index 0000000..17754ec --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/fea/assembly.py @@ -0,0 +1,60 @@ +import math + +import numpy as np +from scipy.sparse import csr_matrix, lil_matrix + +from femsurrogate.fea.element import local_frame_stiffness, transformation_matrix +from femsurrogate.fea.model import BeamModel + + +def node_ids(model: BeamModel) -> tuple[int, ...]: + return tuple(sorted(model.nodes)) + + +def dof_index(model: BeamModel, node_id: int, local_dof: int) -> int: + node_position = node_ids(model).index(node_id) + return node_position * 3 + local_dof + + +def node_dofs(model: BeamModel, node_id: int) -> tuple[int, int, int]: + base = dof_index(model, node_id, 0) + return (base, base + 1, base + 2) + + +def constrained_dofs(model: BeamModel) -> tuple[int, ...]: + return tuple(dof for node_id in sorted(model.fixed_nodes) for dof in node_dofs(model, node_id)) + + +def assemble_global_stiffness(model: BeamModel) -> csr_matrix: + size = 3 * len(model.nodes) + stiffness = lil_matrix((size, size), dtype=float) + E = model.metadata["ElasticModulus"] + A = model.metadata["Area"] + Izz = model.metadata["Izz"] + + for beam in model.beams: + node_i = model.nodes[beam.node_i] + node_j = model.nodes[beam.node_j] + length = math.hypot(node_j.x - node_i.x, node_j.y - node_i.y) + local_stiffness = local_frame_stiffness(E=E, A=A, Izz=Izz, L=length) + transform = transformation_matrix(node_i.x, node_i.y, node_j.x, node_j.y) + element_stiffness = transform.T @ local_stiffness @ transform + element_dofs = (*node_dofs(model, beam.node_i), *node_dofs(model, beam.node_j)) + + for row_local, row_global in enumerate(element_dofs): + for col_local, col_global in enumerate(element_dofs): + stiffness[row_global, col_global] += element_stiffness[row_local, col_local] + + return stiffness.tocsr() + + +def assemble_load_vector(model: BeamModel) -> np.ndarray: + loads = np.zeros(3 * len(model.nodes), dtype=float) + + for node_id, load in model.nodal_loads.items(): + ux_dof, uy_dof, rz_dof = node_dofs(model, node_id) + loads[ux_dof] += load.fx + loads[uy_dof] += load.fy + loads[rz_dof] += load.mz + + return loads diff --git a/FESurrogateModelTutorial/src/femsurrogate/fea/benchmark.py b/FESurrogateModelTutorial/src/femsurrogate/fea/benchmark.py new file mode 100644 index 0000000..9a1200d --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/fea/benchmark.py @@ -0,0 +1,2 @@ +def cantilever_tip_displacement(*, force_y: float, length: float, E: float, Izz: float) -> float: + return force_y * length**3 / (3.0 * E * Izz) diff --git a/FESurrogateModelTutorial/src/femsurrogate/fea/element.py b/FESurrogateModelTutorial/src/femsurrogate/fea/element.py new file mode 100644 index 0000000..73af108 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/fea/element.py @@ -0,0 +1,46 @@ +import math + +import numpy as np + + +def local_frame_stiffness(*, E: float, A: float, Izz: float, L: float) -> np.ndarray: + """Return local frame stiffness with Rz positive clockwise.""" + axial = E * A / L + b12 = 12.0 * E * Izz / L**3 + b6 = 6.0 * E * Izz / L**2 + b4 = 4.0 * E * Izz / L + b2 = 2.0 * E * Izz / L + + return np.array( + [ + [axial, 0.0, 0.0, -axial, 0.0, 0.0], + [0.0, b12, -b6, 0.0, -b12, -b6], + [0.0, -b6, b4, 0.0, b6, b2], + [-axial, 0.0, 0.0, axial, 0.0, 0.0], + [0.0, -b12, b6, 0.0, b12, b6], + [0.0, -b6, b2, 0.0, b6, b4], + ], + dtype=float, + ) + + +def transformation_matrix(x1: float, y1: float, x2: float, y2: float) -> np.ndarray: + dx = x2 - x1 + dy = y2 - y1 + length = math.hypot(dx, dy) + c = dx / length + s = dy / length + + block = np.array( + [ + [c, s, 0.0], + [-s, c, 0.0], + [0.0, 0.0, 1.0], + ], + dtype=float, + ) + + matrix = np.zeros((6, 6), dtype=float) + matrix[:3, :3] = block + matrix[3:, 3:] = block + return matrix diff --git a/FESurrogateModelTutorial/src/femsurrogate/fea/io.py b/FESurrogateModelTutorial/src/femsurrogate/fea/io.py new file mode 100644 index 0000000..a773b97 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/fea/io.py @@ -0,0 +1,70 @@ +import re +from pathlib import Path + +from femsurrogate.fea.model import Beam, BeamModel, Displacement, NodalLoad, Node + + +def _tokens(line: str) -> list[str]: + return [token for token in re.split(r"[,\s]+", line.strip()) if token] + + +def read_beam_example(path: str | Path) -> BeamModel: + metadata: dict[str, float] = {} + nodes: dict[int, Node] = {} + beams: list[Beam] = [] + fixed_nodes: list[int] = [] + nodal_loads: dict[int, NodalLoad] = {} + + for raw_line in Path(path).read_text(encoding="utf-8").splitlines(): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + + parts = _tokens(line) + keyword = parts[0] + + if keyword == "Node": + node_id = int(parts[1]) + nodes[node_id] = Node(id=node_id, x=float(parts[2]), y=float(parts[3])) + elif keyword == "Beam": + beams.append(Beam(id=int(parts[1]), node_i=int(parts[2]), node_j=int(parts[3]))) + elif keyword == "Fix": + fixed_nodes.append(int(parts[1])) + elif keyword == "NodeLoad": + node_id = int(parts[1]) + nodal_loads[node_id] = NodalLoad( + node_id=node_id, + fx=float(parts[2]), + fy=float(parts[3]), + mz=float(parts[4]), + ) + else: + metadata[keyword] = float(parts[1]) + + return BeamModel( + metadata=metadata, + nodes=nodes, + beams=tuple(beams), + fixed_nodes=tuple(fixed_nodes), + nodal_loads=nodal_loads, + ) + + +def read_expected_displacements(path: str | Path) -> dict[int, Displacement]: + displacements: dict[int, Displacement] = {} + + for raw_line in Path(path).read_text(encoding="utf-8").splitlines(): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + + parts = _tokens(line) + node_id = int(parts[0]) + displacements[node_id] = Displacement( + node_id=node_id, + ux=float(parts[1]), + uy=float(parts[2]), + rz=float(parts[3]), + ) + + return displacements diff --git a/FESurrogateModelTutorial/src/femsurrogate/fea/model.py b/FESurrogateModelTutorial/src/femsurrogate/fea/model.py new file mode 100644 index 0000000..b793cdd --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/fea/model.py @@ -0,0 +1,40 @@ +from dataclasses import dataclass + + +@dataclass(frozen=True) +class Node: + id: int + x: float + y: float + + +@dataclass(frozen=True) +class Beam: + id: int + node_i: int + node_j: int + + +@dataclass(frozen=True) +class NodalLoad: + node_id: int + fx: float + fy: float + mz: float + + +@dataclass(frozen=True) +class Displacement: + node_id: int + ux: float + uy: float + rz: float + + +@dataclass(frozen=True) +class BeamModel: + metadata: dict[str, float] + nodes: dict[int, Node] + beams: tuple[Beam, ...] + fixed_nodes: tuple[int, ...] + nodal_loads: dict[int, NodalLoad] diff --git a/FESurrogateModelTutorial/src/femsurrogate/fea/solver.py b/FESurrogateModelTutorial/src/femsurrogate/fea/solver.py new file mode 100644 index 0000000..64ec2d7 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/fea/solver.py @@ -0,0 +1,33 @@ +import numpy as np +from scipy.sparse.linalg import spsolve + +from femsurrogate.fea.assembly import ( + assemble_global_stiffness, + assemble_load_vector, + constrained_dofs, + node_ids, +) +from femsurrogate.fea.model import BeamModel, Displacement + + +def solve_linear_static(model: BeamModel) -> dict[int, Displacement]: + stiffness = assemble_global_stiffness(model) + loads = assemble_load_vector(model) + fixed = np.array(constrained_dofs(model), dtype=int) + all_dofs = np.arange(loads.size) + free = np.setdiff1d(all_dofs, fixed, assume_unique=True) + + displacements = np.zeros_like(loads) + displacements[free] = spsolve(stiffness[free][:, free], loads[free]) + + result: dict[int, Displacement] = {} + for position, node_id in enumerate(node_ids(model)): + base = position * 3 + result[node_id] = Displacement( + node_id=node_id, + ux=float(displacements[base]), + uy=float(displacements[base + 1]), + rz=float(displacements[base + 2]), + ) + + return result diff --git a/FESurrogateModelTutorial/src/femsurrogate/plotting/__init__.py b/FESurrogateModelTutorial/src/femsurrogate/plotting/__init__.py new file mode 100644 index 0000000..d27e13e --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/plotting/__init__.py @@ -0,0 +1 @@ +"""Plotting helpers for diagnostics and model comparison.""" diff --git a/FESurrogateModelTutorial/src/femsurrogate/plotting/comparison.py b/FESurrogateModelTutorial/src/femsurrogate/plotting/comparison.py new file mode 100644 index 0000000..49cfa3f --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/plotting/comparison.py @@ -0,0 +1,27 @@ +import pandas as pd +from matplotlib import pyplot as plt +from matplotlib.figure import Figure + +from femsurrogate.surrogates.common import MetricsReport, metrics_to_dict + + +def metrics_table(reports: list[MetricsReport], *, sort_by: str = "rmse") -> pd.DataFrame: + table = pd.DataFrame([metrics_to_dict(report) for report in reports]) + ascending = sort_by != "r2" + return table.sort_values(sort_by, ascending=ascending).reset_index(drop=True) + + +def plot_metric_comparison( + table: pd.DataFrame, + *, + metric: str, + title: str = "Metric comparison", +) -> Figure: + fig, ax = plt.subplots() + ax.bar(table["model_name"], table[metric]) + ax.set_xlabel("Model") + ax.set_ylabel(metric) + ax.set_title(title) + ax.grid(True, axis="y", alpha=0.3) + fig.tight_layout() + return fig diff --git a/FESurrogateModelTutorial/src/femsurrogate/plotting/diagnostics.py b/FESurrogateModelTutorial/src/femsurrogate/plotting/diagnostics.py new file mode 100644 index 0000000..7cbe341 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/plotting/diagnostics.py @@ -0,0 +1,30 @@ +import pandas as pd +from matplotlib import pyplot as plt +from matplotlib.figure import Figure + + +def plot_parity(predictions: pd.DataFrame, *, title: str = "Parity plot") -> Figure: + y_true = predictions["y_true"] + y_pred = predictions["y_pred"] + axis_min = min(y_true.min(), y_pred.min()) + axis_max = max(y_true.max(), y_pred.max()) + + fig, ax = plt.subplots() + ax.scatter(y_true, y_pred, s=24, alpha=0.8) + ax.plot([axis_min, axis_max], [axis_min, axis_max], color="black", linestyle="--") + ax.set_xlabel("True response") + ax.set_ylabel("Predicted response") + ax.set_title(title) + ax.grid(True, alpha=0.3) + return fig + + +def plot_residuals(predictions: pd.DataFrame, *, title: str = "Residual plot") -> Figure: + fig, ax = plt.subplots() + ax.scatter(predictions["y_pred"], predictions["residual"], s=24, alpha=0.8) + ax.axhline(0.0, color="black", linestyle="--") + ax.set_xlabel("Predicted response") + ax.set_ylabel("Residual") + ax.set_title(title) + ax.grid(True, alpha=0.3) + return fig diff --git a/FESurrogateModelTutorial/src/femsurrogate/surrogates/__init__.py b/FESurrogateModelTutorial/src/femsurrogate/surrogates/__init__.py new file mode 100644 index 0000000..798409d --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/surrogates/__init__.py @@ -0,0 +1 @@ +"""Surrogate model helpers.""" diff --git a/FESurrogateModelTutorial/src/femsurrogate/surrogates/boosting.py b/FESurrogateModelTutorial/src/femsurrogate/surrogates/boosting.py new file mode 100644 index 0000000..27ef2dd --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/surrogates/boosting.py @@ -0,0 +1,21 @@ +from sklearn.ensemble import GradientBoostingRegressor + +from femsurrogate.data.schema import DEFAULT_RANDOM_SEED + + +def make_gradient_boosting( + *, + random_state: int = DEFAULT_RANDOM_SEED, + learning_rate: float = 0.05, + n_estimators: int = 300, + max_depth: int = 3, + subsample: float = 0.9, +) -> GradientBoostingRegressor: + return GradientBoostingRegressor( + loss="squared_error", + learning_rate=learning_rate, + n_estimators=n_estimators, + max_depth=max_depth, + subsample=subsample, + random_state=random_state, + ) diff --git a/FESurrogateModelTutorial/src/femsurrogate/surrogates/common.py b/FESurrogateModelTutorial/src/femsurrogate/surrogates/common.py new file mode 100644 index 0000000..5140575 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/surrogates/common.py @@ -0,0 +1,96 @@ +from dataclasses import asdict, dataclass +from time import perf_counter +from typing import Any + +import numpy as np +import pandas as pd +from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score +from sklearn.model_selection import train_test_split + + +@dataclass(frozen=True) +class SplitData: + X_train: pd.DataFrame + X_test: pd.DataFrame + y_train: pd.Series + y_test: pd.Series + + +@dataclass(frozen=True) +class MetricsReport: + model_name: str + target_column: str + rmse: float + mae: float + r2: float + fit_time_s: float + predict_time_s: float + + +@dataclass(frozen=True) +class EvaluationResult: + metrics: MetricsReport + predictions: pd.DataFrame + + +def split_dataset( + dataset: pd.DataFrame, + *, + feature_columns: list[str], + target_column: str, + test_size: float, + random_state: int, +) -> SplitData: + X = dataset[feature_columns] + y = dataset[target_column] + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + test_size=test_size, + random_state=random_state, + ) + return SplitData(X_train=X_train, X_test=X_test, y_train=y_train, y_test=y_test) + + +def evaluate_model( + model: Any, + X_train: pd.DataFrame, + X_test: pd.DataFrame, + y_train: pd.Series, + y_test: pd.Series, + *, + model_name: str, + target_column: str, +) -> EvaluationResult: + fit_start = perf_counter() + model.fit(X_train, y_train) + fit_time_s = perf_counter() - fit_start + + predict_start = perf_counter() + y_pred = np.asarray(model.predict(X_test), dtype=float) + predict_time_s = perf_counter() - predict_start + y_true = np.asarray(y_test, dtype=float) + + metrics = MetricsReport( + model_name=model_name, + target_column=target_column, + rmse=float(np.sqrt(mean_squared_error(y_true, y_pred))), + mae=float(mean_absolute_error(y_true, y_pred)), + r2=float(r2_score(y_true, y_pred)), + fit_time_s=fit_time_s, + predict_time_s=predict_time_s, + ) + predictions = pd.DataFrame( + { + "y_true": y_true, + "y_pred": y_pred, + "residual": y_true - y_pred, + }, + index=y_test.index, + ) + + return EvaluationResult(metrics=metrics, predictions=predictions) + + +def metrics_to_dict(metrics: MetricsReport) -> dict[str, str | float]: + return asdict(metrics) diff --git a/FESurrogateModelTutorial/src/femsurrogate/surrogates/gpr.py b/FESurrogateModelTutorial/src/femsurrogate/surrogates/gpr.py new file mode 100644 index 0000000..2db602a --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/surrogates/gpr.py @@ -0,0 +1,34 @@ +from sklearn.gaussian_process import GaussianProcessRegressor +from sklearn.gaussian_process.kernels import RBF, ConstantKernel, WhiteKernel +from sklearn.pipeline import Pipeline +from sklearn.preprocessing import StandardScaler + +from femsurrogate.data.schema import DEFAULT_RANDOM_SEED + + +def make_gpr( + *, + random_state: int = DEFAULT_RANDOM_SEED, + alpha: float = 1e-10, + n_restarts_optimizer: int = 0, +) -> Pipeline: + kernel = ( + ConstantKernel(1.0, constant_value_bounds=(1e-3, 1e3)) + * RBF(length_scale=1.0, length_scale_bounds=(1e-3, 1e3)) + + WhiteKernel(noise_level=1e-10, noise_level_bounds=(1e-12, 1e-3)) + ) + return Pipeline( + steps=[ + ("scaler", StandardScaler()), + ( + "regressor", + GaussianProcessRegressor( + kernel=kernel, + alpha=alpha, + normalize_y=True, + n_restarts_optimizer=n_restarts_optimizer, + random_state=random_state, + ), + ), + ] + ) diff --git a/FESurrogateModelTutorial/src/femsurrogate/surrogates/mlp.py b/FESurrogateModelTutorial/src/femsurrogate/surrogates/mlp.py new file mode 100644 index 0000000..8e247d9 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/surrogates/mlp.py @@ -0,0 +1,39 @@ +from sklearn.compose import TransformedTargetRegressor +from sklearn.neural_network import MLPRegressor +from sklearn.pipeline import Pipeline +from sklearn.preprocessing import StandardScaler + +from femsurrogate.data.schema import DEFAULT_RANDOM_SEED + + +def make_mlp( + *, + random_state: int = DEFAULT_RANDOM_SEED, + hidden_layer_sizes: tuple[int, ...] = (64, 32), + alpha: float = 1e-4, + learning_rate_init: float = 1e-3, + early_stopping: bool = True, + max_iter: int = 2000, +) -> Pipeline: + regressor = MLPRegressor( + hidden_layer_sizes=hidden_layer_sizes, + activation="relu", + solver="adam", + alpha=alpha, + learning_rate_init=learning_rate_init, + early_stopping=early_stopping, + max_iter=max_iter, + random_state=random_state, + ) + return Pipeline( + steps=[ + ("scaler", StandardScaler()), + ( + "regressor", + TransformedTargetRegressor( + regressor=regressor, + transformer=StandardScaler(), + ), + ), + ] + ) diff --git a/FESurrogateModelTutorial/src/femsurrogate/surrogates/random_forest.py b/FESurrogateModelTutorial/src/femsurrogate/surrogates/random_forest.py new file mode 100644 index 0000000..08ff32e --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/surrogates/random_forest.py @@ -0,0 +1,20 @@ +from sklearn.ensemble import RandomForestRegressor + +from femsurrogate.data.schema import DEFAULT_RANDOM_SEED + + +def make_random_forest( + *, + random_state: int = DEFAULT_RANDOM_SEED, + n_estimators: int = 300, + max_depth: int | None = None, + min_samples_leaf: int = 2, + n_jobs: int = -1, +) -> RandomForestRegressor: + return RandomForestRegressor( + n_estimators=n_estimators, + max_depth=max_depth, + min_samples_leaf=min_samples_leaf, + random_state=random_state, + n_jobs=n_jobs, + ) diff --git a/FESurrogateModelTutorial/src/femsurrogate/surrogates/registry.py b/FESurrogateModelTutorial/src/femsurrogate/surrogates/registry.py new file mode 100644 index 0000000..b5fad14 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/surrogates/registry.py @@ -0,0 +1,28 @@ +from typing import Any + +from femsurrogate.data.schema import DEFAULT_RANDOM_SEED +from femsurrogate.surrogates.boosting import make_gradient_boosting +from femsurrogate.surrogates.gpr import make_gpr +from femsurrogate.surrogates.mlp import make_mlp +from femsurrogate.surrogates.random_forest import make_random_forest +from femsurrogate.surrogates.rsm import make_rsm + +MODEL_NAMES = ("rsm", "gpr", "random_forest", "gradient_boosting", "mlp") + +_BUILDERS = { + "rsm": make_rsm, + "gpr": make_gpr, + "random_forest": make_random_forest, + "gradient_boosting": make_gradient_boosting, + "mlp": make_mlp, +} + + +def make_model(model_name: str, random_state: int = DEFAULT_RANDOM_SEED, **kwargs: Any): + try: + builder = _BUILDERS[model_name] + except KeyError as exc: + valid = ", ".join(MODEL_NAMES) + raise ValueError(f"Unknown model_name {model_name!r}. Expected one of: {valid}") from exc + + return builder(random_state=random_state, **kwargs) diff --git a/FESurrogateModelTutorial/src/femsurrogate/surrogates/rsm.py b/FESurrogateModelTutorial/src/femsurrogate/surrogates/rsm.py new file mode 100644 index 0000000..fd07f77 --- /dev/null +++ b/FESurrogateModelTutorial/src/femsurrogate/surrogates/rsm.py @@ -0,0 +1,20 @@ +from sklearn.linear_model import Ridge +from sklearn.pipeline import Pipeline +from sklearn.preprocessing import PolynomialFeatures, StandardScaler + +from femsurrogate.data.schema import DEFAULT_RANDOM_SEED + + +def make_rsm( + *, + random_state: int = DEFAULT_RANDOM_SEED, + degree: int = 2, + alpha: float = 1.0, +) -> Pipeline: + return Pipeline( + steps=[ + ("scaler", StandardScaler()), + ("polynomial", PolynomialFeatures(degree=degree, include_bias=False)), + ("regressor", Ridge(alpha=alpha)), + ] + ) diff --git a/FESurrogateModelTutorial/tests/.gitkeep b/FESurrogateModelTutorial/tests/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/FESurrogateModelTutorial/tests/.gitkeep @@ -0,0 +1 @@ + diff --git a/FESurrogateModelTutorial/tests/test_beam_solver.py b/FESurrogateModelTutorial/tests/test_beam_solver.py new file mode 100644 index 0000000..debf60b --- /dev/null +++ b/FESurrogateModelTutorial/tests/test_beam_solver.py @@ -0,0 +1,31 @@ +from pathlib import Path + +import numpy as np + +from femsurrogate.fea.assembly import assemble_global_stiffness, constrained_dofs +from femsurrogate.fea.io import read_beam_example +from femsurrogate.fea.solver import solve_linear_static + +ROOT = Path(__file__).resolve().parents[1] + + +def test_assemble_global_stiffness_for_cantilever_fixture_has_expected_shape(): + model = read_beam_example(ROOT / "BeamExamples" / "CantileverBeam.txt") + stiffness = assemble_global_stiffness(model) + + assert stiffness.shape == (18, 18) + + +def test_fixed_node_dofs_are_constrained(): + model = read_beam_example(ROOT / "BeamExamples" / "CantileverBeam.txt") + + assert constrained_dofs(model) == (0, 1, 2) + + +def test_solve_linear_static_returns_finite_displacements_for_all_nodes(): + model = read_beam_example(ROOT / "BeamExamples" / "CantileverBeam.txt") + displacements = solve_linear_static(model) + + assert set(displacements) == set(model.nodes) + values = np.array([[d.ux, d.uy, d.rz] for d in displacements.values()]) + assert np.isfinite(values).all() diff --git a/FESurrogateModelTutorial/tests/test_beamexamples_io.py b/FESurrogateModelTutorial/tests/test_beamexamples_io.py new file mode 100644 index 0000000..5d3ce96 --- /dev/null +++ b/FESurrogateModelTutorial/tests/test_beamexamples_io.py @@ -0,0 +1,47 @@ +from pathlib import Path + +import pytest + +from femsurrogate.fea.io import read_beam_example, read_expected_displacements + +ROOT = Path(__file__).resolve().parents[1] + + +def test_read_beam_example_parses_cantilever_fixture(): + model = read_beam_example(ROOT / "BeamExamples" / "CantileverBeam.txt") + + assert model.metadata["Area"] == pytest.approx(1.0) + assert model.metadata["Izz"] == pytest.approx(0.0833333) + assert model.metadata["ElasticModulus"] == pytest.approx(2.05e11) + assert model.metadata["Poisson'sRatio"] == pytest.approx(0.3) + + assert len(model.nodes) == 6 + assert model.nodes[1].x == pytest.approx(0.0) + assert model.nodes[6].x == pytest.approx(5.0) + assert model.nodes[6].y == pytest.approx(0.0) + + assert len(model.beams) == 5 + assert model.beams[0].id == 1 + assert model.beams[0].node_i == 1 + assert model.beams[0].node_j == 2 + assert model.beams[-1].node_i == 5 + assert model.beams[-1].node_j == 6 + + assert model.fixed_nodes == (1,) + assert model.nodal_loads[6].fx == pytest.approx(0.0) + assert model.nodal_loads[6].fy == pytest.approx(-100000.0) + assert model.nodal_loads[6].mz == pytest.approx(0.0) + + +def test_read_expected_displacements_parses_reference_values(): + displacements = read_expected_displacements( + ROOT / "BeamExamples" / "CantileverBeam_Displacements.txt" + ) + + assert len(displacements) == 6 + assert displacements[1].ux == pytest.approx(0.0) + assert displacements[1].uy == pytest.approx(0.0) + assert displacements[1].rz == pytest.approx(0.0) + assert displacements[6].ux == pytest.approx(0.0) + assert displacements[6].uy == pytest.approx(-0.000244) + assert displacements[6].rz == pytest.approx(0.000073) diff --git a/FESurrogateModelTutorial/tests/test_cantilever_fixture_regression.py b/FESurrogateModelTutorial/tests/test_cantilever_fixture_regression.py new file mode 100644 index 0000000..e83761f --- /dev/null +++ b/FESurrogateModelTutorial/tests/test_cantilever_fixture_regression.py @@ -0,0 +1,42 @@ +from pathlib import Path + +import numpy as np + +from femsurrogate.fea.benchmark import cantilever_tip_displacement +from femsurrogate.fea.io import read_beam_example, read_expected_displacements +from femsurrogate.fea.solver import solve_linear_static + +ROOT = Path(__file__).resolve().parents[1] +INPUT_PATH = ROOT / "BeamExamples" / "CantileverBeam.txt" +EXPECTED_PATH = ROOT / "BeamExamples" / "CantileverBeam_Displacements.txt" + + +def test_solver_matches_cantilever_fixture_displacements(): + model = read_beam_example(INPUT_PATH) + actual = solve_linear_static(model) + expected = read_expected_displacements(EXPECTED_PATH) + + assert set(actual) == set(expected) + for node_id, expected_displacement in expected.items(): + actual_displacement = actual[node_id] + np.testing.assert_allclose( + [actual_displacement.ux, actual_displacement.uy, actual_displacement.rz], + [expected_displacement.ux, expected_displacement.uy, expected_displacement.rz], + atol=5e-7, + rtol=1e-6, + ) + + +def test_tip_displacement_matches_analytical_cantilever_magnitude(): + model = read_beam_example(INPUT_PATH) + actual_tip_uy = solve_linear_static(model)[6].uy + node_x = [node.x for node in model.nodes.values()] + length = max(node_x) - min(node_x) + analytical_tip_uy = cantilever_tip_displacement( + force_y=model.nodal_loads[6].fy, + length=length, + E=model.metadata["ElasticModulus"], + Izz=model.metadata["Izz"], + ) + + np.testing.assert_allclose(abs(actual_tip_uy), abs(analytical_tip_uy), rtol=1e-9, atol=0.0) diff --git a/FESurrogateModelTutorial/tests/test_dataset_builder.py b/FESurrogateModelTutorial/tests/test_dataset_builder.py new file mode 100644 index 0000000..1e0642e --- /dev/null +++ b/FESurrogateModelTutorial/tests/test_dataset_builder.py @@ -0,0 +1,27 @@ +import pandas as pd + +from femsurrogate.data.bounds import DEFAULT_PARAMETER_BOUNDS +from femsurrogate.data.dataset import build_dataset, run_beam2d_case +from femsurrogate.data.sampling import generate_lhs_samples +from femsurrogate.data.schema import TARGET_COLUMNS, BeamParameters + + +def test_run_beam2d_case_returns_physical_responses(): + result = run_beam2d_case( + BeamParameters(L_m=2.0, b_m=0.05, h_m=0.1, E_pa=200e9, P_n=1000.0) + ) + + assert result.tip_uy_m < 0.0 + assert result.max_abs_bending_stress_pa > 0.0 + assert result.mass_kg > 0.0 + assert result.compliance_j > 0.0 + + +def test_build_dataset_preserves_samples_and_adds_schema_columns(): + samples = generate_lhs_samples(DEFAULT_PARAMETER_BOUNDS, n=4, seed=20260521) + dataset = build_dataset(samples) + + assert len(dataset) == len(samples) + pd.testing.assert_frame_equal(dataset[list(samples.columns)], samples) + for column in ["A_m2", "I_m4", *TARGET_COLUMNS]: + assert column in dataset.columns diff --git a/FESurrogateModelTutorial/tests/test_frame_element.py b/FESurrogateModelTutorial/tests/test_frame_element.py new file mode 100644 index 0000000..366712d --- /dev/null +++ b/FESurrogateModelTutorial/tests/test_frame_element.py @@ -0,0 +1,42 @@ +import numpy as np +import pytest + +from femsurrogate.fea.element import local_frame_stiffness, transformation_matrix + + +def test_local_frame_stiffness_has_expected_shape_and_symmetry(): + stiffness = local_frame_stiffness(E=200.0, A=3.0, Izz=5.0, L=7.0) + + assert stiffness.shape == (6, 6) + np.testing.assert_allclose(stiffness, stiffness.T) + + +def test_local_frame_stiffness_contains_clockwise_rotation_terms(): + E = 210.0 + A = 2.0 + Izz = 4.0 + L = 3.0 + + stiffness = local_frame_stiffness(E=E, A=A, Izz=Izz, L=L) + + assert stiffness[0, 0] == pytest.approx(E * A / L) + assert stiffness[0, 3] == pytest.approx(-E * A / L) + assert stiffness[1, 1] == pytest.approx(12 * E * Izz / L**3) + assert stiffness[1, 2] == pytest.approx(-6 * E * Izz / L**2) + assert stiffness[2, 2] == pytest.approx(4 * E * Izz / L) + assert stiffness[2, 5] == pytest.approx(2 * E * Izz / L) + assert stiffness[4, 4] == pytest.approx(12 * E * Izz / L**3) + assert stiffness[4, 5] == pytest.approx(6 * E * Izz / L**2) + assert stiffness[5, 5] == pytest.approx(4 * E * Izz / L) + + +def test_transformation_matrix_is_identity_for_horizontal_element(): + matrix = transformation_matrix(0.0, 0.0, 2.0, 0.0) + + np.testing.assert_allclose(matrix, np.eye(6)) + + +def test_transformation_matrix_is_orthogonal_for_inclined_element(): + matrix = transformation_matrix(0.0, 0.0, 1.0, 1.0) + + np.testing.assert_allclose(matrix.T @ matrix, np.eye(6), atol=1e-12) diff --git a/FESurrogateModelTutorial/tests/test_plotting_and_results.py b/FESurrogateModelTutorial/tests/test_plotting_and_results.py new file mode 100644 index 0000000..77e658a --- /dev/null +++ b/FESurrogateModelTutorial/tests/test_plotting_and_results.py @@ -0,0 +1,41 @@ +import matplotlib.pyplot as plt +import pandas as pd +from matplotlib.figure import Figure + +from femsurrogate.plotting.comparison import metrics_table, plot_metric_comparison +from femsurrogate.plotting.diagnostics import plot_parity, plot_residuals +from femsurrogate.surrogates.common import MetricsReport + + +def _predictions() -> pd.DataFrame: + return pd.DataFrame( + { + "y_true": [-1.0, -2.0, -3.0], + "y_pred": [-1.1, -1.9, -3.2], + "residual": [0.1, -0.1, 0.2], + } + ) + + +def test_diagnostic_plots_return_figures(): + parity = plot_parity(_predictions(), title="Parity") + residuals = plot_residuals(_predictions(), title="Residuals") + + assert isinstance(parity, Figure) + assert isinstance(residuals, Figure) + plt.close(parity) + plt.close(residuals) + + +def test_metrics_table_and_comparison_plot(): + reports = [ + MetricsReport("rsm", "tip_uy_m", 0.2, 0.1, 0.9, 0.01, 0.001), + MetricsReport("gpr", "tip_uy_m", 0.1, 0.05, 0.95, 0.2, 0.01), + ] + + table = metrics_table(reports) + figure = plot_metric_comparison(table, metric="rmse", title="RMSE") + + assert list(table["model_name"]) == ["gpr", "rsm"] + assert isinstance(figure, Figure) + plt.close(figure) diff --git a/FESurrogateModelTutorial/tests/test_project_structure.py b/FESurrogateModelTutorial/tests/test_project_structure.py new file mode 100644 index 0000000..3a5372c --- /dev/null +++ b/FESurrogateModelTutorial/tests/test_project_structure.py @@ -0,0 +1,18 @@ +import importlib + +import femsurrogate + + +def test_package_exposes_version_string(): + assert isinstance(femsurrogate.__version__, str) + assert femsurrogate.__version__ + + +def test_expected_subpackages_are_importable(): + for module_name in [ + "femsurrogate.fea", + "femsurrogate.data", + "femsurrogate.surrogates", + "femsurrogate.plotting", + ]: + assert importlib.import_module(module_name).__name__ == module_name diff --git a/FESurrogateModelTutorial/tests/test_sampling.py b/FESurrogateModelTutorial/tests/test_sampling.py new file mode 100644 index 0000000..bf3d880 --- /dev/null +++ b/FESurrogateModelTutorial/tests/test_sampling.py @@ -0,0 +1,19 @@ +import pandas as pd + +from femsurrogate.data.bounds import DEFAULT_PARAMETER_BOUNDS +from femsurrogate.data.sampling import generate_lhs_samples + + +def test_lhs_samples_are_reproducible_for_fixed_seed(): + first = generate_lhs_samples(DEFAULT_PARAMETER_BOUNDS, n=8, seed=20260521) + second = generate_lhs_samples(DEFAULT_PARAMETER_BOUNDS, n=8, seed=20260521) + + pd.testing.assert_frame_equal(first, second) + + +def test_lhs_samples_have_expected_columns_and_bounds(): + samples = generate_lhs_samples(DEFAULT_PARAMETER_BOUNDS, n=16, seed=20260521) + + assert list(samples.columns) == list(DEFAULT_PARAMETER_BOUNDS) + for column, bounds in DEFAULT_PARAMETER_BOUNDS.items(): + assert samples[column].between(bounds.lower, bounds.upper).all() diff --git a/FESurrogateModelTutorial/tests/test_surrogate_common.py b/FESurrogateModelTutorial/tests/test_surrogate_common.py new file mode 100644 index 0000000..f6e7d80 --- /dev/null +++ b/FESurrogateModelTutorial/tests/test_surrogate_common.py @@ -0,0 +1,67 @@ +import pandas as pd +from sklearn.linear_model import LinearRegression + +from femsurrogate.surrogates.common import evaluate_model, split_dataset + + +def _toy_dataset() -> pd.DataFrame: + return pd.DataFrame( + { + "x1": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], + "x2": [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5], + "target": [1.0, 2.5, 4.0, 5.5, 7.0, 8.5, 10.0, 11.5], + } + ) + + +def test_split_dataset_is_reproducible(): + dataset = _toy_dataset() + first = split_dataset( + dataset, + feature_columns=["x1", "x2"], + target_column="target", + test_size=0.25, + random_state=20260521, + ) + second = split_dataset( + dataset, + feature_columns=["x1", "x2"], + target_column="target", + test_size=0.25, + random_state=20260521, + ) + + pd.testing.assert_frame_equal(first.X_train, second.X_train) + pd.testing.assert_frame_equal(first.X_test, second.X_test) + pd.testing.assert_series_equal(first.y_train, second.y_train) + pd.testing.assert_series_equal(first.y_test, second.y_test) + + +def test_evaluate_model_returns_metrics_and_predictions(): + dataset = _toy_dataset() + split = split_dataset( + dataset, + feature_columns=["x1", "x2"], + target_column="target", + test_size=0.25, + random_state=20260521, + ) + result = evaluate_model( + LinearRegression(), + split.X_train, + split.X_test, + split.y_train, + split.y_test, + model_name="linear", + target_column="target", + ) + + assert result.metrics.model_name == "linear" + assert result.metrics.target_column == "target" + assert result.metrics.rmse >= 0.0 + assert result.metrics.mae >= 0.0 + assert result.metrics.r2 <= 1.0 + assert result.metrics.fit_time_s >= 0.0 + assert result.metrics.predict_time_s >= 0.0 + assert list(result.predictions.columns) == ["y_true", "y_pred", "residual"] + assert len(result.predictions) == len(split.y_test) diff --git a/FESurrogateModelTutorial/tests/test_surrogate_models.py b/FESurrogateModelTutorial/tests/test_surrogate_models.py new file mode 100644 index 0000000..3cf2c81 --- /dev/null +++ b/FESurrogateModelTutorial/tests/test_surrogate_models.py @@ -0,0 +1,47 @@ +import warnings + +import numpy as np +import pandas as pd +from sklearn.exceptions import ConvergenceWarning + +from femsurrogate.surrogates.registry import MODEL_NAMES, make_model + + +def _toy_regression_data(): + X = pd.DataFrame( + { + "L_m": np.linspace(1.0, 3.0, 12), + "b_m": np.linspace(0.02, 0.08, 12), + "h_m": np.linspace(0.04, 0.16, 12), + "E_pa": np.linspace(100e9, 220e9, 12), + "P_n": np.linspace(100.0, 2000.0, 12), + } + ) + y = -X["P_n"] * X["L_m"] ** 3 / (3.0 * X["E_pa"] * X["b_m"] * X["h_m"] ** 3) + return X, y + + +def test_registry_exposes_expected_surrogate_names(): + assert MODEL_NAMES == ("rsm", "gpr", "random_forest", "gradient_boosting", "mlp") + + +def test_make_model_builds_estimators_that_fit_and_predict(): + X, y = _toy_regression_data() + fast_overrides = { + "random_forest": {"n_estimators": 5, "n_jobs": 1}, + "gradient_boosting": {"n_estimators": 5}, + "mlp": {"hidden_layer_sizes": (4,), "max_iter": 25, "early_stopping": False}, + } + + for model_name in MODEL_NAMES: + model = make_model( + model_name, + random_state=20260521, + **fast_overrides.get(model_name, {}), + ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=ConvergenceWarning) + model.fit(X, y) + predictions = model.predict(X.iloc[:3]) + + assert predictions.shape == (3,) diff --git a/FESurrogateModelTutorial/uv.lock b/FESurrogateModelTutorial/uv.lock new file mode 100644 index 0000000..84bfbd8 --- /dev/null +++ b/FESurrogateModelTutorial/uv.lock @@ -0,0 +1,2146 @@ +version = 1 +revision = 3 +requires-python = ">=3.12, <3.15" +resolution-markers = [ + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform == 'emscripten'", + "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", +] + +[[package]] +name = "anyio" +version = "4.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" }, +] + +[[package]] +name = "appnope" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, +] + +[[package]] +name = "argon2-cffi" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "argon2-cffi-bindings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" }, +] + +[[package]] +name = "argon2-cffi-bindings" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393, upload-time = "2025-07-30T10:01:40.97Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328, upload-time = "2025-07-30T10:01:41.916Z" }, + { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269, upload-time = "2025-07-30T10:01:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558, upload-time = "2025-07-30T10:01:43.943Z" }, + { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364, upload-time = "2025-07-30T10:01:44.887Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637, upload-time = "2025-07-30T10:01:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934, upload-time = "2025-07-30T10:01:47.203Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158, upload-time = "2025-07-30T10:01:48.341Z" }, + { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597, upload-time = "2025-07-30T10:01:49.112Z" }, + { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231, upload-time = "2025-07-30T10:01:49.92Z" }, + { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, + { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, + { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, + { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, + { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, + { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, + { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, + { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, +] + +[[package]] +name = "arrow" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/33/032cdc44182491aa708d06a68b62434140d8c50820a087fac7af37703357/arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7", size = 152931, upload-time = "2025-10-18T17:46:46.761Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205", size = 68797, upload-time = "2025-10-18T17:46:45.663Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + +[[package]] +name = "async-lru" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/1f/989ecfef8e64109a489fff357450cb73fa73a865a92bd8c272170a6922c2/async_lru-2.3.0.tar.gz", hash = "sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6", size = 16332, upload-time = "2026-03-19T01:04:32.413Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl", hash = "sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315", size = 8403, upload-time = "2026-03-19T01:04:30.883Z" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + +[[package]] +name = "babel" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, +] + +[[package]] +name = "bleach" +version = "6.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/18/3c8523962314be6bf4c8989c79ad9531c825210dd13a8669f6b84336e8bd/bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22", size = 203533, upload-time = "2025-10-27T17:57:39.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6", size = 164437, upload-time = "2025-10-27T17:57:37.538Z" }, +] + +[package.optional-dependencies] +css = [ + { name = "tinycss2" }, +] + +[[package]] +name = "certifi" +version = "2026.5.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/ce/ee2ecad540810a79593028e88299baeae54d346cc7a0d94b6199988b89b1/certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d", size = 135422, upload-time = "2026-05-20T11:46:50.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/8c/57e832b7af6d7c5abe66eb3fbe3a3a32f4d11ea23a1aa7131371035be991/certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897", size = 134134, upload-time = "2026-05-20T11:46:48.578Z" }, +] + +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, + { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, + { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, + { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, + { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, + { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/eb/4fc8d0a7110eb5fc9cc161723a34a8a6c200ce3b4fbf681bc86feee22308/charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46", size = 311328, upload-time = "2026-04-02T09:26:24.331Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e3/0fadc706008ac9d7b9b5be6dc767c05f9d3e5df51744ce4cc9605de7b9f4/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2", size = 208061, upload-time = "2026-04-02T09:26:25.568Z" }, + { url = "https://files.pythonhosted.org/packages/42/f0/3dd1045c47f4a4604df85ec18ad093912ae1344ac706993aff91d38773a2/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b", size = 229031, upload-time = "2026-04-02T09:26:26.865Z" }, + { url = "https://files.pythonhosted.org/packages/dc/67/675a46eb016118a2fbde5a277a5d15f4f69d5f3f5f338e5ee2f8948fcf43/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a", size = 225239, upload-time = "2026-04-02T09:26:28.044Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f8/d0118a2f5f23b02cd166fa385c60f9b0d4f9194f574e2b31cef350ad7223/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116", size = 216589, upload-time = "2026-04-02T09:26:29.239Z" }, + { url = "https://files.pythonhosted.org/packages/b1/f1/6d2b0b261b6c4ceef0fcb0d17a01cc5bc53586c2d4796fa04b5c540bc13d/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb", size = 202733, upload-time = "2026-04-02T09:26:30.5Z" }, + { url = "https://files.pythonhosted.org/packages/6f/c0/7b1f943f7e87cc3db9626ba17807d042c38645f0a1d4415c7a14afb5591f/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1", size = 212652, upload-time = "2026-04-02T09:26:31.709Z" }, + { url = "https://files.pythonhosted.org/packages/38/dd/5a9ab159fe45c6e72079398f277b7d2b523e7f716acc489726115a910097/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15", size = 211229, upload-time = "2026-04-02T09:26:33.282Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ff/531a1cad5ca855d1c1a8b69cb71abfd6d85c0291580146fda7c82857caa1/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5", size = 203552, upload-time = "2026-04-02T09:26:34.845Z" }, + { url = "https://files.pythonhosted.org/packages/c1/4c/a5fb52d528a8ca41f7598cb619409ece30a169fbdf9cdce592e53b46c3a6/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d", size = 230806, upload-time = "2026-04-02T09:26:36.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/7a/071feed8124111a32b316b33ae4de83d36923039ef8cf48120266844285b/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7", size = 212316, upload-time = "2026-04-02T09:26:37.672Z" }, + { url = "https://files.pythonhosted.org/packages/fd/35/f7dba3994312d7ba508e041eaac39a36b120f32d4c8662b8814dab876431/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464", size = 227274, upload-time = "2026-04-02T09:26:38.93Z" }, + { url = "https://files.pythonhosted.org/packages/8a/2d/a572df5c9204ab7688ec1edc895a73ebded3b023bb07364710b05dd1c9be/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49", size = 218468, upload-time = "2026-04-02T09:26:40.17Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/890922a8b03a568ca2f336c36585a4713c55d4d67bf0f0c78924be6315ca/charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c", size = 148460, upload-time = "2026-04-02T09:26:41.416Z" }, + { url = "https://files.pythonhosted.org/packages/35/d9/0e7dffa06c5ab081f75b1b786f0aefc88365825dfcd0ac544bdb7b2b6853/charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6", size = 159330, upload-time = "2026-04-02T09:26:42.554Z" }, + { url = "https://files.pythonhosted.org/packages/9e/5d/481bcc2a7c88ea6b0878c299547843b2521ccbc40980cb406267088bc701/charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d", size = 147828, upload-time = "2026-04-02T09:26:44.075Z" }, + { url = "https://files.pythonhosted.org/packages/c1/3b/66777e39d3ae1ddc77ee606be4ec6d8cbd4c801f65e5a1b6f2b11b8346dd/charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063", size = 309627, upload-time = "2026-04-02T09:26:45.198Z" }, + { url = "https://files.pythonhosted.org/packages/2e/4e/b7f84e617b4854ade48a1b7915c8ccfadeba444d2a18c291f696e37f0d3b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c", size = 207008, upload-time = "2026-04-02T09:26:46.824Z" }, + { url = "https://files.pythonhosted.org/packages/c4/bb/ec73c0257c9e11b268f018f068f5d00aa0ef8c8b09f7753ebd5f2880e248/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66", size = 228303, upload-time = "2026-04-02T09:26:48.397Z" }, + { url = "https://files.pythonhosted.org/packages/85/fb/32d1f5033484494619f701e719429c69b766bfc4dbc61aa9e9c8c166528b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18", size = 224282, upload-time = "2026-04-02T09:26:49.684Z" }, + { url = "https://files.pythonhosted.org/packages/fa/07/330e3a0dda4c404d6da83b327270906e9654a24f6c546dc886a0eb0ffb23/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd", size = 215595, upload-time = "2026-04-02T09:26:50.915Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7c/fc890655786e423f02556e0216d4b8c6bcb6bdfa890160dc66bf52dee468/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215", size = 201986, upload-time = "2026-04-02T09:26:52.197Z" }, + { url = "https://files.pythonhosted.org/packages/d8/97/bfb18b3db2aed3b90cf54dc292ad79fdd5ad65c4eae454099475cbeadd0d/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859", size = 211711, upload-time = "2026-04-02T09:26:53.49Z" }, + { url = "https://files.pythonhosted.org/packages/6f/a5/a581c13798546a7fd557c82614a5c65a13df2157e9ad6373166d2a3e645d/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8", size = 210036, upload-time = "2026-04-02T09:26:54.975Z" }, + { url = "https://files.pythonhosted.org/packages/8c/bf/b3ab5bcb478e4193d517644b0fb2bf5497fbceeaa7a1bc0f4d5b50953861/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5", size = 202998, upload-time = "2026-04-02T09:26:56.303Z" }, + { url = "https://files.pythonhosted.org/packages/e7/4e/23efd79b65d314fa320ec6017b4b5834d5c12a58ba4610aa353af2e2f577/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832", size = 230056, upload-time = "2026-04-02T09:26:57.554Z" }, + { url = "https://files.pythonhosted.org/packages/b9/9f/1e1941bc3f0e01df116e68dc37a55c4d249df5e6fa77f008841aef68264f/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6", size = 211537, upload-time = "2026-04-02T09:26:58.843Z" }, + { url = "https://files.pythonhosted.org/packages/80/0f/088cbb3020d44428964a6c97fe1edfb1b9550396bf6d278330281e8b709c/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48", size = 226176, upload-time = "2026-04-02T09:27:00.437Z" }, + { url = "https://files.pythonhosted.org/packages/6a/9f/130394f9bbe06f4f63e22641d32fc9b202b7e251c9aef4db044324dac493/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a", size = 217723, upload-time = "2026-04-02T09:27:02.021Z" }, + { url = "https://files.pythonhosted.org/packages/73/55/c469897448a06e49f8fa03f6caae97074fde823f432a98f979cc42b90e69/charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e", size = 148085, upload-time = "2026-04-02T09:27:03.192Z" }, + { url = "https://files.pythonhosted.org/packages/5d/78/1b74c5bbb3f99b77a1715c91b3e0b5bdb6fe302d95ace4f5b1bec37b0167/charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110", size = 158819, upload-time = "2026-04-02T09:27:04.454Z" }, + { url = "https://files.pythonhosted.org/packages/68/86/46bd42279d323deb8687c4a5a811fd548cb7d1de10cf6535d099877a9a9f/charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b", size = 147915, upload-time = "2026-04-02T09:27:05.971Z" }, + { url = "https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0", size = 309234, upload-time = "2026-04-02T09:27:07.194Z" }, + { url = "https://files.pythonhosted.org/packages/99/85/c091fdee33f20de70d6c8b522743b6f831a2f1cd3ff86de4c6a827c48a76/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a", size = 208042, upload-time = "2026-04-02T09:27:08.749Z" }, + { url = "https://files.pythonhosted.org/packages/87/1c/ab2ce611b984d2fd5d86a5a8a19c1ae26acac6bad967da4967562c75114d/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b", size = 228706, upload-time = "2026-04-02T09:27:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/a8/29/2b1d2cb00bf085f59d29eb773ce58ec2d325430f8c216804a0a5cd83cbca/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41", size = 224727, upload-time = "2026-04-02T09:27:11.175Z" }, + { url = "https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e", size = 215882, upload-time = "2026-04-02T09:27:12.446Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae", size = 200860, upload-time = "2026-04-02T09:27:13.721Z" }, + { url = "https://files.pythonhosted.org/packages/0c/cd/a32a84217ced5039f53b29f460962abb2d4420def55afabe45b1c3c7483d/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18", size = 211564, upload-time = "2026-04-02T09:27:15.272Z" }, + { url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b", size = 211276, upload-time = "2026-04-02T09:27:16.834Z" }, + { url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356", size = 201238, upload-time = "2026-04-02T09:27:18.229Z" }, + { url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab", size = 230189, upload-time = "2026-04-02T09:27:19.445Z" }, + { url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46", size = 211352, upload-time = "2026-04-02T09:27:20.79Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44", size = 227024, upload-time = "2026-04-02T09:27:22.063Z" }, + { url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72", size = 217869, upload-time = "2026-04-02T09:27:23.486Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10", size = 148541, upload-time = "2026-04-02T09:27:25.146Z" }, + { url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f", size = 159634, upload-time = "2026-04-02T09:27:26.642Z" }, + { url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246", size = 148384, upload-time = "2026-04-02T09:27:28.271Z" }, + { url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24", size = 330133, upload-time = "2026-04-02T09:27:29.474Z" }, + { url = "https://files.pythonhosted.org/packages/8d/da/96975ddb11f8e977f706f45cddd8540fd8242f71ecdb5d18a80723dcf62c/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79", size = 216257, upload-time = "2026-04-02T09:27:30.793Z" }, + { url = "https://files.pythonhosted.org/packages/e5/e8/1d63bf8ef2d388e95c64b2098f45f84758f6d102a087552da1485912637b/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960", size = 234851, upload-time = "2026-04-02T09:27:32.44Z" }, + { url = "https://files.pythonhosted.org/packages/9b/40/e5ff04233e70da2681fa43969ad6f66ca5611d7e669be0246c4c7aaf6dc8/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4", size = 233393, upload-time = "2026-04-02T09:27:34.03Z" }, + { url = "https://files.pythonhosted.org/packages/be/c1/06c6c49d5a5450f76899992f1ee40b41d076aee9279b49cf9974d2f313d5/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e", size = 223251, upload-time = "2026-04-02T09:27:35.369Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1", size = 206609, upload-time = "2026-04-02T09:27:36.661Z" }, + { url = "https://files.pythonhosted.org/packages/69/d5/a527c0cd8d64d2eab7459784fb4169a0ac76e5a6fc5237337982fd61347e/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44", size = 220014, upload-time = "2026-04-02T09:27:38.019Z" }, + { url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e", size = 218979, upload-time = "2026-04-02T09:27:39.37Z" }, + { url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3", size = 209238, upload-time = "2026-04-02T09:27:40.722Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0", size = 236110, upload-time = "2026-04-02T09:27:42.33Z" }, + { url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e", size = 219824, upload-time = "2026-04-02T09:27:43.924Z" }, + { url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb", size = 233103, upload-time = "2026-04-02T09:27:45.348Z" }, + { url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe", size = 225194, upload-time = "2026-04-02T09:27:46.706Z" }, + { url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0", size = 159827, upload-time = "2026-04-02T09:27:48.053Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c", size = 174168, upload-time = "2026-04-02T09:27:49.795Z" }, + { url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d", size = 153018, upload-time = "2026-04-02T09:27:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "comm" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, +] + +[[package]] +name = "contourpy" +version = "1.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419, upload-time = "2025-07-26T12:01:21.16Z" }, + { url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979, upload-time = "2025-07-26T12:01:22.448Z" }, + { url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653, upload-time = "2025-07-26T12:01:24.155Z" }, + { url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536, upload-time = "2025-07-26T12:01:25.91Z" }, + { url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397, upload-time = "2025-07-26T12:01:27.152Z" }, + { url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601, upload-time = "2025-07-26T12:01:28.808Z" }, + { url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288, upload-time = "2025-07-26T12:01:31.198Z" }, + { url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386, upload-time = "2025-07-26T12:01:33.947Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018, upload-time = "2025-07-26T12:01:35.64Z" }, + { url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567, upload-time = "2025-07-26T12:01:36.804Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655, upload-time = "2025-07-26T12:01:37.999Z" }, + { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, + { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, + { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, + { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, + { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, + { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, + { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, + { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, + { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, + { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, + { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, + { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, + { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, + { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, + { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, + { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, + { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" }, + { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" }, + { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" }, + { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" }, + { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" }, + { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" }, + { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" }, + { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" }, + { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" }, + { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" }, + { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" }, + { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" }, + { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" }, + { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" }, + { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" }, +] + +[[package]] +name = "cycler" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, +] + +[[package]] +name = "debugpy" +version = "1.8.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/b7/cd8080344452e4874aae67c40d8940e2b4d47b01601a8fd9f44786c757c7/debugpy-1.8.20.tar.gz", hash = "sha256:55bc8701714969f1ab89a6d5f2f3d40c36f91b2cbe2f65d98bf8196f6a6a2c33", size = 1645207, upload-time = "2026-01-29T23:03:28.199Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/57/7f34f4736bfb6e00f2e4c96351b07805d83c9a7b33d28580ae01374430f7/debugpy-1.8.20-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:4ae3135e2089905a916909ef31922b2d733d756f66d87345b3e5e52b7a55f13d", size = 2550686, upload-time = "2026-01-29T23:03:42.023Z" }, + { url = "https://files.pythonhosted.org/packages/ab/78/b193a3975ca34458f6f0e24aaf5c3e3da72f5401f6054c0dfd004b41726f/debugpy-1.8.20-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:88f47850a4284b88bd2bfee1f26132147d5d504e4e86c22485dfa44b97e19b4b", size = 4310588, upload-time = "2026-01-29T23:03:43.314Z" }, + { url = "https://files.pythonhosted.org/packages/c1/55/f14deb95eaf4f30f07ef4b90a8590fc05d9e04df85ee379712f6fb6736d7/debugpy-1.8.20-cp312-cp312-win32.whl", hash = "sha256:4057ac68f892064e5f98209ab582abfee3b543fb55d2e87610ddc133a954d390", size = 5331372, upload-time = "2026-01-29T23:03:45.526Z" }, + { url = "https://files.pythonhosted.org/packages/a1/39/2bef246368bd42f9bd7cba99844542b74b84dacbdbea0833e610f384fee8/debugpy-1.8.20-cp312-cp312-win_amd64.whl", hash = "sha256:a1a8f851e7cf171330679ef6997e9c579ef6dd33c9098458bd9986a0f4ca52e3", size = 5372835, upload-time = "2026-01-29T23:03:47.245Z" }, + { url = "https://files.pythonhosted.org/packages/15/e2/fc500524cc6f104a9d049abc85a0a8b3f0d14c0a39b9c140511c61e5b40b/debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:5dff4bb27027821fdfcc9e8f87309a28988231165147c31730128b1c983e282a", size = 2539560, upload-time = "2026-01-29T23:03:48.738Z" }, + { url = "https://files.pythonhosted.org/packages/90/83/fb33dcea789ed6018f8da20c5a9bc9d82adc65c0c990faed43f7c955da46/debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:84562982dd7cf5ebebfdea667ca20a064e096099997b175fe204e86817f64eaf", size = 4293272, upload-time = "2026-01-29T23:03:50.169Z" }, + { url = "https://files.pythonhosted.org/packages/a6/25/b1e4a01bfb824d79a6af24b99ef291e24189080c93576dfd9b1a2815cd0f/debugpy-1.8.20-cp313-cp313-win32.whl", hash = "sha256:da11dea6447b2cadbf8ce2bec59ecea87cc18d2c574980f643f2d2dfe4862393", size = 5331208, upload-time = "2026-01-29T23:03:51.547Z" }, + { url = "https://files.pythonhosted.org/packages/13/f7/a0b368ce54ffff9e9028c098bd2d28cfc5b54f9f6c186929083d4c60ba58/debugpy-1.8.20-cp313-cp313-win_amd64.whl", hash = "sha256:eb506e45943cab2efb7c6eafdd65b842f3ae779f020c82221f55aca9de135ed7", size = 5372930, upload-time = "2026-01-29T23:03:53.585Z" }, + { url = "https://files.pythonhosted.org/packages/33/2e/f6cb9a8a13f5058f0a20fe09711a7b726232cd5a78c6a7c05b2ec726cff9/debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9c74df62fc064cd5e5eaca1353a3ef5a5d50da5eb8058fcef63106f7bebe6173", size = 2538066, upload-time = "2026-01-29T23:03:54.999Z" }, + { url = "https://files.pythonhosted.org/packages/c5/56/6ddca50b53624e1ca3ce1d1e49ff22db46c47ea5fb4c0cc5c9b90a616364/debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad", size = 4269425, upload-time = "2026-01-29T23:03:56.518Z" }, + { url = "https://files.pythonhosted.org/packages/c5/d9/d64199c14a0d4c476df46c82470a3ce45c8d183a6796cfb5e66533b3663c/debugpy-1.8.20-cp314-cp314-win32.whl", hash = "sha256:352036a99dd35053b37b7803f748efc456076f929c6a895556932eaf2d23b07f", size = 5331407, upload-time = "2026-01-29T23:03:58.481Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d9/1f07395b54413432624d61524dfd98c1a7c7827d2abfdb8829ac92638205/debugpy-1.8.20-cp314-cp314-win_amd64.whl", hash = "sha256:a98eec61135465b062846112e5ecf2eebb855305acc1dfbae43b72903b8ab5be", size = 5372521, upload-time = "2026-01-29T23:03:59.864Z" }, + { url = "https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl", hash = "sha256:5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7", size = 5337658, upload-time = "2026-01-29T23:04:17.404Z" }, +] + +[[package]] +name = "decorator" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/60/8b/32f9823da46cde7df2087faa08cd98d01b908f8dcab982cdba9c84e85355/decorator-5.3.1.tar.gz", hash = "sha256:4cbcdd55a6efadb9dbea26b858f4fb3264567b52d69ca0d25b721b553f60ea82", size = 58084, upload-time = "2026-05-18T06:03:28.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/7f/798705f5296a58ca505d600456748d1be48078eac8a7050d8a98bc9edb89/decorator-5.3.1-py3-none-any.whl", hash = "sha256:f47fe6fdbd2edd623ecfe36875d37aba411624e2670dd395dddae1358689bb3c", size = 10365, upload-time = "2026-05-18T06:03:26.517Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "fastjsonschema" +version = "2.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de", size = 374130, upload-time = "2025-08-14T18:49:36.666Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463", size = 24024, upload-time = "2025-08-14T18:49:34.776Z" }, +] + +[[package]] +name = "femsurrogate-tutorial" +version = "0.1.0" +source = { editable = "." } +dependencies = [ + { name = "joblib" }, + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pandas" }, + { name = "scikit-learn" }, + { name = "scipy" }, +] + +[package.dev-dependencies] +dev = [ + { name = "ipykernel" }, + { name = "jupyterlab" }, + { name = "nbconvert" }, + { name = "pytest" }, + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [ + { name = "joblib" }, + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pandas" }, + { name = "scikit-learn" }, + { name = "scipy" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "ipykernel" }, + { name = "jupyterlab" }, + { name = "nbconvert" }, + { name = "pytest" }, + { name = "ruff" }, +] + +[[package]] +name = "fonttools" +version = "4.63.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/84/69/c97f2c18e0db87d2c7b15da1974dace76ae938f1cfa22e2727a648b7ed43/fonttools-4.63.0.tar.gz", hash = "sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0", size = 3597189, upload-time = "2026-05-14T12:04:30.958Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/ef/b3c6b9b5be2f82416d73fe2ed2e96e2793cd80e7510bd6a17ca79cdd88ec/fonttools-4.63.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:37dd23e621e3b0aef1baa70a303b80aaf38449632cfc8fd2a55fb285bbccfc02", size = 2881131, upload-time = "2026-05-14T12:03:13.386Z" }, + { url = "https://files.pythonhosted.org/packages/44/a0/c815bea63117fa63e4e1c01f8a1110d2112fa003f838e6467094ec2432ce/fonttools-4.63.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a9faff9e0c1f76f9fd55899d2ce785832efebab37eb8ae13995853aef178bef0", size = 2426704, upload-time = "2026-05-14T12:03:15.801Z" }, + { url = "https://files.pythonhosted.org/packages/44/04/0b91d8e916e92ad1fac9e4624760baf0fd5ff2ead614c2f68fb21373f03f/fonttools-4.63.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef3048ef05dbb552b89817713d9cac912e00d0fde4a3105c00d29e52e10c89af", size = 5044298, upload-time = "2026-05-14T12:03:18.085Z" }, + { url = "https://files.pythonhosted.org/packages/77/c7/2342da9830e3e9d4870305ca5d2091d2a83284f2953079b7bdd3b5e029d8/fonttools-4.63.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58dc6bb86a78d782f00f9190ca02c119cf5bbe2807536e361e18d42019f877d8", size = 4999800, upload-time = "2026-05-14T12:03:20.161Z" }, + { url = "https://files.pythonhosted.org/packages/e6/6d/67fe16c48d7ce050979b33f47e0d28a318f02da030602e944c34f7a16ef3/fonttools-4.63.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee08ebfa58f6e1aeff5697ab9582105bb620008c1caafb681e4c557e7483027b", size = 4982666, upload-time = "2026-05-14T12:03:22.87Z" }, + { url = "https://files.pythonhosted.org/packages/f2/00/3bbab338c07c71fa56269953845e92c951a61457bbbb0f1022551ea266d9/fonttools-4.63.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:27fdc65af8da6f88b9c6121c47a464cbe359fcfff7ff6fc2d37a1f395d755b78", size = 5133598, upload-time = "2026-05-14T12:03:25.168Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/aa27c7f98db5b064883dadcc5283947e81e034de42e22a33675878d98b54/fonttools-4.63.0-cp312-cp312-win32.whl", hash = "sha256:af2fd1664d00a397d75f806985ddb36282091c2131a73a6485c23b4a34722263", size = 2292575, upload-time = "2026-05-14T12:03:27.496Z" }, + { url = "https://files.pythonhosted.org/packages/87/36/cccb9bc2a6ab63d1b2980374f0dca72ce95ae267c9b4cfe77455bb70d0d4/fonttools-4.63.0-cp312-cp312-win_amd64.whl", hash = "sha256:59ac449f8cca9b4ffa08d2e7bbadad87ce710d69d1eda5c3c1ce579baa987272", size = 2343211, upload-time = "2026-05-14T12:03:30.057Z" }, + { url = "https://files.pythonhosted.org/packages/0f/8d/d8fec3dcde2963f8c908fb315e5ff2cd0ac34f82394bbbf73a2aa5145ce3/fonttools-4.63.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd7e9857e5e63738b9d9fd707bc1f59c8b09e5177726d23664db393c59bb08bd", size = 2876062, upload-time = "2026-05-14T12:03:32.554Z" }, + { url = "https://files.pythonhosted.org/packages/ef/71/d935dc54e4ff121bfdd11e08702db63a7e6f25af21d8a3d7b7212df53641/fonttools-4.63.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c2a2a42198b696a6f48fad91709afb55176e66a5e566131219dba372fb7f8c59", size = 2424594, upload-time = "2026-05-14T12:03:34.86Z" }, + { url = "https://files.pythonhosted.org/packages/8e/40/e76320afa1df918e146155ef239b1719ee266092e96f5423bfd075affba1/fonttools-4.63.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e874792a8212b44583ea02189d9e693906b2f78b261f372f95d6c563210ac1d", size = 5024840, upload-time = "2026-05-14T12:03:36.745Z" }, + { url = "https://files.pythonhosted.org/packages/ce/36/0b805d8c485f872f65a509cbe3b58a5d0d17bee855333b54a150c79d3061/fonttools-4.63.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22135da48a348785c5e2d5d2d9d6bec5ed44adacbaeb9db12d9493bf6c6bfa68", size = 4975801, upload-time = "2026-05-14T12:03:38.833Z" }, + { url = "https://files.pythonhosted.org/packages/c8/26/2cee03d0aa083ab022da5c07aff9ed3f689da1defb81ad6917c9627896da/fonttools-4.63.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ccf41f2efdf56994d22d73bef4ced1052161958169428d06ba9724ea9e9a64be", size = 4965009, upload-time = "2026-05-14T12:03:41.494Z" }, + { url = "https://files.pythonhosted.org/packages/7e/48/cc4b66d9058c0d0982c833fad10127c4b0e9324606aafa41382295ca4102/fonttools-4.63.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9ced0bd02ac751dd6319b0da88aaef24414e3b0dbc32bb4f24944821a3741a27", size = 5105892, upload-time = "2026-05-14T12:03:43.525Z" }, + { url = "https://files.pythonhosted.org/packages/d8/1f/a98a30a814b9ddef3a2e706025f90b9e0bc94890e6cb15254bc86547d11a/fonttools-4.63.0-cp313-cp313-win32.whl", hash = "sha256:85be818f5506e8a7753153def2c9550178f0ecae6a47b5e0e8dbb23f7cc90380", size = 2291313, upload-time = "2026-05-14T12:03:45.594Z" }, + { url = "https://files.pythonhosted.org/packages/92/46/5177b01f3b4abfdd4409f31cca4ab279c9343a26efbe9ec78c97fc612e02/fonttools-4.63.0-cp313-cp313-win_amd64.whl", hash = "sha256:ba04cb5891d4c0c21b6da95eda8d7b090021508a294fff33464fc7d241e0856b", size = 2342299, upload-time = "2026-05-14T12:03:47.414Z" }, + { url = "https://files.pythonhosted.org/packages/27/d2/23d25e3f247b328be58d04a4c9f894178a0d1eda7d42867cfb388adaf416/fonttools-4.63.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fd1e3094f42d806d3d7c79162fc59e5910fcbe3a7360c385b8da969bc4493745", size = 2875338, upload-time = "2026-05-14T12:03:50.052Z" }, + { url = "https://files.pythonhosted.org/packages/cd/58/7dfa0c761cb3b2964e2a84c4dc986c926a87de0cb9fb60d5b28ded3f2914/fonttools-4.63.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6e528da43bc3791085f8cb6141b1d13e459226790240340fcbb4625649238b03", size = 2422661, upload-time = "2026-05-14T12:03:52.154Z" }, + { url = "https://files.pythonhosted.org/packages/dd/87/64cfa18a7a1621d17b7f4502b2b0ed8a135a90c3db51ea590ee99043e76b/fonttools-4.63.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b2248c5decb223562f7902ff6325077a073f608ee8e33e88ad88db734eb9f49", size = 5010526, upload-time = "2026-05-14T12:03:54.647Z" }, + { url = "https://files.pythonhosted.org/packages/36/e1/a8933a72c45a87177fbde2696e0d0755c8c9062f8c077a961c6215fa27b1/fonttools-4.63.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:308f957cdeaf8abe4e5f2f124902ef405448af92c90f80e302a3b771c2e6116b", size = 4923946, upload-time = "2026-05-14T12:03:56.984Z" }, + { url = "https://files.pythonhosted.org/packages/27/60/872e6e233b8c5e8b41413796ff18b7fe479661bd40147e071b450dfad7a1/fonttools-4.63.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bf00f21eb5fb721dbaf73d1e9da6d02a1af7768f2ebcf9798be98beab8ba90f6", size = 4962489, upload-time = "2026-05-14T12:03:59.443Z" }, + { url = "https://files.pythonhosted.org/packages/30/c4/83c24f2ec38b90cfda84bf4b1a1f49df80e84a1db4e7ac6e0d41bf23bc39/fonttools-4.63.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c1aaa4b9c75798400ac043ce04d74e7830376c85095a5a6ed7cba2f17a266bf4", size = 5071870, upload-time = "2026-05-14T12:04:02.122Z" }, + { url = "https://files.pythonhosted.org/packages/de/40/3ae22b60ff1d41ce0bd044b31238cdc72cef99f28b976f1e128ebd618c9b/fonttools-4.63.0-cp314-cp314-win32.whl", hash = "sha256:22693918177bd9ceabec4736d338045f357769416fc6b0b2508eefef75b08616", size = 2295026, upload-time = "2026-05-14T12:04:04.47Z" }, + { url = "https://files.pythonhosted.org/packages/c3/d4/98078064ccc76b45cb0f6c002452011e93c4bd26f6850344f0951cc1fe89/fonttools-4.63.0-cp314-cp314-win_amd64.whl", hash = "sha256:7d782fac32985914c351556f68ac0855391572bcd87de50e05970d3cd4c96fc5", size = 2347454, upload-time = "2026-05-14T12:04:06.752Z" }, + { url = "https://files.pythonhosted.org/packages/49/4e/652d1580c5f4e39f7d103b0c793e4773129ad633dce4addd0cf4dfebde02/fonttools-4.63.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:6db5140a60a5d731d21ec076745b40a310607731b0a565b50776393188649001", size = 2958152, upload-time = "2026-05-14T12:04:08.706Z" }, + { url = "https://files.pythonhosted.org/packages/0e/55/ad864c9a9b219f552eb46b32cd7906c466e5a578ba0c3abfcc0fe7413eb6/fonttools-4.63.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d76edbff9014094dbf03bd2d074709dfa6ec7aba13d838c937a2b33d2d6a86e", size = 2460809, upload-time = "2026-05-14T12:04:10.783Z" }, + { url = "https://files.pythonhosted.org/packages/ea/2b/0aa8db70f18cf52e49b4ed5ecec68547f981160bf5ded3b5aed6faa0a6f9/fonttools-4.63.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0eac00b9118c3c2f87d272e45341871c5b3066baa3c86897fa634a7c3fb59096", size = 5148649, upload-time = "2026-05-14T12:04:12.747Z" }, + { url = "https://files.pythonhosted.org/packages/7f/63/18e4369c25043096f1048e0c9915951adc4f842bd81c6b18155824d6fa99/fonttools-4.63.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51394295f1a51de8b5f30bdb1e1b9a4231536c7064ef5c6e211eec19fa36036f", size = 4932147, upload-time = "2026-05-14T12:04:14.806Z" }, + { url = "https://files.pythonhosted.org/packages/a1/3f/67f3eac2ffd8a98446c5022f8ed3864eac878a5ff7af8df4c8286dba16cc/fonttools-4.63.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9e12f105d2b6342c559c298afb674006bb2893afc7102dcf8a1b55b0486b4e40", size = 5027237, upload-time = "2026-05-14T12:04:17.675Z" }, + { url = "https://files.pythonhosted.org/packages/1a/ba/4e6214cb38a7b04779e97bb7636de9a5c7f20af7018d03dee0b64c08510a/fonttools-4.63.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:796f27556dbe094c4824f75ca85267e4df776c79036c8441469a4df37038c196", size = 5053933, upload-time = "2026-05-14T12:04:20.818Z" }, + { url = "https://files.pythonhosted.org/packages/34/3b/214dcc19ee31d3d38fb5ad2755c11ef0514e5dc300bbaf41c0b69f393799/fonttools-4.63.0-cp314-cp314t-win32.whl", hash = "sha256:948428a275741f0b64b113c955425a953314f4b9ab9997f73a72c83e68e569c8", size = 2359326, upload-time = "2026-05-14T12:04:24.22Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1e/3ff1a9b523058c2eeb6a9d50f5574e2a738200d0d94107d5bc4105e8da3f/fonttools-4.63.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6d4741eb179121cab9eea4cb2393d24492373a260d7945006358c08cfbf45419", size = 2425829, upload-time = "2026-05-14T12:04:26.829Z" }, + { url = "https://files.pythonhosted.org/packages/2c/47/c99d5268f354002ce80f8d029cd9d7d872969da1de8b93d32de4dc56d6f4/fonttools-4.63.0-py3-none-any.whl", hash = "sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d", size = 1164562, upload-time = "2026-05-14T12:04:29.092Z" }, +] + +[[package]] +name = "fqdn" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015, upload-time = "2021-03-11T07:16:29.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "idna" +version = "3.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "ipykernel" +version = "7.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appnope", marker = "sys_platform == 'darwin'" }, + { name = "comm" }, + { name = "debugpy" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "matplotlib-inline" }, + { name = "nest-asyncio" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ca/8d/b68b728e2d06b9e0051019640a40a9eb7a88fcd82c2e1b5ce70bef5ff044/ipykernel-7.2.0.tar.gz", hash = "sha256:18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e", size = 176046, upload-time = "2026-02-06T16:43:27.403Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl", hash = "sha256:3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661", size = 118788, upload-time = "2026-02-06T16:43:25.149Z" }, +] + +[[package]] +name = "ipython" +version = "9.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "decorator" }, + { name = "ipython-pygments-lexers" }, + { name = "jedi" }, + { name = "matplotlib-inline" }, + { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit" }, + { name = "psutil" }, + { name = "pygments" }, + { name = "stack-data" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/c4/87cda5842cf5c31837c06ddb588e11c3c35d8ece89b7a0108c06b8c9b00a/ipython-9.13.0.tar.gz", hash = "sha256:7e834b6afc99f020e3f05966ced34792f40267d64cb1ea9043886dab0dde5967", size = 4430549, upload-time = "2026-04-24T12:24:55.221Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/86/3060e8029b7cc505cce9a0137431dda81d0a3fde93a8f0f50ee0bf37a795/ipython-9.13.0-py3-none-any.whl", hash = "sha256:57f9d4639e20818d328d287c7b549af3d05f12486ea8f2e7f73e52a36ec4d201", size = 627274, upload-time = "2026-04-24T12:24:53.038Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "isoduration" +version = "20.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "arrow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649, upload-time = "2020-11-01T11:00:00.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, +] + +[[package]] +name = "jedi" +version = "0.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/b7/a3635f6a2d7cf5b5dd98064fc1d5fbbafcb25477bcea204a3a92145d158b/jedi-0.20.0.tar.gz", hash = "sha256:c3f4ccbd276696f4b19c54618d4fb18f9fc24b0aef02acf704b23f487daa1011", size = 3119416, upload-time = "2026-05-01T23:38:47.814Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/93/242e2eab5fe682ffcb8b0084bde703a41d51e17ee0f3a31ff0d9d813620a/jedi-0.20.0-py2.py3-none-any.whl", hash = "sha256:7bdd9c2634f56713299976f4cbd59cb3fa92165cc5e05ea811fb253480728b67", size = 4884812, upload-time = "2026-05-01T23:38:43.919Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "joblib" +version = "1.5.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, +] + +[[package]] +name = "json5" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/4b/6f8906aaf67d501e259b0adab4d312945bb7211e8b8d4dcc77c92320edaa/json5-0.14.0.tar.gz", hash = "sha256:b3f492fad9f6cdbced8b7d40b28b9b1c9701c5f561bef0d33b81c2ff433fefcb", size = 52656, upload-time = "2026-03-27T22:50:48.108Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/42/cf027b4ac873b076189d935b135397675dac80cb29acb13e1ab86ad6c631/json5-0.14.0-py3-none-any.whl", hash = "sha256:56cf861bab076b1178eb8c92e1311d273a9b9acea2ccc82c276abf839ebaef3a", size = 36271, upload-time = "2026-03-27T22:50:47.073Z" }, +] + +[[package]] +name = "jsonpointer" +version = "3.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068, upload-time = "2026-03-23T22:32:32.458Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[package.optional-dependencies] +format-nongpl = [ + { name = "fqdn" }, + { name = "idna" }, + { name = "isoduration" }, + { name = "jsonpointer" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "rfc3987-syntax" }, + { name = "uri-template" }, + { name = "webcolors" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "jupyter-client" +version = "8.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-core" }, + { name = "python-dateutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/e4/ba649102a3bc3fbca54e7239fb924fd434c766f855693d86de0b1f2bec81/jupyter_client-8.8.0.tar.gz", hash = "sha256:d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e", size = 348020, upload-time = "2026-01-08T13:55:47.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl", hash = "sha256:f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a", size = 107371, upload-time = "2026-01-08T13:55:45.562Z" }, +] + +[[package]] +name = "jupyter-core" +version = "5.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" }, +] + +[[package]] +name = "jupyter-events" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonschema", extra = ["format-nongpl"] }, + { name = "packaging" }, + { name = "python-json-logger" }, + { name = "pyyaml" }, + { name = "referencing" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/f8/475c4241b2b75af0deaae453ed003c6c851766dbc44d332d8baf245dc931/jupyter_events-0.12.1.tar.gz", hash = "sha256:faff25f77218335752f35f23c5fe6e4a392a7bd99a5939ccb9b8fbf594636cf3", size = 62854, upload-time = "2026-04-20T23:17:50.66Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/6c/6fcde0c8f616ed360ffd3587f7db9e225a7e62b583a04494d2f069cf64ea/jupyter_events-0.12.1-py3-none-any.whl", hash = "sha256:c366585253f537a627da52fa7ca7410c5b5301fe893f511e7b077c2d93ec8bcf", size = 19512, upload-time = "2026-04-20T23:17:48.927Z" }, +] + +[[package]] +name = "jupyter-lsp" +version = "2.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/ff/1e4a61f5170a9a1d978f3ac3872449de6c01fc71eaf89657824c878b1549/jupyter_lsp-2.3.1.tar.gz", hash = "sha256:fdf8a4aa7d85813976d6e29e95e6a2c8f752701f926f2715305249a3829805a6", size = 55677, upload-time = "2026-04-02T08:10:06.749Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/e8/9d61dcbd1dce8ef418f06befd4ac084b4720429c26b0b1222bc218685eff/jupyter_lsp-2.3.1-py3-none-any.whl", hash = "sha256:71b954d834e85ff3096400554f2eefaf7fe37053036f9a782b0f7c5e42dadb81", size = 77513, upload-time = "2026-04-02T08:10:01.753Z" }, +] + +[[package]] +name = "jupyter-server" +version = "2.18.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "argon2-cffi" }, + { name = "jinja2" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "jupyter-events" }, + { name = "jupyter-server-terminals" }, + { name = "nbconvert" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "prometheus-client" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "pyzmq" }, + { name = "send2trash" }, + { name = "terminado" }, + { name = "tornado" }, + { name = "traitlets" }, + { name = "websocket-client" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ca/15/1eacb0fcb79ef86e8a0a79a708e6ad7435f6f223097dd29a4ce861fabc44/jupyter_server-2.18.2.tar.gz", hash = "sha256:06b4f40d8a7a00bb39d5216859c81374a0e7cfefe6d8a5a7facc5a5c37c679a7", size = 753177, upload-time = "2026-05-06T07:04:36.274Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/50/ecf4f70d65bdb7519b28a33d1b2fee8a4b4ba1ae1a92f15d97e877c5de21/jupyter_server-2.18.2-py3-none-any.whl", hash = "sha256:fa5e46539ded65791838035a2b6001f13e54d5f64b8b3752eb1e91fdd641a5b8", size = 391907, upload-time = "2026-05-06T07:04:34.014Z" }, +] + +[[package]] +name = "jupyter-server-terminals" +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "terminado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/a7/bcd0a9b0cbba88986fe944aaaf91bfda603e5a50bda8ed15123f381a3b2f/jupyter_server_terminals-0.5.4.tar.gz", hash = "sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5", size = 31770, upload-time = "2026-01-14T16:53:20.213Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl", hash = "sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14", size = 13704, upload-time = "2026-01-14T16:53:18.738Z" }, +] + +[[package]] +name = "jupyterlab" +version = "4.5.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-lru" }, + { name = "httpx" }, + { name = "ipykernel" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyter-lsp" }, + { name = "jupyter-server" }, + { name = "jupyterlab-server" }, + { name = "notebook-shim" }, + { name = "packaging" }, + { name = "setuptools" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2b/22/8440ec827762146e7cdecf04335bd348795899d29dc6ae82238707353a2c/jupyterlab-4.5.7.tar.gz", hash = "sha256:55a9822c4754da305f41e113452c68383e214dcf96de760146af89ce5d5117b0", size = 23992763, upload-time = "2026-04-29T16:43:51.328Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/aa/537b8f7d80e799af19af35fb3ddfc970b951088a13c57dd9387dcfbb7f61/jupyterlab-4.5.7-py3-none-any.whl", hash = "sha256:fba4cb0e2c44a52859669d8c98b45de029d5e515f8407bf8534d2a8fc5f0964d", size = 12450123, upload-time = "2026-04-29T16:43:46.639Z" }, +] + +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/90/51/9187be60d989df97f5f0aba133fa54e7300f17616e065d1ada7d7646b6d6/jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", size = 512900, upload-time = "2023-11-23T09:26:37.44Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884, upload-time = "2023-11-23T09:26:34.325Z" }, +] + +[[package]] +name = "jupyterlab-server" +version = "2.28.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "jinja2" }, + { name = "json5" }, + { name = "jsonschema" }, + { name = "jupyter-server" }, + { name = "packaging" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/2c/90153f189e421e93c4bb4f9e3f59802a1f01abd2ac5cf40b152d7f735232/jupyterlab_server-2.28.0.tar.gz", hash = "sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c", size = 76996, upload-time = "2025-10-22T13:59:18.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl", hash = "sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968", size = 59830, upload-time = "2025-10-22T13:59:16.767Z" }, +] + +[[package]] +name = "kiwisolver" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/67/9c61eccb13f0bdca9307614e782fec49ffdde0f7a2314935d489fa93cd9c/kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a", size = 103482, upload-time = "2026-03-09T13:15:53.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/b2/818b74ebea34dabe6d0c51cb1c572e046730e64844da6ed646d5298c40ce/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4e9750bc21b886308024f8a54ccb9a2cc38ac9fa813bf4348434e3d54f337ff9", size = 123158, upload-time = "2026-03-09T13:13:23.127Z" }, + { url = "https://files.pythonhosted.org/packages/bf/d9/405320f8077e8e1c5c4bd6adc45e1e6edf6d727b6da7f2e2533cf58bff71/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72ec46b7eba5b395e0a7b63025490d3214c11013f4aacb4f5e8d6c3041829588", size = 66388, upload-time = "2026-03-09T13:13:24.765Z" }, + { url = "https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819", size = 64068, upload-time = "2026-03-09T13:13:25.878Z" }, + { url = "https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f", size = 1477934, upload-time = "2026-03-09T13:13:27.166Z" }, + { url = "https://files.pythonhosted.org/packages/c8/2f/cebfcdb60fd6a9b0f6b47a9337198bcbad6fbe15e68189b7011fd914911f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2af221f268f5af85e776a73d62b0845fc8baf8ef0abfae79d29c77d0e776aaf", size = 1278537, upload-time = "2026-03-09T13:13:28.707Z" }, + { url = "https://files.pythonhosted.org/packages/f2/0d/9b782923aada3fafb1d6b84e13121954515c669b18af0c26e7d21f579855/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b0f172dc8ffaccb8522d7c5d899de00133f2f1ca7b0a49b7da98e901de87bf2d", size = 1296685, upload-time = "2026-03-09T13:13:30.528Z" }, + { url = "https://files.pythonhosted.org/packages/27/70/83241b6634b04fe44e892688d5208332bde130f38e610c0418f9ede47ded/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6ab8ba9152203feec73758dad83af9a0bbe05001eb4639e547207c40cfb52083", size = 1346024, upload-time = "2026-03-09T13:13:32.818Z" }, + { url = "https://files.pythonhosted.org/packages/e4/db/30ed226fb271ae1a6431fc0fe0edffb2efe23cadb01e798caeb9f2ceae8f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:cdee07c4d7f6d72008d3f73b9bf027f4e11550224c7c50d8df1ae4a37c1402a6", size = 987241, upload-time = "2026-03-09T13:13:34.435Z" }, + { url = "https://files.pythonhosted.org/packages/ec/bd/c314595208e4c9587652d50959ead9e461995389664e490f4dce7ff0f782/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c60d3c9b06fb23bd9c6139281ccbdc384297579ae037f08ae90c69f6845c0b1", size = 2227742, upload-time = "2026-03-09T13:13:36.4Z" }, + { url = "https://files.pythonhosted.org/packages/c1/43/0499cec932d935229b5543d073c2b87c9c22846aab48881e9d8d6e742a2d/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e315e5ec90d88e140f57696ff85b484ff68bb311e36f2c414aa4286293e6dee0", size = 2323966, upload-time = "2026-03-09T13:13:38.204Z" }, + { url = "https://files.pythonhosted.org/packages/3d/6f/79b0d760907965acfd9d61826a3d41f8f093c538f55cd2633d3f0db269f6/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:1465387ac63576c3e125e5337a6892b9e99e0627d52317f3ca79e6930d889d15", size = 1977417, upload-time = "2026-03-09T13:13:39.966Z" }, + { url = "https://files.pythonhosted.org/packages/ab/31/01d0537c41cb75a551a438c3c7a80d0c60d60b81f694dac83dd436aec0d0/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:530a3fd64c87cffa844d4b6b9768774763d9caa299e9b75d8eca6a4423b31314", size = 2491238, upload-time = "2026-03-09T13:13:41.698Z" }, + { url = "https://files.pythonhosted.org/packages/e4/34/8aefdd0be9cfd00a44509251ba864f5caf2991e36772e61c408007e7f417/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9", size = 2294947, upload-time = "2026-03-09T13:13:43.343Z" }, + { url = "https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384", size = 73569, upload-time = "2026-03-09T13:13:45.792Z" }, + { url = "https://files.pythonhosted.org/packages/28/26/192b26196e2316e2bd29deef67e37cdf9870d9af8e085e521afff0fed526/kiwisolver-1.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:f7c7553b13f69c1b29a5bde08ddc6d9d0c8bfb84f9ed01c30db25944aeb852a7", size = 64997, upload-time = "2026-03-09T13:13:46.878Z" }, + { url = "https://files.pythonhosted.org/packages/9d/69/024d6711d5ba575aa65d5538042e99964104e97fa153a9f10bc369182bc2/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09", size = 123166, upload-time = "2026-03-09T13:13:48.032Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/adbb40df306f587054a348831220812b9b1d787aff714cfbc8556e38fccd/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3", size = 66395, upload-time = "2026-03-09T13:13:49.365Z" }, + { url = "https://files.pythonhosted.org/packages/a8/3a/d0a972b34e1c63e2409413104216cd1caa02c5a37cb668d1687d466c1c45/kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd", size = 64065, upload-time = "2026-03-09T13:13:50.562Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0a/7b98e1e119878a27ba8618ca1e18b14f992ff1eda40f47bccccf4de44121/kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3", size = 1477903, upload-time = "2026-03-09T13:13:52.084Z" }, + { url = "https://files.pythonhosted.org/packages/18/d8/55638d89ffd27799d5cc3d8aa28e12f4ce7a64d67b285114dbedc8ea4136/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96", size = 1278751, upload-time = "2026-03-09T13:13:54.673Z" }, + { url = "https://files.pythonhosted.org/packages/b8/97/b4c8d0d18421ecceba20ad8701358453b88e32414e6f6950b5a4bad54e65/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099", size = 1296793, upload-time = "2026-03-09T13:13:56.287Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/f862f94b6389d8957448ec9df59450b81bec4abb318805375c401a1e6892/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8", size = 1346041, upload-time = "2026-03-09T13:13:58.269Z" }, + { url = "https://files.pythonhosted.org/packages/a3/6a/f1650af35821eaf09de398ec0bc2aefc8f211f0cda50204c9f1673741ba9/kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87", size = 987292, upload-time = "2026-03-09T13:13:59.871Z" }, + { url = "https://files.pythonhosted.org/packages/de/19/d7fb82984b9238115fe629c915007be608ebd23dc8629703d917dbfaffd4/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23", size = 2227865, upload-time = "2026-03-09T13:14:01.401Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b9/46b7f386589fd222dac9e9de9c956ce5bcefe2ee73b4e79891381dda8654/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859", size = 2324369, upload-time = "2026-03-09T13:14:02.972Z" }, + { url = "https://files.pythonhosted.org/packages/92/8b/95e237cf3d9c642960153c769ddcbe278f182c8affb20cecc1cc983e7cc5/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902", size = 1977989, upload-time = "2026-03-09T13:14:04.503Z" }, + { url = "https://files.pythonhosted.org/packages/1b/95/980c9df53501892784997820136c01f62bc1865e31b82b9560f980c0e649/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167", size = 2491645, upload-time = "2026-03-09T13:14:06.106Z" }, + { url = "https://files.pythonhosted.org/packages/cb/32/900647fd0840abebe1561792c6b31e6a7c0e278fc3973d30572a965ca14c/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0", size = 2295237, upload-time = "2026-03-09T13:14:08.891Z" }, + { url = "https://files.pythonhosted.org/packages/be/8a/be60e3bbcf513cc5a50f4a3e88e1dcecebb79c1ad607a7222877becaa101/kiwisolver-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276", size = 73573, upload-time = "2026-03-09T13:14:12.327Z" }, + { url = "https://files.pythonhosted.org/packages/4d/d2/64be2e429eb4fca7f7e1c52a91b12663aeaf25de3895e5cca0f47ef2a8d0/kiwisolver-1.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c", size = 64998, upload-time = "2026-03-09T13:14:13.469Z" }, + { url = "https://files.pythonhosted.org/packages/b0/69/ce68dd0c85755ae2de490bf015b62f2cea5f6b14ff00a463f9d0774449ff/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1", size = 125700, upload-time = "2026-03-09T13:14:14.636Z" }, + { url = "https://files.pythonhosted.org/packages/74/aa/937aac021cf9d4349990d47eb319309a51355ed1dbdc9c077cdc9224cb11/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e", size = 67537, upload-time = "2026-03-09T13:14:15.808Z" }, + { url = "https://files.pythonhosted.org/packages/ee/20/3a87fbece2c40ad0f6f0aefa93542559159c5f99831d596050e8afae7a9f/kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7", size = 65514, upload-time = "2026-03-09T13:14:18.035Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7f/f943879cda9007c45e1f7dba216d705c3a18d6b35830e488b6c6a4e7cdf0/kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c", size = 1584848, upload-time = "2026-03-09T13:14:19.745Z" }, + { url = "https://files.pythonhosted.org/packages/37/f8/4d4f85cc1870c127c88d950913370dd76138482161cd07eabbc450deff01/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368", size = 1391542, upload-time = "2026-03-09T13:14:21.54Z" }, + { url = "https://files.pythonhosted.org/packages/04/0b/65dd2916c84d252b244bd405303220f729e7c17c9d7d33dca6feeff9ffc4/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489", size = 1404447, upload-time = "2026-03-09T13:14:23.205Z" }, + { url = "https://files.pythonhosted.org/packages/39/5c/2606a373247babce9b1d056c03a04b65f3cf5290a8eac5d7bdead0a17e21/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1", size = 1455918, upload-time = "2026-03-09T13:14:24.74Z" }, + { url = "https://files.pythonhosted.org/packages/d5/d1/c6078b5756670658e9192a2ef11e939c92918833d2745f85cd14a6004bdf/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl", hash = "sha256:89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3", size = 1072856, upload-time = "2026-03-09T13:14:26.597Z" }, + { url = "https://files.pythonhosted.org/packages/cb/c8/7def6ddf16eb2b3741d8b172bdaa9af882b03c78e9b0772975408801fa63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18", size = 2333580, upload-time = "2026-03-09T13:14:28.237Z" }, + { url = "https://files.pythonhosted.org/packages/9e/87/2ac1fce0eb1e616fcd3c35caa23e665e9b1948bb984f4764790924594128/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021", size = 2423018, upload-time = "2026-03-09T13:14:30.018Z" }, + { url = "https://files.pythonhosted.org/packages/67/13/c6700ccc6cc218716bfcda4935e4b2997039869b4ad8a94f364c5a3b8e63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310", size = 2062804, upload-time = "2026-03-09T13:14:32.888Z" }, + { url = "https://files.pythonhosted.org/packages/1b/bd/877056304626943ff0f1f44c08f584300c199b887cb3176cd7e34f1515f1/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3", size = 2597482, upload-time = "2026-03-09T13:14:34.971Z" }, + { url = "https://files.pythonhosted.org/packages/75/19/c60626c47bf0f8ac5dcf72c6c98e266d714f2fbbfd50cf6dab5ede3aaa50/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2", size = 2394328, upload-time = "2026-03-09T13:14:36.816Z" }, + { url = "https://files.pythonhosted.org/packages/47/84/6a6d5e5bb8273756c27b7d810d47f7ef2f1f9b9fd23c9ee9a3f8c75c9cef/kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53", size = 68410, upload-time = "2026-03-09T13:14:38.695Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/060f45052f2a01ad5762c8fdecd6d7a752b43400dc29ff75cd47225a40fd/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8df31fe574b8b3993cc61764f40941111b25c2d9fea13d3ce24a49907cd2d615", size = 123231, upload-time = "2026-03-09T13:14:41.323Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a7/78da680eadd06ff35edef6ef68a1ad273bad3e2a0936c9a885103230aece/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1d49a49ac4cbfb7c1375301cd1ec90169dfeae55ff84710d782260ce77a75a02", size = 66489, upload-time = "2026-03-09T13:14:42.534Z" }, + { url = "https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e", size = 64063, upload-time = "2026-03-09T13:14:44.759Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac", size = 1475913, upload-time = "2026-03-09T13:14:46.247Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f0/f768ae564a710135630672981231320bc403cf9152b5596ec5289de0f106/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e7f886f47ab881692f278ae901039a234e4025a68e6dfab514263a0b1c4ae05", size = 1282782, upload-time = "2026-03-09T13:14:48.458Z" }, + { url = "https://files.pythonhosted.org/packages/e2/9f/1de7aad00697325f05238a5f2eafbd487fb637cc27a558b5367a5f37fb7f/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5060731cc3ed12ca3a8b57acd4aeca5bbc2f49216dd0bec1650a1acd89486bcd", size = 1300815, upload-time = "2026-03-09T13:14:50.721Z" }, + { url = "https://files.pythonhosted.org/packages/5a/c2/297f25141d2e468e0ce7f7a7b92e0cf8918143a0cbd3422c1ad627e85a06/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a4aa69609f40fce3cbc3f87b2061f042eee32f94b8f11db707b66a26461591a", size = 1347925, upload-time = "2026-03-09T13:14:52.304Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d3/f4c73a02eb41520c47610207b21afa8cdd18fdbf64ffd94674ae21c4812d/kiwisolver-1.5.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:d168fda2dbff7b9b5f38e693182d792a938c31db4dac3a80a4888de603c99554", size = 991322, upload-time = "2026-03-09T13:14:54.637Z" }, + { url = "https://files.pythonhosted.org/packages/7b/46/d3f2efef7732fcda98d22bf4ad5d3d71d545167a852ca710a494f4c15343/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:413b820229730d358efd838ecbab79902fe97094565fdc80ddb6b0a18c18a581", size = 2232857, upload-time = "2026-03-09T13:14:56.471Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ec/2d9756bf2b6d26ae4349b8d3662fb3993f16d80c1f971c179ce862b9dbae/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5124d1ea754509b09e53738ec185584cc609aae4a3b510aaf4ed6aa047ef9303", size = 2329376, upload-time = "2026-03-09T13:14:58.072Z" }, + { url = "https://files.pythonhosted.org/packages/8f/9f/876a0a0f2260f1bde92e002b3019a5fabc35e0939c7d945e0fa66185eb20/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e4415a8db000bf49a6dd1c478bf70062eaacff0f462b92b0ba68791a905861f9", size = 1982549, upload-time = "2026-03-09T13:14:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4f/ba3624dfac23a64d54ac4179832860cb537c1b0af06024936e82ca4154a0/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d618fd27420381a4f6044faa71f46d8bfd911bd077c555f7138ed88729bfbe79", size = 2494680, upload-time = "2026-03-09T13:15:01.364Z" }, + { url = "https://files.pythonhosted.org/packages/39/b7/97716b190ab98911b20d10bf92eca469121ec483b8ce0edd314f51bc85af/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5092eb5b1172947f57d6ea7d89b2f29650414e4293c47707eb499ec07a0ac796", size = 2297905, upload-time = "2026-03-09T13:15:03.925Z" }, + { url = "https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e", size = 75086, upload-time = "2026-03-09T13:15:07.775Z" }, + { url = "https://files.pythonhosted.org/packages/70/15/9b90f7df0e31a003c71649cf66ef61c3c1b862f48c81007fa2383c8bd8d7/kiwisolver-1.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:fa6248cd194edff41d7ea9425ced8ca3a6f838bfb295f6f1d6e6bb694a8518df", size = 66577, upload-time = "2026-03-09T13:15:09.139Z" }, + { url = "https://files.pythonhosted.org/packages/17/01/7dc8c5443ff42b38e72731643ed7cf1ed9bf01691ae5cdca98501999ed83/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d1ffeb80b5676463d7a7d56acbe8e37a20ce725570e09549fe738e02ca6b7e1e", size = 125794, upload-time = "2026-03-09T13:15:10.525Z" }, + { url = "https://files.pythonhosted.org/packages/46/8a/b4ebe46ebaac6a303417fab10c2e165c557ddaff558f9699d302b256bc53/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc4d8e252f532ab46a1de9349e2d27b91fce46736a9eedaa37beaca66f574ed4", size = 67646, upload-time = "2026-03-09T13:15:12.016Z" }, + { url = "https://files.pythonhosted.org/packages/60/35/10a844afc5f19d6f567359bf4789e26661755a2f36200d5d1ed8ad0126e5/kiwisolver-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6783e069732715ad0c3ce96dbf21dbc2235ab0593f2baf6338101f70371f4028", size = 65511, upload-time = "2026-03-09T13:15:13.311Z" }, + { url = "https://files.pythonhosted.org/packages/f8/8a/685b297052dd041dcebce8e8787b58923b6e78acc6115a0dc9189011c44b/kiwisolver-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7c4c09a490dc4d4a7f8cbee56c606a320f9dc28cf92a7157a39d1ce7676a657", size = 1584858, upload-time = "2026-03-09T13:15:15.103Z" }, + { url = "https://files.pythonhosted.org/packages/9e/80/04865e3d4638ac5bddec28908916df4a3075b8c6cc101786a96803188b96/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a075bd7bd19c70cf67c8badfa36cf7c5d8de3c9ddb8420c51e10d9c50e94920", size = 1392539, upload-time = "2026-03-09T13:15:16.661Z" }, + { url = "https://files.pythonhosted.org/packages/ba/01/77a19cacc0893fa13fafa46d1bba06fb4dc2360b3292baf4b56d8e067b24/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bdd3e53429ff02aa319ba59dfe4ceeec345bf46cf180ec2cf6fd5b942e7975e9", size = 1405310, upload-time = "2026-03-09T13:15:18.229Z" }, + { url = "https://files.pythonhosted.org/packages/53/39/bcaf5d0cca50e604cfa9b4e3ae1d64b50ca1ae5b754122396084599ef903/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cdcb35dc9d807259c981a85531048ede628eabcffb3239adf3d17463518992d", size = 1456244, upload-time = "2026-03-09T13:15:20.444Z" }, + { url = "https://files.pythonhosted.org/packages/d0/7a/72c187abc6975f6978c3e39b7cf67aeb8b3c0a8f9790aa7fd412855e9e1f/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:70d593af6a6ca332d1df73d519fddb5148edb15cd90d5f0155e3746a6d4fcc65", size = 1073154, upload-time = "2026-03-09T13:15:22.039Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ca/cf5b25783ebbd59143b4371ed0c8428a278abe68d6d0104b01865b1bbd0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:377815a8616074cabbf3f53354e1d040c35815a134e01d7614b7692e4bf8acfa", size = 2334377, upload-time = "2026-03-09T13:15:23.741Z" }, + { url = "https://files.pythonhosted.org/packages/4a/e5/b1f492adc516796e88751282276745340e2a72dcd0d36cf7173e0daf3210/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0255a027391d52944eae1dbb5d4cc5903f57092f3674e8e544cdd2622826b3f0", size = 2425288, upload-time = "2026-03-09T13:15:25.789Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/9b21fbe91a61b8f409d74a26498706e97a48008bfcd1864373d32a6ba31c/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:012b1eb16e28718fa782b5e61dc6f2da1f0792ca73bd05d54de6cb9561665fc9", size = 2063158, upload-time = "2026-03-09T13:15:27.63Z" }, + { url = "https://files.pythonhosted.org/packages/b1/02/83f47986138310f95ea95531f851b2a62227c11cbc3e690ae1374fe49f0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e3aafb33aed7479377e5e9a82e9d4bf87063741fc99fc7ae48b0f16e32bdd6f", size = 2597260, upload-time = "2026-03-09T13:15:29.421Z" }, + { url = "https://files.pythonhosted.org/packages/07/18/43a5f24608d8c313dd189cf838c8e68d75b115567c6279de7796197cfb6a/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7a116ae737f0000343218c4edf5bd45893bfeaff0993c0b215d7124c9f77646", size = 2394403, upload-time = "2026-03-09T13:15:31.517Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b5/98222136d839b8afabcaa943b09bd05888c2d36355b7e448550211d1fca4/kiwisolver-1.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1dd9b0b119a350976a6d781e7278ec7aca0b201e1a9e2d23d9804afecb6ca681", size = 79687, upload-time = "2026-03-09T13:15:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/99/a2/ca7dc962848040befed12732dff6acae7fb3c4f6fc4272b3f6c9a30b8713/kiwisolver-1.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:58f812017cd2985c21fbffb4864d59174d4903dd66fa23815e74bbc7a0e2dd57", size = 70032, upload-time = "2026-03-09T13:15:34.411Z" }, + { url = "https://files.pythonhosted.org/packages/1c/fa/2910df836372d8761bb6eff7d8bdcb1613b5c2e03f260efe7abe34d388a7/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:5ae8e62c147495b01a0f4765c878e9bfdf843412446a247e28df59936e99e797", size = 130262, upload-time = "2026-03-09T13:15:35.629Z" }, + { url = "https://files.pythonhosted.org/packages/0f/41/c5f71f9f00aabcc71fee8b7475e3f64747282580c2fe748961ba29b18385/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f6764a4ccab3078db14a632420930f6186058750df066b8ea2a7106df91d3203", size = 138036, upload-time = "2026-03-09T13:15:36.894Z" }, + { url = "https://files.pythonhosted.org/packages/fa/06/7399a607f434119c6e1fdc8ec89a8d51ccccadf3341dee4ead6bd14caaf5/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c31c13da98624f957b0fb1b5bae5383b2333c2c3f6793d9825dd5ce79b525cb7", size = 194295, upload-time = "2026-03-09T13:15:38.22Z" }, + { url = "https://files.pythonhosted.org/packages/b5/91/53255615acd2a1eaca307ede3c90eb550bae9c94581f8c00081b6b1c8f44/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:1f1489f769582498610e015a8ef2d36f28f505ab3096d0e16b4858a9ec214f57", size = 75987, upload-time = "2026-03-09T13:15:39.65Z" }, +] + +[[package]] +name = "lark" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/34/28fff3ab31ccff1fd4f6c7c7b0ceb2b6968d8ea4950663eadcb5720591a0/lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", size = 382732, upload-time = "2025-10-27T18:25:56.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "matplotlib" +version = "3.10.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "contourpy" }, + { name = "cycler" }, + { name = "fonttools" }, + { name = "kiwisolver" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pillow" }, + { name = "pyparsing" }, + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/63/1b/4be5be87d43d327a0cf4de1a56e86f7f84c89312452406cf122efe2839e6/matplotlib-3.10.9.tar.gz", hash = "sha256:fd66508e8c6877d98e586654b608a0456db8d7e8a546eb1e2600efd957302358", size = 34811233, upload-time = "2026-04-24T00:14:13.539Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/c6/5581e26c72233ebb2a2a6fed2d24fb7c66b4700120b813f51b0555acf0b6/matplotlib-3.10.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f0c3c28d9fbcc1fe7a03be236d73430cf6409c41fb2383a7ac52fe932b072cb1", size = 8319908, upload-time = "2026-04-24T00:12:21.323Z" }, + { url = "https://files.pythonhosted.org/packages/b7/18/4880dd762e40cd360c1bf06e890c5a97b997e91cb324602b1a19950ad5ce/matplotlib-3.10.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41cb28c2bd769aa3e98322c6ab09854cbcc52ab69d2759d681bba3e327b2b320", size = 8216016, upload-time = "2026-04-24T00:12:23.4Z" }, + { url = "https://files.pythonhosted.org/packages/32/91/d024616abdba99e83120e07a20658976f6a343646710760c4a51df126029/matplotlib-3.10.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ae20801130378b82d647ff5047c07316295b68dc054ca6b3c13519d0ea624285", size = 8789336, upload-time = "2026-04-24T00:12:26.096Z" }, + { url = "https://files.pythonhosted.org/packages/5c/04/030a2f61ef2158f5e4c259487a92ac877732499fb33d871585d89e03c42d/matplotlib-3.10.9-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c63ebcd8b4b169eb2f5c200552ae6b8be8999a005b6b507ed76fb8d7d674fe2", size = 9604602, upload-time = "2026-04-24T00:12:29.052Z" }, + { url = "https://files.pythonhosted.org/packages/fc/c2/541e4d09d87bb6b5830fc28b4c887a9a8cf4e1c6cee698a8c05552ae2003/matplotlib-3.10.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d75d11c949914165976c621b2324f9ef162af7ebf4b057ddf95dd1dba7e5edcf", size = 9670966, upload-time = "2026-04-24T00:12:32.131Z" }, + { url = "https://files.pythonhosted.org/packages/04/a1/4571fc46e7702de8d0c2dc54ad1b2f8e29328dea3ee90831181f7353d93c/matplotlib-3.10.9-cp312-cp312-win_amd64.whl", hash = "sha256:d091f9d758b34aaaaa6331d13574bf01891d903b3dec59bfff458ef7551de5d6", size = 8217462, upload-time = "2026-04-24T00:12:35.226Z" }, + { url = "https://files.pythonhosted.org/packages/4b/d0/2269edb12aa30c13c8bcc9382892e39943ce1d28aab4ec296e0381798e81/matplotlib-3.10.9-cp312-cp312-win_arm64.whl", hash = "sha256:10cc5ce06d10231c36f40e875f3c7e8050362a4ee8f0ee5d29a6b3277d57bb42", size = 8136688, upload-time = "2026-04-24T00:12:37.442Z" }, + { url = "https://files.pythonhosted.org/packages/aa/d3/8d4f6afbecb49fc04e060a57c0fce39ea51cc163a6bd87303ccd698e4fa6/matplotlib-3.10.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b580440f1ff81a0e34122051a3dfabb7e4b7f9e380629929bde0eff9af72165f", size = 8320331, upload-time = "2026-04-24T00:12:39.688Z" }, + { url = "https://files.pythonhosted.org/packages/63/d9/9e14bc7564bf92d5ffa801ae5fac819ce74b925dfb55e3ebde61a3bbad3e/matplotlib-3.10.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b1b745c489cd1a77a0dc1120a05dc87af9798faebc913601feb8c73d89bf2d1e", size = 8216461, upload-time = "2026-04-24T00:12:42.494Z" }, + { url = "https://files.pythonhosted.org/packages/8a/17/4402d0d14ccf1dfc70932600b68097fbbf9c898a4871d2cbbe79c7801a32/matplotlib-3.10.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8f3bcac1ca5ed000a6f4337d47ba67dfddf37ed6a46c15fd7f014997f7bf865f", size = 8790091, upload-time = "2026-04-24T00:12:44.789Z" }, + { url = "https://files.pythonhosted.org/packages/3e/0b/322aeec06dd9b91411f92028b37d447342770a24392aa4813e317064dad5/matplotlib-3.10.9-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a8d66a55def891c33147ba3ba9bfcabf0b526a43764c818acbb4525e5ed0838", size = 9605027, upload-time = "2026-04-24T00:12:47.583Z" }, + { url = "https://files.pythonhosted.org/packages/74/88/5f13482f55e7b00bcfc09838b093c2456e1379978d2a146844aae05350ad/matplotlib-3.10.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d843374407c4017a6403b59c6c81606773d136f3259d5b6da3131bc814542cc2", size = 9671269, upload-time = "2026-04-24T00:12:50.878Z" }, + { url = "https://files.pythonhosted.org/packages/c5/e0/0840fd2f93da988ec660b8ad1984abe9f25d2aed22a5e394ff1c68c88307/matplotlib-3.10.9-cp313-cp313-win_amd64.whl", hash = "sha256:f4399f64b3e94cd500195490972ae1ee81170df1636fa15364d157d5bdd7b921", size = 8217588, upload-time = "2026-04-24T00:12:53.784Z" }, + { url = "https://files.pythonhosted.org/packages/47/b9/d706d06dd605c49b9f83a2aed8c13e3e5db70697d7a80b7e3d7915de6b17/matplotlib-3.10.9-cp313-cp313-win_arm64.whl", hash = "sha256:ba7b3b8ef09eab7df0e86e9ae086faa433efbfbdb46afcb3aa16aabf779469a8", size = 8136913, upload-time = "2026-04-24T00:12:56.501Z" }, + { url = "https://files.pythonhosted.org/packages/9b/45/6e32d96978264c8ca8c4b1010adb955a1a49cfaf314e212bbc8908f04a61/matplotlib-3.10.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:09218df8a93712bd6ea133e83a153c755448cf7868316c531cffcc43f69d1cc9", size = 8368019, upload-time = "2026-04-24T00:12:58.896Z" }, + { url = "https://files.pythonhosted.org/packages/86/0a/c8e3d3bba245f0f7fc424937f8ff7ef77291a36af3edb97ccd78aa93d84f/matplotlib-3.10.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:82368699727bfb7b0182e1aa13082e3c08e092fa1a25d3e1fd92405bff96f6d4", size = 8264645, upload-time = "2026-04-24T00:13:01.406Z" }, + { url = "https://files.pythonhosted.org/packages/3d/aa/5bf5a14fe4fed73a4209a155606f8096ff797aad89c6c35179026571133e/matplotlib-3.10.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3225f4e1edcb8c86c884ddf79ebe20ecd0a67d30188f279897554ccd8fded4dc", size = 8802194, upload-time = "2026-04-24T00:13:03.702Z" }, + { url = "https://files.pythonhosted.org/packages/dd/5e/b4be852d6bba6fd15893fadf91ff26ae49cb91aac789e95dde9d342e664f/matplotlib-3.10.9-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de2445a0c6690d21b7eb6ce071cebad6d40a2e9bdf10d039074a96ba19797b99", size = 9622684, upload-time = "2026-04-24T00:13:06.647Z" }, + { url = "https://files.pythonhosted.org/packages/4c/3d/ed428c971139112ef730f62770654d609467346d09d4b62617e1afd68a5a/matplotlib-3.10.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b2b9516251cb89ff618d757daec0e2ed1bf21248013844a853d87ef85ab3081d", size = 9680790, upload-time = "2026-04-24T00:13:10.009Z" }, + { url = "https://files.pythonhosted.org/packages/e7/09/052e884aaf2b985c63cb79f715f1d5b6a3eaa7de78f6a52b9dbc077d5b53/matplotlib-3.10.9-cp313-cp313t-win_amd64.whl", hash = "sha256:e9fae004b941b23ff2edcf1567a857ed77bafc8086ffa258190462328434faf8", size = 8287571, upload-time = "2026-04-24T00:13:13.087Z" }, + { url = "https://files.pythonhosted.org/packages/f4/38/ae27288e788c35a4250491422f3db7750366fc8c97d6f36fbdecfc1f5518/matplotlib-3.10.9-cp313-cp313t-win_arm64.whl", hash = "sha256:6b63d9c7c769b88ab81e10dc86e4e0607cf56817b9f9e6cf24b2a5f1693b8e38", size = 8188292, upload-time = "2026-04-24T00:13:15.546Z" }, + { url = "https://files.pythonhosted.org/packages/d6/e6/3bd8afd04949f02eabc1c17115ea5255e19cacd4d06fc5abdde4eeb0052c/matplotlib-3.10.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:172db52c9e683f5d12eaf57f0f54834190e12581fe1cc2a19595a8f5acb4e77d", size = 8321276, upload-time = "2026-04-24T00:13:18.318Z" }, + { url = "https://files.pythonhosted.org/packages/41/86/86231232fff41c9f8e4a1a7d7a597d349a02527109c3af7d618366122139/matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97e35e8d39ccc85859095e01a53847432ba9a53ddf7986f7a54a11b73d0e143f", size = 8218218, upload-time = "2026-04-24T00:13:20.974Z" }, + { url = "https://files.pythonhosted.org/packages/85/8f/becc9722cafc64f5d2eb0b7c1bf5f585271c618a45dbd8fabeb021f898b6/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aba1615dabe83188e19d4f75a253c6a08423e04c1425e64039f800050a69de6b", size = 9608145, upload-time = "2026-04-24T00:13:23.228Z" }, + { url = "https://files.pythonhosted.org/packages/32/5d/f7e914f7d9325abff4057cee62c0fa70263683189f774473cbfb534cd13b/matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34cf8167e023ad956c15f36302911d5406bd99a9862c1a8499ea6f7c0e015dc2", size = 9885085, upload-time = "2026-04-24T00:13:25.849Z" }, + { url = "https://files.pythonhosted.org/packages/a5/fd/fa69f2221534e80cc5772ac2b7d222011a2acafc2ec7216d5dd174c864ae/matplotlib-3.10.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:59476c6d29d612b8e9bb6ce8c5b631be6ba8f9e3a2421f22a02b192c7dd28716", size = 9672358, upload-time = "2026-04-24T00:13:28.906Z" }, + { url = "https://files.pythonhosted.org/packages/ab/1a/5a4f747a8b271cbb024946d2dd3c913ab5032ba430626f8c3528ada96b4b/matplotlib-3.10.9-cp314-cp314-win_amd64.whl", hash = "sha256:336b9acc64d309063126edcdaca00db9373af3c476bb94388fe9c5a53ad13e6f", size = 8349970, upload-time = "2026-04-24T00:13:31.904Z" }, + { url = "https://files.pythonhosted.org/packages/64/dc/95d60ecaefe30680a154b52ea96ab4b0dab547f1fd6aa12f5fb655e89cae/matplotlib-3.10.9-cp314-cp314-win_arm64.whl", hash = "sha256:2dc9477819ffd78ad12a20df1d9d6a6bd4fec6aaa9072681465fddca052f1456", size = 8272785, upload-time = "2026-04-24T00:13:34.511Z" }, + { url = "https://files.pythonhosted.org/packages/70/a0/005d68bc8b8418300ce6591f18586910a8526806e2ab663933d9f20a41e9/matplotlib-3.10.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:da4e09638420548f31c354032a6250e473c68e5a4e96899b4844cf39ddea23fe", size = 8367999, upload-time = "2026-04-24T00:13:36.962Z" }, + { url = "https://files.pythonhosted.org/packages/22/05/1236cc9290be70b2498af20ca348add76e3fffe7f67b477db5133a84f3ea/matplotlib-3.10.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:345f6f68ecc8da0ca56fad2ea08fde1a115eda530079eca185d50a7bc3e146c6", size = 8264543, upload-time = "2026-04-24T00:13:39.851Z" }, + { url = "https://files.pythonhosted.org/packages/cd/c2/071f5a5ff6c5bd63aaaf2f45c811d9bf2ced94bde188d9e1a519e21d0cba/matplotlib-3.10.9-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4edcfbd8565339aa62f1cd4012f7180926fdbe71850f7b0d3c379c175cd6b66c", size = 9622800, upload-time = "2026-04-24T00:13:42.296Z" }, + { url = "https://files.pythonhosted.org/packages/95/57/da7d1f10a85624b9e7db68e069dd94e58dc41dbf9463c5921632ecbe3661/matplotlib-3.10.9-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6be157fe17fc37cb95ac1d7374cf717ce9259616edec911a78d9d26dae8522d4", size = 9888561, upload-time = "2026-04-24T00:13:45.026Z" }, + { url = "https://files.pythonhosted.org/packages/67/b2/ef8d6bb59b0edb6c16c968b70f548aa13b54348972def5aa6ac85df67145/matplotlib-3.10.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4e42042d54db34fda4e95a7bd3e5789c2a995d2dad3eb8850232ee534092fbbf", size = 9680884, upload-time = "2026-04-24T00:13:48.066Z" }, + { url = "https://files.pythonhosted.org/packages/61/1c/d21bfeb9931881ebe96bcfcff27c7ae4b160ae0ec291a714c42641a56d75/matplotlib-3.10.9-cp314-cp314t-win_amd64.whl", hash = "sha256:c27df8b3848f32a83d1767566595e43cfaa4460380974da06f4279a7ec143c39", size = 8432333, upload-time = "2026-04-24T00:13:51.008Z" }, + { url = "https://files.pythonhosted.org/packages/78/23/92493c3e6e1b635ccfff146f7b99e674808787915420373ac399283764c2/matplotlib-3.10.9-cp314-cp314t-win_arm64.whl", hash = "sha256:a49f1eadc84ca85fd72fa4e89e70e61bf86452df6f971af04b12c60761a0772c", size = 8324785, upload-time = "2026-04-24T00:13:53.633Z" }, +] + +[[package]] +name = "matplotlib-inline" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/c0/9f7c9a46090390368a4d7bcb76bb87a4a36c421e4c0792cdb53486ffac7a/matplotlib_inline-0.2.2.tar.gz", hash = "sha256:72f3fe8fce36b70d4a5b612f899090cd0401deddc4ea90e1572b9f4bfb058c79", size = 8150, upload-time = "2026-05-08T17:33:33.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/09/5b161152e2d90f7b87f781c2e1267494aef9c32498df793f73ad0a0a494a/matplotlib_inline-0.2.2-py3-none-any.whl", hash = "sha256:3c821cf1c209f59fb2d2d64abbf5b23b67bcb2210d663f9918dd851c6da1fcf6", size = 9534, upload-time = "2026-05-08T17:33:32.055Z" }, +] + +[[package]] +name = "mistune" +version = "3.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/84/620cc3f7e3adf6f5067e10f4dbae71295d8f9e16d5d3f9ef97c40f2f592c/mistune-3.2.1.tar.gz", hash = "sha256:7c8e5501d38bac1582e067e46c8343f17d57ea1aaa735823f3aba1fd59c88a28", size = 98003, upload-time = "2026-05-03T14:33:22.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/7f/a946aa4f8752b37102b41e64dca18a1976ac705c3a0d1dfe74d820a02552/mistune-3.2.1-py3-none-any.whl", hash = "sha256:78cdb0ba5e938053ccf63651b352508d2efa9411dc8810bfb05f2dc5140c0048", size = 53749, upload-time = "2026-05-03T14:33:20.551Z" }, +] + +[[package]] +name = "nbclient" +version = "0.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "nbformat" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/91/1c1d5a4b9a9ebba2b4e32b8c852c2975c872aec1fe42ab5e516b2cecd193/nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9", size = 62554, upload-time = "2025-12-23T07:45:46.369Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440", size = 25465, upload-time = "2025-12-23T07:45:44.51Z" }, +] + +[[package]] +name = "nbconvert" +version = "7.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "bleach", extra = ["css"] }, + { name = "defusedxml" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyterlab-pygments" }, + { name = "markupsafe" }, + { name = "mistune" }, + { name = "nbclient" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "pandocfilters" }, + { name = "pygments" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/b1/708e53fe2e429c103c6e6e159106bcf0357ac41aa4c28772bd8402339051/nbconvert-7.17.1.tar.gz", hash = "sha256:34d0d0a7e73ce3cbab6c5aae8f4f468797280b01fd8bd2ca746da8569eddd7d2", size = 865311, upload-time = "2026-04-08T00:44:14.914Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/f8/bb0a9d5f46819c821dc1f004aa2cc29b1d91453297dbf5ff20470f00f193/nbconvert-7.17.1-py3-none-any.whl", hash = "sha256:aa85c087b435e7bf1ffd03319f658e285f2b89eccab33bc1ba7025495ab3e7c8", size = 261927, upload-time = "2026-04-08T00:44:12.845Z" }, +] + +[[package]] +name = "nbformat" +version = "5.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastjsonschema" }, + { name = "jsonschema" }, + { name = "jupyter-core" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", size = 142749, upload-time = "2024-04-04T11:20:37.371Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454, upload-time = "2024-04-04T11:20:34.895Z" }, +] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, +] + +[[package]] +name = "notebook-shim" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/54/d2/92fa3243712b9a3e8bafaf60aac366da1cada3639ca767ff4b5b3654ec28/notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb", size = 13167, upload-time = "2024-02-14T23:35:18.353Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307, upload-time = "2024-02-14T23:35:16.286Z" }, +] + +[[package]] +name = "numpy" +version = "2.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/ad/fed0499ce6a338d2a03ebae59cd15093910c8875328855781952abf6c2fe/numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda", size = 20735807, upload-time = "2026-05-18T23:37:14.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/2a/3d7b5ac8aac24feaf9ad7ed58f45b0bbc06d37e4338ae84c9f2298b570f9/numpy-2.4.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1", size = 16689119, upload-time = "2026-05-18T23:33:54.065Z" }, + { url = "https://files.pythonhosted.org/packages/ea/12/92c4c131527599e8288d6918e888d88726f84d805d784b771f32408aeaef/numpy-2.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb", size = 14699246, upload-time = "2026-05-18T23:33:57.621Z" }, + { url = "https://files.pythonhosted.org/packages/ad/fe/c0a6b7b2ca128a8fb228575147073b660656734b8ebe4d76c8fd748dcc79/numpy-2.4.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41", size = 5204410, upload-time = "2026-05-18T23:34:00.302Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d4/9770d14ba719432bb90a421bfd443872ed0f70f7264b64bec12ea363d5fd/numpy-2.4.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698", size = 6551240, upload-time = "2026-05-18T23:34:02.852Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c6/50a46a6205feba2343f1d6d17438107c5dc491ed1c736e6ea68689fd906b/numpy-2.4.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f", size = 15671012, upload-time = "2026-05-18T23:34:05.485Z" }, + { url = "https://files.pythonhosted.org/packages/99/60/14115e6364fa676c5397c2ad3004e527e9aa487abf5d0706ec81bbd08529/numpy-2.4.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853", size = 16645538, upload-time = "2026-05-18T23:34:09.265Z" }, + { url = "https://files.pythonhosted.org/packages/ae/c5/693cbe59e57db94d2231fa519ca3978dc9e19da5a8f088588f5c6e947ff2/numpy-2.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a", size = 17020706, upload-time = "2026-05-18T23:34:13.053Z" }, + { url = "https://files.pythonhosted.org/packages/ef/fc/85b7c4eff9b4966ade25c2273cf7e7012e92366c032058653934b37de044/numpy-2.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2", size = 18368541, upload-time = "2026-05-18T23:34:17.024Z" }, + { url = "https://files.pythonhosted.org/packages/f6/81/e1b27545deedce7f4a0b348618c6b62d74e36a4dc9ccd42f3eb2f85eee32/numpy-2.4.6-cp312-cp312-win32.whl", hash = "sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45", size = 5962825, upload-time = "2026-05-18T23:34:20.3Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ca/feab00bd44aa5fe1ad2c18f08b4d3bb92e26484b0b1d1443897809ed528c/numpy-2.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751", size = 12321687, upload-time = "2026-05-18T23:34:23.095Z" }, + { url = "https://files.pythonhosted.org/packages/63/cf/5a6d34850a39d1093558564f77ee8e8e0bee5061151b8f05a55711001ec7/numpy-2.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8", size = 10221482, upload-time = "2026-05-18T23:34:25.876Z" }, + { url = "https://files.pythonhosted.org/packages/fb/82/bdab26d7438c6791ca31b7c024ca37c1eab8b726ba236129005cd4a06e45/numpy-2.4.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0", size = 16684648, upload-time = "2026-05-18T23:34:29.41Z" }, + { url = "https://files.pythonhosted.org/packages/1b/30/a80189bcc7f5e4258b3fbc3968d909d1756f54d023299ecc39ad6fdb9ef8/numpy-2.4.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb", size = 14693902, upload-time = "2026-05-18T23:34:33.013Z" }, + { url = "https://files.pythonhosted.org/packages/97/12/70b5d0d7c15e1ebb8a6a84a8caa1d19e181d84fb58bb6d70aca29099dec1/numpy-2.4.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f", size = 5198992, upload-time = "2026-05-18T23:34:36.132Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8c/ebd2a8f8a83541f8d38cc5667e8c2b69cecfd30da6e45693e8158857d44b/numpy-2.4.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3", size = 6546944, upload-time = "2026-05-18T23:34:38.484Z" }, + { url = "https://files.pythonhosted.org/packages/bb/c5/7b863a97a91671a0338f4253bd3b5a3d3852f0692dae91711c9f4a10e787/numpy-2.4.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b", size = 15669392, upload-time = "2026-05-18T23:34:41.257Z" }, + { url = "https://files.pythonhosted.org/packages/a5/9d/3584b9984ca4c047aea75214ce1a4c4c73d849bd71b604264b7f5653f8a8/numpy-2.4.6-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089", size = 16633220, upload-time = "2026-05-18T23:34:45.075Z" }, + { url = "https://files.pythonhosted.org/packages/05/ae/7c67fba23bd98caec7c99261f3a16072ade14813486b0282cb29846de832/numpy-2.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a", size = 17020800, upload-time = "2026-05-18T23:34:49.065Z" }, + { url = "https://files.pythonhosted.org/packages/d9/5d/3b6725cb31d983c5e66916f5d36f6d7e5521129e4c4404d64f918292a5b6/numpy-2.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605", size = 18357600, upload-time = "2026-05-18T23:34:52.709Z" }, + { url = "https://files.pythonhosted.org/packages/f7/da/2ccc6c2fe8898dee01d90c75c5f5f914a23daf99e3e0f59516a08760c8b5/numpy-2.4.6-cp313-cp313-win32.whl", hash = "sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91", size = 5961134, upload-time = "2026-05-18T23:34:55.618Z" }, + { url = "https://files.pythonhosted.org/packages/b5/cd/9cc4dc876fb065d5c220aae4d5e14826b2715331bb7618ce1fb07a679d99/numpy-2.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359", size = 12318598, upload-time = "2026-05-18T23:34:58.928Z" }, + { url = "https://files.pythonhosted.org/packages/39/1e/c0bcba1f8694116485fe28fd1be698c278fcda4141c5b0e53a2aed8b12a8/numpy-2.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778", size = 10222272, upload-time = "2026-05-18T23:35:02.167Z" }, + { url = "https://files.pythonhosted.org/packages/63/6d/cc5619247c8f4204e507f5883528372e4ac4bb189e579fb859a12e480b1f/numpy-2.4.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1", size = 14821197, upload-time = "2026-05-18T23:35:05.468Z" }, + { url = "https://files.pythonhosted.org/packages/00/58/f1c39161c87d9e9bed660f1ed4bafc0e403d5ec9650b6dd77aead07d489b/numpy-2.4.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe", size = 5326287, upload-time = "2026-05-18T23:35:08.693Z" }, + { url = "https://files.pythonhosted.org/packages/af/57/3917ab0fd97f271a8694513581b8a36c655f111c446852c302f04ccdb6fc/numpy-2.4.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997", size = 6646763, upload-time = "2026-05-18T23:35:11.459Z" }, + { url = "https://files.pythonhosted.org/packages/eb/0f/037e64c494b67581ae18193d770adef354c41f3f2c8ebf865602d949bf8f/numpy-2.4.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20", size = 15728070, upload-time = "2026-05-18T23:35:14.79Z" }, + { url = "https://files.pythonhosted.org/packages/21/a6/5d2bae9c9542eb4df16dc9c46dc79c186e9bad53805dfa5399a6023c6db0/numpy-2.4.6-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d", size = 16681752, upload-time = "2026-05-18T23:35:18.836Z" }, + { url = "https://files.pythonhosted.org/packages/92/14/23d1dfb410ae362cd59ce53e936b1513d545eb40db3949ced632e19a459e/numpy-2.4.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67", size = 17086024, upload-time = "2026-05-18T23:35:22.52Z" }, + { url = "https://files.pythonhosted.org/packages/4b/6e/23595a2c642cdf3bc567877064bdd7f91c8b0038a4453cf2daf7248eafe9/numpy-2.4.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd", size = 18403398, upload-time = "2026-05-18T23:35:26.398Z" }, + { url = "https://files.pythonhosted.org/packages/8a/90/0ac3bc947217e66dec77e7cbc6a1979d1af70b6461b82f620d3bccd5e4c8/numpy-2.4.6-cp313-cp313t-win32.whl", hash = "sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab", size = 6084971, upload-time = "2026-05-18T23:35:29.387Z" }, + { url = "https://files.pythonhosted.org/packages/77/71/5673e351671a1d2bd6063b91b44f70c0affea7d1516fa7a6572941ba4aa1/numpy-2.4.6-cp313-cp313t-win_amd64.whl", hash = "sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75", size = 12458532, upload-time = "2026-05-18T23:35:32.175Z" }, + { url = "https://files.pythonhosted.org/packages/3f/88/19d3503c5046e688f049274b27a3ef3d771152fa80d3ba3d01a3dff61abe/numpy-2.4.6-cp313-cp313t-win_arm64.whl", hash = "sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd", size = 10291881, upload-time = "2026-05-18T23:35:35.465Z" }, + { url = "https://files.pythonhosted.org/packages/f8/91/3ab2044d05fd16d343c5ac2e69b127f1b2854040dd20b193257c78028bd3/numpy-2.4.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079", size = 16683458, upload-time = "2026-05-18T23:35:38.353Z" }, + { url = "https://files.pythonhosted.org/packages/8e/62/764ce66fa4147ae6d73071a3abf804ffe606f174618697c571acdf26a7c9/numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7", size = 14704559, upload-time = "2026-05-18T23:35:42.14Z" }, + { url = "https://files.pythonhosted.org/packages/60/61/23f27c172f022e04025b7dc2367f4d63c1a398120607ec896228649a6f48/numpy-2.4.6-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5", size = 5209716, upload-time = "2026-05-18T23:35:45.377Z" }, + { url = "https://files.pythonhosted.org/packages/03/71/21cf70dc6ea3e3acb95fc53a265b2fc248b981f0194ceb5b475271b8809d/numpy-2.4.6-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096", size = 6543947, upload-time = "2026-05-18T23:35:47.926Z" }, + { url = "https://files.pythonhosted.org/packages/d5/91/64288395ee1799bd2e0b04a305dce9666da90c961e1f3fe982a05ee1c036/numpy-2.4.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b", size = 15685197, upload-time = "2026-05-18T23:35:50.863Z" }, + { url = "https://files.pythonhosted.org/packages/f3/eb/ebffaa97dc55502df69584a8f0dcf07f69a3e0b3e2323670a2722db9aa39/numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8", size = 16638245, upload-time = "2026-05-18T23:35:54.752Z" }, + { url = "https://files.pythonhosted.org/packages/b8/0b/54f9da33128d7e350fab89c7455902eeae70349ee52bddb448dc4a576f45/numpy-2.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402", size = 17036587, upload-time = "2026-05-18T23:35:58.355Z" }, + { url = "https://files.pythonhosted.org/packages/b6/f0/fdebc1052db1cc37c64beb22072d67cd6d1c71adca1299f53dec2b5e20d3/numpy-2.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb", size = 18363226, upload-time = "2026-05-18T23:36:02.845Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b4/298628d98c72b57e57f7165ae6a481a1deaf6f3c28262a6e4c739c275930/numpy-2.4.6-cp314-cp314-win32.whl", hash = "sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1", size = 6010196, upload-time = "2026-05-18T23:36:05.92Z" }, + { url = "https://files.pythonhosted.org/packages/df/ac/46de6dda46478f7942f839e094970be2d4a861e005c4b3bf07c92e291a09/numpy-2.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261", size = 12450334, upload-time = "2026-05-18T23:36:09.107Z" }, + { url = "https://files.pythonhosted.org/packages/78/92/b8b798ac784102c0da830d2257d59358e3d3d90d1e2b3f2575dad976c5cf/numpy-2.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6", size = 10495678, upload-time = "2026-05-18T23:36:12.766Z" }, + { url = "https://files.pythonhosted.org/packages/30/34/ec28d1aa8115971537c01469ab2011ee96827930f0a124de1000cc2a7ed7/numpy-2.4.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a", size = 14823672, upload-time = "2026-05-18T23:36:16.473Z" }, + { url = "https://files.pythonhosted.org/packages/16/bd/f6d1fede4e54e8042a7ff97bb495510f3c220f94bcd9e8b228e87c92cc0d/numpy-2.4.6-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e", size = 5328731, upload-time = "2026-05-18T23:36:19.767Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f0/e105b9e2fd728a9910103884decd6951d9dd73896b914a98d9a231de02ee/numpy-2.4.6-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e", size = 6649805, upload-time = "2026-05-18T23:36:22.266Z" }, + { url = "https://files.pythonhosted.org/packages/82/dd/1206a7ca6ab15e3f02069707ca96222e202af681bb73756da7527f3cb837/numpy-2.4.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43", size = 15730496, upload-time = "2026-05-18T23:36:25.713Z" }, + { url = "https://files.pythonhosted.org/packages/51/e7/38d3ea825dcab85a591734decb2f6c67caa7c8367d374df1a1c3842f9b07/numpy-2.4.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e", size = 16679616, upload-time = "2026-05-18T23:36:29.652Z" }, + { url = "https://files.pythonhosted.org/packages/93/b7/caabfdf53edf663e0b4eb74d7d405d83baef09eb5e83bcd32d601d72b93e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895", size = 17085145, upload-time = "2026-05-18T23:36:33.449Z" }, + { url = "https://files.pythonhosted.org/packages/f9/45/68d7c33a6bcf3e5aa3bdbd57a367e6f615286dfd6482f97e8ffeb734306e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4", size = 18403813, upload-time = "2026-05-18T23:36:37.369Z" }, + { url = "https://files.pythonhosted.org/packages/9c/50/0753655aa844c99cd9e018aacf76f130f1bd81d881bb74bc0aef5d73a8ba/numpy-2.4.6-cp314-cp314t-win32.whl", hash = "sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063", size = 6156982, upload-time = "2026-05-18T23:36:40.817Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d4/7c67becf668f973cb490cec3e98dfd799d866f9c989a54d355672cfa0db6/numpy-2.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627", size = 12638908, upload-time = "2026-05-18T23:36:43.996Z" }, + { url = "https://files.pythonhosted.org/packages/43/bb/e1c71a4295b1b1d1393d50dbb4f2a36283c6859d9d3892e84f00ec5a91d5/numpy-2.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66", size = 10565867, upload-time = "2026-05-18T23:36:47.114Z" }, +] + +[[package]] +name = "packaging" +version = "26.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, +] + +[[package]] +name = "pandas" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "python-dateutil" }, + { name = "tzdata", marker = "sys_platform == 'emscripten' or sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/87/4341c6252d1c47b08768c3d25ac487362bf403f0313ddae4a2a26c9b1b4c/pandas-3.0.3.tar.gz", hash = "sha256:696a4a00a2a2a35d4e5deb3fc946641b96c944f02230e4f76137fe35d806c4fc", size = 4651414, upload-time = "2026-05-11T18:54:29.21Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/f1/392f8c5bfc16f66a0d2d41561c01627c228fe7ed2a0d056ef11315042570/pandas-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fed2ff7fd9779120e388e285fc029bd5cf9490cdd2e4166a9ee22c0e49a9ab09", size = 10357846, upload-time = "2026-05-11T18:52:36.143Z" }, + { url = "https://files.pythonhosted.org/packages/cf/3d/b16412745651e855f357e5e66930248688378853a6e2698a214e331fba1f/pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4", size = 9899550, upload-time = "2026-05-11T18:52:38.976Z" }, + { url = "https://files.pythonhosted.org/packages/31/a8/fa2535168fffcedf67f4f6de28d2dd903a747ca7c8ea6989451aaeb3a92f/pandas-3.0.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0383c72c75cdcca61a9e116e611143902dbfd08bff356829c2f6d1cf40a9ca8c", size = 10412965, upload-time = "2026-05-11T18:52:41.915Z" }, + { url = "https://files.pythonhosted.org/packages/65/b6/09b01cdbc15224e2850365192d17b7bdebb8bdbd8780ed221fcdf0d9a515/pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9", size = 10894600, upload-time = "2026-05-11T18:52:45.02Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a4/2eb28f2fccb4ced4a2c79ab2a5dee9ade1ebf44922ebad6fea158c9f95d4/pandas-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e65d5407dc0b394f509699650e4a2ec01c0514f21850f453fa60f3be79a5dbf", size = 11422824, upload-time = "2026-05-11T18:52:48.058Z" }, + { url = "https://files.pythonhosted.org/packages/f8/45/830bb57f533a4604b355e07edcb8ea18cf88b5f94e5fca92f27052d7c597/pandas-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8894dc474d648fe7b6ff0ca9b0bd73950d19952bc1a6534540762c5d79d305c", size = 11950889, upload-time = "2026-05-11T18:52:50.905Z" }, + { url = "https://files.pythonhosted.org/packages/b9/c5/fc1b368f303087d20e8c9bf3d6ceb186263cfac0ade735cd938538bea839/pandas-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc", size = 9755463, upload-time = "2026-05-11T18:52:53.386Z" }, + { url = "https://files.pythonhosted.org/packages/86/bd/fda8f9705b1b09c6ebe14bfc0fa0e4ec8584d54ea673628f157ff55131af/pandas-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:557409bc4178e70ee8d9ddb494798e51ebf6ea59330f6be22c51bab2a7db6c49", size = 9066158, upload-time = "2026-05-11T18:52:56.038Z" }, + { url = "https://files.pythonhosted.org/packages/c5/90/62d8302883c44308c477e222c3daf7c813a34c8e96985882fbd53d964352/pandas-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:67b3b64c11910cfa29f4e94a14d3bff9ee693b6fc76055e7cad549cee0aec5fa", size = 10331071, upload-time = "2026-05-11T18:52:58.838Z" }, + { url = "https://files.pythonhosted.org/packages/7f/ae/6a6493c783a101f165e4356953ba3c74d6f77f0042fa7d753da9dfbb640c/pandas-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39436b377d56d2a2e52d0395bdbee171f01068e99af5250509aceeb929f765c7", size = 9875690, upload-time = "2026-05-11T18:53:01.431Z" }, + { url = "https://files.pythonhosted.org/packages/62/7c/5df8e9f56c69a2769fbe9382a5ef8f2658c007e376434e1e2cbb57ad895f/pandas-3.0.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4be06d68f9ddcfc645b87534911da79a8fbffc7573c80e0edcf42a5020624d8", size = 10381634, upload-time = "2026-05-11T18:53:04.393Z" }, + { url = "https://files.pythonhosted.org/packages/99/68/1237369725aa617bb358263d535803e3053fdbc593513ec5ed9c9896b5b6/pandas-3.0.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a4eeb6830daf35a71cc09649bd823e2b542dac246cdee9614c6e4bd65028cd6a", size = 10891243, upload-time = "2026-05-11T18:53:07.643Z" }, + { url = "https://files.pythonhosted.org/packages/25/93/77d108e8af7222b4a503ebde0e30215b1c2e4f8e53a526431890f22d5586/pandas-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1928e07221f82db493cd4af1e23c1bfca524a19a4699887975bff68f49a72bfb", size = 11388659, upload-time = "2026-05-11T18:53:10.634Z" }, + { url = "https://files.pythonhosted.org/packages/d0/bd/eff5b4399f332ac386c853f6cd2bd3fa2ca0061b9f36ecd9c4d7c4265649/pandas-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51b1fe551acb77dac643c6fda86084d8d446c10fe64b06a9cc29c4cc8540e7f2", size = 11942880, upload-time = "2026-05-11T18:53:13.536Z" }, + { url = "https://files.pythonhosted.org/packages/2c/20/559ace4200982c3887d0b86bfd0d856a2143ef8ddab63cc07934951a964c/pandas-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:a82d532a3351d435432cd913edbccaf8b8e01d4dd0e5ced5a8d2e8ecd94c7e44", size = 9757091, upload-time = "2026-05-11T18:53:16.306Z" }, + { url = "https://files.pythonhosted.org/packages/3a/66/69055a09fe200f29f922a3eeec4804611900b95f52d932ece3393c3c0c19/pandas-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:275c14e0fce14a2ec20eee474aecd305478ea3c1e6f6a9d8fe219a165542717e", size = 9057282, upload-time = "2026-05-11T18:53:18.768Z" }, + { url = "https://files.pythonhosted.org/packages/57/0e/efe801b0e6811e8e650cd21b7f2608e30f08a7067e2bf6e8752b0d56ee3c/pandas-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:46997386d528eb40376ecd6b033cf4a8a1e5282580f68f43de875b78cba2199d", size = 10767016, upload-time = "2026-05-11T18:53:21.227Z" }, + { url = "https://files.pythonhosted.org/packages/ea/dc/eb55135a1d5f0f0519f28da1f609a206d2cad1f9c35c32d51e38dd7261ae/pandas-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261e308dfb22448384b7580cf719d2f998fe2966c92893c3e77d14008af1f066", size = 10420210, upload-time = "2026-05-11T18:53:23.982Z" }, + { url = "https://files.pythonhosted.org/packages/c6/3e/b1d5d955ce33ffecb407465a60bc32769d74fcf68224b7ae67ae11d4dea4/pandas-3.0.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dd1a5d1def6a46002e964510bdc67c368aa0951df5d1d9f8365336f5a1f490cd", size = 10336126, upload-time = "2026-05-11T18:53:26.731Z" }, + { url = "https://files.pythonhosted.org/packages/f5/76/a01261711ab60a22d71b862f0de20e4c504bf80457270ad8cb42110f6abc/pandas-3.0.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d72828c20c6d6e83e1e22a6a3b47b326b71664112fa9705dcbccfd7a39b62085", size = 10728051, upload-time = "2026-05-11T18:53:29.125Z" }, + { url = "https://files.pythonhosted.org/packages/e9/21/ea191195e587b18cf682e97f433f81b2d0fbe341380e80a3e0d6e4403c8e/pandas-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d26cbe1fcfc12e8fd900e2454163e466b2d3af84f7c75481df7683ffc073d870", size = 11350796, upload-time = "2026-05-11T18:53:32.056Z" }, + { url = "https://files.pythonhosted.org/packages/64/69/f0eaaf54939f0e8c6768fd06be9af2cef9b36048b96dfb9e1b2c685a807e/pandas-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e91cec1879ada0624fc3dc9953c5cbd60208e59c0db28f540c5d6d47502422f", size = 11799741, upload-time = "2026-05-11T18:53:34.985Z" }, + { url = "https://files.pythonhosted.org/packages/45/a4/865e0e510cae5fc2194de4db28be638952de942571ba9125934fd9c01d47/pandas-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:08d789b41f87e0905880e293cedf6197ce71fe67cc081358b1e148a491b9bd13", size = 10499958, upload-time = "2026-05-11T18:53:37.857Z" }, + { url = "https://files.pythonhosted.org/packages/86/54/effdcc3c0ff7a08037889200e148ebe94c16c4f653be078c7b3675955df1/pandas-3.0.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3650109c0f22879df8bd6179ab9ee3d7f1d1d4e7e0094a3f0032d9f51e2e64ac", size = 10336065, upload-time = "2026-05-11T18:53:41.099Z" }, + { url = "https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bab900348131a7db1f69a7309ef141fd5680f1487094193bcbbb61791573bf8f", size = 9926101, upload-time = "2026-05-11T18:53:43.515Z" }, + { url = "https://files.pythonhosted.org/packages/ae/e9/e35cf11c8a136e757b956f5f0efdcaa50aecde85ea055f1898dfc68262f3/pandas-3.0.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba7e08b9ac1d54569cd1e256e3668975ed624d6826f7b68df0342b012007bddb", size = 10457553, upload-time = "2026-05-11T18:53:46.394Z" }, + { url = "https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d71c63ae4ebdbf70209742096f1fc46a83a0613c99d4b23766cced9ff8cd62a", size = 10914065, upload-time = "2026-05-11T18:53:49.134Z" }, + { url = "https://files.pythonhosted.org/packages/c4/c2/1ef644445fcd72e3627bceec77e3560636f87ddce4ed841afe76b83b5bf9/pandas-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3a2ec42c98ffa2565a67e08e218d06d72576d758d90facb7c00805194d8f360", size = 11459188, upload-time = "2026-05-11T18:53:52.527Z" }, + { url = "https://files.pythonhosted.org/packages/7e/49/4d8d4f42cbc9c4adc7a1870f269c02cbd6cd40d059622c06fb298addcbad/pandas-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:335f62418ed562cfc3c49e9e196375c28b729dcef8543abf4f9438e381bf3c76", size = 11982966, upload-time = "2026-05-11T18:53:55.043Z" }, + { url = "https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:3c20a521bbb85902f79f7270c80a59e1b5452d96d170c034f207181870f97ac5", size = 9876755, upload-time = "2026-05-11T18:53:58.067Z" }, + { url = "https://files.pythonhosted.org/packages/2a/af/33c469653b0ba03b50c3a98192d4c07f0c75c66b263ceb097fce0ee97d31/pandas-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:a2d2dff8a04f3917b55ab3910c32990f8ddf7eceba114947838cefa976a68977", size = 9198658, upload-time = "2026-05-11T18:54:00.733Z" }, + { url = "https://files.pythonhosted.org/packages/a2/fa/b8c257bd76b8bd060c3a9151c1fca05e9b9c5e3af5d0f549c0356f6d143d/pandas-3.0.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:0d589105b3c14645af1738ff279b2995102d8f7a03b0a66dc8d95550eb513e04", size = 10787242, upload-time = "2026-05-11T18:54:03.564Z" }, + { url = "https://files.pythonhosted.org/packages/54/eb/f19206ffb0bf1919002969aa448b4702c6594845156a6f8050674855aac3/pandas-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:13fc1e853d9e04743d11ba75a985ccbc2a317fe07d8af61e445a6fd24dacd6a6", size = 10436369, upload-time = "2026-05-11T18:54:06.311Z" }, + { url = "https://files.pythonhosted.org/packages/fd/24/c7c39fb4fe22b71a0c2d78bf0c585c600092d85f94f086d2b3b2f6ca27e2/pandas-3.0.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:819959dab7bbd0049c15623fbac4e29a191b9528160a61fb1032242d8ced2d9c", size = 10358306, upload-time = "2026-05-11T18:54:09.085Z" }, + { url = "https://files.pythonhosted.org/packages/16/ec/dd2a9eb7fa1204df88c0864164e35b228ac581062ac612ba0a67fd812e4c/pandas-3.0.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:60ae316d3fd75d1858d450d0db0103ea2be3e7d4a95ec2f064f7e2ae63f7b028", size = 10758394, upload-time = "2026-05-11T18:54:11.956Z" }, + { url = "https://files.pythonhosted.org/packages/95/6e/00c61ea8e85b4f6d8d35e11852a1a4998fc7fafc91c6a602d1cc9c972d64/pandas-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd3a518890b400d32f9023722dc9a9a5c969f00b415419a3c06c043f09bb5d7d", size = 11375717, upload-time = "2026-05-11T18:54:14.539Z" }, + { url = "https://files.pythonhosted.org/packages/31/89/8fc1c268969fac43688d65fd92e67df24bd128d53cb4d2eee534cd307399/pandas-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9c39be2d709d01fa972a0cabc522389fceca4f3969332ba25a7d6c5802cf976a", size = 11828897, upload-time = "2026-05-11T18:54:17.146Z" }, + { url = "https://files.pythonhosted.org/packages/56/3b/e7d20dea247a3e6dc0bd8a6953854afbedc03951def4e7371e05e7263e25/pandas-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4db8c527972a821cf5286b40ccc57642a39bc62e62022b42f99f8a67fca8c3a1", size = 10900855, upload-time = "2026-05-11T18:54:19.72Z" }, + { url = "https://files.pythonhosted.org/packages/0f/54/68a0978d1ef8502b8492099beaa6e7a0c1b32e3b5d4f677f5810cb08711c/pandas-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b2c95f8bfc1ee412bf482605d7bfd30c12d1d26bd59fdd91efeef1d4718decb1", size = 9466464, upload-time = "2026-05-11T18:54:22.754Z" }, +] + +[[package]] +name = "pandocfilters" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/6f/3dd4940bbe001c06a65f88e36bad298bc7a0de5036115639926b0c5c0458/pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e", size = 8454, upload-time = "2024-01-18T20:08:13.726Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc", size = 8663, upload-time = "2024-01-18T20:08:11.28Z" }, +] + +[[package]] +name = "parso" +version = "0.8.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/4b/90c937815137d43ce71ba043cd3566221e9df6b9c805f24b5d138c9d40a7/parso-0.8.7.tar.gz", hash = "sha256:eaaac4c9fdd5e9e8852dc778d2d7405897ec510f2a298071453e5e3a07914bb1", size = 401824, upload-time = "2026-05-01T23:13:02.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/5d/8268b644392ee874ee82a635cd0df1773de230bde356c38de28e298392cc/parso-0.8.7-py2.py3-none-any.whl", hash = "sha256:a8926eb2a1b915486941fdbd31e86a4baf88fe8c210f25f2f35ecec5b574ca1c", size = 107025, upload-time = "2026-05-01T23:12:58.867Z" }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + +[[package]] +name = "pillow" +version = "12.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5", size = 46987819, upload-time = "2026-04-01T14:46:17.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/58/be/7482c8a5ebebbc6470b3eb791812fff7d5e0216c2be3827b30b8bb6603ed/pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5", size = 5308279, upload-time = "2026-04-01T14:43:13.246Z" }, + { url = "https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421", size = 4695490, upload-time = "2026-04-01T14:43:15.584Z" }, + { url = "https://files.pythonhosted.org/packages/de/af/4e8e6869cbed569d43c416fad3dc4ecb944cb5d9492defaed89ddd6fe871/pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987", size = 6284462, upload-time = "2026-04-01T14:43:18.268Z" }, + { url = "https://files.pythonhosted.org/packages/e9/9e/c05e19657fd57841e476be1ab46c4d501bffbadbafdc31a6d665f8b737b6/pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76", size = 8094744, upload-time = "2026-04-01T14:43:20.716Z" }, + { url = "https://files.pythonhosted.org/packages/2b/54/1789c455ed10176066b6e7e6da1b01e50e36f94ba584dc68d9eebfe9156d/pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005", size = 6398371, upload-time = "2026-04-01T14:43:23.443Z" }, + { url = "https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780", size = 7087215, upload-time = "2026-04-01T14:43:26.758Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f8/2f6825e441d5b1959d2ca5adec984210f1ec086435b0ed5f52c19b3b8a6e/pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5", size = 6509783, upload-time = "2026-04-01T14:43:29.56Z" }, + { url = "https://files.pythonhosted.org/packages/67/f9/029a27095ad20f854f9dba026b3ea6428548316e057e6fc3545409e86651/pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5", size = 7212112, upload-time = "2026-04-01T14:43:32.091Z" }, + { url = "https://files.pythonhosted.org/packages/be/42/025cfe05d1be22dbfdb4f264fe9de1ccda83f66e4fc3aac94748e784af04/pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940", size = 6378489, upload-time = "2026-04-01T14:43:34.601Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5", size = 7084129, upload-time = "2026-04-01T14:43:37.213Z" }, + { url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414", size = 2463612, upload-time = "2026-04-01T14:43:39.421Z" }, + { url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c", size = 4100837, upload-time = "2026-04-01T14:43:41.506Z" }, + { url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2", size = 4176528, upload-time = "2026-04-01T14:43:43.773Z" }, + { url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c", size = 3640401, upload-time = "2026-04-01T14:43:45.87Z" }, + { url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795", size = 5308094, upload-time = "2026-04-01T14:43:48.438Z" }, + { url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f", size = 4695402, upload-time = "2026-04-01T14:43:51.292Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed", size = 6280005, upload-time = "2026-04-01T14:43:54.242Z" }, + { url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9", size = 8090669, upload-time = "2026-04-01T14:43:57.335Z" }, + { url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed", size = 6395194, upload-time = "2026-04-01T14:43:59.864Z" }, + { url = "https://files.pythonhosted.org/packages/67/ee/21d4e8536afd1a328f01b359b4d3997b291ffd35a237c877b331c1c3b71c/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3", size = 7082423, upload-time = "2026-04-01T14:44:02.74Z" }, + { url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9", size = 6505667, upload-time = "2026-04-01T14:44:05.381Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795", size = 7208580, upload-time = "2026-04-01T14:44:08.39Z" }, + { url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e", size = 6375896, upload-time = "2026-04-01T14:44:11.197Z" }, + { url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b", size = 7081266, upload-time = "2026-04-01T14:44:13.947Z" }, + { url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06", size = 2463508, upload-time = "2026-04-01T14:44:16.312Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b", size = 5309927, upload-time = "2026-04-01T14:44:18.89Z" }, + { url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f", size = 4698624, upload-time = "2026-04-01T14:44:21.115Z" }, + { url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612", size = 6321252, upload-time = "2026-04-01T14:44:23.663Z" }, + { url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c", size = 8126550, upload-time = "2026-04-01T14:44:26.772Z" }, + { url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea", size = 6433114, upload-time = "2026-04-01T14:44:29.615Z" }, + { url = "https://files.pythonhosted.org/packages/36/a3/f9a77144231fb8d40ee27107b4463e205fa4677e2ca2548e14da5cf18dce/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4", size = 7115667, upload-time = "2026-04-01T14:44:32.773Z" }, + { url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4", size = 6538966, upload-time = "2026-04-01T14:44:35.252Z" }, + { url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea", size = 7238241, upload-time = "2026-04-01T14:44:37.875Z" }, + { url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24", size = 6379592, upload-time = "2026-04-01T14:44:40.336Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98", size = 7085542, upload-time = "2026-04-01T14:44:43.251Z" }, + { url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453", size = 2465765, upload-time = "2026-04-01T14:44:45.996Z" }, + { url = "https://files.pythonhosted.org/packages/bf/98/4595daa2365416a86cb0d495248a393dfc84e96d62ad080c8546256cb9c0/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8", size = 4100848, upload-time = "2026-04-01T14:44:48.48Z" }, + { url = "https://files.pythonhosted.org/packages/0b/79/40184d464cf89f6663e18dfcf7ca21aae2491fff1a16127681bf1fa9b8cf/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b", size = 4176515, upload-time = "2026-04-01T14:44:51.353Z" }, + { url = "https://files.pythonhosted.org/packages/b0/63/703f86fd4c422a9cf722833670f4f71418fb116b2853ff7da722ea43f184/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295", size = 3640159, upload-time = "2026-04-01T14:44:53.588Z" }, + { url = "https://files.pythonhosted.org/packages/71/e0/fb22f797187d0be2270f83500aab851536101b254bfa1eae10795709d283/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed", size = 5312185, upload-time = "2026-04-01T14:44:56.039Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae", size = 4695386, upload-time = "2026-04-01T14:44:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/70/62/98f6b7f0c88b9addd0e87c217ded307b36be024d4ff8869a812b241d1345/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601", size = 6280384, upload-time = "2026-04-01T14:45:01.5Z" }, + { url = "https://files.pythonhosted.org/packages/5e/03/688747d2e91cfbe0e64f316cd2e8005698f76ada3130d0194664174fa5de/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be", size = 8091599, upload-time = "2026-04-01T14:45:04.5Z" }, + { url = "https://files.pythonhosted.org/packages/f6/35/577e22b936fcdd66537329b33af0b4ccfefaeabd8aec04b266528cddb33c/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f", size = 6396021, upload-time = "2026-04-01T14:45:07.117Z" }, + { url = "https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286", size = 7083360, upload-time = "2026-04-01T14:45:09.763Z" }, + { url = "https://files.pythonhosted.org/packages/5e/26/d325f9f56c7e039034897e7380e9cc202b1e368bfd04d4cbe6a441f02885/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50", size = 6507628, upload-time = "2026-04-01T14:45:12.378Z" }, + { url = "https://files.pythonhosted.org/packages/5f/f7/769d5632ffb0988f1c5e7660b3e731e30f7f8ec4318e94d0a5d674eb65a4/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104", size = 7209321, upload-time = "2026-04-01T14:45:15.122Z" }, + { url = "https://files.pythonhosted.org/packages/6a/7a/c253e3c645cd47f1aceea6a8bacdba9991bf45bb7dfe927f7c893e89c93c/pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7", size = 6479723, upload-time = "2026-04-01T14:45:17.797Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150", size = 7217400, upload-time = "2026-04-01T14:45:20.529Z" }, + { url = "https://files.pythonhosted.org/packages/d6/94/220e46c73065c3e2951bb91c11a1fb636c8c9ad427ac3ce7d7f3359b9b2f/pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1", size = 2554835, upload-time = "2026-04-01T14:45:23.162Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ab/1b426a3974cb0e7da5c29ccff4807871d48110933a57207b5a676cccc155/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463", size = 5314225, upload-time = "2026-04-01T14:45:25.637Z" }, + { url = "https://files.pythonhosted.org/packages/19/1e/dce46f371be2438eecfee2a1960ee2a243bbe5e961890146d2dee1ff0f12/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3", size = 4698541, upload-time = "2026-04-01T14:45:28.355Z" }, + { url = "https://files.pythonhosted.org/packages/55/c3/7fbecf70adb3a0c33b77a300dc52e424dc22ad8cdc06557a2e49523b703d/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166", size = 6322251, upload-time = "2026-04-01T14:45:30.924Z" }, + { url = "https://files.pythonhosted.org/packages/1c/3c/7fbc17cfb7e4fe0ef1642e0abc17fc6c94c9f7a16be41498e12e2ba60408/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe", size = 8127807, upload-time = "2026-04-01T14:45:33.908Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c3/a8ae14d6defd2e448493ff512fae903b1e9bd40b72efb6ec55ce0048c8ce/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd", size = 6433935, upload-time = "2026-04-01T14:45:36.623Z" }, + { url = "https://files.pythonhosted.org/packages/6e/32/2880fb3a074847ac159d8f902cb43278a61e85f681661e7419e6596803ed/pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e", size = 7116720, upload-time = "2026-04-01T14:45:39.258Z" }, + { url = "https://files.pythonhosted.org/packages/46/87/495cc9c30e0129501643f24d320076f4cc54f718341df18cc70ec94c44e1/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06", size = 6540498, upload-time = "2026-04-01T14:45:41.879Z" }, + { url = "https://files.pythonhosted.org/packages/18/53/773f5edca692009d883a72211b60fdaf8871cbef075eaa9d577f0a2f989e/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43", size = 7239413, upload-time = "2026-04-01T14:45:44.705Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e4/4b64a97d71b2a83158134abbb2f5bd3f8a2ea691361282f010998f339ec7/pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354", size = 6482084, upload-time = "2026-04-01T14:45:47.568Z" }, + { url = "https://files.pythonhosted.org/packages/ba/13/306d275efd3a3453f72114b7431c877d10b1154014c1ebbedd067770d629/pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1", size = 7225152, upload-time = "2026-04-01T14:45:50.032Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb", size = 2556579, upload-time = "2026-04-01T14:45:52.529Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.9.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "prometheus-client" +version = "0.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/fb/d9aa83ffe43ce1f19e557c0971d04b90561b0cfd50762aafb01968285553/prometheus_client-0.25.0.tar.gz", hash = "sha256:5e373b75c31afb3c86f1a52fa1ad470c9aace18082d39ec0d2f918d11cc9ba28", size = 86035, upload-time = "2026-04-09T19:53:42.359Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/9b/d4b1e644385499c8346fa9b622a3f030dce14cd6ef8a1871c221a17a67e7/prometheus_client-0.25.0-py3-none-any.whl", hash = "sha256:d5aec89e349a6ec230805d0df882f3807f74fd6c1a2fa86864e3c2279059fed1", size = 64154, upload-time = "2026-04-09T19:53:41.324Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "psutil" +version = "7.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" }, + { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" }, + { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" }, + { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" }, + { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" }, + { url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" }, + { url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" }, + { url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" }, + { url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" }, + { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, + { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" }, + { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" }, + { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" }, + { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" }, + { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" }, + { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "pyparsing" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, +] + +[[package]] +name = "pytest" +version = "9.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-json-logger" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/ff/3cc9165fd44106973cd7ac9facb674a65ed853494592541d339bdc9a30eb/python_json_logger-4.1.0.tar.gz", hash = "sha256:b396b9e3ed782b09ff9d6e4f1683d46c83ad0d35d2e407c09a9ebbf038f88195", size = 17573, upload-time = "2026-03-29T04:39:56.805Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/be/0631a861af4d1c875f096c07d34e9a63639560a717130e7a87cbc82b7e3f/python_json_logger-4.1.0-py3-none-any.whl", hash = "sha256:132994765cf75bf44554be9aa49b06ef2345d23661a96720262716438141b6b2", size = 15021, upload-time = "2026-03-29T04:39:55.266Z" }, +] + +[[package]] +name = "pywinpty" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/54/37c7370ba91f579235049dc26cd2c5e657d2a943e01820844ffc81f32176/pywinpty-3.0.3.tar.gz", hash = "sha256:523441dc34d231fb361b4b00f8c99d3f16de02f5005fd544a0183112bcc22412", size = 31309, upload-time = "2026-02-04T21:51:09.524Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/d4/aeb5e1784d2c5bff6e189138a9ca91a090117459cea0c30378e1f2db3d54/pywinpty-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:c9081df0e49ffa86d15db4a6ba61530630e48707f987df42c9d3313537e81fc0", size = 2113098, upload-time = "2026-02-04T21:54:37.711Z" }, + { url = "https://files.pythonhosted.org/packages/b9/53/7278223c493ccfe4883239cf06c823c56460a8010e0fc778eef67858dc14/pywinpty-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:15e79d870e18b678fb8a5a6105fd38496b55697c66e6fc0378236026bc4d59e9", size = 234901, upload-time = "2026-02-04T21:53:31.35Z" }, + { url = "https://files.pythonhosted.org/packages/e5/cb/58d6ed3fd429c96a90ef01ac9a617af10a6d41469219c25e7dc162abbb71/pywinpty-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9c91dbb026050c77bdcef964e63a4f10f01a639113c4d3658332614544c467ab", size = 2112686, upload-time = "2026-02-04T21:52:03.035Z" }, + { url = "https://files.pythonhosted.org/packages/fd/50/724ed5c38c504d4e58a88a072776a1e880d970789deaeb2b9f7bd9a5141a/pywinpty-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:fe1f7911805127c94cf51f89ab14096c6f91ffdcacf993d2da6082b2142a2523", size = 234591, upload-time = "2026-02-04T21:52:29.821Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ad/90a110538696b12b39fd8758a06d70ded899308198ad2305ac68e361126e/pywinpty-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:3f07a6cf1c1d470d284e614733c3d0f726d2c85e78508ea10a403140c3c0c18a", size = 2112360, upload-time = "2026-02-04T21:55:33.397Z" }, + { url = "https://files.pythonhosted.org/packages/44/0f/7ffa221757a220402bc79fda44044c3f2cc57338d878ab7d622add6f4581/pywinpty-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:15c7c0b6f8e9d87aabbaff76468dabf6e6121332c40fc1d83548d02a9d6a3759", size = 233107, upload-time = "2026-02-04T21:51:45.455Z" }, + { url = "https://files.pythonhosted.org/packages/28/88/2ff917caff61e55f38bcdb27de06ee30597881b2cae44fbba7627be015c4/pywinpty-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:d4b6b7b0fe0cdcd02e956bd57cfe9f4e5a06514eecf3b5ae174da4f951b58be9", size = 2113282, upload-time = "2026-02-04T21:52:08.188Z" }, + { url = "https://files.pythonhosted.org/packages/63/32/40a775343ace542cc43ece3f1d1fce454021521ecac41c4c4573081c2336/pywinpty-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:34789d685fc0d547ce0c8a65e5a70e56f77d732fa6e03c8f74fefb8cbb252019", size = 234207, upload-time = "2026-02-04T21:51:58.687Z" }, + { url = "https://files.pythonhosted.org/packages/8d/54/5d5e52f4cb75028104ca6faf36c10f9692389b1986d34471663b4ebebd6d/pywinpty-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:0c37e224a47a971d1a6e08649a1714dac4f63c11920780977829ed5c8cadead1", size = 2112910, upload-time = "2026-02-04T21:52:30.976Z" }, + { url = "https://files.pythonhosted.org/packages/0a/44/dcd184824e21d4620b06c7db9fbb15c3ad0a0f1fa2e6de79969fb82647ec/pywinpty-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:c4e9c3dff7d86ba81937438d5819f19f385a39d8f592d4e8af67148ceb4f6ab5", size = 233425, upload-time = "2026-02-04T21:51:56.754Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "pyzmq" +version = "27.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "implementation_name == 'pypy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, + { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, + { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, + { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, + { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, + { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, + { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, + { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, + { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, + { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, +] + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760, upload-time = "2019-10-28T16:00:19.144Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242, upload-time = "2019-10-28T16:00:13.976Z" }, +] + +[[package]] +name = "rfc3987-syntax" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lark" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239, upload-time = "2025-07-18T01:05:05.015Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/e7/98a2f4ac921d82f33e03f3835f5bf3a4a40aa1bfdc57975e74a97b2b4bdd/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad", size = 375086, upload-time = "2025-11-30T20:22:17.93Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a1/bca7fd3d452b272e13335db8d6b0b3ecde0f90ad6f16f3328c6fb150c889/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05", size = 359053, upload-time = "2025-11-30T20:22:19.297Z" }, + { url = "https://files.pythonhosted.org/packages/65/1c/ae157e83a6357eceff62ba7e52113e3ec4834a84cfe07fa4b0757a7d105f/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28", size = 390763, upload-time = "2025-11-30T20:22:21.661Z" }, + { url = "https://files.pythonhosted.org/packages/d4/36/eb2eb8515e2ad24c0bd43c3ee9cd74c33f7ca6430755ccdb240fd3144c44/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd", size = 408951, upload-time = "2025-11-30T20:22:23.408Z" }, + { url = "https://files.pythonhosted.org/packages/d6/65/ad8dc1784a331fabbd740ef6f71ce2198c7ed0890dab595adb9ea2d775a1/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f", size = 514622, upload-time = "2025-11-30T20:22:25.16Z" }, + { url = "https://files.pythonhosted.org/packages/63/8e/0cfa7ae158e15e143fe03993b5bcd743a59f541f5952e1546b1ac1b5fd45/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1", size = 414492, upload-time = "2025-11-30T20:22:26.505Z" }, + { url = "https://files.pythonhosted.org/packages/60/1b/6f8f29f3f995c7ffdde46a626ddccd7c63aefc0efae881dc13b6e5d5bb16/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23", size = 394080, upload-time = "2025-11-30T20:22:27.934Z" }, + { url = "https://files.pythonhosted.org/packages/6d/d5/a266341051a7a3ca2f4b750a3aa4abc986378431fc2da508c5034d081b70/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6", size = 408680, upload-time = "2025-11-30T20:22:29.341Z" }, + { url = "https://files.pythonhosted.org/packages/10/3b/71b725851df9ab7a7a4e33cf36d241933da66040d195a84781f49c50490c/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51", size = 423589, upload-time = "2025-11-30T20:22:31.469Z" }, + { url = "https://files.pythonhosted.org/packages/00/2b/e59e58c544dc9bd8bd8384ecdb8ea91f6727f0e37a7131baeff8d6f51661/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5", size = 573289, upload-time = "2025-11-30T20:22:32.997Z" }, + { url = "https://files.pythonhosted.org/packages/da/3e/a18e6f5b460893172a7d6a680e86d3b6bc87a54c1f0b03446a3c8c7b588f/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e", size = 599737, upload-time = "2025-11-30T20:22:34.419Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e2/714694e4b87b85a18e2c243614974413c60aa107fd815b8cbc42b873d1d7/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394", size = 563120, upload-time = "2025-11-30T20:22:35.903Z" }, + { url = "https://files.pythonhosted.org/packages/6f/ab/d5d5e3bcedb0a77f4f613706b750e50a5a3ba1c15ccd3665ecc636c968fd/rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf", size = 223782, upload-time = "2025-11-30T20:22:37.271Z" }, + { url = "https://files.pythonhosted.org/packages/39/3b/f786af9957306fdc38a74cef405b7b93180f481fb48453a114bb6465744a/rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b", size = 240463, upload-time = "2025-11-30T20:22:39.021Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d2/b91dc748126c1559042cfe41990deb92c4ee3e2b415f6b5234969ffaf0cc/rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e", size = 230868, upload-time = "2025-11-30T20:22:40.493Z" }, + { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, + { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, + { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, + { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, + { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, + { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, + { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, + { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, + { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, + { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, + { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, + { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, + { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, + { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, + { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, + { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, + { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" }, + { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" }, + { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" }, + { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" }, + { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" }, + { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" }, + { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" }, + { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" }, + { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" }, + { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" }, + { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" }, + { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" }, + { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" }, + { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" }, + { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" }, + { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" }, + { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" }, + { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, +] + +[[package]] +name = "ruff" +version = "0.15.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/21/a7d5c126d5b557715ef81098f3db2fe20f622a039ff2e626af28d674ab80/ruff-0.15.13.tar.gz", hash = "sha256:f9d89f17f7ba7fb2ed42921f0df75da797a9a5d71bc39049e2c687cf2baf44b7", size = 4678180, upload-time = "2026-05-14T13:44:37.869Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/61/11d458dc6ac22504fd8e237b29dfd40504c7fbbcc8930402cfe51a8e63ed/ruff-0.15.13-py3-none-linux_armv6l.whl", hash = "sha256:444b580fc72fd6887e650acd3e575e18cdc79dbcf42fb4030b491057921f61f8", size = 10738279, upload-time = "2026-05-14T13:44:18.7Z" }, + { url = "https://files.pythonhosted.org/packages/86/ca/caa871ee7be718c45256fada4e16a218ee3e33f0c4a46b729a60a24912e6/ruff-0.15.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6590d009e7cb7ebf36f83dbdd44a3fa48a0994ff6f1cdc1b08006abe58f98dc7", size = 11124798, upload-time = "2026-05-14T13:44:06.427Z" }, + { url = "https://files.pythonhosted.org/packages/d3/19/43f5f2e568dddde567fc41f8471f9432c09563e19d3e617a48cfa52f8f0a/ruff-0.15.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1c26d2f66163deeb6e08d8b39fbbe983ce3c71cea06a6d7591cfd1421793c629", size = 10460761, upload-time = "2026-05-14T13:44:04.375Z" }, + { url = "https://files.pythonhosted.org/packages/99/df/cf938cd6de3003178f03ad7c1ea2a6c099468c03a35037985070b37e76be/ruff-0.15.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbd6f94b434f896308e4d57fb7bfde0d02b99f7a64b3bdab0fdfa6a864203a5", size = 10804451, upload-time = "2026-05-14T13:44:25.221Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7d/5d0973129b154ded2225729169d7068f26b467760b146493fde138415f23/ruff-0.15.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf3259f3be4d181bda591da5db2571aed6853c6a048157756448020bc6c5cd22", size = 10534285, upload-time = "2026-05-14T13:44:08.888Z" }, + { url = "https://files.pythonhosted.org/packages/1f/e3/6b999bbc66cd51e5f073842bc2a3995e99c5e0e72e16b15e7261f7abf57a/ruff-0.15.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae9c17e5eb4430c154e76abc25d79a318190f5a997f38fb6b114416c5319ffc9", size = 11312063, upload-time = "2026-05-14T13:44:11.274Z" }, + { url = "https://files.pythonhosted.org/packages/af/5a/642639e9f5db04f1e97fbd6e091c6fd20725bdf072fb114d00eefb9e6eb8/ruff-0.15.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e2e39bff6c341f4b577a21b801326fab0b11847f48fcaa83f00a113c9b3cb55", size = 12183079, upload-time = "2026-05-14T13:44:01.634Z" }, + { url = "https://files.pythonhosted.org/packages/19/4c/7585735f6b53b0f12de13618b2f7d250a844f018822efc899df2e7b8295f/ruff-0.15.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e8d9a8e08013542e94d3220bc5b62cc3e5ef87c5f74bff367d3fac14fab013e6", size = 11440833, upload-time = "2026-05-14T13:43:59.043Z" }, + { url = "https://files.pythonhosted.org/packages/e8/31/bf1a0803d077e679cfeee5f2f67290a0fa79c7385b5d9a8c17b9db2c48f0/ruff-0.15.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc411dfebe5eebe55ce041c6ae080eb7668955e866daa2fbb16692a784f1c4ca", size = 11434486, upload-time = "2026-05-14T13:44:27.761Z" }, + { url = "https://files.pythonhosted.org/packages/e1/4e/62c9b999875d4f14db80f277c030578f5e249c9852d65b7ac7ad0b43c041/ruff-0.15.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:768494eb08b9cee54e2fd27969966f74db5a57f6eaa7a90fcb3306af34dfc4bd", size = 11385189, upload-time = "2026-05-14T13:44:13.704Z" }, + { url = "https://files.pythonhosted.org/packages/fc/89/7e959047a104df3eb12863447c110140191fc5b6c4f379ea2e803fcdb0e4/ruff-0.15.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:fb75f9a3a7e42ffe117d734494e6c5e5cb3565d66e12612cb63d0e572a41a5b6", size = 10781380, upload-time = "2026-05-14T13:43:56.734Z" }, + { url = "https://files.pythonhosted.org/packages/ff/52/5fd18f3b88cab63e88aa11516b3b4e1e5f720e5c330f8dbe5c26210f41f8/ruff-0.15.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8cb74dd33bb2f6613faf7fc03b660053b5ac4f80e706d5788c6335e2a8048d51", size = 10540605, upload-time = "2026-05-14T13:44:20.748Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e0/9e35f338990d3e41a82875ff7053ffe97541dae81c9d02143177f381d572/ruff-0.15.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:7ef823f817fcd191dc934e984be9cf4094f808effa16f2542ad8e821ba02bbf2", size = 11036554, upload-time = "2026-05-14T13:44:16.256Z" }, + { url = "https://files.pythonhosted.org/packages/c2/13/070fb048c24080fba188f66371e2a92785be257ad02242066dc7255ac6e9/ruff-0.15.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f345a13937bd7f09f6f5d19fa0721b0c103e00e7f62bc67089a8e5e037719e0b", size = 11528133, upload-time = "2026-05-14T13:44:22.808Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8c/b1e1666aef7fc6555094d73ae6cd981701781ae85b97ceefc0eebd0b4668/ruff-0.15.13-py3-none-win32.whl", hash = "sha256:4044f94208b3b05ba0fc4a4abd0558cf4d6459bd18325eead7fd8cc66f909b41", size = 10721455, upload-time = "2026-05-14T13:44:35.697Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a6/870a3e8a50590bb92be184ad928c2922f088b00d9dc5c5ec7b924ee08c22/ruff-0.15.13-py3-none-win_amd64.whl", hash = "sha256:7064884d442b7d477b4e7473d12da7f08851d2b1982763c5d3f388a19468a1a4", size = 11900409, upload-time = "2026-05-14T13:44:30.389Z" }, + { url = "https://files.pythonhosted.org/packages/9b/36/9c015cd052fca743dae8cb2aeb16b551444787467db42ceab0fc968865af/ruff-0.15.13-py3-none-win_arm64.whl", hash = "sha256:2471da9bd1068c8c064b5fd9c0c4b6dddffd6369cb1cd68b29993b1709ff1b21", size = 11179336, upload-time = "2026-05-14T13:44:33.026Z" }, +] + +[[package]] +name = "scikit-learn" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "joblib" }, + { name = "numpy" }, + { name = "scipy" }, + { name = "threadpoolctl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/d4/40988bf3b8e34feec1d0e6a051446b1f66225f8529b9309becaeef62b6c4/scikit_learn-1.8.0.tar.gz", hash = "sha256:9bccbb3b40e3de10351f8f5068e105d0f4083b1a65fa07b6634fbc401a6287fd", size = 7335585, upload-time = "2025-12-10T07:08:53.618Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/74/e6a7cc4b820e95cc38cf36cd74d5aa2b42e8ffc2d21fe5a9a9c45c1c7630/scikit_learn-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5fb63362b5a7ddab88e52b6dbb47dac3fd7dafeee740dc6c8d8a446ddedade8e", size = 8548242, upload-time = "2025-12-10T07:07:51.568Z" }, + { url = "https://files.pythonhosted.org/packages/49/d8/9be608c6024d021041c7f0b3928d4749a706f4e2c3832bbede4fb4f58c95/scikit_learn-1.8.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:5025ce924beccb28298246e589c691fe1b8c1c96507e6d27d12c5fadd85bfd76", size = 8079075, upload-time = "2025-12-10T07:07:53.697Z" }, + { url = "https://files.pythonhosted.org/packages/dd/47/f187b4636ff80cc63f21cd40b7b2d177134acaa10f6bb73746130ee8c2e5/scikit_learn-1.8.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4496bb2cf7a43ce1a2d7524a79e40bc5da45cf598dbf9545b7e8316ccba47bb4", size = 8660492, upload-time = "2025-12-10T07:07:55.574Z" }, + { url = "https://files.pythonhosted.org/packages/97/74/b7a304feb2b49df9fafa9382d4d09061a96ee9a9449a7cbea7988dda0828/scikit_learn-1.8.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0bcfe4d0d14aec44921545fd2af2338c7471de9cb701f1da4c9d85906ab847a", size = 8931904, upload-time = "2025-12-10T07:07:57.666Z" }, + { url = "https://files.pythonhosted.org/packages/9f/c4/0ab22726a04ede56f689476b760f98f8f46607caecff993017ac1b64aa5d/scikit_learn-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:35c007dedb2ffe38fe3ee7d201ebac4a2deccd2408e8621d53067733e3c74809", size = 8019359, upload-time = "2025-12-10T07:07:59.838Z" }, + { url = "https://files.pythonhosted.org/packages/24/90/344a67811cfd561d7335c1b96ca21455e7e472d281c3c279c4d3f2300236/scikit_learn-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:8c497fff237d7b4e07e9ef1a640887fa4fb765647f86fbe00f969ff6280ce2bb", size = 7641898, upload-time = "2025-12-10T07:08:01.36Z" }, + { url = "https://files.pythonhosted.org/packages/03/aa/e22e0768512ce9255eba34775be2e85c2048da73da1193e841707f8f039c/scikit_learn-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d6ae97234d5d7079dc0040990a6f7aeb97cb7fa7e8945f1999a429b23569e0a", size = 8513770, upload-time = "2025-12-10T07:08:03.251Z" }, + { url = "https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:edec98c5e7c128328124a029bceb09eda2d526997780fef8d65e9a69eead963e", size = 8044458, upload-time = "2025-12-10T07:08:05.336Z" }, + { url = "https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74b66d8689d52ed04c271e1329f0c61635bcaf5b926db9b12d58914cdc01fe57", size = 8610341, upload-time = "2025-12-10T07:08:07.732Z" }, + { url = "https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8fdf95767f989b0cfedb85f7ed8ca215d4be728031f56ff5a519ee1e3276dc2e", size = 8900022, upload-time = "2025-12-10T07:08:09.862Z" }, + { url = "https://files.pythonhosted.org/packages/1c/f9/9b7563caf3ec8873e17a31401858efab6b39a882daf6c1bfa88879c0aa11/scikit_learn-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:2de443b9373b3b615aec1bb57f9baa6bb3a9bd093f1269ba95c17d870422b271", size = 7989409, upload-time = "2025-12-10T07:08:12.028Z" }, + { url = "https://files.pythonhosted.org/packages/49/bd/1f4001503650e72c4f6009ac0c4413cb17d2d601cef6f71c0453da2732fc/scikit_learn-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:eddde82a035681427cbedded4e6eff5e57fa59216c2e3e90b10b19ab1d0a65c3", size = 7619760, upload-time = "2025-12-10T07:08:13.688Z" }, + { url = "https://files.pythonhosted.org/packages/d2/7d/a630359fc9dcc95496588c8d8e3245cc8fd81980251079bc09c70d41d951/scikit_learn-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7cc267b6108f0a1499a734167282c00c4ebf61328566b55ef262d48e9849c735", size = 8826045, upload-time = "2025-12-10T07:08:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/cc/56/a0c86f6930cfcd1c7054a2bc417e26960bb88d32444fe7f71d5c2cfae891/scikit_learn-1.8.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:fe1c011a640a9f0791146011dfd3c7d9669785f9fed2b2a5f9e207536cf5c2fd", size = 8420324, upload-time = "2025-12-10T07:08:17.561Z" }, + { url = "https://files.pythonhosted.org/packages/46/1e/05962ea1cebc1cf3876667ecb14c283ef755bf409993c5946ade3b77e303/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72358cce49465d140cc4e7792015bb1f0296a9742d5622c67e31399b75468b9e", size = 8680651, upload-time = "2025-12-10T07:08:19.952Z" }, + { url = "https://files.pythonhosted.org/packages/fe/56/a85473cd75f200c9759e3a5f0bcab2d116c92a8a02ee08ccd73b870f8bb4/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80832434a6cc114f5219211eec13dcbc16c2bac0e31ef64c6d346cde3cf054cb", size = 8925045, upload-time = "2025-12-10T07:08:22.11Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b7/64d8cfa896c64435ae57f4917a548d7ac7a44762ff9802f75a79b77cb633/scikit_learn-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ee787491dbfe082d9c3013f01f5991658b0f38aa8177e4cd4bf434c58f551702", size = 8507994, upload-time = "2025-12-10T07:08:23.943Z" }, + { url = "https://files.pythonhosted.org/packages/5e/37/e192ea709551799379958b4c4771ec507347027bb7c942662c7fbeba31cb/scikit_learn-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf97c10a3f5a7543f9b88cbf488d33d175e9146115a451ae34568597ba33dcde", size = 7869518, upload-time = "2025-12-10T07:08:25.71Z" }, + { url = "https://files.pythonhosted.org/packages/24/05/1af2c186174cc92dcab2233f327336058c077d38f6fe2aceb08e6ab4d509/scikit_learn-1.8.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c22a2da7a198c28dd1a6e1136f19c830beab7fdca5b3e5c8bba8394f8a5c45b3", size = 8528667, upload-time = "2025-12-10T07:08:27.541Z" }, + { url = "https://files.pythonhosted.org/packages/a8/25/01c0af38fe969473fb292bba9dc2b8f9b451f3112ff242c647fee3d0dfe7/scikit_learn-1.8.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:6b595b07a03069a2b1740dc08c2299993850ea81cce4fe19b2421e0c970de6b7", size = 8066524, upload-time = "2025-12-10T07:08:29.822Z" }, + { url = "https://files.pythonhosted.org/packages/be/ce/a0623350aa0b68647333940ee46fe45086c6060ec604874e38e9ab7d8e6c/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29ffc74089f3d5e87dfca4c2c8450f88bdc61b0fc6ed5d267f3988f19a1309f6", size = 8657133, upload-time = "2025-12-10T07:08:31.865Z" }, + { url = "https://files.pythonhosted.org/packages/b8/cb/861b41341d6f1245e6ca80b1c1a8c4dfce43255b03df034429089ca2a2c5/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb65db5d7531bccf3a4f6bec3462223bea71384e2cda41da0f10b7c292b9e7c4", size = 8923223, upload-time = "2025-12-10T07:08:34.166Z" }, + { url = "https://files.pythonhosted.org/packages/76/18/a8def8f91b18cd1ba6e05dbe02540168cb24d47e8dcf69e8d00b7da42a08/scikit_learn-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:56079a99c20d230e873ea40753102102734c5953366972a71d5cb39a32bc40c6", size = 8096518, upload-time = "2025-12-10T07:08:36.339Z" }, + { url = "https://files.pythonhosted.org/packages/d1/77/482076a678458307f0deb44e29891d6022617b2a64c840c725495bee343f/scikit_learn-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:3bad7565bc9cf37ce19a7c0d107742b320c1285df7aab1a6e2d28780df167242", size = 7754546, upload-time = "2025-12-10T07:08:38.128Z" }, + { url = "https://files.pythonhosted.org/packages/2d/d1/ef294ca754826daa043b2a104e59960abfab4cf653891037d19dd5b6f3cf/scikit_learn-1.8.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:4511be56637e46c25721e83d1a9cea9614e7badc7040c4d573d75fbe257d6fd7", size = 8848305, upload-time = "2025-12-10T07:08:41.013Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e2/b1f8b05138ee813b8e1a4149f2f0d289547e60851fd1bb268886915adbda/scikit_learn-1.8.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:a69525355a641bf8ef136a7fa447672fb54fe8d60cab5538d9eb7c6438543fb9", size = 8432257, upload-time = "2025-12-10T07:08:42.873Z" }, + { url = "https://files.pythonhosted.org/packages/26/11/c32b2138a85dcb0c99f6afd13a70a951bfdff8a6ab42d8160522542fb647/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2656924ec73e5939c76ac4c8b026fc203b83d8900362eb2599d8aee80e4880f", size = 8678673, upload-time = "2025-12-10T07:08:45.362Z" }, + { url = "https://files.pythonhosted.org/packages/c7/57/51f2384575bdec454f4fe4e7a919d696c9ebce914590abf3e52d47607ab8/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15fc3b5d19cc2be65404786857f2e13c70c83dd4782676dd6814e3b89dc8f5b9", size = 8922467, upload-time = "2025-12-10T07:08:47.408Z" }, + { url = "https://files.pythonhosted.org/packages/35/4d/748c9e2872637a57981a04adc038dacaa16ba8ca887b23e34953f0b3f742/scikit_learn-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:00d6f1d66fbcf4eba6e356e1420d33cc06c70a45bb1363cd6f6a8e4ebbbdece2", size = 8774395, upload-time = "2025-12-10T07:08:49.337Z" }, + { url = "https://files.pythonhosted.org/packages/60/22/d7b2ebe4704a5e50790ba089d5c2ae308ab6bb852719e6c3bd4f04c3a363/scikit_learn-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f28dd15c6bb0b66ba09728cf09fd8736c304be29409bd8445a080c1280619e8c", size = 8002647, upload-time = "2025-12-10T07:08:51.601Z" }, +] + +[[package]] +name = "scipy" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0", size = 30573822, upload-time = "2026-02-23T00:26:24.851Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/48/b992b488d6f299dbe3f11a20b24d3dda3d46f1a635ede1c46b5b17a7b163/scipy-1.17.1-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:35c3a56d2ef83efc372eaec584314bd0ef2e2f0d2adb21c55e6ad5b344c0dcb8", size = 31610954, upload-time = "2026-02-23T00:17:49.855Z" }, + { url = "https://files.pythonhosted.org/packages/b2/02/cf107b01494c19dc100f1d0b7ac3cc08666e96ba2d64db7626066cee895e/scipy-1.17.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:fcb310ddb270a06114bb64bbe53c94926b943f5b7f0842194d585c65eb4edd76", size = 28172662, upload-time = "2026-02-23T00:18:01.64Z" }, + { url = "https://files.pythonhosted.org/packages/cf/a9/599c28631bad314d219cf9ffd40e985b24d603fc8a2f4ccc5ae8419a535b/scipy-1.17.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:cc90d2e9c7e5c7f1a482c9875007c095c3194b1cfedca3c2f3291cdc2bc7c086", size = 20344366, upload-time = "2026-02-23T00:18:12.015Z" }, + { url = "https://files.pythonhosted.org/packages/35/f5/906eda513271c8deb5af284e5ef0206d17a96239af79f9fa0aebfe0e36b4/scipy-1.17.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:c80be5ede8f3f8eded4eff73cc99a25c388ce98e555b17d31da05287015ffa5b", size = 22704017, upload-time = "2026-02-23T00:18:21.502Z" }, + { url = "https://files.pythonhosted.org/packages/da/34/16f10e3042d2f1d6b66e0428308ab52224b6a23049cb2f5c1756f713815f/scipy-1.17.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e19ebea31758fac5893a2ac360fedd00116cbb7628e650842a6691ba7ca28a21", size = 32927842, upload-time = "2026-02-23T00:18:35.367Z" }, + { url = "https://files.pythonhosted.org/packages/01/8e/1e35281b8ab6d5d72ebe9911edcdffa3f36b04ed9d51dec6dd140396e220/scipy-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:02ae3b274fde71c5e92ac4d54bc06c42d80e399fec704383dcd99b301df37458", size = 35235890, upload-time = "2026-02-23T00:18:49.188Z" }, + { url = "https://files.pythonhosted.org/packages/c5/5c/9d7f4c88bea6e0d5a4f1bc0506a53a00e9fcb198de372bfe4d3652cef482/scipy-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a604bae87c6195d8b1045eddece0514d041604b14f2727bbc2b3020172045eb", size = 35003557, upload-time = "2026-02-23T00:18:54.74Z" }, + { url = "https://files.pythonhosted.org/packages/65/94/7698add8f276dbab7a9de9fb6b0e02fc13ee61d51c7c3f85ac28b65e1239/scipy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f590cd684941912d10becc07325a3eeb77886fe981415660d9265c4c418d0bea", size = 37625856, upload-time = "2026-02-23T00:19:00.307Z" }, + { url = "https://files.pythonhosted.org/packages/a2/84/dc08d77fbf3d87d3ee27f6a0c6dcce1de5829a64f2eae85a0ecc1f0daa73/scipy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:41b71f4a3a4cab9d366cd9065b288efc4d4f3c0b37a91a8e0947fb5bd7f31d87", size = 36549682, upload-time = "2026-02-23T00:19:07.67Z" }, + { url = "https://files.pythonhosted.org/packages/bc/98/fe9ae9ffb3b54b62559f52dedaebe204b408db8109a8c66fdd04869e6424/scipy-1.17.1-cp312-cp312-win_arm64.whl", hash = "sha256:f4115102802df98b2b0db3cce5cb9b92572633a1197c77b7553e5203f284a5b3", size = 24547340, upload-time = "2026-02-23T00:19:12.024Z" }, + { url = "https://files.pythonhosted.org/packages/76/27/07ee1b57b65e92645f219b37148a7e7928b82e2b5dbeccecb4dff7c64f0b/scipy-1.17.1-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:5e3c5c011904115f88a39308379c17f91546f77c1667cea98739fe0fccea804c", size = 31590199, upload-time = "2026-02-23T00:19:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ae/db19f8ab842e9b724bf5dbb7db29302a91f1e55bc4d04b1025d6d605a2c5/scipy-1.17.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6fac755ca3d2c3edcb22f479fceaa241704111414831ddd3bc6056e18516892f", size = 28154001, upload-time = "2026-02-23T00:19:22.241Z" }, + { url = "https://files.pythonhosted.org/packages/5b/58/3ce96251560107b381cbd6e8413c483bbb1228a6b919fa8652b0d4090e7f/scipy-1.17.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:7ff200bf9d24f2e4d5dc6ee8c3ac64d739d3a89e2326ba68aaf6c4a2b838fd7d", size = 20325719, upload-time = "2026-02-23T00:19:26.329Z" }, + { url = "https://files.pythonhosted.org/packages/b2/83/15087d945e0e4d48ce2377498abf5ad171ae013232ae31d06f336e64c999/scipy-1.17.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4b400bdc6f79fa02a4d86640310dde87a21fba0c979efff5248908c6f15fad1b", size = 22683595, upload-time = "2026-02-23T00:19:30.304Z" }, + { url = "https://files.pythonhosted.org/packages/b4/e0/e58fbde4a1a594c8be8114eb4aac1a55bcd6587047efc18a61eb1f5c0d30/scipy-1.17.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b64ca7d4aee0102a97f3ba22124052b4bd2152522355073580bf4845e2550b6", size = 32896429, upload-time = "2026-02-23T00:19:35.536Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5f/f17563f28ff03c7b6799c50d01d5d856a1d55f2676f537ca8d28c7f627cd/scipy-1.17.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:581b2264fc0aa555f3f435a5944da7504ea3a065d7029ad60e7c3d1ae09c5464", size = 35203952, upload-time = "2026-02-23T00:19:42.259Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a5/9afd17de24f657fdfe4df9a3f1ea049b39aef7c06000c13db1530d81ccca/scipy-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:beeda3d4ae615106d7094f7e7cef6218392e4465cc95d25f900bebabfded0950", size = 34979063, upload-time = "2026-02-23T00:19:47.547Z" }, + { url = "https://files.pythonhosted.org/packages/8b/13/88b1d2384b424bf7c924f2038c1c409f8d88bb2a8d49d097861dd64a57b2/scipy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6609bc224e9568f65064cfa72edc0f24ee6655b47575954ec6339534b2798369", size = 37598449, upload-time = "2026-02-23T00:19:53.238Z" }, + { url = "https://files.pythonhosted.org/packages/35/e5/d6d0e51fc888f692a35134336866341c08655d92614f492c6860dc45bb2c/scipy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:37425bc9175607b0268f493d79a292c39f9d001a357bebb6b88fdfaff13f6448", size = 36510943, upload-time = "2026-02-23T00:20:50.89Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fd/3be73c564e2a01e690e19cc618811540ba5354c67c8680dce3281123fb79/scipy-1.17.1-cp313-cp313-win_arm64.whl", hash = "sha256:5cf36e801231b6a2059bf354720274b7558746f3b1a4efb43fcf557ccd484a87", size = 24545621, upload-time = "2026-02-23T00:20:55.871Z" }, + { url = "https://files.pythonhosted.org/packages/6f/6b/17787db8b8114933a66f9dcc479a8272e4b4da75fe03b0c282f7b0ade8cd/scipy-1.17.1-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:d59c30000a16d8edc7e64152e30220bfbd724c9bbb08368c054e24c651314f0a", size = 31936708, upload-time = "2026-02-23T00:19:58.694Z" }, + { url = "https://files.pythonhosted.org/packages/38/2e/524405c2b6392765ab1e2b722a41d5da33dc5c7b7278184a8ad29b6cb206/scipy-1.17.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:010f4333c96c9bb1a4516269e33cb5917b08ef2166d5556ca2fd9f082a9e6ea0", size = 28570135, upload-time = "2026-02-23T00:20:03.934Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c3/5bd7199f4ea8556c0c8e39f04ccb014ac37d1468e6cfa6a95c6b3562b76e/scipy-1.17.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:2ceb2d3e01c5f1d83c4189737a42d9cb2fc38a6eeed225e7515eef71ad301dce", size = 20741977, upload-time = "2026-02-23T00:20:07.935Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b8/8ccd9b766ad14c78386599708eb745f6b44f08400a5fd0ade7cf89b6fc93/scipy-1.17.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:844e165636711ef41f80b4103ed234181646b98a53c8f05da12ca5ca289134f6", size = 23029601, upload-time = "2026-02-23T00:20:12.161Z" }, + { url = "https://files.pythonhosted.org/packages/6d/a0/3cb6f4d2fb3e17428ad2880333cac878909ad1a89f678527b5328b93c1d4/scipy-1.17.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:158dd96d2207e21c966063e1635b1063cd7787b627b6f07305315dd73d9c679e", size = 33019667, upload-time = "2026-02-23T00:20:17.208Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c3/2d834a5ac7bf3a0c806ad1508efc02dda3c8c61472a56132d7894c312dea/scipy-1.17.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:74cbb80d93260fe2ffa334efa24cb8f2f0f622a9b9febf8b483c0b865bfb3475", size = 35264159, upload-time = "2026-02-23T00:20:23.087Z" }, + { url = "https://files.pythonhosted.org/packages/4d/77/d3ed4becfdbd217c52062fafe35a72388d1bd82c2d0ba5ca19d6fcc93e11/scipy-1.17.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dbc12c9f3d185f5c737d801da555fb74b3dcfa1a50b66a1a93e09190f41fab50", size = 35102771, upload-time = "2026-02-23T00:20:28.636Z" }, + { url = "https://files.pythonhosted.org/packages/bd/12/d19da97efde68ca1ee5538bb261d5d2c062f0c055575128f11a2730e3ac1/scipy-1.17.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94055a11dfebe37c656e70317e1996dc197e1a15bbcc351bcdd4610e128fe1ca", size = 37665910, upload-time = "2026-02-23T00:20:34.743Z" }, + { url = "https://files.pythonhosted.org/packages/06/1c/1172a88d507a4baaf72c5a09bb6c018fe2ae0ab622e5830b703a46cc9e44/scipy-1.17.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e30bdeaa5deed6bc27b4cc490823cd0347d7dae09119b8803ae576ea0ce52e4c", size = 36562980, upload-time = "2026-02-23T00:20:40.575Z" }, + { url = "https://files.pythonhosted.org/packages/70/b0/eb757336e5a76dfa7911f63252e3b7d1de00935d7705cf772db5b45ec238/scipy-1.17.1-cp313-cp313t-win_arm64.whl", hash = "sha256:a720477885a9d2411f94a93d16f9d89bad0f28ca23c3f8daa521e2dcc3f44d49", size = 24856543, upload-time = "2026-02-23T00:20:45.313Z" }, + { url = "https://files.pythonhosted.org/packages/cf/83/333afb452af6f0fd70414dc04f898647ee1423979ce02efa75c3b0f2c28e/scipy-1.17.1-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:a48a72c77a310327f6a3a920092fa2b8fd03d7deaa60f093038f22d98e096717", size = 31584510, upload-time = "2026-02-23T00:21:01.015Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a6/d05a85fd51daeb2e4ea71d102f15b34fedca8e931af02594193ae4fd25f7/scipy-1.17.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:45abad819184f07240d8a696117a7aacd39787af9e0b719d00285549ed19a1e9", size = 28170131, upload-time = "2026-02-23T00:21:05.888Z" }, + { url = "https://files.pythonhosted.org/packages/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:3fd1fcdab3ea951b610dc4cef356d416d5802991e7e32b5254828d342f7b7e0b", size = 20342032, upload-time = "2026-02-23T00:21:09.904Z" }, + { url = "https://files.pythonhosted.org/packages/c9/35/2c342897c00775d688d8ff3987aced3426858fd89d5a0e26e020b660b301/scipy-1.17.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7bdf2da170b67fdf10bca777614b1c7d96ae3ca5794fd9587dce41eb2966e866", size = 22678766, upload-time = "2026-02-23T00:21:14.313Z" }, + { url = "https://files.pythonhosted.org/packages/ef/f2/7cdb8eb308a1a6ae1e19f945913c82c23c0c442a462a46480ce487fdc0ac/scipy-1.17.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:adb2642e060a6549c343603a3851ba76ef0b74cc8c079a9a58121c7ec9fe2350", size = 32957007, upload-time = "2026-02-23T00:21:19.663Z" }, + { url = "https://files.pythonhosted.org/packages/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eee2cfda04c00a857206a4330f0c5e3e56535494e30ca445eb19ec624ae75118", size = 35221333, upload-time = "2026-02-23T00:21:25.278Z" }, + { url = "https://files.pythonhosted.org/packages/d9/77/5b8509d03b77f093a0d52e606d3c4f79e8b06d1d38c441dacb1e26cacf46/scipy-1.17.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d2650c1fb97e184d12d8ba010493ee7b322864f7d3d00d3f9bb97d9c21de4068", size = 35042066, upload-time = "2026-02-23T00:21:31.358Z" }, + { url = "https://files.pythonhosted.org/packages/f9/df/18f80fb99df40b4070328d5ae5c596f2f00fffb50167e31439e932f29e7d/scipy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:08b900519463543aa604a06bec02461558a6e1cef8fdbb8098f77a48a83c8118", size = 37612763, upload-time = "2026-02-23T00:21:37.247Z" }, + { url = "https://files.pythonhosted.org/packages/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:3877ac408e14da24a6196de0ddcace62092bfc12a83823e92e49e40747e52c19", size = 37290984, upload-time = "2026-02-23T00:22:35.023Z" }, + { url = "https://files.pythonhosted.org/packages/7c/56/fe201e3b0f93d1a8bcf75d3379affd228a63d7e2d80ab45467a74b494947/scipy-1.17.1-cp314-cp314-win_arm64.whl", hash = "sha256:f8885db0bc2bffa59d5c1b72fad7a6a92d3e80e7257f967dd81abb553a90d293", size = 25192877, upload-time = "2026-02-23T00:22:39.798Z" }, + { url = "https://files.pythonhosted.org/packages/96/ad/f8c414e121f82e02d76f310f16db9899c4fcde36710329502a6b2a3c0392/scipy-1.17.1-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:1cc682cea2ae55524432f3cdff9e9a3be743d52a7443d0cba9017c23c87ae2f6", size = 31949750, upload-time = "2026-02-23T00:21:42.289Z" }, + { url = "https://files.pythonhosted.org/packages/7c/b0/c741e8865d61b67c81e255f4f0a832846c064e426636cd7de84e74d209be/scipy-1.17.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:2040ad4d1795a0ae89bfc7e8429677f365d45aa9fd5e4587cf1ea737f927b4a1", size = 28585858, upload-time = "2026-02-23T00:21:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1b/3985219c6177866628fa7c2595bfd23f193ceebbe472c98a08824b9466ff/scipy-1.17.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:131f5aaea57602008f9822e2115029b55d4b5f7c070287699fe45c661d051e39", size = 20757723, upload-time = "2026-02-23T00:21:52.039Z" }, + { url = "https://files.pythonhosted.org/packages/c0/19/2a04aa25050d656d6f7b9e7b685cc83d6957fb101665bfd9369ca6534563/scipy-1.17.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9cdc1a2fcfd5c52cfb3045feb399f7b3ce822abdde3a193a6b9a60b3cb5854ca", size = 23043098, upload-time = "2026-02-23T00:21:56.185Z" }, + { url = "https://files.pythonhosted.org/packages/86/f1/3383beb9b5d0dbddd030335bf8a8b32d4317185efe495374f134d8be6cce/scipy-1.17.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e3dcd57ab780c741fde8dc68619de988b966db759a3c3152e8e9142c26295ad", size = 33030397, upload-time = "2026-02-23T00:22:01.404Z" }, + { url = "https://files.pythonhosted.org/packages/41/68/8f21e8a65a5a03f25a79165ec9d2b28c00e66dc80546cf5eb803aeeff35b/scipy-1.17.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a9956e4d4f4a301ebf6cde39850333a6b6110799d470dbbb1e25326ac447f52a", size = 35281163, upload-time = "2026-02-23T00:22:07.024Z" }, + { url = "https://files.pythonhosted.org/packages/84/8d/c8a5e19479554007a5632ed7529e665c315ae7492b4f946b0deb39870e39/scipy-1.17.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a4328d245944d09fd639771de275701ccadf5f781ba0ff092ad141e017eccda4", size = 35116291, upload-time = "2026-02-23T00:22:12.585Z" }, + { url = "https://files.pythonhosted.org/packages/52/52/e57eceff0e342a1f50e274264ed47497b59e6a4e3118808ee58ddda7b74a/scipy-1.17.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a77cbd07b940d326d39a1d1b37817e2ee4d79cb30e7338f3d0cddffae70fcaa2", size = 37682317, upload-time = "2026-02-23T00:22:18.513Z" }, + { url = "https://files.pythonhosted.org/packages/11/2f/b29eafe4a3fbc3d6de9662b36e028d5f039e72d345e05c250e121a230dd4/scipy-1.17.1-cp314-cp314t-win_amd64.whl", hash = "sha256:eb092099205ef62cd1782b006658db09e2fed75bffcae7cc0d44052d8aa0f484", size = 37345327, upload-time = "2026-02-23T00:22:24.442Z" }, + { url = "https://files.pythonhosted.org/packages/07/39/338d9219c4e87f3e708f18857ecd24d22a0c3094752393319553096b98af/scipy-1.17.1-cp314-cp314t-win_arm64.whl", hash = "sha256:200e1050faffacc162be6a486a984a0497866ec54149a01270adc8a59b7c7d21", size = 25489165, upload-time = "2026-02-23T00:22:29.563Z" }, +] + +[[package]] +name = "send2trash" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/f0/184b4b5f8d00f2a92cf96eec8967a3d550b52cf94362dad1100df9e48d57/send2trash-2.1.0.tar.gz", hash = "sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459", size = 17255, upload-time = "2026-01-14T06:27:36.056Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/78/504fdd027da3b84ff1aecd9f6957e65f35134534ccc6da8628eb71e76d3f/send2trash-2.1.0-py3-none-any.whl", hash = "sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c", size = 17610, upload-time = "2026-01-14T06:27:35.218Z" }, +] + +[[package]] +name = "setuptools" +version = "82.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4f/db/cfac1baf10650ab4d1c111714410d2fbb77ac5a616db26775db562c8fab2/setuptools-82.0.1.tar.gz", hash = "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9", size = 1152316, upload-time = "2026-03-09T12:47:17.221Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl", hash = "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb", size = 1006223, upload-time = "2026-03-09T12:47:15.026Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "soupsieve" +version = "2.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + +[[package]] +name = "terminado" +version = "0.18.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess", marker = "os_name != 'nt'" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701, upload-time = "2024-03-12T14:34:39.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154, upload-time = "2024-03-12T14:34:36.569Z" }, +] + +[[package]] +name = "threadpoolctl" +version = "3.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, +] + +[[package]] +name = "tinycss2" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" }, +] + +[[package]] +name = "tornado" +version = "6.5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/f1/3173dfa4a18db4a9b03e5d55325559dab51ee653763bb8745a75af491286/tornado-6.5.5.tar.gz", hash = "sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9", size = 516006, upload-time = "2026-03-10T21:31:02.067Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa", size = 445983, upload-time = "2026-03-10T21:30:44.28Z" }, + { url = "https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521", size = 444246, upload-time = "2026-03-10T21:30:46.571Z" }, + { url = "https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5", size = 447229, upload-time = "2026-03-10T21:30:48.273Z" }, + { url = "https://files.pythonhosted.org/packages/34/01/74e034a30ef59afb4097ef8659515e96a39d910b712a89af76f5e4e1f93c/tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07", size = 448192, upload-time = "2026-03-10T21:30:51.22Z" }, + { url = "https://files.pythonhosted.org/packages/be/00/fe9e02c5a96429fce1a1d15a517f5d8444f9c412e0bb9eadfbe3b0fc55bf/tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e", size = 448039, upload-time = "2026-03-10T21:30:53.52Z" }, + { url = "https://files.pythonhosted.org/packages/82/9e/656ee4cec0398b1d18d0f1eb6372c41c6b889722641d84948351ae19556d/tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca", size = 447445, upload-time = "2026-03-10T21:30:55.541Z" }, + { url = "https://files.pythonhosted.org/packages/5a/76/4921c00511f88af86a33de770d64141170f1cfd9c00311aea689949e274e/tornado-6.5.5-cp39-abi3-win32.whl", hash = "sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7", size = 448582, upload-time = "2026-03-10T21:30:57.142Z" }, + { url = "https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl", hash = "sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b", size = 448990, upload-time = "2026-03-10T21:30:58.857Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c8/876602cbc96469911f0939f703453c1157b0c826ecb05bdd32e023397d4e/tornado-6.5.5-cp39-abi3-win_arm64.whl", hash = "sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6", size = 448016, upload-time = "2026-03-10T21:31:00.43Z" }, +] + +[[package]] +name = "traitlets" +version = "5.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/22/40f55b26baeab80c2d7b3f1db0682f8954e4617fee7d90ce634022ef05c6/traitlets-5.15.0.tar.gz", hash = "sha256:4fead733f81cf1c4c938e06f8ca4633896833c9d89eff878159457f4d4392971", size = 163197, upload-time = "2026-05-06T08:05:58.016Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/98/a9937a969d018a23badfea0b381f66783649d48e0ea6c41923265c3cbeb3/traitlets-5.15.0-py3-none-any.whl", hash = "sha256:fb36a18867a6803deab09f3c5e0fa81bb7b26a5c9e82501c9933f759166eff40", size = 85877, upload-time = "2026-05-06T08:05:55.853Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/19/1b9b0e29f30c6d35cb345486df41110984ea67ae69dddbc0e8a100999493/tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10", size = 198254, upload-time = "2026-04-24T15:22:08.651Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" }, +] + +[[package]] +name = "uri-template" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678, upload-time = "2023-06-21T01:49:05.374Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140, upload-time = "2023-06-21T01:49:03.467Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/ee/afaf0f85a9a18fe47a67f1e4422ed6cf1fe642f0ae0a2f81166231303c52/wcwidth-0.7.0.tar.gz", hash = "sha256:90e3a7ea092341c44b99562e75d09e4d5160fe7a3974c6fb842a101a95e7eed0", size = 182132, upload-time = "2026-05-02T16:04:12.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/52/e465037f5375f43533d1a80b6923955201596a99142ed524d77b571a1418/wcwidth-0.7.0-py3-none-any.whl", hash = "sha256:5d69154c429a82910e241c738cd0e2976fac8a2dd47a1a805f4afed1c0f136f2", size = 110825, upload-time = "2026-05-02T16:04:11.033Z" }, +] + +[[package]] +name = "webcolors" +version = "25.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/7a/eb316761ec35664ea5174709a68bbd3389de60d4a1ebab8808bfc264ed67/webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf", size = 53491, upload-time = "2025-10-31T07:51:03.977Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d", size = 14905, upload-time = "2025-10-31T07:51:01.778Z" }, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, +] + +[[package]] +name = "websocket-client" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, +]

5?$`8a5!fF(}zX1~Np8Eua%jNf>vF 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∓{9H}dkNd%)Kl9s14m>2!iawz+=Mn%m(?htha(%ceF>0LetIa zC3>_+NtlPSbZYuiW!W8`(DX_THMt<;8KN&b4Z%hNq!GzjE1lFal4*=UYSJEV518e& zj!swtDLHYNbZNG8af&IedE$-TY3vO_pZj5^2Y zv?4jxD-sXvTO7MOH024}fVpfQESW?HLP5+B_dKV#aABL+f)5iUKd71@-sK^Ch(=M& zmAB>9W8?RyKQfW%!f!HImtmzZ>JD3L`TBaBq@j@}ZO`bG$THp@S$LvnO$1kgT{9SV z1^KUBl?<1{L7=UXXRhoRm|n~+BZf!rf6Kx7mlZc}NM0-wxA8gKyAkiXRwPJ~(1d!f zd+6mn51OYuIk?YE=ci>wNYH5VryJ%U4h<8B44~?HgKuRcMo?9xN~EMw#~hze7E<(u z%LuI}RYGGpwt^jFUe|ngesARX4MVEMiu6v@O;zXV<(X(G8RkZmm#dHgaE@~4i~VHF z%u-b?UYuUjFs53SEnu-~9IEb+*y|0(JNyh1NqNB=r^+FIGfrYV`+mg^gP^D`>G!=c zEooUv@*ut4O;{SC6zYwEoYkg0W^A3V+q7S(kWuY$Fixg#B|b*sm@|KI{QJ32;9s=% zF)3Vlv~(TQdO;c1u$qD+90$|jX*^drZ_W~QHu_h`CBBM>)Y@(6dy%M**J#Ia(8_*f zCGxAV1qPYF-QBirThBCR4{U1f5R*EFyj8437vz*LlDlK`)Yw;C?l8-o+nmC>SDEA9 z+>5@-Q(q|xu|9gk4~wE*SK2keMET2D=FnE&gmpM?aAL|{#$~v4^hEGjwp60&YJ@mVq*iJ7ItxeHlThBhe{Mi3| zF7MXNkvK5i-nwnetIV=<(Mpg$Tj1eRZv_&@R6764>dm}V*-kK0B}#S^`PN3Vn$OClA6!!Tt2*>rt{BZCHZP1w}HtV#BN058=2qj-GfpX3*(a8H{ z#IYRSJ`SS~?uiYcLs-tn$ng|J;G5-ntXFf^Khc0BJt-S+^}HZp?$p6PoF!K~q))NZe$qr-U4n3ym?@RKeDVDghn{XBJ-`Vm(?6l5AZ+Znfd%(G>!SWT)@rl%*%uX zZV~ zxTp@aBCZ8$yd0li)biX%voHeep}Q^>i49UH}BYsY*uX z`yg-|tIIs>3vCtpk@`$&DH}-#R;!kpSqE-{bwxBC3SNH!eV7W{A{T!368k zMOM3`C|>eM-eo@S`2!#v*nq`byb^5%);o3U)mc0M#cr-wXsOFIkm@$^XxlXRe|kV?$Luwiw_7$OMjXx%hlAm z`V4NTOlCH#s#BiWSuK$6S`D0l+Ej=~cIl5r6%7?~sNKI%pEGZ5!MrK?ZTc=hyx0WA zt?PLg3{NDcR$jaX$K4T(|7>@@%^WGE)IF=5JhK$cwkt$Q5}VYpO?|2nIr#j4O{>ri p3m5#6P-IMj`fqnBxi0r}Pe)hU=cfl!PLS&!Ryw*rdGFcF{|6FqFjfEn literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/mlp_parity.png b/FESurrogateModelTutorial/reports/figures/mlp_parity.png new file mode 100644 index 0000000000000000000000000000000000000000..cfc8f41f86ebf64bc7450aa37bc762e0796ab087 GIT binary patch literal 39882 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 ABLDyZ literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/mlp_residuals.png b/FESurrogateModelTutorial/reports/figures/mlp_residuals.png new file mode 100644 index 0000000000000000000000000000000000000000..14c29c2a207580d9da9ac5ac7843f463017a46a5 GIT binary patch literal 38616 zcmeFZS5#C@v@Y5N5tSr}1W8H~5m2IpCg&_5IZH-CvNRbKL{ucxga#yMB&P=a0m&e- z$vJ0%rpcV@fA4+vIQ!w=hkM6;x{RUC&|X!wYE{je^9w6nQ(b}hHtlT)1VXH&D60j5 z;Q2!!xH*Ib;9to3R2RXAh`XG=ySB59yO)KlHAKzA{oNa9_c!*IOrF-RZuZVjeB95U zaSK0XvU7KT=O)6#^Y(v#gWK8FmWNG#*Z{P0>z$&38w5f{j{SpUn>GacikDTAmC|{i zvNLltMf=rp%U?d^FQQ(}Y~=)!N1unb2_I|Wn@ry@@Zfrk>*$5Ls$tSEDYdSdIsJ3`Psq^0_w z!ZUpAZ;&gw`J32JL52ShJ_!xx0Im8W&32Gt54&x1X zd4UG_#E%~VxR*d_%=z{b2vw>Z^^moRGzzTnLOX5p}MWTU8%uyr}t-hMMV#K@DEBA!KAo~u?0xn0_SRN}xGQ>?eH=860IXm@d`d^;8wo~eL zIyYag4hx{IrmEleFKrE!+`e;X1$-;c$Qk*nUu5g4{dif1tb#(a=k9QBWaGs_Pjo^8 z`$|UX#@zK)jr-2zD{=~oKL4%JLUwvl&)5e}wZG`7Ai+s^kU+?2t_EY+mA1zK6!W5A z;@bDn&E36{`QgJ~7ezG=qXokLmuS6?44E)GlX~~(J>Z7uU0huHJvK-3m&Tj?e12XI zq)E)xeQOY!^BsQbJd_o_^pVQ+9rm$y2sn(qla-ejsTqFFAne+Jsut&-k&CMzFk3HA+g-*zhN_Ro|De>)geV6ghE z?Ch>+Ru$FA1aSr-rxata8IK&)>Q-rU{Fg686~42L-Z^2rEkSs$VA5i@#wUk8r{30d zm07e}b$p{=rOwaKKNwQsfzMW~^duyk)*K9(mUC$5bf$XEa-3uK5||afB_1}fCOP&V zHeX*g7<*1wyKav^Kcu}rSt9M~?&d9ZK0n@Z9aa-ka&jsW4$D?axIcku3#aHib>JD} zX}++8wYpzVs?=Gu5_oUs=c;O?*WA8+TXg`zP-D}VbTFvE2zP_}U({}Rh#mIwS&!ts zT;z$0isE%$R)h;U#?y)Wj$bgWdkmgqAKH->w|<%AE)rv!c3g-ooUERt$ZzI@LD3>B z%gc$T3U3{EEbs%!Jt zbnEnRK;qopi530D?_?pYe{HodS?^5)m~Dl_)xOKICB6GQr=vTSLj0VZJzFS`N&8&* z${rGf(CEMmG?$KKgfPvcwePl;Ait8q}^4{Go{DJ-an9PbAFiAjg7N4iED#J@vGySX1LEz@sO#o%2!%} z-pg5}Pd2Z9>E9H${wOfe=J7+rtA%f(yWb0jij9Q$6tsLER)vil#rdT|n8@y);6QLq zF}pKR?#NG{z8h9Kz|#g^ED=R+jT9T9PAf=!j^YSRz|ws3+^!0dCHoGz(D zh(aO}BJG%3yGL~Nllei-aYXXYB1I@=hb68pkr@w^iR&dA)uU(TXB`ScYpP}kDTHjl zK(Ex)!CZGzWbCj&jD}I5tP(~Ewf~bIR9AybVitGrC?D!``~puR^?HpM)w0{go))W? zEZB8%de|o>jkGVDu5+`cd1fAX%eCkb6N;u)nfkqngT4v9x#DLKIW4^Q6#KDATQ{4y2G@pTQo46nv*Fdv8fRHDaog z`eU`PuSzGF#9}1lN7BA*nE57|8u15#j9wX1C<~WSbu4Bsz%2MY z*yWHcjG8;oHTkXPAOknsV#W7l<>b1;82#-+!yJ@u?o^Ff6c*~0da|{^#k|WI&1fJe zj6sYLNcIc&_3t#M`q48DUI`O!dZr>@hDC0g!OEsLE;`u}@1_0EHrQis999g7$B@vA zB&OTj^CcH8@>>;Z2P3# z{7vNEurfnt)rRsWafRKEFe-3#SlDQBaWO^0r(1tB98D|Ga&~pT7XdAWeu`mJds3yK zW>1C&i{kzC)kbdGaqU}6%O7yBTrqUx#umEDKP@|pNyq+=EpZ3>SOiCsX_1}?5~#Iq z%tP#cb&$~ff=|w&bSU8Jkg*Oty1pf;5Q4Zw@5&!J>Zwmg3tsWvKvjLJB^h?#86C=q zyT05DP}_@jG$4fP5z{exFW=R+GR0%=DR@=5yjfT(D8bIcl2}eXOD*D_$3ftHDfap| z(VAFWl_RQ~HNn^twyLahVHvlQ_{>5&>VQIIPm`i1HkL)9G-wpBV9H_O2j%#tapTqH zd2&(a8O(PyONpZHe7C`R@Q0jSu%z0T%o|Gr7T*Z`bnVF?gz{Esd`S8|(6-=VgHzqg z{TPUB7-vpyt|;FJ5SYRFuv_DZJruP~CAaRC7}cm_^NnG=>~JG~ra@C)l?t1_&u<#6 zd+wj2ny;*#>eaNgqJ_O2`z^tdtC}pR79A6VWVkv3r%!1Eq(z}i)hx(y3|Notc1(eHb)*~K>?_PTo1To2C#TFt=6#nqRR%;r0Y z+T8M0OkFxTS&B?fCU_4^J*qdvsXpd+aHZnP$NA5l*ZuCWPpAiF7VuW<+|fL}M)2)q zVsB#e#X&?D?}ovTd42Ol!0?prb@nBlBvQLl8ZaPeZZ?wa7&x_qsVt z`MWGDQR+R<*H72|Rqm9iOI*4elv{-pF^W&W$((YaA@wWjxY{ziezNl1Yu9*qDHl!q zK)_*{D5vW854NaNG|FtHddi6t)r7;O`9avX%Zmsi`RNbh+2xxbuq8oCyo%kL|5u-nSlg_vt-D@FLfII7_k*^_f69P|mu=SUe*hx1 zN(ce5?<8t4Q(-0OCc}3PiA$a1ohf$o=4cE^50kAyV)VG&$?w?nsGA!}#+YwPZGwv71`>+B1-%9vVJT9)L14%g_or887(Z zfMMoQe|<$xPOh5rlHs9A|3gtxqkbsH*r3ubYNXW642Irh1$ko(t4e%gx=MnO<5+K@ zAH9gXBJ61WVY1*`-YNI3F*T5#zIG}$tco`CKW)d4i}yZU?ZU1z|1tAYM^p(L^$6PC zjP|{~2$o{0jHHBVK9n?#E0p>D$$SWFhDHyu8OsDk_|))%#CdhR>N>YI;so#L9=C)&B{aknVg64U$085p=* z!$^fXHfE6xZl`~jI@C&Mu!|bEF)iR~V(IU{TQO#xM^___poGx(%sL2!5Zza4w;N@X zZ?I2to&47z;n!e;mq<^AZPPVRPaAt*ov!r_@HFlR^Q~*sW_fInzw|#@xOuu$GuJ(h z0?~Zs5;K>uzHa9YlE_r4v?PA}=nbgvTB_GF$PoKiz%PhfWF{fvaUkwEH~tMhHSoEv zcAhikD8;Th$@SY4EzS%7e9ZAu3*+_N7|I?$Yz-ym!&KM~aJ!kA`JvM41T{dh6W(}vJjE&?Fj|xe{p5Fc^w;4Ud%3iV)nnWCm&6YQ zk4_q^rjs+`u?$ zBCo%qlN+-WN zxkxy!t`wUmXYp-@vm+iKH`*|cW^vaeu7d1E^tf&f=BPd3V|STv3F!Pr&lrw4b_iKSZwsHu{KKN!X@9t~?GfV{a|fzgje&%`56uj46) zW9}%0VtnVkw9gI3|2e+gAJz@h)g1%fi*Pu6Hc9ziwrv&rVNG?1CLEm)~)>YcJv0v<3$tC&O*a>d5_gZxwY${92Iy zQcWLAk;Yy?xY4o)lF#SuLjpc4pD8&%LnZvq+}%nK*Sd#F%_N3pYRrEHKa!h#rLO)h z|3==#jsBD9kuw9pZ zaMv9G$E*fO^Vub?FDl@Ss6ss+ZAa(7i|twso^Q3?XW|Hqw@{^+7h$__TSSyx#C^D_ z5b<)o$CeGRO^GRTa@#0GNe|2xTnsbqwz?+&l@@NfjhF@ruT4O_&u(1@zIT1VjQX8g z$H)}~)Q3e-a11}1n3g{;ixUfWw2(-P><>%YUtOH$Q0*WwvoY8x4Pv-04&XH9D7ZlKR+v}@XUCIa0Ku+7`W?e0T|MeB7c_qQj|2a-x zKmEwU4;bS5q(j2$;^glTh?Z%k0Iq;QeD1i}Ekj~8J4&-e0tlau?VCBQ;gkN4b%=X? z=-t`>7kfdVrqusHVW@_>OaMreJ>03cBf=d~!w`Rzf}4Mz;-Rg8N)!okG|SVcUwTL( zElSeh!u<%fn?uVR&Vt>mAsf;0sXV72Ka$fhaPuYX#IIHrcAeZYQjQQAtviE2Qt*jD zVspZ}-r%#kcd%8>Tz;sSvrKhQSx2_E4%Ja_oQ6V!@mvprQ#9{rA$4-N=CX{ym&86g zn(6Ms^@B0E*7|q9jtc9J1=Wh#!+?!Ny5p`tnh?lE2mo?4^WD|cNcMU=yLj#&arhbY zaOhSu_CMRYY&x%Xf1@9gkpY36+?9diK;o1s>ef@59G*wD2a88=YkUgl-{P8dP5k#8 zG*Ev?pmO$vs6dp8j@8B-m%PGeibUA0t8P*L5sJ_VT!q#y?T zr%|h%hacEjxBeZ+#)T+X|11lu>5oVM^pf>m=1;it^P#40v2ol~$qUE7svFeFtkpcXIRMGHYFF8{!Gv~^gID3y^J zaERC9fXm`Q2w7RYa3Cii2|SX5w0%(ge}*0=O&Xyx4Y=&*mZp1_*d_!yfonoypLgx1EJ5UlTFiHI&`(bKJ>28f)taC4Tm1$>ZErMRn7ldoSpIXrHpelyoi-7qgd>CZ7+d@lgxIAqf8XE86Bx0;%*4obu*WwZ~J7yRVl*$|( z&XqE=$dI{BH@T+wSmLdiRf*iIMqN-J;(|&2Kv*~(WYbg$8+5nJI*zt)$&%qhdpqu$ zq>~V%M;zf~^xPbyKl&WUy;*vQ)<*0!e2A-zKa`kJvys!Vv5|?z#xK2k{vHC^4hHK| zIxyGuX362Y)>VpvZJcOcL11TcMg}X|P+lQa={QYBw8~Z^L@brjF1Sg;=Zc@KD2r&F;TOCT0XK`R5b!@t6{nI->=Q63UFTx|kSsK_O zOv~8x^I^K!3JGp8dvCI757*7%Yt?yjHUWwsvV}5s8fi_t<9Y9Fd2)^~HpGW24y{-E zU$e6gsy$;n6^4fg{wFZ|u*Iz|WHANjB_v+--Aw?L-3#M$?VD~I z+4hYLN)yjLe_40qIZI9VVwMz`E-gsw>o7dA&|M}06UNlj2HcruDG^u zKfe^tjUqj*N06-D`EA-$n@7l(rlIgK$7YSvrc9k92p%gY52#cak#E%(p0D^~1mNP4W4;GYI+d5_1lX4+#ugRw_BB0FM zKBr-Id13baL?ryV7F1A~{B>rdy1VwPN+GqFfs3_{KHimN;#L3AlGiJ{)`vE=Z**tF zPa|PH-JFE$TX>Lt1~;&MWY>+KrpCNtu?SOuvzLoB|-ZMcd>%X;e?-#3FPX-sWh4*>Cb?9mNmU|LwF`T?mZbMiU zmWH~M2(PcZOMC2knti`Ist0}qS<3t zhy2Tf;OU-=O@up5QynveQg!S;acYb3w$hp5T!&iaqF5BpHLg5*zEy3r9XhM7#A2y4{BS`qV;7cy~7I z9Yz6mTyR^^!i;jK>d3m&&OY4f0{u~b5cctJ`MG}ehRLwGs*g}BOD~;KOsO4ta!RAL zZKxWOJDYwg8Raj=IbbFKs)N^!m0RS8F^ZjR{d}PCPIYI~2;GEt+rytx3(;`B^=)Bj z3gY!F#oDEdq>%Z8xOCKTQn@DKT zM>X>UJp9Js?tdhuG~x~q+uraSbNpkGST80h@S`^rW9#C^J2L8{WGpy(7$G= z=d8e?S9ot9zm!{FEwylT+}gJAD5eEBthI9Hm>IrG8-L{AMx_tg4lF`|-q}9-Sm)Ye zN=&J%S~RO<3`B)GG(kQB(u zoZEuWPP=R%l_s~u#fkaMLnDav-Wm9^{&c{2qRtqVTd?85cs}b&gITye;m%}Ie(2$3 z6|}9?7hg0j5dz}cp`qoKsw)KzTXd@4{7=CQ^o{uD$p;Yi`>=~ZvU#=JUYMh8%GB#u z?zM)44Du**Z6AupjeH2MMQ0uXzKB_G8gi}VmOlT*AL_PY?xGdid-C!hPQl`yLYc;e z2X^yS4tc}|k!X)H4H%9Z;Iz3|ep?QYrVKbv`J9L^vJ1_9C18jPxd8MKAr4pvrQ1i_ zukOCVy<*_4KQ#~C7LH#*{X6;Vb777H2su3RVK+(!?px3At~z(3h>~X;j|-IXD_sH# z#GY-DPNYLU>uxNPg|*4ab$^-jgr|=VYZ_vh)KpCAdU|6%Jxit7C`Wv{RnU6gTgO8!5 zMfgwaN$LHmuWaA_xYnjkU#3J*U(rxdT7+^rFcq}#;6Yn+gqlnm%tD*X74N@=J_;Lh zWnmVYyB8;s1m{d9vFYSVCiSK>+z`()nL8A_(O0lPP?QH7Mu4S}csztQnTzZ`ym23b z{{&Zp3Ez%1*#Gf}h3Z*GPUX>d9D3pBlVG)$IS>MxDFgg7ELhD4zaT^|o?Q<}7^ofn z2v_1ywjEFF$crQ6I@fj!egwt>qH#=sf8&tV{n4%5J!06M3fQVFi-0JI8j3uER0B}O zVT9(+j_7mq>Nm8ij7k#E#YSNNF(n}7`~X2Q;HO3|GF+T8Lw#Q1CkHm$e-$Nua&h@F zG%j%EOHS7ii}01~-e_6?A1(D}nL3wR8IOPwNRMzuT61b>UYMO)#C(At7v4HM;$mi7 zY}*<^m0%_-?2$2aJ^eyZ|B~>$=@9;6sXXWp*b09lr&^+lMga-wj2pj-?v4oCtwGQJoTUu$NTHU!~-o1e8k=QQ3h$*vsLr>#rsaVL1<6N7v{+H-Z3^R?l+$ups zB<~-OO`XW7&I{kJKAwiPQIV440{^RXQ@#;?)`yc;S0l2|SKc~92=9S-@u>_(_IZTC zO=-Y%f{~%{(K!A^vG)$XaJGC33!P`|)*WKAtzUI)dUfaI9ZEfA-n^gV8c?V1X_2|s zPw4`h6zT{9&MHcB4jE0thU(ece+Ki@KS?Hkz;$!TRXG63EwPnResH_jzp|yFA8+Jx z|Hl15bHLwz_B9VY%bp%_j8f&R-w!XvKu$D6Ds!yc7;(Hm8@TRKYjahQekSg(dza} zc07EGj**_Ds-QjbQoqaN$S;DY41&)GR$^NU*q7|0*xQuqdk?xKjEB9WBvwbRCG8&VOxbYfa97XYFV2GZ07K zY?U+8OFv-9kg~||7UvaHH5}y-j~(-i4I(JWH}E!HMT@zp5}zFz8>VE!HEPb>>8Vg51O6^8TwT&=$HKN9_s+hrWLv z{Q@=A2r1Ws1>3sM=4bVxawp61(iK@ryRXEf3(4%EP7aW~1}={EVXnnY=Fj-CB3{~I z9%mI}b`!|rkL6o-@kKMqY(k9{swFRwK^uNYHYe<008jCOs^J9glOGhF@`b5&?pMB$ zjJy|p7k{f@m6+U28+ACLgp2A9&KphUeyfF%qEuSQW=_3vNJqR!VGmwHwE$+8puCIr z-Tjo>UD#W6N^heS>6Ct#xw>b5=n%}P%GN!=;oI^urJ_@iOf`M?chvniF&goE9BwCT zT}c(Um|lrnzAj65_^dIWSKhk7E0tA4T>SHugV2{Jd{)LU9rX~|$!c(wJT)F))8&++R0w9$Wh$WSMRS68>)?Rr4ZrQ9oP#m9aE|7x45Vf((>W1QmC@= z)%i$q+dG*ub~{7T{LV%T4;D8U-4pvS+#FETELhweaOB#nz3|uZ{|9nz5iB&bdeFm@ zAmBLG3CKZCfSYFn(vF8M&;6CY{$ng$=zGw`&h~61T@Awr&^jyvXAR({A*2t+vIDjX zx5WZP=mUE$iIgbLaF>_lOVO3T6NHmzZEmpoJSIBBuv13n@qV3H zXnLOLOs7z{7$~&%;w~GhI~YZhZ=9+}^T2QzVS?)_m-7uLqV26N;7VGcf+&B@zA3>iUAou_v!oWLOY+t^iR=&ArAS3T_+O>Vj;mowv z<14pw%ISRBer?S}X|KcAAKQ@kip$VaRd9%+RiZduBVa6D(}!9>CI8i$rVr7KncGa8 zK3~{NnPQWUa^Kr65@uC;{xhC!jn&e^&)J8P9P^;jv=iLdW{6gtAZ4B#=@ z*vs@uj+4LUKH6)IyD|Y)m(bCk*0s3F#$2`s$?T`EUj>9P-b1iE*%-pN=jOhV@4R?t znH}UJ#D=bQ3@X@P#XE^UqN%$PO-BFFmR~KtI+sPc$cQwqd6rrE+=z1vx>&ia817-! zwYy{xO?}mD7$WCIZuF)$t90+K+^U>zL{x3(v+(YLnDJWN2_La3d^3Xp8?Ql0?uutd zLv9*GMgm>-4s2BCQ%^ek;y+!8DShdT8z~YCj|h(~oA&MM7k|E2Zfg7?C5fC}D0NEF zq2r#P#%Oa_{@mNx-Xk4~b$f`z&RnmId&=Xl7MG*ycfFZ;fjqe~G6<{@z`YHup)d2i5~WpBhx~$Q&HpQQc`z_(wK+@lm#3kD;qe!`aYo z><^hpyanhZeF+7f-##DC=V;TIFEGMCrs*C!fb-x?sdd_?+_L@lp)ab$q-Pp6|0|@g zen9-ZsAEmy@<{ve;`>9Hlpc2zlbk8ozp61`SJ!g4iS9VgzVal%#lPoH74;I_Dl)9< zUib>MM6ky8wzd~Q4%ge%h(3a-6Qx5T4@{zrdKjn@&Y_D50!H+B45#C{ zZgw6EW}j1KP(cBQr%=oG(4B9|W@&r18`%T&C~={wyOhafI(v70zn#og&AWZjIa~XL z)tnA&tWcKAK#QGCr<-ZY_2(d)HDXue2@=(R(Tz9|$#%OnO^_pFtE&}6Y2MVvF&b1W z2eGXivzW#wsfT)SfCg~iF#T3krt_P_P9u|TaUvm!8FsSi@^UqXC$Rf2Xxt?@K4m}4 zq`?!*sHJghD=RDibn-L1x;tWFC89GLS86f^a*U_dq|Tv32JUtr&yROymb-tna!z9w z#8pd+9@6eko%71J(dy1OkzyvXY^753jjd)WbiM zSG(u?{9+9(XXk5R))8mY*Cg1Mw#)g?y!4}*?`+*+$N0q_v&NdtF}s^!=5Eb0OP@o3 z*k}>gy`A5XTjh*jgGy^GRc9r!;dJlLH28{y?c|f>$G_q~w6pQoubX53cAp_?#$dLY zz=K7>Dq%`EYvo*U?eCh&M7g^e$h8;0XK7nn4g58ZY5Z;UfW*27vEBIyedCnQ1vicP ziak+6p_WwU_*J6kxf0<}Zz|yBDmenotx@jTZu=r$yKhz}J?9J=*YVy-rQ^s^j`qolM|*c+DU_n$I!Oz??j=)gTsd#Yhu9y? zZ%bHd7-m@APkGFlK_l;>Zf*#xZ&Uchulg6u{`+Exu=WKs)n#*=kgS*QqOu!zSn5Hz# zRWqn39Bos;wFT|wR%41a_FD-eVY`c#ua`$)U2@&- z`@)OMNQK(#;u}3avd{d!{TW!x_Lz=kweqd2o#nim6xMfU$S%%w zMl>Ct)fKLL{1I}&1StBx8qAVAV>2B@EjX5b$Q5$ga?WgA`+@Vl6zUXriP_;;h?tpU z7Q2+8C)&F^Teju%L1-^>wn^a#NT^}ej*BP^;pNo!5KH@X_fVBQG2GYV>yH~_*S(0z zET=(8CzWnFJkw=V?xv9g7l6ua$e>ZLbeac71D}aWs|pT=Q&mNmj&1X?KHxW6zsA)p zrl95qx-+2(nZ5eP5W0Q}@9nA7^2>J!t7Tb5fy;N-wtdY@GsJ(LeP~$5zVHul>@}Vm z-D$&oGQXgEX$rC-`vJIN^&5D{S}~UYX9UTC0TNbqy4rF%C9N^F&I2b1NSbgvJy;n6 zLXbyOK(40^r)1!b5$^m7Y0hI5mB ziht?F18F~W#<++6F6(qIPL#qmyL(TR0&)0nepm=nP`dKfsrm@zE-WXQE3f$HX*3tq@CoAol zz2^M9qWngINUNlN^9kR#i=1SqC%pI8fwcIUl2%F6+2$jh41s|^h6;G{5&fsh;CQdJ z8?E}q916@$ifL2+}7Xf6I=&XV`7JYCFJsJQ3tyB?kqyNk1qMke=s zxMKuACn3HT5|L8iUQf`cHTNzE&uf(z=p4$udTO*zw0gB|_jG7s?W}_GV&k38Obv<9 z=xh7H)$n7MO)AF{WF)}uvTb}T0YfM3{juE1Ea{?pDQ_Zy#JS3@)C%U=bWwg8_ODVLfeRsSBgM^LGN8cJ=@Lr>(3E6_xjd+p6yo@2{r zRi>OSBmNiLW5vnv_xUoy9&-rt&M!24@=Yg;cVejJYlK0)*7qE%*5V62!;0?(X)1w? zir0RKg@S+c)b#zrN48HOTPlHX7bv~vH^(Py6!T+px%?jcA9@BPLpMGo=-C&Y8We-f z&Z|RNj9xD6i`5F^1b3!)o6p3X9l^u#Dy8Jda|0dyL}7_+HzM?S`moUoI>}YrnHx-%3K}uOjus+IVFdgPvIR z2&cPKs!>J6sQ7&5%sghm&FtfkJ2R4S7HSpo=zOVkoNJRzDwx^tWEraS>-xk9D-@jn zBkb?huWub%=yRr}vhhy&QmfGCQn9XbiKBeCwi8u|=|Lgk+I?^23XDtmsbMsil0XvNn_;sD2>>r*kSwG$l4^e2ulV&x>(*Kejohw=h7^Uv~+ z4v?(YQIoY^4!@!v0dogXbi=9&xG+b~oO2-eLeLBv7>*WmbKH8#MpzLnzC$^3SqGF7 z;z#;PICWykNL})Ta{WvbbVU8$82wX^{&dIcmuDuLlvvqC%X>b$ZrbjwIrjwq*jo_X z@Hj3VA7o{E!*TaU=f_NV-Kr_$mTU2;SNjHWsv9BNU$R4cxyJ>$+~-)|lZa5u_SY)9 zb@Gqn2<=VZ z)`c0`xVp%pQ0@A$CnF5f7;`ngFZYE#Z|%_=PHAos5?|(L35Rq;ryjdixRe6|Su&6V zEV>#QxTc^3D{c^+>*!BL%I&?@1jCP$+IdoNk_^<~y^RTPw(lctT(pB5NbxnqsJ5KK z2bJOvc1k^6m=~mfUKvct;{*T_AP}NGc9WdbUeW-xC*u5BXzS2Ztqp?jQ~l@jZf50d z$8QmZQrMSmD1vK>#8%NXsC5KgG3(^vo_CdZNNhBg&t_Yr7&V}`bLjBN-~PWEWnv(a zlhhI)QO2KF8^~z77Uy3hjVb2itZ9KC$>E7}(GO<7BtFGtzXfcnr2q80Phbbz0nC`} zQG3i^iT}EcwAn+=%b;p2(YM|=66|;zn~SOa>rNOnFW#5XOLC4UYnYbEo${Nl1C+M}vzSm~b8%JOp} ztzJWrK`|krWLJ6LRvU0r->s=Hnt#!&W*E{J*j$DT<$HeMFO1V1<-sAO1@}UxEOX?+ zKWM_|p8(WkYDg&!e(I4m4`ihC`Y$op2jC$DKW?3m51~1z5sFu|e3Rvtmvn4cS+ek5 z+o7#%{m}9>o@5`liX7)dG^J={_vh4(6sfe+4-1p0>(8!*giM@)&}FF3rOS=>Zi;f+ zG-N)@mfD?XtoX>K@55tZK!O5}>xzg>gGg%l94}wE+-WWxL}FolO%cw!GBL65!#@-9 zg;Qe#Nb_?fP^yWMfg6{ULpGTwFJB8cRp|f0ti5)O0xY72QQf+r?EFo9xlpMvI-sEb z8`Js_z@J*|&vhMsD};eE-5@QBh% z5PuDXP$wwm6At8wN>HR3;dy6XW6 ze(NG|9;{_ZT)q>UdIHFqE{dL~=I&J*zlNGLH+E_=)KYKW!dDFawaI3o(sb`$-_JL8 zsj2@+cZ4%YP|VB4>bt4dpiJ*T;xwAu$BMlE4~(j{5C^~V?hI}CR^USn2^37*Y@99s z6O@Z5V;}!10T%wUV)5!zNRRXoJ|!$5f%;35SyAhpA&Tbyw9CpV8pp1+L?*osyk4&v zA8wj@?DNgK>+H2fe^EWq7Lt7Wrx&6boslaP%id(V*GrYIOxu^=J{{)%R=dRXe$@&KcF@(_5f&>nP^N6W-O^MflAHw9 zt5`qa5)3rQ>by0Gb{_wInH_M1TJwOK%;_bQ+9dM)R_@U(>G5!niHn4=WA_d|4MB1a zi{j4ab1i0d6_I7i2P6ejb5TdeF_bz!3?lrB1?4E5@w)yTn}N}%^(6)#Xrs56My!S0 zfs&qA_8!)oX7$R*HtIvx3d(p8h{k}7qC}6u5yK$VwXWQ+>Hp}&txq8^CL#kN`Q3{8 z%h%g6KH>&%#f=>z)0=Niq$m z?@o_Zt;DP}tQ^i^L?mpDCw~SJZ5lTlL;d258l?~0-IZv%xy~l!nx7VK`{G-Xb3FjJ zB}+q4rJ(7xd^&gu}?%Vc*~RSk~<(F_<^V6)&=Cj z5g`Nc;V2K>B1{!YW(|;0(=~x)6aliE@9goye)x9k?k!XP_2HE`cw~zQi6C6IM;`0E zXe_QUkiK%;GI~?KiA%V`lT-QvX%SA-jsD5)oI>u*3)hq9xQP-T$4&u|fkNIJ*lJg- zvFSx{A2dodwG#xIkEGl9hMy9;zqhqUiE;7X6m2|MGZ&>Jp)lTbDcTSak$p9{7V?we zA(n479hn#reiWU`b{=Wl69lwDx+ae5O4j}n#1PM3&Dka?%j_nFGdGgs96WnDyzzge z`L+XA%V**kS`h!zrJ#4WNw4N)+;)Y?kEdv(H;^*NP}l3eU-8PxA;_+rTd%S1k^SJS zCGp*h`0^Fa&>}JYc@&si$ZX%QF@_h!zn^f%JrQ z+q}r_UvWzfDem!uM8=CuDwl>9~a z-@pH-RM}tozuWnL%|uRh5H$DC$2-{p*H_UgDNjME9s^*f9;{1x_l}6q@f%Q6Mq-8k zM!^2J0vtw|+Ff9`u?7}pERC73SBe0jyAm+B^ezE2cHH|fz)_>Dudg3o1FC_z^9!tp zW?UodLmAe~{pl`qR#}-Q472+-xCHpFb%C;+6)-ZQy?j;l$YI*%H-iLqr5_^Zc zR?^ba(rS0Qj`!WXB*pw!deQ36GeC0j2j!M{jTzX&=bd}vxekC$DLHx9u{)N7l|f@* zI3_ELC9VGf=rs`eQ5blBKBR+dI`eZ8Pk?op4MN9j^~smCZE(?x>N`_y$e9yA$GbPv%1z5!|sD@woUWX1y-Ns&<9TM2>h^~ z8dp%kBr&O@T+qPwm}n}AO4lH!ekS?*3(aePf8YS`xunI;I8zp$gyZZCa7}-P<_77# zc~jJzETjRv^_-0oj`05LLtWr8>b(To{l;1BOBWzww=-ZUazutlYnMx>;!UeP-_^c3%;4J)BrdKp=K6gvG^Ymqc_S z3Gwl(=qu&Pgwpe2?_kg^KU}c zX`jK8ST@yt$OXPvvTZ&pGcdDadjDTerT=ZGO449?^ytwMt_1NXew7@aN-DLjqZ{Q| z_bQg4)z;ge@tPCxIGwg9P4n5$3Ae*y55OCRoc3NzHNE+70NLiT!)q=!s!1Zh-PGCJ z%a1Y4oAH3>3VYGe(5%ivmvY$0u8J;w7W=Mdz1Qfm9!a&mbhZflu_E}%;$FaY!!!Uh zR_otPRrei@$7N@^m+5LSt>6UT*`f5ctC*K<_;1V2VcO@T;~QwYW=c+gq7bW@9 zt{cepdjS)T%k|g+n_5z=H}}^ELV_6ZIs^}b_f5Obz*_6tCxBAa(TVK^*e=oG(JS!2 z1%Bt*>5E3MJ=3%rtijJ*L+ZiFtJqiE7QlMbj_B#>i5V@_OO7Tn3@d$#eH#HmKu-b> z&+$cns%W3FF!7lfnj7n=#=c`AasCLnKsa^FW~gX=3!-PJwem{+Rico!E8S5lMREB|p{ zQa&qLC@CX1)<<@DT}kv07F3}}0;AlEHT?Q=^6vF_ntI?_3*H#@XaKzHzec~{Qmpq* zS2w<^Z31}bA59s1uf*lN35mBl0aiCL0)JYoSzxZ|?*NXNsGE$we~2E8E)+~QA8lx}>^A^5y)We#ctOUi z``pHM4moxM)&mHr^>Swvo0O^?-xc;rl_fk2`$mkf{CG`MtL`TLeKm$G#SA*J|FQJ$ zTwntlkgHj>}#<8{$@bmwF{y&@tW2;wbkooY|h3~H#zV$2?hp|F)B@5bRI}Q4@ zvSdP7Zr!=F^aC6D#hLbHT7bS-4RK|Y`9?gE+kWCS+D!j()WQO<+k}(7X+zSN=CbU{ zJZ)rw1_ii)kd_E7+j7ItYv95Jlqa&D3|+Ao!P21m6Z%g(3iu z*|s$%)Hb%Lv{Y2tX{EnpElE_ah0-N((HXX5EqcD9UeHF3Z>)s)dvo9rQR4Q(n}$V(X( zODtV2+Yw5c#g%McHM>7ebO%ROOtN0_CwB)Iyh8E-8?L6JKft$ueP8^zW^s3c>E1o& z&nC!~dT@0t$^LZ}qcr4->_S4y2#*}ZXaIdq)gr^m{>Cb}uSlIa!=IdGKUV};c<{zY zY!aWUrR*QUu~Pbc!-Z9BAC3p;3VlyQ{F$0P@V2=F(DH_uM6J6zLnXyL`z1>Cu54q%|rAJd1U<304Co8)+$(^V24|TUWXj9XIR;gm|wOP@;`651O#z3_(?cstt_bl4BFA3P=07p z2)z}TO5&ckMvyOSA(&|drBC+jSAgzTl9lxY-A(AOc=Xf&+zt3842P*)14h-` zNB=&#k%k&pIXrZ7@FV9?_O~n;?-WCg+r4_W=7p5|3v|#&!6PfcS+=X8d-&qtL||HT zpH?>p`Es4&qm+_*k|sa-u^xZD-mY7kj(qOY8!AzMzj^b9*Q8anu&gY0cp*kx7}QX7 z133Bkli=LJaoQp*^Rc&vP2@_+Y+&6hPjdBM@Xo(){sfRksc9KQUNZ{~CbZY6Cu^cT z;15l38&aLC<@zQn@R!ks)>tP(2aYu|AH6v)G`_j!G?Oah&7Bu$QWN3kBavc1XIWhw zA*HF-Gh8({l-)Mo)svBhMWeu--p@;6&GJu9ntv?VdVsR=t|z@k`L{6V$m(!3)ojB# z%z7$gyb?{GoR%X;Yy0yjtLOQrg&pRPj|>qkTkVv$VSD&H73JGOo5pL=)Ps6mx+RE1 zyYj0=cST46rLXRlyA!KTL_s`4VR8O8$LsNrY=kfBQ(uiAZq-8yoZm?#rY2_?|$&W$X3yt zuVd8H>%xr^#e;0usVGKiW@kxNeC~}&DB~SlcFKi$FG2F>+rE7b%0Qy%AhMim$$1sI z;I-#Z38SCFj=SM*{3(xkKu^fB`T_hX5hJ))3!vz zyeZ;~qrj2XqQZ?_sqs`sVkP-k??{Cm`5-_@{KwOnxsJbdHon*kgE*NoGxhPdPH zT2gLswA;*ddJ_YWvd*o7#vTxWUtrt0vs5@%!+t_hq3B&eV7a>0M{S2Jm`*vf-%IU{ zirytCsAQbh!%xie)S`4Ihk^r+K{7eKYyYc6g#ZMx;q^=IP)%}U_a zXc0T8?Q{25GL-OIT|BylWo>WNk1kV!Iv!fb`&B&r%NlU6IF*%^M_VZ6Qs~${ygoLV zK2(It(B!^$?~|(c?~l$PfAW9Vj%>>~-aE~fbhu0-Gw(3nv+S!Y)uPsXiWC+!MGfg` zmqb3&(u5}iBMRvAcp}NFtSPQewI+$-$};Q<4)@)1lh%&pbVtQ2<;p5na;^l$Y~50A z;rUT7RpY&H7m&>9-Z@)Z5xFQdHauzm{^~7kZFXaiNo~jevQQl^9F5_V^Y(=T?z7_B!AM?>OB&aB1L{@rW9-?l&#~p^Y6Eep%CHpJ;&??y|GblpGv0VO`w46B%4xp;TBl4$ z=eTot$^3x~#GSX>>TZ?qkd@!?;x97Yp~L?Ab=MLF@E7MF=d6p+qN!PRIyz)BUtD^y zf=Ad}4%x!EzgP`Yb1sXd1|7fS>`)n{W2s8-_Qh`&^!TiLntpqozS3DvcKeZk~e z*^UjHlxKsK%(YTBZWJzoR*&wM1Ues{XJiiPO_pWMzn8BsF6H4DbEKX8?Q#I&*+s@` zHb$~;)$bbCcMaT~rbeafwNar3%i-PRjV-P})9M}XVa|fc+Ibn#A@?y$s>?a2lGA+w zsP={U*RKyK_-8`fc>Kh@!pYn%@e%^6E;?Plw#aF=hJWyzFo!akE++`kl!V^-aLCbK z+%-4!-T(OMmv8%92M_!uk7_q@bC6iPK9oPgc7aFzOn^97V=zs2?W&XX!v5}Y8*)*m zRbcKryvRK)awz7CF}@+Gc!h>B{mgE-qQXF!>h5`DEGZw+;e* zqw3St-bTxI+lO+73fy*9#cRt@zrcTl66EIgNo_L&!%ldMJtgi0@#|=X&ahRx5&x$kY(%O|bnMI);J^Mie&6ymAb`v9+guyx z+%WkyI!E1!nlw8pDJl6&m%9DGfJ?uBi@06NJbdH2UOrHd&74%(0z;cWuMH=s%}cer z(ZqC%H3tW(50is1bB*sDiBWVb;&bBQl#?jr<3#&d)7Q|o#J`*_F^6lvKN_+5hz(&4 z=QGYZ+S8<4SUrz(u}d*0oSl`xvv|NOmf%@aZPj9x#jOTg_QK7^lPDm5ciqN=tI_|< zN0AE>*Y>jg1%_vjm;|Je{>1;dbKBQHO;@w1Rji6t7a@)LsL!;kT`wQCKUx>aAIY&4 zEuc8ZC*GpCVYbmT5+^@h6rYhUf zQR?hjFIX^2!Aq_aQGt7E0Wu0B4JEj3rA{FDh<}@>xb~q!Xwo{w)%O-#g{@ftH>GBx z{*|iI;1~@Ok?;&`VP|6tEwM=SI0hz#HqbA5PXyi_J5N43Aoc`m1TT2h6`~|D+)%FP z+5xww&gz9g>#i;CulRX+<+)SZ7sF@qpz@jJYnk^D#~qaLo0YS5%LCa54GAMduaZq4 z#*h34H3eUUZ2|*#v9r&Zw~`C&e^s?aVvT%aeW5#6Xe2VEo}beZcZq3;yrK)U(A9^f zj2kyTqcbgdvO{MEPAjsKhpb1n7+&kU1_<(>n}Z>r{v9zceE=Wp66^qIn4#A2yY(7I zOI4vKR#6WTpe)robWtR|13d059@JO+`92_TeXi$r8|bfhK1XFuHW@zk_1ycnP->lDg(3QyRCbkoS%SKSCU#B zZ7c2H;isPGYbAKS;Wg6efOicImwa$UXzA)I-E^$u<$T8JJSnLIW2h~<{yTuMOd1fB zm+r8>n8UlP;DmQ&VbicWy@3ButA}4jh%W%k{T7{r-iJ$0A88;7Xx z7lcxx`v$VU+d=e(+RGgN24U{G;Yje_xxR{!V-Mz$ zR@KTKko{6j3y7w@+paxXRaYM4E>GxheN`TAF}v7Dpd=yj1vdmrYHu_|WRD|yY^A6V zWsIGTTat|c;L*eoaqPm+qIz+EBHw>p-Gvv)aq^2Lrc}%b>IL7_BZFyu+Rl7!*6z?%sYuUMv0 zO8JddYKUomg|(eGfYfp|#?n}WWi8|?kE({@pbU;hycu=;HsuH-6i#`2`1Z+)iKr)M zT#UJN<-YT*S%Ng5-ev7gLa67w^S`PVC*879rV%!g>GiH2E=rJyPBuX$1VH0|$2F5$An8;Z#ePyDO(C|8xua-SEwxm@874&azh+aB_*)A7O^A(- zxlxl&NiT`PTK^cM>dF7$A$_E)=;&`fVa27To;dG{fDJiob57jfe6AjbYB|eRZGNWx zG0lQc>^Jb{_uoiIJ>U~MO3Zxoc}nvbHLrKAUO*5g=A#Px6>Pa}fuz{15@?Uri&7%D zWpYE8XOp$hei_gE(_X>>rrUox?xW$t(4gQ`a(*+368(6EFdpB#y%4bsu#bCkoT3m zMel(8!*h7ploUp1-can-RD>2Qr3LDQ(w^5+)AsswD-(tsedR^<`Q%sV{FXYX#D^r( z{^wTIi65qZsqReE`fo;v8yHZwvt3unCfNQ$(WYIH0A74LkDyA-C>R9^RT`;N2Qjn* zN>K!Snscs#{M}pbKTl^OiqQOl5!M5W(Z{k%1r+xpI9QSxFayK$Ko{q%IM(Q&SyfxS zb}@0ulYgZmKm}^{QfP>gTWwGF*Ga!0pwXp9Ct5x;Ei&Ak?U=o#sHd0sI-|%gz=5pK z8f4QONiafXByfKwBs^?vN6{z?aCK!CVuP!x7jh+^qeEUzNruHR82nq#wVZYb;eV$* zIyzeN#fMM#A<)@XJQ=SGY@F6@^YZZU_{)by=ktu524rm7pFcb>%V)77%@%_3m09qw zud#OcOBUF2T$(){$`IMNWguw!`K=xDhwUA|UPVr784^a_JGnS3L;lP^y`Ma}eBWjP zK9n3O)vJSI!&qXhZxLcYF|+furzJ?YvX@ANW!k}zn`^|{J~oj`9uwUn*6GwHa9f#$ z%?oy!>DNYiX0M~&v0*DSMo)M5opAqht%*{UAw4bF;CW#Cw#>|n3}x&@m(UX}rs*#~ zGEjO4q`f-7P#NSzcT`qZk_^i|ueugJu-)h?dborzt6i;}#3AS#Jmz#y=NC^_>Bf7y^0CGOK32cr>|n{coK7a}5lo^~Jg; zCh`;f;>=fZD{LaZ2by@!9oWrre`M?GIqFNqOFL%Ji9HSXQ5t+&Ox7Thp{Ls%rjI~# z)@kB6=eHWH&>vTSc+0XDP;u22^5qh2&?&3m-;4*aaz*a@_Z_4wMNFf&Ini3O)9Lwg z`leQM1Ifj}KZxO7yixO^z5Dl*4diQW?^{XWd%E=>ZU-R;eZSNu@M#KKV3I^r>MF62 zA|Xe6$VUS;@7s8tbbi}rR?KBaxZeO$k7m(+wtbJyy!kKT9F!Scm#mydfUrf!QyFeI zoWU~a0P?lll0!TD+t;`bD%DRLs^r*5KT4G?)B5Y{@stVno%hM~uy^)YnF!g##ekkW z0BJl$CM&I@^HP~gl)TGXZ%RVbd8zVml};uqH3GxBzoX!ZktAOse~19x#4FA?l)WmG>ztrOqZ@ZrWn z^}1Mf!-t8sMJstc3dNNV(#qk zmgE<1x&Jb~Y4hfb=EQ@Nj!xq0_wwn#-2+oASnjZjk=p|qy9_`vNLFRjfWQG_dRxvo zirjJ(PpcT{77tOQ<@F@p{F7}%l2mxabv(OyJE1;>6>A|92;)2Xgw+5KW|;)JHCo@p zh3!1b6*h7n+_|&ZN8CP*$=<`m@jL^& zgY4LlmwF=8^I;WtUMpk|Q%AAD+<&kwEqx+ij2%~ES_#+LQy_@9Ptc&H*U3-T%#$jU zB0;No2#o_10Lb}=`d*!#T9IU^#P>+Sb`+UMm)b(DlBQ2cBw{G-p&$ zW0W5(3=n(L+saVjvWN#AvwlmS$oi(EywSRU78twW13icHFgwVJhk7p1NV*!^)wNjA zr1d)QBLn*LOU3(~SO1gW;=Eiq<;3yh_cYoCZw_BZlzk=FtYEcqV#@b z*lIgBxPq4W_N47Uc<@a_8X-kw!R_`lj}5EJZy$wuOv>H~TWP-C`?&5K=d0c447ak~ ztkC$={`3yRz-Bu=zHgDIO*GGyj}YALLgG<~;>@mYJ^zOpM26CoejtZ?zDd(0(5DR`L6bLn;PCAUd`e`X&s+qXUR zgKgQ_Z8T<*r0L4WoFVKYfn(wru)yadM0rU`rB|?Ox#2WpjRYa@tzq@c$EgFb+m+u? zOvrAIC$iS3A18Xqy7*Z5eeuV;!sL9+c`yn8y+Ro=ReQ z4(oen;Tf*uFeg0*-ol{&H}9uU*--Afod+?mnyF57ygR8 zT?PU9%+t**flYwW2=QXq?%hh=O_vJQrKK0{$g(93x}WGJ^NE zM@nX3_-??p;sLa5+ZKEtf;RK&l>CC>9tRe+Lxx^5`gLwfhEQ>^KM4b}2g7%i=7=(h zfaYX2hR~Nsd>yIOKzG`XH)1+;UC(Cz2RCsBdfu7+2-#~5 zr{GhqhB-m0XrLOtp@u$x4mWX73bk>NR3T|}cW@A{m+Q&MetO22U+NHIOxKFHhV^IZ zzq1L&ALtTzZu>9ywA#auiMno+81&br!Y(sMj?W~pKZl&yWhJ4)8@4NaW zb+tQ63sX)HS0 z)wlF;l!_ZY&(u>1=XoMF@_}KL@F~*n3}wy5Mix`g^4(9HYSL%J0&IFFddVQ0KbrUH0>) zP1^Tw^d6AY)L;1k$Gu+=aP&T>1R90<(VauX(J^K#5l=ZM)sUb02!^w>V2gH6QD$(_ z9S=EU54`IkXzDKL_S;v_+7t7hl?(GyOXOthLLVq6 zM$98H6ld}T#D(XI3S4R9}cyrp3P9oVO^bXQailnF?g?)bkNQ0!04!Qv+ z!nP+|z-KbDk?b<6zC7a7>M{5FyrFm?y(1Yul5anW`**tC3YPiBs4zQm^mu|M<$Kkq ziP8uX&=w)H7gFmLDlf#5x9VpHRoJ3Th+2TtqGw`O*dt!F+&Yw<(XJM4f$xZt$*=w2 z>F6sq{n6q3zpv!x{n_#S-?|?=w$Z$PW~YXDK#V2W7n#XGI+)^`1>h?bVo(Ye0?6~K(sU-G=t%O0lisTck$V?Unq`b#um&=U6Y&l z?zsM=8YF-NN*Wn7a5@NlhP78n2E>3-KWd{1+Z1;-+kvD`Vb{O%+4dbQ=&yY4MELdS z19Ol-gq-YTp#7xs4B!BopZo3oAe8CvQvtQNKKp-rlARz)MJv`UQ|&qY2jz{igQn1@cY}st7!G zV7u%R5Kx57yJPii3>_K2^n;6b+xFA1j2*s)v2GAJ$lOeE^dMsrl`Q_~p)Ap<{|7&k5%e+Uv5rv(3e?w&)HNp6!uyuEc)5HCSEh%rvya0~k zh-mc34wsiR7^Vg$3nCO#Z_MB%4+E0Q;kNqUb)+J)e*5h=Gm~vk#Tkb5Ru)3;h-V)NUF&vs6pzgJf&+1D?Z4pY!xJQ4JQPb|m8@e*#sVGqs@+{u5>)Fne zfc{4_iQ0Piq9=+PlMRU}!hJCbCG)v(6DdNB*o{ujx7~3WqYvB4jucCJ)GZAC768^$KQBf=&|P2l@=5nm;&+BJIWNR=UL7W*(>oa!d87rOPj1oBv~Pf zTJY7SH^=}Cg2VGFE%uLMO3VweM)T?_JEP##A-@UE5`>g+^>**woXoi%B({62C)@;*jrA=B#DJZh{RCFaZlDJ4WJrwmV9Y&UPzVBa zI?QFopR+nlU$F*NEFjY=R#}t=cqXbl{T&x8cr&HGKWvcn!byGDv#Dl#BH$Dbk?^&0 zwW+s(=0tiJl6)eE73t+4Tr3*lo#C`Tk1vPK77@!Bpi@QEuUr}#DGl++v!D5yZ98NG zV2Bj1vZ1~|X!q8lKz|h4MbZyY zZ0;w@VP=;o@s&$iqg^zmEEd*ZA}%3=kpT?b+zBG| zO(nBDYL}^MeazyA8dza;)lcmE*jifpzGx=1xTWhZ7}w!!pjqSIvAapFZoBSbA1MSq z^AnD}EB}x<+uHkUwmS@$Fqo&R)L_hf-$7Z-5Dh;TVEs zNXJdj08V`JsI}zP{BF)=J+LrKtPLLSZG7VC$MxVw;9ZG6}(?x#~64mff~g3v5g;(7~l~C}lQjqHgc}S7}0+@$=hPrQU_ozhIhHx1XqG-`vLi zO7Q29kZZZS6v9p5gevqjkaL;a`4by5^eU2vZoa+Xj0q|F2T4A3FA%|5AfYb#7KBz$VAhq=e0+S`XaVqEdB2oM z%L=cOwz9iT8SWR|V%3Vt>7LiWgULUe__&T*Eo^_ggsDqeMV_(rm)=&xaGJdDTJH*^ ze*ql&j|KnR<+*{u$C;zH`5v1Mtkk`pJ-c-MBj&GCG&5%lWqu1uTH=V7H$}WDni`E} z+mIOorcWQ~_VHby_4w{sMo_^$|M1Cl+WepCDYJ!x16x52#0=$`j7+a5daW6$GuFVV zJRKa!Rozjjpm*5x_oQ5clJMGLh+5qNgermFZ{)CJ76pbfIAf3O0-H~lp zG_ZR}s{-tj;s)&CIOpGOegADG?z^MCPy`Tt(ceL*Vsq;9FN_QN8po~k_NY<`tC6SSpAky92yP%ZoB%s?s{+u=Q2 z85l;q&%bvQ-s4v0Jt6b!+s_?k$$r{9zvDG&ytgQb?EXg}YV&kZ`7z7yZNqy%WZ|?K z-1r;+{%es?&U1iJeryxi#nhjc-9|HwBDW_0pNVBgtr^Opp`p9DxL&C>SASXV3XMn! z&*nS1fPzZayu16yWVt_DE7j#)vs*GVx<{5=4-Q=>c4M^i?}rXR{J;Jh zy_@{Jftgqh{QniulDAa;HS$}WnGJkHCP>_V*TI98EwhsYoSA~NnLH^Ury=&> z;lrmuv3&B;?2pQcj!%xdo`73C)BW7FBk0?F_>8R#fWjeX#8j_y-kzT9gu)hvJ=P`G z?V)g%M6Uv5IIKYv<*UJi=H z{Dbg8K7|>}%(J^iZhSr-G&P06eSSteckW~X$B43;iND}yjE(b>4G>N$89?i(I|638 zLfbxe0i@%mawfz@87JV5`cbi}sNKMyzd)01PUb$lKxLnh0TPG{#Pt`dqLW;sjFTy4 zLiwVM3=G#?B+y092Tk*eSC0{>(4OPc1J9$H`$5boo4k>Uk5u$?5jb1Sq}PgRXMb*2sx`t?>cg&%GN>qCbtwI`3i;LL@zR4>7a22Xh2^H& zAzvsHtR*Dn%xuDdUMDsCj+n<;a^rDl?qp}rvukKXqcCzV1u#SD@{sI>iMXW>i<)%6 z;<^z71AvAscmoU`Mhm?7Ye+-c;*gL071ix*0s=_|qoksnm|)HV{p+X9vmz_+9g@Ll z#-U${*=%DMdU(5rQC&>6+Qy}>6|)&PeGwKW6j$F-=w52J=6!|$ItU4+=mIcXTU(cP zCbyW$JgA>V2Uwsy>3U<;ym*Sk`QYM-say-qh}lDcU+S3w7>DaW$7&E#Nj8>kr|Lrc zaLfAhgWV-tgB<$$jX~|}N=2SzlbMZDuJZcxwwP2uUhRk0#t`?j8%uz#l~A_RRrGVp zw}rWt^LK(vTevR0&beM4Cc_w)ymHy?R$~GyHR^z@pUM(;ihKu96@-L@$|{!; zu-Ec2QVP95)iiT`AEQvstG{9xJm7ujrKbBtM4HEs>%WHa!U9`)fMt_@*Dol&q~6$T z07LH*T619iVWTdWobqp&FtYR)Lk%+U{h^rP!^P*0Z6P>gyT}! z>PMsFvYtX0)KeSnjruRSfFf+tkGb*!lo=A3sH6CvueF_UoSfsjeP;9L&es~abLpO%CVpS#{@m=}|@ffzN4n=qWigdM7=8 zn>}$t$=Y?>zNoa)a{?>oZ_$Nr;~w97ILv2@*c-1tC%5=Z+YAiqV)S{-XX0ss|Ldw` zC}p9VQ;rEAXSA;lV~roZ4bl3yH4vu?j#WDrCwvrL#(vSO2$aCe>qjbdLQ2xSJR7;Q z`lEUOcqg{#?i4!F({gfF3(VM5BTUNM&Q(=aWwdHa&F#~76yEiP(4%ky`0(p*Fxs@# zNT)J>4WQ?XZrZ+O^FYA_bA#7E8|XUgbZMLD&2xmpw?*{kfzr)OjW!n*(cUg_Qqd=W z-6qA4IuT4nq*J|4KdWwamC0n%TE*a-=$#O9|0s~8(*WHY0$7?#Cj4q87_16$<2(FJ zvfKa+)z>6d&1_;{lehAurGcQ5oao3sLOOYQk~TlNSEcb+_2$)dcNX2=cCOI;Y3gS7 ziC@cdO9NwK~gtLvP9VE(4Q9e~R?dC~HUkhn=9@Fo?Xl<`>d$sO&TFSzpuB`p?C3 zf%ofWb&c60C!LgfMK=$;(gz0n2J;XNaPa%gRnMr`W$@U4nc#QLvv(Y$mJ9Z=g1&|E z!Yyol#_)P*K|{NbgQ9`7qLa+&yv*2dbkU2i?C>#caU+hpzU3zAOBpN;lgVMzuI8@r z-Mk@jYkJa_hZ-_{Hi{?Hr{m*_L>(d`dJi3|-JZH?{pFaAgMaJG;1FwivEKyi&1WtO zLYT2N*5EPZ1-7M9!bxh9u_fKnHVfDx>DoMOiFwcnr^7D~?S4yem()+F(z84oHun4a zn*%Q$<;X~eEunL8)-OE4sD7Mp*-gK9>6SOtTTxhM_ZK&vY}WjTjr0p==K`XX*yIYm zs8P7R zGWxo2pr89(ldQx>(u+guZD(BOr0;4L;TmfFhJA~}O3&5MIKJ0FRp}pDbwo2(8(p9u zddSNs15>K9e=e10{`uz}=(bvM*G~z&67=)*?2IWrtx9j{7xK{m9@_|=o$2)Ol~YiL z9Q!7!3st2W@sBwLRZqz%;s;}MEaFEOT9mPD#Sn*3fsmSFGWln(t8e}4mp%>1Ny#R z&~`mOD&briECl0F!|8oE8JhDA_1boYd#oO$YkL(1SP#WtNm^R~1>RG0d!5<7;M zEUv)QVfpmwlM6DZe6*SSet|9%F6B&JYi^*=$(meAmA1+CCo$x##0NFALUtFT@Wwy^ zyM@=n}7cNISZ;($|DGn-hkzN zwa;tw@jYuc8mD${K81%+k~OYj>k3+*%IA@>u`yW_Plw8|BlohF8_=a7U&35aOL`1hZa_5YO2{}(@>mW2tFn<`kO5IP(qbJEGq z1faSva~3KQKI#Ob;znh0(AE>?vC+LRS0$ThQd)6DM)xW#qFee4+^}x7kzBFmB=p`` zMx={b1ZC}R$C+Zy>$VdzKkZvY7x9yuqS*yH$0RPwFFA@? z$%TX`ioF+0{&287nHYMwho}c;aI*~@7LXP%iCso0RS^ zwG6eSR;QkEItf($f*FO<8REps`%Z}r45v}JdHMKcUHy$U(T<~tpnF01ulq(W2`7%j z(&h=N$%O8s1@dM;aOw{eGJapY-Q0GNfJLUmZ(v|x-?8JJKb0tOAT2U2OG-z{SW=Fw zxa?-_GME{JqeUR!5J`pgD;zbRXf4YFdH6EYLd>Dih~v$Fgn1CnxWu!_IP#Q)SJw)M zlbQ5^^(dMXuID}6R5mfLqJAT96UTNJ7Z+lBTLj}NP9!XQ-pU0elR{h?WRp_EH)ZGJ zzJbMl?z6=LI(4OongWTAhfIej4L;E+Qq<_!8!cH=fnU~h-~m_O`Bk3{(N>%%BYwux zgPYfa%Sd|HKV_~pgizG6tzWfVvtD8#vART{u1%RP!hj4#zVHB)LQ32_muMtn4Bb7; z$8ml=TQ|=1C<2e}S?hZu=L1EjWNh~K95VAm+XgY*gv_PqiqA&OE5M#+mypmTc^lgn&cLoblBI#6Bs6fRYjZ_WqhkceF_xQ(cL- zmt$S)*)^kPW@aVAOgRSI=fTD<#33bn;03j(7h_Zo9n%tMNbL@F-o?vXwKUTvCL&_b z-gTLEBr6uO`bdSB))_X|3AFTz2+zzx9PFGkR|5&^N%~Bv83`x+-O|HeB7-TpOJCZk zkGB|tV+%bRpV3>melToLr*T%pyft{=jpM%tbzec0@4)N`zPWnC?%r+RrkxL`R$7s$xF~4xB)KWytSLEe`1YbG%k3rso0s%KIwXl#LkI%=4Sp ze(f7_S`asAj~j@fGBPqM#ZE4|CH)EDhunD37P)UVAUMInp!-T-I!Y7gS8ZV5<|E~L zXhf*qWAl&-GdDIimUZGoQ?PbRMW>L{3VVmYd?{>DA8X{5jVVP z4B_f~m{f-Bmg?7uCXyAZolVxp0GeI!%!IdPL$$~{HIU{2{O&m_Y!@Q1EuhRY0i$5X z31HUI(Q(+D2#9ooNH*K7Iyuxfq=$hoV-qRjN=#ychJG;Q3T+t6o*#AI2{L?T@R23? z;1oHFPJw3WGe8K7)Of^>Q`oc5aT>W`Eo@YlzzCNS2w-e7%53J!9T&d5vBwYuH7!3d zDEvCZ{mmX;1DILXi7ppqyuYzpR1kHvYyQf0>#WH9sj^OV&Rk&J;!8zs=;%3TK?MFf z+Yn$Z`XLERRcjt3_FdLz!7;wTjsq=6YSsMs-M0>xwt@7b9J?)65C_WjuY|7OkOdur zai9p64fC>P%kly>VPS8*5MRtq;jX?c=M7GFdc$mLYN`u1uMNvIdR`6tqXBNN+*2%n z5sn|x;u2(TVtE@3TDoRvEy12X({)$X@8*rtJFp0wA9&}LjtK2TMQ45BhHYluY=(v{ zC*8!x7|#!BW#GkFMh+y9eq((*^f7ziKBjNIa^(ugv%2=uuZL0R@5gr%XVrkO_!rw* zvoNiwi&89JIx@TLUV2H%nN!%Q%s48>r)^i!?OugBy>t$`r6$!^9tiuNqk8l(bFwhi z1I@nL*J~3(;S?^rmccK@o)`wvVB`&R|5b!JAQQ6G22XT$Pq?plQB-kIdl;JONdEWJJ zt~c@unRh=S)3S89gGE?ctwDG%CU6ZnoYGgjVhhF0V||h6KghQbaC?*-vx|T5wt=;BTsWRUSZw%_Uxn?a zUrX62pxwVA;c;(Y4PCBMV9~|y8v?iFeJk?(C>Mm=&Mgs=z4csBYBl z%YCn(a1YXx4?qvOXqN!tSC)RCxHb}Ab%#ezERTI;(&AFRl>4MV;GeL;YH9hUbcz@v zOSgVwOe+&huMl=j+}q00B?dS%Sc7=3UzuY zJXBjUAXFXC6ln7`V?gRvO#PLw8V1&DG_%^F#vqUER&cQPMvs>>Q(gkgWs7&FRGY1u zUDT?ok}cblaoli)mVV49Hyi(=n_|M$(%!FQ<2L4H?I0k$i0`&L!=)55vB)A;^Mszy zLjnSI>2mqC$Hq)nYH0K^b!T~aC7OoM)m;f}lIc-7`aJ%o4U5WWw!M1`Jpv+1`qt5T z!UqF)gTK4-vQ%HK{u%+fWyKT6vey%gX-U7`W`TxkoU)%Umkb0 zer-uw-jA-IchO7A-lTjv=StgsI&q7J0r_09+3p$WK53K6xWC@o8|5ZX6{WWqJ#gN+ z8`_yCW$Ugk8!n348}VzUx_hjidI8u#zHe)V9og4xnY_;vcZ~Ynpj1LEt4wvmW5r48 zR)crebP@8qxg7Vv&B5bBeq7=N$o2A{$9#3Np{&x$gv{<)nm$R@n3vG6J|Hj@!{it% zjwwqD&Sg$2Z#9qP&u%8Z+j!c_5P~q>Z}`tKwHR9a7owJ}N9C zX|sACk4in^0P<`9f*ixRDI9lN#~O8D!i9U$2R~9`YegAZSd3yHzkRO3Y0ov=1cpe5q95I@Y~piqhhsQlaTFqWS&f5?v^4Lw zM1k(=b^;B!pdi}Zd~%gBhDW7xT&lW!bk!SxjOFZgO`KfkDwrJBiH$#b4jv%KaE0#; zq^vg{v53^Yx$)(9wmu>^bwT=8;UDfWJ+)CwpC#ANIIXY}Ec{b&0o}_K`!0-rEi||1 z-4+jC{CJq_ZEKVw=U7wHlT_olWhE0#7cAR#mmRf{O*9&R#-wK;iC*t7`6y@n1?VQ4 z&IF1!Rw5HPg$%y54-Dpmx1ZAIg)P%k;e3tW5l2H+U)b$BFutTk!-32-&#&#CsQ=PE zLxyL(L~PSsBB812)CpTvzS|M>^Rsz(T0xuc!AOpj+z~=9vw6HIr;XGq%~U9>j#lEi zp!LTh9yzvh5#2)WcNXG5cR;#mz9F|tE0Njb-~X69E=K+StG{>Ej~#!F|J@;v P{9Nk9+2gTCFW>op=NUs$ literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/random_forest_parity.png b/FESurrogateModelTutorial/reports/figures/random_forest_parity.png new file mode 100644 index 0000000000000000000000000000000000000000..eafac9726b69b2c254a9bf0e83ffcaf6b8ff7f9b GIT binary patch literal 41000 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 literal 0 HcmV?d00001 diff --git a/FESurrogateModelTutorial/reports/figures/random_forest_residuals.png b/FESurrogateModelTutorial/reports/figures/random_forest_residuals.png new file mode 100644 index 0000000000000000000000000000000000000000..e7fd7e72e31a91754cf2ad63bd1ec096444e251d GIT binary patch literal 39038 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