{"sections":[{"heading":"Keep amplitude data separate from the time grid","paragraphs":["CUS loads an external amplitude row and uses the supplied Ts to assign its sample spacing. The data file is not a time/voltage CSV: it contains exactly one nonempty data line of amplitude values. The three teaching values are 0, 1m and 0, which mean 0 V, 1 mV and 0 V for these voltage sources. Comments can be separate lines beginning with an asterisk.","Use a compatible JoSIM 2.9 build containing the maintained quoted-filename repair. The checked Windows candidate is distinct from older installed/review binaries and still needs final-package verification. A normal product licence is required for simulation; no licence file is included in the example.","Extract the complete download, preserving lib/drivers.cir and lib/Measured wave (A),1.txt below main.cir. The sample filename deliberately contains spaces, parentheses and a comma. Its quoted path is relative to the defining include, not the caller’s current directory. Preserve filename case and matching quotes."]},{"figures":[{"asset_id":"josim-cus-source","caption":"Actual complete source with the reported static argument errors retained. This is a reproduced editor/runtime disagreement, not a clean editor state."}],"heading":"Open and run the complete example","steps":["Open main.cir in JoSIM-Pro. Keep the lib directory alongside it. Open lib/drivers.cir to inspect the seven CUS declarations and their loads.","Read each source as CUS(file Ts Sf Im Td periodic). Supply Ts explicitly. The supported selectors are 0 hold, 1 linear and 2 cubic. This guide uses explicit values for the intended route and retains omitted/default and time-valued periodic arguments only as diagnostic comparisons.","Save any source changes, choose an existing writable result destination, and request Run. The complete example uses a 1 ps integration/output step and a 75 ps stop time. Expect 76 samples and seven named voltage traces.","Inspect V(HOLD), V(LINEAR), V(CUBIC), V(DEFAULT), V(DELAY), V(REPEAT) and V(PERIOD). Use each axis label: most teaching plots display mV, while the 0.5 mV delayed signal is shown as 500 microvolts. The raw CLI CSV is in seconds and volts.","The source image below deliberately shows KB-CUS-003: six static argument errors on valid quoted-path source lines. The current runtime and independent numerical check pass. Diagnose this bounded disagreement using the complete files and a simple-filename control; do not dismiss unrelated errors or remove necessary quoting."]},{"figures":[{"asset_id":"josim-cus-waveforms","caption":"Seven actual current plots. HOLD, LINEAR and CUBIC have different timing/shapes; DEFAULT matches LINEAR, and the final time-valued argument does not enable repetition."}],"heading":"Check what the controls mean in this candidate","paragraphs":["Choose the interpolation by the waveform you intend to apply, then verify its timing. A smoother curve is not automatically a better representation of measured data. Explicit defaults avoid relying on the unresolved reference-table wording."],"table":{"columns":["Control or trace","Checked interpretation"],"rows":[["Ts = 10p","Sample spacing is 10 ps. The runtime clamps a smaller requested spacing to its integration step; a smaller output step alone does not restore lost sample timing."],["Sf = 1, or 0.5 for DELAY","Multiply amplitude values once. 1m with Sf = 0.5 is 0.0005 V, not 0.5 V."],["Im = 0 / HOLD","Hold the current sample within each interval. The nonzero 1 mV interval lies between 10 and 20 ps."],["Im = 1 / LINEAR","This implementation ramps from the previous amplitude to the current one over an interval, starting from zero. For this row the ramp peak is at 20 ps rather than the cubic sample peak at 10 ps."],["Im = 2 / CUBIC","The exercised spline passes through the three sample values with a natural left boundary and zero right slope. It can overshoot: the 1 ps teaching grid reaches about 1.02214 mV for a 1 mV input maximum."],["DEFAULT","Omitting Im selects linear in the exercised runtime. It exactly matches LINEAR, despite the manual table listing default 0 (KB-DOC-005)."],["Td = 5p / DELAY","Shift the half-scale held waveform by 5 ps. Before that delay its value is zero."],["periodic = 1 / REPEAT","Enable repetition. Three samples at 10 ps give a 30 ps cycle; set zero for no repetition."],["periodic = 30p / PERIOD","This time-valued argument rounds to false and does not request a 30 ps cycle. The manual’s Repeat period label conflicts with the flag semantics (KB-DOC-005)."]],"wrap":true}},{"code":"New-Item -ItemType Directory -Path results-first -ErrorAction Stop | Out-Null\n& $JoSIM -P 17 -o .\\results-first\\waveforms.csv .\\main.cir\nif ($LASTEXITCODE -ne 0) { throw 'JoSIM did not complete; inspect its first diagnostic.' }\n& $Python -B .\\check_custom.py --csv .\\results-first\\waveforms.csv --report .\\results-first\\check.json\nif ($LASTEXITCODE -ne 0) { throw 'The teaching waveform reference did not pass.' }","heading":"Run and check the raw numerical CSV from an agent","language":"powershell","paragraphs":["In PowerShell, set $JoSIM to the full path of the compatible CLI and $Python to a Python 3 interpreter, then work in the extracted example directory. Use a new results-first directory; the script deliberately refuses a reused result directory.","The independent teaching checker requires the exact eight raw-SI columns and 76 finite rows. It compares 60 interior time samples with separate piecewise equations using 2e-12 V absolute and 1e-9 relative tolerances. It avoids deciding discontinuity sides from floating-point rounding at sample boundaries. These tolerances test this synthetic source-transfer example; they are not a general solver or device-accuracy target.","An unsupported selector such as 9 can complete with a zero waveform on this candidate (KB-CUS-001). The checker rejects that result. Process exit 0, a finite matrix or a plausible plot alone does not establish the requested stimulus."]},{"code":"& $Python -B .\\prepare_samples.py --csv .\\samples.csv --output .\\lib\\converted.txt\nif ($LASTEXITCODE -ne 0) { throw 'Sample conversion was refused; check units and the time grid.' }","heading":"Convert an explicitly declared uniform CSV","language":"powershell","paragraphs":["The supplied samples.csv has exactly time_s,voltage_V columns with a zero-based, uniformly spaced time axis. prepare_samples.py is a small teaching utility supplied with this guide, not a claim that CUS directly imports tabular CSV. It writes one new amplitude row and reports Ts_seconds; it never overwrites an existing destination.","The command creates lib/converted.txt. To use it, change the CUS references in your saved working copy to converted.txt, retain Ts = 1e-11 s and Sf = 1 for the supplied SI values, then request a new Run. The checked converted row reproduces the original teaching arrays.","For your own data, convert physical units explicitly and require uniform sampling. This utility refuses an irregular grid, nonfinite data, another header/unit declaration or a nonzero starting time. It does not silently resample or shift measurements. Decide on a resampling method elsewhere and use Td explicitly for any intended delay.","check_custom.py contains the fixed teaching reference. It is expected to reject a different measured waveform; provide an appropriate independent reference and acceptance criteria for that data rather than weakening the teaching check."]},{"heading":"Rerun after changing external sample data","paragraphs":["Preserve the amplitude file with the source and result. In KB-CUS-002, changing its row from 0 1m 0 to 0 2m 0 left the existing arrays unchanged and the GUI still said Results current. The netlist itself was neither modified nor semantically dirty.","Request Run explicitly after changing the sample file. The native check rereads it and doubles all seven waveforms; restoring the original bytes and running again recovers the original arrays. A second process explicitly reopening the saved hierarchy reproduces them. This is saved-file reproducibility, not automatic GUI-session restoration.","Changing the external file after a run does not retroactively change that run’s data. Treat the current indicator and the preserved sample-file revision as separate evidence, particularly when sharing or comparing results."]},{"heading":"Recover from a failed or misleading waveform","table":{"columns":["Observed problem","Next check"],"rows":[["File could not be found/opened","Preserve lib and resolve the filename against the defining source/include. Use matching quotes, correct case and readable files. Older binaries may lack the maintained quoted-path repair."],["Exactly one data line / no waveform data","Use a single nonempty amplitude row. A normal multirow time/voltage CSV needs explicit conversion."],["Bad numeric value","Read the actual file, physical line and sample index in the diagnostic. Preserve the original measured data before correcting it."],["Too few CUS values","Supply a filename and Ts; the checked argument guard requires both."],["Static Invalid waveform arguments, runtime passes","KB-CUS-003: retain this candidate’s quoted-path parser disagreement; inspect the actual path and numerical output, then use a complete simple-filename copy as a diagnostic control."],["No repeat, unexpected linear timing or zero stimulus","Use explicit supported Im/Td/periodic values and the table above. A time period is not the final flag; an unsupported Im can silently produce zeros."],["Old plot after a sample edit","KB-CUS-002: request a new Run and compare the actual current-generation data with the intended sample bytes."]],"wrap":true}},{"heading":"Scope of the recorded workflow","paragraphs":["The fresh isolated Windows candidate passes 25 CLI/client/static-API checks and 20 independent native/source/output checks. It includes quoted special filenames in an included directory, unrelated process working directories, both quote styles, complete SI conversion, expected failures and numerical recovery. Four fresh native simulations across two normal app processes retain separate current CSVs.","KB-DOC-005 and KB-CUS-001/002/003 remain findings, not repairs. Case-sensitive filesystems, other platforms, final distributed packages, physical picker/pointer paths, arbitrary waveform grammars and measured-device accuracy still need their own qualification."]},{"code":"* Synthetic CUS comparison; retain the complete lib directory\n.INCLUDE \"lib/drivers.cir\"\n.OPTION ANALYSIS=VOLTAGE INTEGRATION=BDF\n.TRAN 1p 75p 0 1p\n.PRINT V(HOLD) V(LINEAR) V(CUBIC) V(DEFAULT) V(DELAY) V(REPEAT) V(PERIOD)\n.END","heading":"Save main.cir","language":"text"},{"code":"* The waveform path belongs to this include, not the caller's working directory\nVHold HOLD 0 CUS(\"Measured wave (A),1.txt\" 10p 1 0 0 0)\nVLinear LINEAR 0 CUS(\"Measured wave (A),1.txt\" 10p 1 1 0 0)\nVCubic CUBIC 0 CUS(\"Measured wave (A),1.txt\" 10p 1 2 0 0)\nVDefault DEFAULT 0 CUS(\"Measured wave (A),1.txt\" 10p)\nVDelay DELAY 0 CUS(\"Measured wave (A),1.txt\" 10p 0.5 0 5p 0)\nVRepeat REPEAT 0 CUS(\"Measured wave (A),1.txt\" 10p 1 0 0 1)\nVPeriod PERIOD 0 CUS(\"Measured wave (A),1.txt\" 10p 1 0 0 30p)\nRHold HOLD 0 50\nRLinear LINEAR 0 50\nRCubic CUBIC 0 50\nRDefault DEFAULT 0 50\nRDelay DELAY 0 50\nRRepeat REPEAT 0 50\nRPeriod PERIOD 0 50","heading":"Save lib/drivers.cir","language":"text"},{"code":"* Voltage amplitudes in V; exactly one data line, no time column\n0 1m 0","heading":"Save lib/Measured wave (A),1.txt","language":"text"},{"code":"time_s,voltage_V\n0,0\n1e-11,0.001\n2e-11,0","heading":"Save samples.csv","language":"csv"},{"code":"\"\"\"Convert an explicit uniform time_s,voltage_V CSV to one CUS amplitude row.\n\nThis preserves the supplied values. It does not guess units, resample an\nirregular axis, remove an initial time offset, or qualify measurement quality.\n\"\"\"\nimport argparse\nimport csv\nimport json\nimport math\nfrom pathlib import Path\nimport sys\n\n\ndef main():\n    p = argparse.ArgumentParser(description=__doc__)\n    p.add_argument('--csv', required=True, type=Path)\n    p.add_argument('--output', required=True, type=Path, help='New amplitude filename in an existing directory')\n    args = p.parse_args()\n    try:\n        if args.output.exists() or not args.output.parent.is_dir():\n            raise ValueError('Choose a new amplitude filename in an existing directory.')\n        with args.csv.open(encoding='utf-8-sig', newline='') as stream:\n            reader = csv.reader(stream)\n            if next(reader) != ['time_s', 'voltage_V']:\n                raise ValueError('Declare the two columns exactly as time_s,voltage_V; convert other units explicitly first.')\n            rows = [[float(v) for v in row] for row in reader if row]\n        if len(rows) < 2 or any(len(row) != 2 or not all(math.isfinite(v) for v in row) for row in rows):\n            raise ValueError('Provide at least two finite time/voltage pairs.')\n        if rows[0][0] != 0:\n            raise ValueError('Start the supplied time axis at zero; choose any physical CUS delay explicitly.')\n        step = rows[1][0] - rows[0][0]\n        if step <= 0 or any(b[0] <= a[0] or not math.isclose(b[0] - a[0], step, rel_tol=1e-9, abs_tol=abs(step) * 1e-12)\n                            for a, b in zip(rows, rows[1:])):\n            raise ValueError('CUS requires a strictly increasing uniform sample grid; explicitly resample irregular data elsewhere.')\n        text = ' '.join(format(row[1], '.17g') for row in rows) + '\\n'\n        with args.output.open('x', encoding='utf-8', newline='\\n') as stream:\n            stream.write(text)\n        print(json.dumps({'status': 'converted', 'samples': len(rows), 'Ts_seconds': step, 'Sf': 1,\n                          'first_sample_time_s': 0, 'last_sample_time_s': rows[-1][0],\n                          'limit': 'One voltage-amplitude row; choose interpolation, delay and repeat flag explicitly and verify the result.'}))\n        return 0\n    except (OSError, ValueError, StopIteration) as error:\n        print(str(error), file=sys.stderr)\n        return 2\n\n\nif __name__ == '__main__':\n    raise SystemExit(main())","heading":"Save prepare_samples.py","language":"python"},{"code":"\"\"\"Check only the complete synthetic CUS teaching deck's raw-SI CLI CSV.\n\nThe reference is independent piecewise mathematics for the exercised 2.9\nsemantics. It is not a general measured-waveform, model or accuracy validator.\nThe cubic reference uses a natural left end and zero first derivative at the\nright end; its three-point coefficients follow those four boundary equations.\n\"\"\"\nimport argparse\nimport csv\nimport json\nimport math\nfrom pathlib import Path\nimport sys\n\nNAMES = ('HOLD', 'LINEAR', 'CUBIC', 'DEFAULT', 'DELAY', 'REPEAT', 'PERIOD')\nABS_TOL_V = 2e-12\nREL_TOL = 1e-9\n\n\ndef hold(x):\n    return 1e-3 if 1 <= x < 2 else 0.0\n\n\ndef linear(x):\n    if 1 <= x < 2:\n        return 1e-3 * (x - 1)\n    if 2 <= x <= 3:\n        return 1e-3 * (3 - x)\n    return 0.0\n\n\ndef cubic(x):\n    if x < 0 or x > 3:\n        return 0.0\n    if x <= 1:\n        return 1e-3 * (x - (5 / 7) * (x ** 3 - x))\n    if x <= 2:\n        u = x - 1\n        return 1e-3 * (1 - u - (5 / 7) * ((1 - u) ** 3 - (1 - u))\n                       + (6 / 7) * (u ** 3 - u))\n    # Its clamped zero right slope gives constant extrapolation in the tail.\n    return 0.0\n\n\ndef expected(t):\n    x = t / 1e-11\n    return dict(HOLD=hold(x), LINEAR=linear(x), CUBIC=cubic(x), DEFAULT=linear(x),\n                DELAY=0.5 * hold((t - 5e-12) / 1e-11), REPEAT=hold(x % 3), PERIOD=hold(x))\n\n\ndef main():\n    p = argparse.ArgumentParser(description=__doc__)\n    p.add_argument('--csv', required=True, type=Path)\n    p.add_argument('--report', required=True, type=Path, help='New JSON result in an existing directory')\n    args = p.parse_args()\n    try:\n        if args.report.exists() or not args.report.parent.is_dir():\n            raise ValueError('Choose a new report filename in an existing directory.')\n        with args.csv.open(encoding='utf-8-sig', newline='') as stream:\n            reader = csv.reader(stream)\n            columns = next(reader)\n            if columns != ['time', *['V(' + n + ')' for n in NAMES]]:\n                raise ValueError('Expected the complete teaching deck raw-SI CLI columns; GUI-formatted exports can use different axes or labels.')\n            rows = [[float(v) for v in row] for row in reader if row]\n        if len(rows) != 76 or any(len(row) != 8 or not all(math.isfinite(v) for v in row) for row in rows):\n            raise ValueError('Expected 76 finite rows and eight complete columns.')\n        if not (rows[0][0] == 0 and math.isclose(rows[-1][0], 75e-12, rel_tol=1e-12, abs_tol=1e-23)\n                and all(a[0] < b[0] for a, b in zip(rows, rows[1:]))):\n            raise ValueError('Expected an increasing raw-seconds axis from 0 to 75 ps.')\n        errors = {n: 0.0 for n in NAMES}\n        compared = 0\n        for row in rows:\n            # Do not decide left/right continuity from floating-point rounding\n            # at a sample boundary. Compare the interior physical samples.\n            if min(abs(row[0] / 5e-12 - round(row[0] / 5e-12)), 1.0) < 1e-7:\n                continue\n            values = expected(row[0])\n            for name, value in zip(NAMES, row[1:]):\n                error = abs(value - values[name])\n                errors[name] = max(errors[name], error)\n                if not math.isclose(value, values[name], rel_tol=REL_TOL, abs_tol=ABS_TOL_V):\n                    raise ValueError('Teaching waveform mismatch for ' + name + ' at ' + str(row[0]) + ' s.')\n            compared += 1\n        if compared < 50:\n            raise ValueError('Too few independent interior samples.')\n        report = {'status': 'passed', 'samples': len(rows), 'interior_samples_compared': compared,\n                  'quantities': {'time': 's', 'voltages': 'V'}, 'max_absolute_error_V': errors,\n                  'absolute_tolerance_V': ABS_TOL_V, 'relative_tolerance': REL_TOL,\n                  'scope': 'Complete synthetic teaching deck on recorded 2.9 CUS semantics. Default interpolation and final periodic flag are explicitly checked; the cubic clamped tail is included. No arbitrary measured data or physical-device accuracy qualification.'}\n        with args.report.open('x', encoding='utf-8', newline='\\n') as stream:\n            json.dump(report, stream, indent=2)\n            stream.write('\\n')\n        print(json.dumps({'status': 'passed', 'samples': len(rows), 'interior_samples_compared': compared}))\n        return 0\n    except (OSError, ValueError, StopIteration) as error:\n        print(str(error), file=sys.stderr)\n        return 2\n\n\nif __name__ == '__main__':\n    raise SystemExit(main())","heading":"Save check_custom.py","language":"python"}],"canonical_url":"https://www.sun-magnetics.com/knowledge-base/josim-custom-waveform","url":"/knowledge-base/josim-custom-waveform","known_issues":[{"disposition":"supported_path","id":"KB-CUS-001","title":"Unsupported interpolation can succeed with a zero waveform","public_notice":"Use documented interpolation selectors 0, 1 or 2 and independently check the waveform. An unsupported selector producing zeros is not a valid result.","claim_scope":"Only the affected claim and recorded build/input; not whole-guide or final-release acceptance"},{"disposition":"verified_workaround","id":"KB-CUS-002","title":"An external sample edit can leave the prior plot labelled current","public_notice":"Run again after changing an external waveform file and preserve its bytes with the result. The netlist current indicator alone does not establish external-data freshness.","claim_scope":"Only the affected claim and recorded build/input; not whole-guide or final-release acceptance"},{"disposition":"verified_workaround","id":"KB-CUS-003","title":"Valid quoted CUS paths can receive static argument errors","public_notice":"A separate simple-filename teaching copy isolates this static-parser disagreement and reproduces the waveform. Preserve necessary quotes in real paths and investigate unrelated diagnostics separately.","claim_scope":"Only the affected claim and recorded build/input; not whole-guide or final-release acceptance"},{"disposition":"supported_path","id":"KB-DOC-005","title":"CUS defaults and repeat argument differ from the syntax table","public_notice":"Supply explicit sample spacing, scale, interpolation, delay and periodic flag. On this candidate the last argument is a Boolean repeat flag, not a time-valued period; omitted defaults are diagnostic comparisons.","claim_scope":"Only the affected claim and recorded build/input; not whole-guide or final-release acceptance"}],"search_record":{"execution":true,"relatedProducts":[],"version_tags":["JoSIM-Pro 2.9 target"],"text":"Drive JoSIM from a custom waveform or uniformly sampled CSV Keep amplitude samples, time spacing, interpolation and repeat behaviour explicit; load the complete external files and verify their timing and units with a checked example. JoSIM-Pro 2.9.0 release target; newly frozen Windows CUS review candidate How to CUS external waveform sampled measured CSV one amplitude data row time spacing Ts scale Sf Im delay periodic flag linear default interpolation cubic overshoot quoted mixed case spaces commas parentheses filename include relative path Invalid waveform arguments static editor false positive Results current external sample file changed rerun unsupported interpolation zero waveform uniform time_s voltage_V CSV convert irregular resample Keep amplitude data separate from the time grid CUS loads an external amplitude row and uses the supplied Ts to assign its sample spacing. The data file is not a time/voltage CSV: it contains exactly one nonempty data line of amplitude values. The three teaching values are 0, 1m and 0, which mean 0 V, 1 mV and 0 V for these voltage sources. Comments can be separate lines beginning with an asterisk. Use a compatible JoSIM 2.9 build containing the maintained quoted-filename repair. The checked Windows candidate is distinct from older installed/review binaries and still needs final-package verification. A normal product licence is required for simulation; no licence file is included in the example. Extract the complete download, preserving lib/drivers.cir and lib/Measured wave (A),1.txt below main.cir. The sample filename deliberately contains spaces, parentheses and a comma. Its quoted path is relative to the defining include, not the caller’s current directory. Preserve filename case and matching quotes.  Open and run the complete example Open main.cir in JoSIM-Pro. Keep the lib directory alongside it. Open lib/drivers.cir to inspect the seven CUS declarations and their loads. Read each source as CUS(file Ts Sf Im Td periodic). Supply Ts explicitly. The supported selectors are 0 hold, 1 linear and 2 cubic. This guide uses explicit values for the intended route and retains omitted/default and time-valued periodic arguments only as diagnostic comparisons. Save any source changes, choose an existing writable result destination, and request Run. The complete example uses a 1 ps integration/output step and a 75 ps stop time. Expect 76 samples and seven named voltage traces. Inspect V(HOLD), V(LINEAR), V(CUBIC), V(DEFAULT), V(DELAY), V(REPEAT) and V(PERIOD). Use each axis label: most teaching plots display mV, while the 0.5 mV delayed signal is shown as 500 microvolts. The raw CLI CSV is in seconds and volts. The source image below deliberately shows KB-CUS-003: six static argument errors on valid quoted-path source lines. The current runtime and independent numerical check pass. Diagnose this bounded disagreement using the complete files and a simple-filename control; do not dismiss unrelated errors or remove necessary quoting.  Actual complete source with the reported static argument errors retained. This is a reproduced editor/runtime disagreement, not a clean editor state. Actual drivers.cir editor contains the seven complete quoted CUS sources and six reproduced static argument errors despite successful independently checked runtime results. Check what the controls mean in this candidate Choose the interpolation by the waveform you intend to apply, then verify its timing. A smoother curve is not automatically a better representation of measured data. Explicit defaults avoid relying on the unresolved reference-table wording.  Control or trace Checked interpretation Ts = 10p Sample spacing is 10 ps. The runtime clamps a smaller requested spacing to its integration step; a smaller output step alone does not restore lost sample timing. Sf = 1, or 0.5 for DELAY Multiply amplitude values once. 1m with Sf = 0.5 is 0.0005 V, not 0.5 V. Im = 0 / HOLD Hold the current sample within each interval. The nonzero 1 mV interval lies between 10 and 20 ps. Im = 1 / LINEAR This implementation ramps from the previous amplitude to the current one over an interval, starting from zero. For this row the ramp peak is at 20 ps rather than the cubic sample peak at 10 ps. Im = 2 / CUBIC The exercised spline passes through the three sample values with a natural left boundary and zero right slope. It can overshoot: the 1 ps teaching grid reaches about 1.02214 mV for a 1 mV input maximum. DEFAULT Omitting Im selects linear in the exercised runtime. It exactly matches LINEAR, despite the manual table listing default 0 (KB-DOC-005). Td = 5p / DELAY Shift the half-scale held waveform by 5 ps. Before that delay its value is zero. periodic = 1 / REPEAT Enable repetition. Three samples at 10 ps give a 30 ps cycle; set zero for no repetition. periodic = 30p / PERIOD This time-valued argument rounds to false and does not request a 30 ps cycle. The manual’s Repeat period label conflicts with the flag semantics (KB-DOC-005). Seven actual current plots. HOLD, LINEAR and CUBIC have different timing/shapes; DEFAULT matches LINEAR, and the final time-valued argument does not enable repetition. Actual seven current CUS plots compare hold, linear, cubic, omitted interpolation, delay/scale, repeat flag and a time-valued nonrepeating argument. Each axis states its own display units. Run and check the raw numerical CSV from an agent In PowerShell, set $JoSIM to the full path of the compatible CLI and $Python to a Python 3 interpreter, then work in the extracted example directory. Use a new results-first directory; the script deliberately refuses a reused result directory. The independent teaching checker requires the exact eight raw-SI columns and 76 finite rows. It compares 60 interior time samples with separate piecewise equations using 2e-12 V absolute and 1e-9 relative tolerances. It avoids deciding discontinuity sides from floating-point rounding at sample boundaries. These tolerances test this synthetic source-transfer example; they are not a general solver or device-accuracy target. An unsupported selector such as 9 can complete with a zero waveform on this candidate (KB-CUS-001). The checker rejects that result. Process exit 0, a finite matrix or a plausible plot alone does not establish the requested stimulus. New-Item -ItemType Directory -Path results-first -ErrorAction Stop | Out-Null\n& $JoSIM -P 17 -o .\\results-first\\waveforms.csv .\\main.cir\nif ($LASTEXITCODE -ne 0) { throw 'JoSIM did not complete; inspect its first diagnostic.' }\n& $Python -B .\\check_custom.py --csv .\\results-first\\waveforms.csv --report .\\results-first\\check.json\nif ($LASTEXITCODE -ne 0) { throw 'The teaching waveform reference did not pass.' } Convert an explicitly declared uniform CSV The supplied samples.csv has exactly time_s,voltage_V columns with a zero-based, uniformly spaced time axis. prepare_samples.py is a small teaching utility supplied with this guide, not a claim that CUS directly imports tabular CSV. It writes one new amplitude row and reports Ts_seconds; it never overwrites an existing destination. The command creates lib/converted.txt. To use it, change the CUS references in your saved working copy to converted.txt, retain Ts = 1e-11 s and Sf = 1 for the supplied SI values, then request a new Run. The checked converted row reproduces the original teaching arrays. For your own data, convert physical units explicitly and require uniform sampling. This utility refuses an irregular grid, nonfinite data, another header/unit declaration or a nonzero starting time. It does not silently resample or shift measurements. Decide on a resampling method elsewhere and use Td explicitly for any intended delay. check_custom.py contains the fixed teaching reference. It is expected to reject a different measured waveform; provide an appropriate independent reference and acceptance criteria for that data rather than weakening the teaching check. & $Python -B .\\prepare_samples.py --csv .\\samples.csv --output .\\lib\\converted.txt\nif ($LASTEXITCODE -ne 0) { throw 'Sample conversion was refused; check units and the time grid.' } Rerun after changing external sample data Preserve the amplitude file with the source and result. In KB-CUS-002, changing its row from 0 1m 0 to 0 2m 0 left the existing arrays unchanged and the GUI still said Results current. The netlist itself was neither modified nor semantically dirty. Request Run explicitly after changing the sample file. The native check rereads it and doubles all seven waveforms; restoring the original bytes and running again recovers the original arrays. A second process explicitly reopening the saved hierarchy reproduces them. This is saved-file reproducibility, not automatic GUI-session restoration. Changing the external file after a run does not retroactively change that run’s data. Treat the current indicator and the preserved sample-file revision as separate evidence, particularly when sharing or comparing results.  Recover from a failed or misleading waveform  Observed problem Next check File could not be found/opened Preserve lib and resolve the filename against the defining source/include. Use matching quotes, correct case and readable files. Older binaries may lack the maintained quoted-path repair. Exactly one data line / no waveform data Use a single nonempty amplitude row. A normal multirow time/voltage CSV needs explicit conversion. Bad numeric value Read the actual file, physical line and sample index in the diagnostic. Preserve the original measured data before correcting it. Too few CUS values Supply a filename and Ts; the checked argument guard requires both. Static Invalid waveform arguments, runtime passes KB-CUS-003: retain this candidate’s quoted-path parser disagreement; inspect the actual path and numerical output, then use a complete simple-filename copy as a diagnostic control. No repeat, unexpected linear timing or zero stimulus Use explicit supported Im/Td/periodic values and the table above. A time period is not the final flag; an unsupported Im can silently produce zeros. Old plot after a sample edit KB-CUS-002: request a new Run and compare the actual current-generation data with the intended sample bytes. Scope of the recorded workflow The fresh isolated Windows candidate passes 25 CLI/client/static-API checks and 20 independent native/source/output checks. It includes quoted special filenames in an included directory, unrelated process working directories, both quote styles, complete SI conversion, expected failures and numerical recovery. Four fresh native simulations across two normal app processes retain separate current CSVs. KB-DOC-005 and KB-CUS-001/002/003 remain findings, not repairs. Case-sensitive filesystems, other platforms, final distributed packages, physical picker/pointer paths, arbitrary waveform grammars and measured-device accuracy still need their own qualification.  Save main.cir * Synthetic CUS comparison; retain the complete lib directory\n.INCLUDE \"lib/drivers.cir\"\n.OPTION ANALYSIS=VOLTAGE INTEGRATION=BDF\n.TRAN 1p 75p 0 1p\n.PRINT V(HOLD) V(LINEAR) V(CUBIC) V(DEFAULT) V(DELAY) V(REPEAT) V(PERIOD)\n.END Save lib/drivers.cir * The waveform path belongs to this include, not the caller's working directory\nVHold HOLD 0 CUS(\"Measured wave (A),1.txt\" 10p 1 0 0 0)\nVLinear LINEAR 0 CUS(\"Measured wave (A),1.txt\" 10p 1 1 0 0)\nVCubic CUBIC 0 CUS(\"Measured wave (A),1.txt\" 10p 1 2 0 0)\nVDefault DEFAULT 0 CUS(\"Measured wave (A),1.txt\" 10p)\nVDelay DELAY 0 CUS(\"Measured wave (A),1.txt\" 10p 0.5 0 5p 0)\nVRepeat REPEAT 0 CUS(\"Measured wave (A),1.txt\" 10p 1 0 0 1)\nVPeriod PERIOD 0 CUS(\"Measured wave (A),1.txt\" 10p 1 0 0 30p)\nRHold HOLD 0 50\nRLinear LINEAR 0 50\nRCubic CUBIC 0 50\nRDefault DEFAULT 0 50\nRDelay DELAY 0 50\nRRepeat REPEAT 0 50\nRPeriod PERIOD 0 50 Save lib/Measured wave (A),1.txt * Voltage amplitudes in V; exactly one data line, no time column\n0 1m 0 Save samples.csv time_s,voltage_V\n0,0\n1e-11,0.001\n2e-11,0 Save prepare_samples.py \"\"\"Convert an explicit uniform time_s,voltage_V CSV to one CUS amplitude row.\n\nThis preserves the supplied values. It does not guess units, resample an\nirregular axis, remove an initial time offset, or qualify measurement quality.\n\"\"\"\nimport argparse\nimport csv\nimport json\nimport math\nfrom pathlib import Path\nimport sys\n\n\ndef main():\n    p = argparse.ArgumentParser(description=__doc__)\n    p.add_argument('--csv', required=True, type=Path)\n    p.add_argument('--output', required=True, type=Path, help='New amplitude filename in an existing directory')\n    args = p.parse_args()\n    try:\n        if args.output.exists() or not args.output.parent.is_dir():\n            raise ValueError('Choose a new amplitude filename in an existing directory.')\n        with args.csv.open(encoding='utf-8-sig', newline='') as stream:\n            reader = csv.reader(stream)\n            if next(reader) != ['time_s', 'voltage_V']:\n                raise ValueError('Declare the two columns exactly as time_s,voltage_V; convert other units explicitly first.')\n            rows = [[float(v) for v in row] for row in reader if row]\n        if len(rows) < 2 or any(len(row) != 2 or not all(math.isfinite(v) for v in row) for row in rows):\n            raise ValueError('Provide at least two finite time/voltage pairs.')\n        if rows[0][0] != 0:\n            raise ValueError('Start the supplied time axis at zero; choose any physical CUS delay explicitly.')\n        step = rows[1][0] - rows[0][0]\n        if step <= 0 or any(b[0] <= a[0] or not math.isclose(b[0] - a[0], step, rel_tol=1e-9, abs_tol=abs(step) * 1e-12)\n                            for a, b in zip(rows, rows[1:])):\n            raise ValueError('CUS requires a strictly increasing uniform sample grid; explicitly resample irregular data elsewhere.')\n        text = ' '.join(format(row[1], '.17g') for row in rows) + '\\n'\n        with args.output.open('x', encoding='utf-8', newline='\\n') as stream:\n            stream.write(text)\n        print(json.dumps({'status': 'converted', 'samples': len(rows), 'Ts_seconds': step, 'Sf': 1,\n                          'first_sample_time_s': 0, 'last_sample_time_s': rows[-1][0],\n                          'limit': 'One voltage-amplitude row; choose interpolation, delay and repeat flag explicitly and verify the result.'}))\n        return 0\n    except (OSError, ValueError, StopIteration) as error:\n        print(str(error), file=sys.stderr)\n        return 2\n\n\nif __name__ == '__main__':\n    raise SystemExit(main()) Save check_custom.py \"\"\"Check only the complete synthetic CUS teaching deck's raw-SI CLI CSV.\n\nThe reference is independent piecewise mathematics for the exercised 2.9\nsemantics. It is not a general measured-waveform, model or accuracy validator.\nThe cubic reference uses a natural left end and zero first derivative at the\nright end; its three-point coefficients follow those four boundary equations.\n\"\"\"\nimport argparse\nimport csv\nimport json\nimport math\nfrom pathlib import Path\nimport sys\n\nNAMES = ('HOLD', 'LINEAR', 'CUBIC', 'DEFAULT', 'DELAY', 'REPEAT', 'PERIOD')\nABS_TOL_V = 2e-12\nREL_TOL = 1e-9\n\n\ndef hold(x):\n    return 1e-3 if 1 <= x < 2 else 0.0\n\n\ndef linear(x):\n    if 1 <= x < 2:\n        return 1e-3 * (x - 1)\n    if 2 <= x <= 3:\n        return 1e-3 * (3 - x)\n    return 0.0\n\n\ndef cubic(x):\n    if x < 0 or x > 3:\n        return 0.0\n    if x <= 1:\n        return 1e-3 * (x - (5 / 7) * (x ** 3 - x))\n    if x <= 2:\n        u = x - 1\n        return 1e-3 * (1 - u - (5 / 7) * ((1 - u) ** 3 - (1 - u))\n                       + (6 / 7) * (u ** 3 - u))\n    # Its clamped zero right slope gives constant extrapolation in the tail.\n    return 0.0\n\n\ndef expected(t):\n    x = t / 1e-11\n    return dict(HOLD=hold(x), LINEAR=linear(x), CUBIC=cubic(x), DEFAULT=linear(x),\n                DELAY=0.5 * hold((t - 5e-12) / 1e-11), REPEAT=hold(x % 3), PERIOD=hold(x))\n\n\ndef main():\n    p = argparse.ArgumentParser(description=__doc__)\n    p.add_argument('--csv', required=True, type=Path)\n    p.add_argument('--report', required=True, type=Path, help='New JSON result in an existing directory')\n    args = p.parse_args()\n    try:\n        if args.report.exists() or not args.report.parent.is_dir():\n            raise ValueError('Choose a new report filename in an existing directory.')\n        with args.csv.open(encoding='utf-8-sig', newline='') as stream:\n            reader = csv.reader(stream)\n            columns = next(reader)\n            if columns != ['time', *['V(' + n + ')' for n in NAMES]]:\n                raise ValueError('Expected the complete teaching deck raw-SI CLI columns; GUI-formatted exports can use different axes or labels.')\n            rows = [[float(v) for v in row] for row in reader if row]\n        if len(rows) != 76 or any(len(row) != 8 or not all(math.isfinite(v) for v in row) for row in rows):\n            raise ValueError('Expected 76 finite rows and eight complete columns.')\n        if not (rows[0][0] == 0 and math.isclose(rows[-1][0], 75e-12, rel_tol=1e-12, abs_tol=1e-23)\n                and all(a[0] < b[0] for a, b in zip(rows, rows[1:]))):\n            raise ValueError('Expected an increasing raw-seconds axis from 0 to 75 ps.')\n        errors = {n: 0.0 for n in NAMES}\n        compared = 0\n        for row in rows:\n            # Do not decide left/right continuity from floating-point rounding\n            # at a sample boundary. Compare the interior physical samples.\n            if min(abs(row[0] / 5e-12 - round(row[0] / 5e-12)), 1.0) < 1e-7:\n                continue\n            values = expected(row[0])\n            for name, value in zip(NAMES, row[1:]):\n                error = abs(value - values[name])\n                errors[name] = max(errors[name], error)\n                if not math.isclose(value, values[name], rel_tol=REL_TOL, abs_tol=ABS_TOL_V):\n                    raise ValueError('Teaching waveform mismatch for ' + name + ' at ' + str(row[0]) + ' s.')\n            compared += 1\n        if compared < 50:\n            raise ValueError('Too few independent interior samples.')\n        report = {'status': 'passed', 'samples': len(rows), 'interior_samples_compared': compared,\n                  'quantities': {'time': 's', 'voltages': 'V'}, 'max_absolute_error_V': errors,\n                  'absolute_tolerance_V': ABS_TOL_V, 'relative_tolerance': REL_TOL,\n                  'scope': 'Complete synthetic teaching deck on recorded 2.9 CUS semantics. Default interpolation and final periodic flag are explicitly checked; the cubic clamped tail is included. No arbitrary measured data or physical-device accuracy qualification.'}\n        with args.report.open('x', encoding='utf-8', newline='\\n') as stream:\n            json.dump(report, stream, indent=2)\n            stream.write('\\n')\n        print(json.dumps({'status': 'passed', 'samples': len(rows), 'interior_samples_compared': compared}))\n        return 0\n    except (OSError, ValueError, StopIteration) as error:\n        print(str(error), file=sys.stderr)\n        return 2\n\n\nif __name__ == '__main__':\n    raise SystemExit(main())","id":"josim-custom-waveform","keywords":"CUS external waveform sampled measured CSV one amplitude data row time spacing Ts scale Sf Im delay periodic flag linear default interpolation cubic overshoot quoted mixed case spaces commas parentheses filename include relative path Invalid waveform arguments static editor false positive Results current external sample file changed rerun unsupported interpolation zero waveform uniform time_s voltage_V CSV convert irregular resample","kind":"How to","title":"Drive JoSIM from a custom waveform or uniformly sampled CSV","product":"JoSIM-Pro"},"version":"2.9.0 release target; newly frozen Windows CUS review candidate","id":"josim-custom-waveform","related":["/knowledge-base/josim-netlist-basics","/knowledge-base/josim-transient-timestep","/knowledge-base/josim-workspace-diagnostics","/knowledge-base/josim-api-output","/knowledge-base/josim-run-current-source"],"downloads":[{"url":"/_functions/kbExample?name=josim-custom-waveform.zip","scope":"Exact checked input files plus instructions; final-release/platform applicability remains pending.","files":["main.cir","lib/drivers.cir","lib/Measured wave (A),1.txt","samples.csv","prepare_samples.py","check_custom.py","README.txt"],"id":"josim-custom-waveform","requires":["Compatible licensed JoSIM 2.9 candidate with maintained quoted-path repair","Complete lib directory and writable new output directory","Python 3 for supplied SI preparation/reference utilities"],"title":"Complete nested waveform hierarchy, SI sample converter and independent checker"}],"publication_status":"published","numerical_output":null,"provenance":{"execution_checks":[{"routes":["cli"],"scope":"25 independent checks cover a complete nested source/sample hierarchy, quoted special filenames, unrelated working directory, seven raw-SI waveforms, piecewise reference, explicit SI CSV conversion and error guards. Default/repeat documentation, unsupported-selector zero output and six static argument false positives remain explicit. Actual downloaded inputs repeat these checks; twelve download comparisons and both literal commands pass.","result":"passed","articles":["josim-custom-waveform"],"purpose":"current-cus-cli-reference-conversion-and-runtime-static-disagreements","version":"Frozen current-source Windows JoSIM-Pro 2.9 CUS review candidate","id":"VAL-062","records":["25 CLI/client/static-API checks","12 actual-download/native/CLI/exact-command checks"],"limit":"No case-sensitive filesystem, non-Windows/final package or arbitrary measured-device accuracy qualification.","observed":{"voltage_traces":7,"samples":76,"last_parameter":"rounded periodic boolean flag","issues":["KB-DOC-005","KB-CUS-001","KB-CUS-003"],"default_interpolation":"linear","cycle_for_three_samples_and_ten_ps":"30 ps","converter_cases":6,"cli_cases":14}},{"routes":["gui-native-scenario"],"scope":"20 independent checks cover two normal app processes, four fresh successful runs, seven current plots/CSVs, raw-SI reference agreement, external sample change/rerun/restore and missing-file rejection. The prior plot can remain labelled current after its external data changes. Actual downloaded inputs repeat these checks; twelve download comparisons and both literal commands pass.","result":"passed","articles":["josim-custom-waveform"],"purpose":"native-file-backed-waveform-rerun-recovery-and-external-data-freshness","version":"Frozen current-source Windows JoSIM-Pro 2.9 CUS review candidate","id":"VAL-063","records":["20 native/source/current-output checks","12 actual-download/native/CLI/exact-command checks"],"limit":"No product repair, physical picker/pointer, automatic session restoration, case-sensitive filesystem, other platform/final package or arbitrary measured-device accuracy qualification.","observed":{"owned_processes":2,"fresh_successful_runs":4,"traces_per_run":7,"issues":["KB-CUS-002","KB-CUS-003"],"independent_interior_samples":60,"prior_result_after_external_edit":"Results current with unchanged prior arrays until explicit Run","max_absolute_error_V":{"REPEAT":0,"HOLD":0,"DEFAULT":3.2526065174565133e-19,"CUBIC":4.119968255444917e-18,"LINEAR":3.2526065174565133e-19,"PERIOD":0,"DELAY":0},"samples_per_run":76}}],"figure_evidence":[{"evidence_limit":"Recorded teaching source/result state only. Static false positives remain visible; plots have scaled axes and do not establish arbitrary physical accuracy or final-package acceptance.","id":"josim-cus-source","reference_label":"Current-source Windows JoSIM 2.9 native CUS teaching scenario, reviewed 4 November 2026"},{"evidence_limit":"Recorded teaching source/result state only. Static false positives remain visible; plots have scaled axes and do not establish arbitrary physical accuracy or final-package acceptance.","id":"josim-cus-waveforms","reference_label":"Current-source Windows JoSIM 2.9 native CUS teaching scenario, reviewed 4 November 2026"}],"review_notes":["Four reproduced limits remain explicit: KB-DOC-005 and KB-CUS-001/002/003. The runtime includes the maintained filename repair; final distributed-package/platform and physical-operator checks remain open."],"scope":"Recorded inputs/builds only. Complete walkthrough and final-package acceptance remain separate.","verification_requirements":{"gui_method":"product-native-scenario","status":"review-incomplete","illustrations":"required","required":["technical-review","release-applicability","execution","gui-workflow","recovery","illustrations"],"legacy_walkthrough_field":"pending retained; not full GUI/release acceptance"},"sources":[{"id":"josim-pro:docs/manual_source/sections/syntax.tex","section":"Waveform and source functions / Custom Waveform; explicit current default/repeat mismatch remains tracked"},{"id":"validation:custom-waveform-20261104","section":"VAL-062 full CLI/static/client checks; VAL-063 normal native source/result/rerun recovery"}]},"title":"Drive JoSIM from a custom waveform or uniformly sampled CSV","type":"How to","markdown_url":"/_functions/kbResource?path=markdown%2Fjosim-custom-waveform.md","summary":"Keep amplitude samples, time spacing, interpolation and repeat behaviour explicit; load the complete external files and verify their timing and units with a checked example.","product":"JoSIM-Pro"}