WAAM Path Weave Modifier
Given a G-code toolpath in the XY plane, superimposes a continuous sine-wave weave along the path, parameterized by amplitude and wavelength.
The input path "threads" the centre of the produced output sine-wave path; the weave is always perpendicular to the instantaneous heading.
Usage
python weave_modifier.py \
--input_gcode <input_gcode_file> \
[--output_gcode <output_gcode_file>] \
[--output_plot <output_plot_file>] \
[--amplitude <mm>] \
[--wavelength <mm>] \
[--first_layer_amplitude <mm>] \
[--first_layer_wavelength <mm>] \
[--resolution <mm>]
Arguments
--input_gcode: Path to input G-code file (required)--output_gcode: Path to output G-code file (auto-inferred beside input if omitted)--output_plot: Path to output plot image file (auto-inferred beside input if omitted)--amplitude: Weave amplitude in mm (default: 2.0)--wavelength: Weave wavelength in mm (default: 3.0)--first_layer_amplitude: Override amplitude for the first layer in mm (defaults to--amplitude)--first_layer_wavelength: Override wavelength for the first layer in mm (defaults to--wavelength)--resolution: Resampling resolution in mm (default: 0.1)
When --output_gcode / --output_plot are omitted they are placed beside the input file as:
{stem}_amp{A}mm_wave{W}mm.gcode
{stem}_comparison_amp{A}mm_wave{W}mm.png
Example
python weave_modifier.py \
--input_gcode input_data/test_path.gcode \
--amplitude 3.0 \
--wavelength 1.5
Expected output
On a successful run the tool prints a per-path summary, the output G-code path, and the comparison plot path. Example for a multi-layer slicer input invoked with --amplitude 3 --wavelength 1.5:
Parsing SANDBOX/v2_whispers_walnut.gcode ...
Found 28 extrusion path(s)
Path 0: 1842 pts, length = 3421.7 mm (amp=3.0, wlen=1.5)
resampled -> 34218 pts, weaved length = 7214.9 mm
Path 1: 1517 pts, length = 2874.2 mm (amp=3.0, wlen=1.5)
resampled -> 28743 pts, weaved length = 6056.3 mm
...
Path 27: 1433 pts, length = 2711.0 mm (amp=3.0, wlen=1.5)
resampled -> 27110 pts, weaved length = 5713.8 mm
Writing G-code ...
Wrote SANDBOX/v2_whispers_walnut_amp3mm_wave1.5mm.gcode
Generating plot ...
Saved SANDBOX/v2_whispers_walnut_comparison_amp3mm_wave1.5mm.png
Done.
Things worth noting in the output:
Found N extrusion path(s)— every contiguous run ofG1moves withE != 0is counted as one path. Non-extrusion lines (travels, comments, M-codes) are preserved verbatim between paths.Path i: <pts> pts, length = <mm>— the input polyline for that path.resampled -> <pts>— after arc-length resampling at--resolution(default0.1 mm).weaved length = <mm>— the arc length of the weaved output for that path. It will always be longer than the input (by roughly a factor set by amplitude/wavelength), which is why proportional E-distribution is used when emitting G-code.- Final two lines name the two artefacts written: the
.gcode(weaved toolpath) and the.png(2-panel comparison plot described below).
Plot explainer
The comparison plot is a single PNG with two side-by-side panels:

- Left — Full Path Overview. Every extrusion path in the file, drawn at true scale and equal aspect. Input paths are
steelblue, weaved paths arecrimson. Layer alpha increases slightly with layer index so stacked geometry is visually separable. At typical WAAM scales (wavelengths of 1–3 mm) the weave appears as a dense red "band" enveloping the blue centreline — use this panel to confirm extent, coverage, and that no layer was dropped. - Right — Detail (Layer 1). A zoomed window (±18 mm) centred ~25 % along the first extrusion path. This is where you visually verify the weave itself: continuous sinusoid, perpendicular-to-heading, threading the input path through its centre, with the expected amplitude (peak transverse offset, half of peak-to-peak) and wavelength (one full period along arc length). The blue centreline should always pass through every zero crossing of the red curve; lobes should be symmetric about it.
If the detail panel shows discontinuities, asymmetric lobes, or amplitude/wavelength that don't match the CLI arguments, the usual culprit is a --resolution value too coarse relative to --wavelength (rule of thumb: resolution ≤ wavelength / 20).