Skip to content

Releases

v0.11.0

Choose a tag to compare

@github-actions github-actions released this 07 Nov 20:54

Added

  • CITATION.cff: cite the original pysrim paper (Ostrouchov, Zhang, Weber 2018, JOSS); every git author and co-author is listed in CITATION.cff and the package metadata.
  • New documentation front page (docs/index.md) with two routes: a Python route (install, the boron reference case) and an agent route (install the skill, give it a task), and four sidebar sections (Get started, Gallery, Guides, Reference).
  • Example gallery (docs/gallery.md) with a picture and its code for every entry; the pictures are rebuilt by docs/gallery/make.py, and the entries that run SRIM need an installed SRIM.
  • First-simulation page (docs/first-simulation.md) replaces the 2018 tutorial.
  • Agent guide (docs/agents.md): how an AI coding agent uses the pysrim2 skill, with example prompts.
  • Examples page (docs/examples.md) lists the example scripts and notebooks.
  • Regenerated API reference (docs/api/), one page per part of the library.
  • Citing page (docs/citing.md) with the BibTeX entry and the SRIM citation, and a citing section in the README.
  • The documentation is built in CI (docs job, sphinx-build -W), so a warning fails the build as it does on Read the Docs.

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 07 Nov 07:14

Added

  • Beam distributions in run.yaml and RunSpec: ion.energy_keV, ion.angle_deg and ion.azimuth_deg take a number or a distribution (Gaussian, uniform, triangular, log-normal, histogram file or inline, or a Python function), ion.position sets the start position, and beam: chooses exact or binned mode; --set and scan keys reach into the distributions. Runs without distributions are unchanged.
  • Exact mode of a distributed run (beam.mode: exact, the default) samples every ion from the distributions and writes SRIM's TRIM.DAT, so one TRIM.run() runs exactly that beam (calculation 1 and 2 become SRIM 4 and 5); the histogram files it used are copied to the run folder's beam/ folder. Up to 99 999 ions per run. An in-place run (srim_directory=) never deletes a TRIM.DAT or beam/ file that pysrim2 did not write, and an exact run there is refused if such a TRIM.DAT would be overwritten.
  • Binned beams in scans (beam.mode: binned): each scan point with a binned beam runs as one SRIM run per bin, the ions split over the bins by apportionment, in beam batches for precision targets and batch_ions; the bins' results are merged back into one result per point. Exact distributed points with more than 99 999 ions need batch_ions: 99999.
  • Point folders of batched scan points record their units (run.yaml, units.csv, and beam_bins.csv for binned beams), and srim.beam.open_results(point_dir) re-opens a finished batched point as one merged result.
  • Documentation for beam distributions: docs/beam.md (both modes, every shape, histogram files, Python functions, seeds, results and limits), an example script (examples/scripts/beam_energy_spread.py), a notebook (examples/notebooks/Beam.ipynb), beam sections in docs/run-spec.md, docs/scans.md and docs/dataframes.md, and an agent-skill section (skills/pysrim2/SKILL.md, section 8).
  • srim.beam.run_beam(spec) runs a distributed run spec (one TRIM run for an exact beam of up to 99 999 ions, else a one-point scan that splits exact beams into units and runs binned beams per bin) and returns the results; srim.beam.sampled_ions(results) reads the sampled ions back from TRIM.DAT, and srim.beam.plot_beam(results, parameter) draws the defined density over the sampled beam or the bins (matplotlib, the plot extra). pysrim2 run accepts distributed specs and prints where the results are.

Changed

  • The scan cache key and point id cover beam distributions: their definitions, histogram content (not only the file path) and the source of Python-function distributions, so a changed distribution never reuses an old run. Specs without distributions keep their keys.

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 06 Nov 23:26

Changed

  • TRIM.run() and SR.run() now run in an isolated directory by default. Every run works in its own private copy of the SRIM install (hard links for the read-only files, so a copy adds well under 15 % of SRIM's size; real copies of what SRIM writes) under <data dir>/runs (or work_dir=); the installed SRIM directory is never written to, so any number of runs, scripts, scans or users can run at the same time. On Linux each run also gets its own clone of the wine prefix, so cleaning up after a failure only stops that run's wine processes. The returned Results points at the run directory (results.directory); pass output_dir= to get the output files and run.yaml in a folder of your choice (the run directory is then removed unless keep=True); run_dir= reuses a srim.rundir.RunDir. A failed run keeps its directory for debugging and names it in the error.
    Migration: code that read outputs from the SRIM directory after run() (TRIM.copy_output_files(srim_dir(), dest), Results(srim_dir())) must use the returned results instead: TRIM.copy_output_files(results.directory, dest) or run(output_dir=dest). Passing srim_directory= explicitly keeps the old in-place behaviour, now under an exclusive file lock (a second run waits and prints a message after 5 s; lock_timeout= limits the wait).

  • TRIM.copy_output_files copies the files that SRIM writes to its SRIM Outputs subfolder instead of moving them, so a Results of the source (the one run() returned) keeps working afterwards.

  • pysrim2 run uses an isolated run directory too, so several can run at once.

  • Runs no longer change the process working directory (the input writers take a directory= argument and SRIM is started with cwd=), so run() is safe in threads. Under xvfb-run every run claims its own display number (-n, via lock files <tmp>/.pysrim2-xvfb-<N>.lock) instead of racing with -a; an X server that fails to start is retried up to three times.

  • Run directories without output_dir= are deleted automatically once unused for 7 days (PYSRIM2_RUN_RETENTION_DAYS, 0 keeps them; failed runs too); Results.close() / with trim.run() as results: delete one at once; pysrim2 clean runs [--older-than DAYS] [--dry-run] and pysrim2 doctor (size of the run directories) manage them. Open Results keep their run directory alive (shared lock) and pruning skips folders younger than a minute; leftovers that cannot be deleted are reported with a warning, and files shared with the SRIM install (hard links) never have their mode changed.

  • Reading outputs from the installed SRIM directory (Results(srim_dir()), TRIM.copy_output_files(srim_dir(), ...)) after isolated runs gives a one-time UserWarning explaining the 0.9.0 change.

  • Nothing is ever created in the installed SRIM directory: the lock for in-place runs lives in <data dir>/locks/, and copying the install waits for an in-place run that is writing; an in-place run in a read-only SRIM directory fails with a clear message. Relative work_dir= is made absolute.

Added

Documentation

  • New pages docs/scans.md (scan concepts, extractors and their columns and units, precision, the result table, cache, backends, live views, exit codes, tmux over SSH) and docs/concurrency.md (isolated run directories, locks, migration from 0.8, one cache for several scans). docs/cli.md lists the new commands.
  • A scan notebook (examples/notebooks/Scan.ipynb), an example scan (examples/scripts/angle_energy_scan.py and scan.yaml, run by the tests with real SRIM) and a scans section in the agent skill (skills/pysrim2/SKILL.md, section 7).

Scan definition and extractors

  • srim.scan.Scan(base, grid=, points=, extract=, ions=, seed=, batch_ions=) defines a parameter scan: a cartesian grid and/or zipped points over dotted keys (ion.energy_keV, target[0].thickness_nm), points() with a stable id per point (spec_hash), and a scan: section in run.yaml read by Scan.from_yaml / written by Scan.to_yaml. srim.scan.Precision describes a precision goal for ions=. Errors name the dotted key; number_ions and seed are not scan parameters.
  • srim.scan.extract: extractors turn a run's outputs into scan columns (register, get, available, resolve, combine) with predefined implant_summary, vacancy_at(depth_nm), peak_vacancy_depth, sputter_yield, backscattered_fraction, transmitted_fraction, ions_in_layer(layer_index) and energy_to_recoils.
  • srim.scan precision targets: Scan(..., ions=Precision(target=, rel=|abs=, min_ions=, max_ions=, batch_ions=)) runs each point in batches of ions (batch seeds derived from the point seed) until the target's standard error (<value>_err, the batch-means estimator) reaches the goal; the value is the extractors applied to all batches merged. A point that reaches max_ions first has status max_ions and a warning; a stopped point keeps the estimate of its finished batches. batch_finished events report each decision.
  • srim.scan.ScanResult: one row per scan point (parameters, id, values with <value>_err, n_ions, seeds, status, error, path relative to base_dir=, so exports hold no host paths) with to_parquet, to_csv (a folder with scan.csv and metadata.yaml), to_hdf5 and plot(x, y, hue) (matplotlib, error bars from <value>_err).
  • New optional extra pysrim2[plot] (matplotlib) for ScanResult.plot; pysrim2[all] includes it.

Running a scan

  • A scan folder holds a .pysrim2-scan marker (written by run_scan and prepare_slurm) and a running scan holds .scan.lock: a second run_scan in the same folder raises srim.scan.ScanBusy before it writes anything.
  • srim.scan.run_scan(scan, workers=, scan_dir=, on_event=, stop_event=, retries=) runs the points of a scan in worker processes (workers defaults to the CPU count minus one; each worker reuses one private run directory). It writes a scan folder (scan.yaml, points/<id>/ with the outputs and run.yaml, result/) and returns the ScanResult. A failed point is retried once with the same seed, then reported with its error (points/<id>/error.log) while the scan goes on. Progress and results arrive as JSON-safe events (srim.scan.events: scan_started, point_started, point_finished, point_failed, worker_stats, ...) from one thread, in order. Ctrl-C (or stop_event) stops scheduling, kills the running SRIM runs (also children that ignore SIGTERM) and keeps the finished points; the others get status stopped and a point_stopped event. Workers stop with their parent (POSIX: a killed scan leaves no SRIM running; its run directories are pruned by later scans). Workers that keep dying stop the scan with an error. Python extractors may be passed as callables: scan.yaml stores them as python:<module>:<name> references, which read back for module-level functions (lambdas raise a clear error when the file is read). backend="container" runs each unit in its own container (the next item).
  • srim.scan.Scan(..., batch_ions=N) (YAML scan.batch_ions) splits a point with a fixed ion count into batches of N ions, each an independent run with its own derived seed, spread over the workers; the point's values and <value>_err are the batch-means estimate, as for a precision target, and each batch is cached. The default (None) keeps one run per point. Not allowed with a precision target.
  • srim.scan.run_scan(..., pause_event=): while the event is set no new unit starts (running units finish, a stop still works); each change is reported as a scan_paused event (ScanPaused, paused).
  • srim.scan.run_batches(spec, n_ions, batch_ions, seed) runs a calculation as batches with deterministic recorded seeds (derive_seed) and returns MergedResults (per-ion tables concatenated with global ion numbers and a batch column, depth profiles merged as ion-count-weighted means, collisions streamed), usable like Results by the extractors and exports.

Result cache

  • srim.scan result cache: run_scan(..., cache=) keeps every finished SRIM run (its output folder with run.yaml) in <scan folder>/cache (or $PYSRIM2_CACHE, or the folder given; cache=False turns it off), keyed by srim.scan.cache_key(spec, seed): a SHA-256 of the run spec that writes TRIM.IN (number_ions included) and the seed, never of provenance. A rerun, or another scan that needs the same runs, reuses them without computing them again (point_cached events; status cached); a precision rerun with a tighter goal runs only its new batches; two scans that need the same run compute it once (per-key locks, so the second waits and reuses it). Entries are written atomically, failed runs are never stored, and an entry made with another SRIM build is computed again and replaced by the new run. A point all of whose runs come from the cache has status cached (a precision point that stops at max_ions keeps that status). srim.scan.clear_cache(path) empties a pysrim2 cache folder: it removes only the cache's own entries and keeps its lock files, and it warns about anything else it finds. pysrim2 scan clean is the command-line form.

Backends

  • srim.scan.run_scan(..., backend="container", image=, runtime=) runs every unit in its own container of the pysrim2 image (Podman or Docker, found like pysrim2 install; PYSRIM2_IMAGE or the release image). Events, results and cache are the same as for the local back end. The worker that runs a unit removes its container when the scan is stopped, and a Docker run gets the seccomp profile that wine needs. Without a container runtime the scan fails before any worker starts. A custom runner= is not allowed with this back end. Containers run with --platform linux/amd64 (the image is amd64-only) and --network=none.
  • Job folders: srim.scan.backends.run_job(dir) and pysrim2 run-job DIR run the units of a folde...
Read more

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 05 Nov 04:32

All SRIM outputs as pandas DataFrames (incl. per-ion positions, trajectories, backscattered/transmitted/sputtered atoms and full cascades), editable run.yaml run specs with pysrim2 run, and export to Parquet/HDF5/CSV.

Added

  • CI reports, informationally, the RANGE_3D digest of the same spec and seed on Linux (wine), Windows and in the container (the repro-report job compares Linux and Windows; the container digest is listed separately); same-platform reruns are asserted identical (tests/integration/test_reproducibility.py). Observed: Linux (wine) and the container are bit-identical, native Windows gives the same summary but different per-ion detail (see docs/run-spec.md).

  • .df (a pandas DataFrame, first column depth_A, columns named with SRIM units) and .metadata on Ioniz, Vacancy, NoVacancy, EnergyToRecoils, Phonons and Range; Results.to_dataframes(include=None) returns them as a dict.

  • srim.output.Range3D reads RANGE_3D.txt (per-ion final positions) into a DataFrame with columns ion, depth_A, y_A, z_A; Results.range3d holds it (None if the file is absent) and Results.to_dataframes() includes it.

  • Range.summary returns the range and straggling values SRIM prints in the RANGE.txt header (depth, lateral, radial, skewness, kurtosis). srim.analysis.implant_summary(df) computes the same quantities from the per-ion positions of Range3D (standard deviations with ddof=1).

  • srim.output.EXYZ, Backscat, Transmit and Sputter read EXYZ.txt, BACKSCAT.txt, TRANSMIT.txt and SPUTTER.txt into DataFrames (ion, atomic_number, energy_eV, depth_A, y_A, z_A, cos_x, cos_y, cos_z; EXYZ: ion, energy_keV, depth_A, y_A, z_A, electronic_stopping_eV_per_A, last_recoil_energy_eV); Results.exyz, .backscat, .transmit, .sputter hold them (None if absent; parsed on first access, streaming, so large files are cheap to open) and to_dataframes() returns them. A zero-byte event file gives an empty frame and a warning. They replace the stubs. EXYZ parser based on work by philis-johan. Fixtures generated with real SRIM in test_files/outputs-0.8/.

  • Collision.iter_events() streams COLLISON.txt line by line as flat event dicts (ion, kind = ion for a collision of the primary ion or recoil for a cascade recoil, energy_keV, depth_A, y_A, z_A, atom, recoil_energy_eV, target_displacements, target_vacancies, target_replacements, target_interstitials, plus atomic_number, electronic_stopping_eV_per_A, vacancy, replacement); Collision.df collects them into a DataFrame chunk-wise. Results.collision (lazy, None if absent) and Results.to_dataframes(include=["collision"]) expose them; to_dataframes() leaves collision out by default (opt-in like the exports, since COLLISON.txt can be several GB).

  • Results.to_parquet(directory), .to_hdf5(path) and .to_csv(directory) export the tables (optionally selected with include=; collision only on request) with metadata: the table's .metadata, pysrim2 version, export time and an optional run spec (source is the file name only; Parquet: schema key pysrim2; HDF5: node attribute pysrim2; CSV: metadata.yaml). Collision.to_parquet(path, chunk_rows=100_000) (also a chunk_rows argument of the Results.to_* methods) and Collision.to_csv stream the cascade events in chunks, so memory stays small for huge COLLISON.txt files. New optional extras pysrim2[parquet] (pyarrow) and pysrim2[hdf5] (PyTables); Collision.metadata. The spec argument of the exports accepts a RunSpec (stored as its mapping) or a dict; anything else raises TypeError.

  • run.yaml: srim.spec.RunSpec (and IonSpec, LayerSpec, ElementSpec) describes a run with units in the key names (energy_keV, thickness_nm, density_g_cm3, angle_deg, ...), validates it with errors naming the dotted key (SpecError), and round-trips to a byte-identical TRIM.IN. TRIM.to_spec(), TRIM.from_spec(), TRIM.to_yaml(), TRIM.from_yaml(); the seed is always recorded. TRIM.run() writes run.yaml with provenance (pysrim2 version, SRIM SHA-256, platform, backend, start/end time, host) next to the outputs (write_spec=False to skip), TRIM.copy_output_files copies it, and Results.spec is the default spec of the to_parquet/to_hdf5/to_csv exports (no host name). See docs/run-spec.md.

  • Documentation: new pages docs/dataframes.md (every column, Range.summary, implant_summary, iter_events), docs/export.md, and a full schema reference in docs/run-spec.md; the README shows .df and implant_summary.

  • pysrim2 run run.yaml [--set dotted.key=value ...] [--output DIR] runs TRIM from a run spec (values converted by the schema; outputs and run.yaml copied to DIR, default ./srim-output-<UTC timestamp>), and pysrim2 import TRIM.IN [-o run.yaml] turns an existing TRIM.IN into a run spec. Exit codes in docs/cli.md.

  • Example notebooks rewritten on the 0.8.0 API (default SRIM location, .df tables, implant_summary, Collision.iter_events() / .df, Parquet export, run.yaml with TRIM.from_spec and pysrim2 run), with small ion counts and no committed outputs; Regular SRIM Calculation.ipynb is now Regular_SRIM_Calculation.ipynb, and KTaO3.ipynb is merged into SiC.ipynb. A srim-marked test (tests/integration/test_run_notebooks.py, nbclient) executes them; a static test checks that they are valid and import existing names.

  • examples/scripts/run_yaml_example/ (a run.yaml and README for pysrim2 run run.yaml --set ion.energy_keV=30); the agent skill and examples/agents/README.md teach .df, implant_summary, event tables, cascades with iter_events() and chunked export, and run.yaml.

Changed

  • A Layer without a name is now named after its elements (Si+C, or the formula for Layer.from_formula("SiC", ...); the same default for a layer without name: in run.yaml) instead of the text None. This changes the layer name written to TRIM.IN (and run.yaml) for unnamed layers compared with 0.7.0.

Fixed

  • The .df element columns of Kinchin-Pease tables (vacancies_<element>_..., absorbed_<element>_...) are named after the element for single-element targets instead of 1; the header of those tables lists no symbols, so they are read from the target section. Multi-element targets keep the numbers.

  • A zero-byte RANGE_3D.txt gives an empty Range3D frame (same columns) and a warning, like the event files, instead of raising. Range3D also warns when a line in the data section cannot be parsed (a truncated final line is still ignored silently).

  • The reference example's "lateral straggle" (341.6 A for the boron case) was the root mean square of the radial distance, not what SRIM calls lateral straggling; the example and skill now report SRIM's definitions (lateral straggle 241.8 A, radial straggle 154.9 A).

  • Results.range3d also finds RANGE_3D.txt in the SRIM Outputs subfolder.

  • A table header whose element names cannot be read now warns before the element columns fall back to 1, 2, ...; the Vacancy.knock_ons docs give the correct unit (knock-ons per Angstrom per ion).

  • Collision (COLLISON.txt) now parses every ion: the file is decoded as cp437 and split on SRIM's box-drawing column separators, so numbers no longer fail with glued separator characters (508 of 1000 ions of the SiC-C fixture raised ValueError/IndexError). Cascades without a summary line and stray recoil lines are handled; the per-ion dict API is unchanged.

  • pysrim2 install exits 130 with a [skip] ... cancelled line on Ctrl-C during a step instead of printing a traceback.

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 04 Nov 19:47

pysrim2 can now set up SRIM itself: uv tool install pysrim2 && pysrim2 install on Windows and Linux, or the ghcr.io/fsibt/pysrim2 container (Podman/Docker).

Added

  • Documentation for the installer, the container, the command line and the agent skill (docs/installation.rst, container.md, cli.md, agents.md); the README and AGENTS.md describe the 0.7.0 setup. Example scripts for the current API in examples/scripts/ (reference case, multilayer damage profile, stopping table) and an agent example in examples/agents/.
  • pysrim2 install [COMPONENT ...] (with --dry-run and --yes) and pysrim2 doctor [--json] set up and check SRIM.
  • srim.installer.install_srim() downloads SRIM-2013 from pinned sources and verifies its checksum.
  • srim.installer.wine sets up a private wine prefix with the VB5 runtime and OCX components for SRIM on Linux; it never touches ~/.wine or $WINEPREFIX.
  • pysrim2 install runtime|image installs a container runtime (Podman preferred; Docker Desktop is never installed by pysrim2) and pulls the ghcr.io/fsibt/pysrim2 image; pysrim2 doctor checks both.
  • Integration tests that run real TRIM/SR (pytest -m srim).
  • SRIM location defaults to pysrim2's data directory (override with PYSRIM2_SRIM_DIR); an existing /tmp/srim is still used.
  • Container image ghcr.io/fsibt/pysrim2 (linux/amd64: pysrim2, SRIM-2013 and wine, non-root) built and tested by CI. Run it as its default user (do not pass -u).
  • Agent skill pysrim2 (skills/pysrim2/SKILL.md with a runnable example, shipped inside the wheel): pysrim2 install skill [--agent claude|all] [--scope user|project] copies it to ~/.claude/skills/, <project>/.claude/skills/ (and ~/.agents/skills/ for --agent all); it never overwrites a differing skill it did not write unless --yes. skill is part of the default pysrim2 install set and pysrim2 doctor checks an installed copy is current.

Changed

  • Linux: pysrim2 always runs SRIM in its own private wine prefix. If you used pysrim with /tmp/srim and ~/.wine, run pysrim2 install wine once (an existing /tmp/srim is still found).
  • The source distribution no longer includes CLAUDE.md, docs/superpowers/, .github/ or tests/.
  • The srim.plot functions take a Results object and read its attributes; passing a dict no longer works.

Fixed

  • TRIM.run()/SR.run() no longer print Mesa/EGL ("MESA-EGL", "pci id for fd") warnings; xvfb/EGL noise is dropped from both stdout and stderr and EGL/Mesa logging is turned down in wine's environment.
  • pysrim2 install runtime shows the Windows "open a new terminal" hint only when no Podman machine exists; pysrim2 install --dry-run no longer names podman in the pull command when no runtime is installed.
  • Wine setup always runs its own pinned, checksum-verified winetricks instead of one found on PATH (old copies do not know the OCX verbs).
  • pysrim2 install wine no longer hangs when a wine driver host crashes (openSUSE, wine 11): the USB/controller/Bluetooth drivers and Mono/Gecko prompts are disabled through WINEDLLOVERRIDES, wine's crash debugger is emptied, and a wineserver that does not exit within 60 s is stopped.
  • pysrim2 install wine no longer hangs after wineboot finishes: wine output is captured in a temporary file, so the background wineserver cannot keep a pipe open (same for TRIM.run()/SR.run() stderr).
  • TRIM.run() and SR.run() no longer print xvfb's "X connection to :N broken" line when SRIM exits under wine; other stderr output is kept and shown after the run. A failing run raises srim.srim.SRIMProcessError (a subprocess.CalledProcessError) whose message includes that stderr.
  • pysrim2 install prints [ok] <step>: installed (with the SRIM directory for srim) after each step succeeds.
  • A failed or interrupted (Ctrl-C) pysrim2 install wine stops the private prefix's wineserver instead of leaving wine processes running.
  • pysrim2 install prints a line as each long sub-step starts (wine prefix, winetricks, VB5 runtime, SRIM download/verify/unpack) instead of staying silent for minutes.
  • pysrim2 doctor and pysrim2 install no longer suggest "pysrim2 install wine" on distributions without known package commands; they point to the WineHQ download page instead.
  • pysrim2 install wine knows the package commands for openSUSE (zypper) and Arch (pacman, untested).
  • SRIM and the wine setup run under a 1024x768x24 virtual screen; the default 8-bit xvfb-run screen made wineboot hang on wine 11.
  • Container image: Docker 29's built-in seccomp profile makes 32-bit wine fail ("socket: Function not implemented"); pysrim2 ships Docker's current default profile as srim/data/seccomp-docker.json (pysrim2 install image copies it to the data directory and prints the docker run --security-opt seccomp=... line). Podman is the default and needs no profile (its hint uses :Z on the /data mount).
  • pysrim2 install vb5 (Windows) puts the Visual Basic 5 runtime and OCX controls next to SRIM so TRIM starts on native Windows.
  • Wine setup finds wineserver where Ubuntu installs it.
  • TRIM.run() and SR.run() delete old output first and raise SRIMRunError if SRIM wrote no result, so a crash never returns a previous run's data.
  • Winetricks downloads go to pysrim2's own cache instead of ~/.cache/winetricks.
  • TRIM.run and SR.run read their results correctly when srim_directory is a relative path.
  • SR output ranges in km are parsed instead of raising SRIMOutputParseError.
  • Parsing SRIM output no longer prints debug output to stdout.

Removed

  • The obsolete costrouc/pysrim Docker example (examples/docker/), the historical Docker benchmark page (docs/benchmarks.rst), examples/input/ and unused generated files in examples/images/.

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 23:42

Changes since pysrim 0.5.10. See
changes from pysrim for credits and details.

Added

  • Run SRIM under xvfb-run -a when it is available, so no display is needed (Jan Mayer).
  • Parse SRIM output written with comma decimal separators (philis-johan, MrRobot2211).
  • Support the m (metre) length unit in SR output (Angus Hollands).
  • SRIMOutputParseError for unknown units in SR output.
  • GitHub Actions: lint, test matrix (Python 3.11 to 3.15 on Linux, Windows and macOS), build, and a trusted-publishing release workflow.
  • Ruff configuration and pre-commit hooks.
  • Documentation: change list relative to pysrim, changelog page, AGENTS.md.

Changed

  • The distribution is renamed to pysrim2; the import name srim is unchanged. It cannot be installed alongside pysrim.
  • Requires Python 3.11 or newer.
  • Packaging uses pyproject.toml, hatchling and uv (Angus Hollands).
  • Wine is detected with shutil.which through a shared launch helper (Mirochill).
  • Code formatted with ruff.
  • Documentation uses the furo theme, is built with uv, and is hosted at https://pysrim2.readthedocs.io.
  • README and installation instructions rewritten for pysrim2.

Fixed

  • Removed the distutils import so the package imports on Python 3.12 and later (lievcm).
  • Regular expressions use raw strings, removing invalid escape sequence warnings (lievcm).
  • Ion energies with a leading or trailing decimal point (such as .3 keV) are parsed (Mirochill, George Apostolopoulos, SimonF24).
  • Positive autosave intervals are accepted (Mirochill).
  • The sputtered output setting is honoured independently of ranges (Mirochill).
  • The element database file is closed after loading.
  • Undefined names: the NotImpementedError typo in SRIM_Output._read_target, and missing numpy import and folder argument in srim.plot.
  • Plot functions read Results attributes instead of subscripting Results.
  • Docstring markup errors that produced Sphinx warnings.

Removed

  • Support for Python versions before 3.11.
  • setup.py, setup.cfg, the conda recipe, install.sh, default.nix, GitLab CI and the old Dockerfiles. A container image and a SRIM installer for wine are planned.

Versions up to and including 0.5.10 were released as pysrim by Chris Ostrouchov.

SRIM-2013 (third-party, non-commercial use only)

Choose a tag to compare

@arunpersaud arunpersaud released this 03 Nov 23:52

SRIM-2013 -- Copyright SRIM.com (James F. Ziegler), www.srim.org. All Rights Reserved.

This release redistributes the unmodified SRIM-2013 archive (srim.2013.zip). From
SRIM's own legal notice (srim/Data/LEGAL.rtf, attached):

"SRIM may be copied and distributed freely. However, no commercial use may be
made of the code, the associated files, or of its results ... without a
written license from SRIM.org."

"...this program and its associated files ... are to be used solely for
experimental uses and are not to be sold, distributed to a commercial
organization, or be commercially exploited in any manner."

By downloading or using SRIM you accept SRIM.com's disclaimer and user agreement
in LEGAL.rtf. SRIM is NOT covered by pysrim2's MIT license and is provided "as is"
without warranty. If you work for a commercial organization, obtain SRIM and a
license from SRIM.org instead of using this copy.

pysrim2 downloads this file automatically (pysrim2 install srim) and verifies
its SHA-256 checksum (see SHA256SUMS).