ppak10/Agentic-SLS-ASTM
Agentic-SLS-ASTM ASTM mechanical-test specimens (D638 tensile, D790 flex) printed on the Inova Mk1 SLS printer and pulled on an MTS / TestWorks Instron. Each row is a single specimen with full geometry, scalar results, stress–strain + raw DAQ curves, and — for SLS rows — FK references and an embedded snapshot of the upstream print profile from ppak10/Agentic-SLS-Database. Rows are self-contained for ML use: the full PrintProfile JSON is inlined, so features (material/energy… See the full description on the dataset page: https://huggingface.co/datasets/ppak10/Agentic-SLS-ASTM.
Agentic-SLS-ASTM
ASTM mechanical-test specimens (D638 tensile, D790 flex) printed on the Inova Mk1 SLS printer and pulled on an MTS / TestWorks Instron. Each row is a single specimen with full geometry, scalar results, stress–strain + raw DAQ curves, and — for SLS rows — FK references and an embedded snapshot of the upstream print profile from `ppak10/Agentic-SLS-Database`.
Rows are self-contained for ML use: the full PrintProfile JSON is inlined, so features (material/energy profile) and target (mechanical response) live on the same row.
from datasets import load_dataset
tensile = load_dataset("ppak10/Agentic-SLS-ASTM", "D638", split="train")
flex = load_dataset("ppak10/Agentic-SLS-ASTM", "D790", split="train")Figure style. All figures share one house style (ported from the `AdditiveLLM2-OA` figures): DM Sans typeface, framed axes with inward ticks, a light dashed grid, and dual PNG (dpi 1200) + vector PDF export. The SLS batches are colored by an ordered orange ramp (gold → deep brown, in print chronology, built around #F97415); the FormLabs PA12GF benchtop reference is drawn in a contrasting blue so it reads clearly as the external benchmark.Batch clusters
Replaces the old overlaid composite (which, at 76–80 curves, was unreadable). Each specimen collapses to a single point at its stress–strain peak — x = strain at peak, y = ultimate strength — and each batch becomes a ±1 SD confidence ellipse (covariance-based) around its specimens' peak points. This carries the headline ultimate-strength number and shows how tightly each batch clusters, with none of the overlaid-curve clutter. (Peak is derived as max(stress) over the saved curve, not read from PeakStress — TestWorks often leaves that scalar null for D638 tensile.) Groups with fewer than 3 specimens draw a connecting segment or a bare marker instead of an ellipse.
Regenerate with uv run scripts/plots/03_batch_clusters.py.
Per-batch detail
To read the actual stress–strain curves for one batch without cross-batch clutter, each batch (plus the FormLabs PA12GF reference) gets its own figure under `assets/batches/` — {standard}_{batch}.png — with each specimen individually colored and keyed by sample_id in the legend. Two examples:
Regenerate with uv run scripts/plots/04_batch_details.py.
Broken-out controls & specimen types
Materials/geometries that don't belong on the batch comparison get their own axes. PLA/PETG filament controls (D638 only) print at much higher stress/strain than either PA12 material; the FormLabs Nylon 12 White control is a second, distinct reference material; and Batch M's 12 Type IV (narrow-section) tensile specimens have a different gauge geometry than its Type I dogbones.
PLA/PETG controls (D638 only — D790 has no filament controls; PLA in blue, PETG in teal):
FormLabs Nylon 12 White control:
The D638 export is a raw load/extension curve with no gauge length in the file itself — strain/stress are derived using a user-confirmed 25mm extensometer starting length (gauge_length_mm set explicitly in 31_2026_07_23_tensile_nylon12white_fl.py, not read from the xlsx).
Batch M Type IV (narrow-section) tensile specimens, D638 only — each of the 12 specimens is individually labeled (1-6, 8-11, 13-14; specimen numbers 7 and 12 aren't part of this xlsx export, per the lab's own numbering) rather than grouped into one legend entry:
Regenerate with uv run scripts/plots/01_controls.py.
Batch averages (SLS Nylon 12 GF only)
One mean stress-strain curve per SLS batch, ± 1 sample standard deviation across specimens (shaded band), for our own Inova Mk1 SLS Nylon 12 GF prints plus the FormLabs PA12GF reference (in blue) — PLA/PETG and the Nylon 12 White control are excluded (their own figures). Each specimen is first trimmed at its stress peak (loading branch only), then linearly interpolated onto a common strain grid bounded by the shortest specimen's peak strain in that batch, so every point in the mean is backed by the same specimen count and no fracture-branch spike distorts the band. See scripts/plots/02_batch_averages.py for the full averaging method (including why one D790 specimen — a degenerate 3-point curve — is dropped from its batch's average).
The same mean ± 1 SD banding is also rendered for the FormLabs Nylon 12 White control on its own (excluded from the figure above for the same reason as its raw-curve figure — see Composite stress–strain):
Regenerate with uv run scripts/plots/02_batch_averages.py.
Configs
One JSONL file per specimen — SLS rows are named after their sample_id (e.g. data/D638/A1.jsonl, data/D790/E10.jsonl); non-SLS controls use {material}_TSR{n}.jsonl (e.g. data/D638/PLA_TSR6.jsonl, data/D790/PA12GF_FL_TSR1.jsonl). Both configs share the same row schema and are produced by the per-session scripts under scripts/specimens/.
Specimens are labeled with a sample_id of the form {batch_label}{seq} (e.g. A1, C7), where the batch label identifies the print batch they came from. Batch labels are usually a single letter, but J / J_MB are the same 2026-07-06 print batch split by post-processing: J specimens were tested as-printed, J_MB specimens were media blasted before testing. The same sample_id may appear in both configs — C1 in D638 and C1 in D790 are different physical specimens that came from the same Batch C print. Batches O and P (2026-08-03) are the first use of Nylon 11 SLS powder in this dataset — two separate prints, tested only as ASTM D638 Type IV (Batch P also has D790 flex); Batch Q (2026-08-07) is a third Nylon 11 print, D638 Type IV only. Their seq follows each batch's own lab specimen numbering rather than starting at 1: Batch O is O10-O13, Batch P's D638 numbering skips P7 (the xlsx export's own Test Run 7 sheet is labeled "SAMPLE 8"), and Batch Q's numbering skips Q7 (physical specimen 7 broke — its xlsx tab is a "broken" placeholder), giving Q1-Q6, Q8-Q14.
Source Layout
source/
2026_05_26/ # one folder per test session
*.tsproj # TestWorks project pointer
*.xlsx # TestWorks Excel export, one sheet per specimen
TST1.Test/
TestRuns/
TSR{n}.TestRun/
Data/DaqTaskActivity1.h5 # raw DAQ scans (10 Hz)
AnalysisRuns/ANR1.AnalysisRun/
persistent.h5 # analyzed scalars + curvesTest sessions covered:
TSR11 in Batch E 3pt test/ exists on disk but has empty Data/ (aborted run, no DAQ scans) and no corresponding xlsx sheet — it is excluded from the JSONL. TSR4 in Batch I flex (Flex 6-30/) is excluded for a similar reason: test_end_reason is "Test Stopped" rather than a detected break. Batch Q physical specimen 7 broke — its xlsx tab holds only the text "broken" — so it too is excluded, and Batch Q's sample_ids skip Q7.
Batches K through U (2026-07-15 through 2026-08-19) have no raw TestRuns//h5 folders at all — only TestWorks xlsx exports were handed off, so all of these rows are xlsx_only (see scripts/specimens/_lib.py's build_row_from_xlsx). Batch M's 12 Type IV specimens are a narrow-section ASTM D638 geometry (6mm × 4.15mm vs Type I's 12.8mm × 3.1mm) from the same print as its 5 Type I specimens — same batch_label, distinguished by astm.type. Batches O, P, Q, and R are entirely Type IV as well, but of a different SLS powder (Nylon 11, first used in this dataset in these batches — see notes on their rows) rather than a geometry variant of an existing batch, so they're excluded from the batch-average/cluster figures the same way Type IV rows always are, but get their own per-batch detail figures rather than sharing Batch M's combined Type IV figure (see scripts/plots/_lib.py's TYPE_IV_DEDICATED_BATCHES). Batch Q's and R's exports are more minimal still: each sheet holds only the already-analyzed strain/stress curve with no geometry (Width/Thickness) or scalar-metric columns, so those rows' geometry and metrics are null — except peak_stress_pa, which the extract derives from the curve itself (max stress; see derive_d638_peak in scripts/specimens/_lib.py) — while curves.strain/curves.stress_pa are populated (consumers re-derive modulus from the curve). The FormLabs Nylon 12 White tensile control's xlsx export is a raw load/extension curve with no gauge length in the file — strain/stress_pa are derived using a user-confirmed 25mm extensometer gauge length declared in the script itself (see Composite stress–strain above); its flex counterpart derives normally via the D790 chord formulas. The Batch Q, R, T, and U flex specimens (D790, tested 2026-08-23) are curve-only in the opposite way: each sheet holds only the raw load-deflection trace (col A mm deflection, col B N load) with no Width/Thickness, so the D790 chord formulas have no geometry to work from — curves.strain/curves.stress_pa and all metrics (including flexural modulus) are null, and only curves.extension_m/curves.load_n are populated. Consequently these batches do not appear on the D790 stress–strain figures (there is no derivable stress/strain to plot until specimen geometry is supplied).
Batch H's 5 flex specimens (2026_06_30/Flex 6-30/) don't have a raw TestRuns folder — it looks like it was overwritten when the Batch I TestWorks project reused the same default TST1.Test name in the same directory. flex_h_6.30.xlsx is the only surviving record, so those 5 rows are built from that xlsx export alone: the raw load/extension curve (curves.load_n/curves.extension_m) comes from its embedded columns, but curves.strain/curves.stress_pa are empty and several metrics fields (modulus_pa, strain_at_peak, strain_at_yield, etc.) are null, since deriving them requires the support span, which this export doesn't surface. See each row's notes field.
Row shape
{
"sample_id": "A1",
"batch_label": "A",
"specimen_id": "2026_05_26/TSR1",
"test_date": "2026-05-26",
"session_folder": "2026_05_26",
"test_run_name": "TSR1",
"specimen_index": 1,
"material_class": "SLS",
"astm": { "standard": "D638", "type": "Type I", "year": "2022" },
"test_end_reason": "Break Detected",
"geometry": {
"width_mm": 12.9, "thickness_mm": 3.2,
"area_mm2": 41.28, "gauge_length_mm": 103.0
},
"job_id": "ba17a5ba-a5f6-4d60-8832-b6c13a2dfa67",
"print_date": "2026-05-25",
"print_profile_id": "52715389-d580-4be9-9194-ed300bdf911b",
"object_hash": "E4251951376A82B4303394F832996A2E9883EAB0",
"session_id": null,
"print_profile_snapshot": { "...full PrintProfile JSON..." },
"metrics": {
"modulus_pa": 341090566.27,
"peak_load_n": null, "peak_stress_pa": null, "strain_at_peak": null,
"load_at_break_n": null, "stress_at_break_pa": null, "strain_at_break": null,
"energy_to_break_j": null,
"yield_stress_pa": null, "strain_at_yield": null
},
"curves": {
"time_s": [/* N */],
"extension_m": [/* N */],
"load_n": [/* N */],
"strain": [/* N */],
"stress_pa": [/* N */]
},
"notes": "",
"source_paths": {
"persistent_h5": "source/2026_05_26/TST1.Test/TestRuns/TSR1.TestRun/AnalysisRuns/ANR1.AnalysisRun/persistent.h5",
"daq_h5": "source/2026_05_26/TST1.Test/TestRuns/TSR1.TestRun/Data/DaqTaskActivity1.h5",
"xlsx": "source/2026_05_26/tensile_testing_5.26.xlsx",
"xlsx_sheet": "Sheet1"
}
}Notes on results
sample_idandbatch_labelare null for non-SLS control rows (PLA, PETG, FormLabs PA12GF — they didn't come from an SLS print batch). Filter onmaterial_class == "SLS"to get the rows that link back to Database.- Batches E–I currently have
job_id,print_profile_id,object_hash, andprint_profile_snapshotall null — their source print jobs aren't in Database yet. The mechanical results are still valid. metrics.peak_*andmetrics.*_at_breakare oftennullin the D638 tensile rows because TestWorks did not detect a peak/break point on those runs. D790 flex rows have these fields more consistently populated. Thecurves.stress_pa/curves.strainarrays are populated regardless, so consumers can re-derive peak/break with their own criteria.- Batch H's flex rows (
data/D790/H1.jsonl–H5.jsonl) are the one exception: their raw TestRuns folder is missing (see Test sessions covered above), so they're built from the TestWorks xlsx export alone.curves.strain/curves.stress_paare empty and mostmetricsfields are null for these 5 rows specifically — checknoteson a row before assuming a null metric means TestWorks failed to detect it. notesis a free-text field, empty for most rows; it's used to flag exceptions like the Batch H flex sourcing above or the FormLabs vertical-print orientation.metrics.modulus_pamatches the kN/mm² value in the TestWorks xlsx after unit conversion (e.g. tensile 0.341 kN/mm² → 3.41 × 10⁸ Pa). For D790, TestWorks computes the flexural modulus via the 3-point-bend formula directly; values may look unintuitive compared to the tensile modulus.- DAQ scans are in SI units (m, N, s); stress is Pa and strain is dimensionless.
- For D790,
geometry.gauge_length_mmis always null (gauge length is a tensile concept; flex uses support span which is not surfaced).
