Skip to main content

Extended XYZ file format tools

Project description

Extended XYZ specification and parsing tools

This repository contains a specification of the extended XYZ (extxyz) file format, and tools for reading and writing to it from programs written in C, Fortran, Python and Julia.

Installation

Python

The latest development version can be installed via

pip install git+https://github.com/libAtoms/extxyz

This requires Python 3.6+ and a working C compiler, plus the PCRE2 and libcleri libraries. libcleri is included here as a submodule and will be compiled automatically, but you may need to install PCRE2 with something similar to one of the following commands.

brew install pcre2 # Mac OS, with homebrew
sudo apt-get install libpcre2-dev # Ubuntu

Binary wheels for Linux and MacOS which do not require PCRE2 or libcleri are built in the GitHub CI for each tagged release.

Stable releases are made to PyPI, so you can install with

pip install extxyz

libextxyz C library

The underlying parser is written in C. The C code is compiled automatically when you build the Python package, but you can also compile it as shared library libextxyz.so as follows

make -C libextxyz
make -C libextxyz install

The Makefile respects the usual environment variables CC, CFLAGS, LDFLAGS, etc, plus prefix (default /usr/local).

Fortran bindings

To build the fextxyz exectuable demonstrating the Fortran bindings, you first need to download and compile QUIP -- see the CI for an example of how to do that automatically. Then, set QUIP_ROOT and QUIP_ARCH

export QUIP_ARCH=linux_x86_64_gfortran
export QUIP_ROOT=/path/to/QUIP
make -C libextxyz fextxyz

The Fortran bindings will later be moved to QUIP, since they are tied to QUIP's Dictionary and Atoms types.

Julia bindings

Julia bindings are distributed in a separate package, named ExtXYZ.jl. See its documentation for further details.

Usage

Usage of the Python package is similar to the ase.io.read() and ase.io.write() functions, e.g:

from extxyz import read, iread, write, ExtXYZTrajectoryWriter
from ase.build import bulk
from ase.optimize import BFGS
from ase.calculators.emt import EMT

atoms = bulk("Cu") * 3
frames = [atoms.copy() for frame in range(3)]
for frame in frames:
    frame.rattle()
    
write("filename.xyz", frames)

frames = read("filename.xyz") # all frames in file
atoms = read("filename.xyz", index=0) # first frame in file
write("newfile.xyz", frames)

traj = ExtXYZTrajectoryWriter("traj.xyz", atoms=atoms)
atoms.calc = EMT()
opt = BFGS(atoms, trajectory=traj)
opt.run(fmax=1e-3)

There is also an extxyz command line tool for testing purposes, see extxyz -h for help. This can alternatively be invoked via python -m extxyz.

Remaining issues

  1. make treatement of 9 elem old-1d consistent: now extxyz.py always reshapes (not just Lattice) to 3x3, but extxyz.c does not.
  2. Since we're using python regexp/PCRE, we could make per-atom strings be more complex, e.g. bare or quoted strings from key-value pairs. Should we?
  3. Decide what to do about unparseable comment lines. Just assume an old fashioned xyz with an arbitrary line, or fail? I don't think we really want every parsing breaking typo to result in plain xyz.
  4. Used to be able to quote with {}. Do we want to support this?

Extended XYZ specifcation

General formatting

  • Allowed characters: printable subset of ASCII, single byte
  • Allowed whitespace: plain space and tab (no fancy unicode nonbreaking space, etc)
  • Allowed end-of line (EOL) characters set by implementation + OS
    • pure python: whatever is used to return lines by file object iterator
    • low level c: fgets()
  • Blank lines: allowed only as 2nd line of each frame (for plain xyz) and at end of file

General definitions

  • regex: PCRE/python regular expression
  • Whitespace: regex \s, i.e. space and tab

Primitive Data Types

String

Sequence of one or more allowed characters, optionally quoted, but must be quoted in some circumstances.

  • Allowed characters - all except newline
  • Entire string may be surrounded by double quotes, as first and last characters (must match). Quotes inside string that are same as containing quotes must be escaped with backslash. Outermost double quotes are not considered part of string value.
  • Strings that contain any of the following characters must be quoted (not just backslash escaped)
    • whitespace (regex \s)
    • equals =
    • double quote ", must be represented by \"
    • comma ,
    • open or close square bracket [ ] or curly brackets { }
    • backslash, must be represented by double backslash \\
    • newline, must be represented by \n
  • Backslash \: only present in quoted strings, only used for escaping next character. All backslash escaped characters are the following character itself except \n, which encodes a newline.
  • Must conform to one of the following regex
    • quoted string: (")(?:(?=(\\?))\2.)*?\1
    • bare (unquoted) string: (?:[^\s=",}{\]\[\\]|(?:\\[\s=",}{\]\[\\]))+
  • only used in comment line key-value pairs, not per-atom data

Simple string

Sequence of one or more allowed characters, unquoted (so even outermost quotes are part of string), and without whitespace

  • allowed characters - regex \S, i.e. all except newline and whitespace
  • regex \S+
  • only used in per-atom data, not comment line key-value pairs

Logical/boolean

  • T or F or [tT]rue or [fF]alse or TRUE or FALSE
  • regex
    • true: (?:[tT]rue|TRUE|T)\b
    • false: (?:[fF]alse|FALSE|F)\b

Integer number

string of one or more decimal digits, optionally preceded by sign

  • regex [+-]?+(?:0|[1-9][0-9]*)+\b

Floating point number

  • optional leading sign [+-], decimal number including optional decimal point ., optional [dDeE] folllowed by exponent consisting of optional sign followed by string of one or more digits
  • regex
    • integer without leading sign bare_int = '(?:0|[1-9][0-9]*)'
    • optional sign opt_sign = '[+-]?'
    • floating number with decimal point float_dec = '(?:' + bare_int + '\.|\.)[0-9]*'
    • exponent exp = '(?:[dDeE]'+opt_sign+'[0-9]+)?'
    • end of number num_end = '(?:\b|(?=\W)|$)'
    • combined float regexp opt_sign + '(?:' + float_dec + exp + '|' + bare_int + exp + '|' + bare_int + ')' + num_end

Order for identifying primitive data types, accept first one that matches

  • int
  • float
  • bool
  • bare string (containing no whitespace or special characters)
  • quoted string (starting and ending with double quote and containing only allowed characters)

one dimensional array (vector)

sequence of one or more of the same primitive type

  • new style: opens with [, one or more of the same primitive type separated by commas and optional whitespace, ends with ]
  • backward compatible: opens with " or {, one or more of the same primitive types (all types allowed in {}, all except string in "") separated by whitespace, ends with matching " or }. For backward compatibility, a single element backward compatible array is interpreted as a scalar of the same type.
  • primitive data type is determined by same priority as single primitive item, but must be satisfied by entire list simultaneously. E.g. all integers will result in an integer array, but a mix of integer and float will result in a float array, and a mix of integer and valid strings will results in a string array.

two dimensional array (matrix)

sequence of one or more new style one dimensional arrays of the same length and type

  • opens with [, one or more new style one dimensional arrays separated by commas, ends with ]
  • all contained one dimensional arrays in a single two dimensional array must have same number and primitive data type elements, and will be promoted to other possible types if necessary to parse entire array. E.g. a row of integers followed by a row of strings will be promoted to a 2-d string array.

XYZ file

A concatenation of 1 or more FRAMES (below), with optional blank lines at the end (but not between frames)

FRAME

  • Line 1: a single integer <N> preceded and followed by optional whitespace
  • Line 2: zero or more per-config key=value pairs (see key-value pairs below)
  • Lines 3..N+2: per-atom data lines with M columns each (see Properties and Per-Atom Data below)

key=value pairs on second ("comment") line

Associates per-configuration value with key. Spaces are allowed around = sign, which do not become part of the key or value.

Key: bare or quoted string

Value: primitive type, 1-D array, or 2-D array. Type is determined from context according to order specified above.

Special key "Properties”: defines the columns in the subsequent lines in the frame.

  • Value is a string with the format of a series of triplets, separated by “:”, each triplet having the format: “<name>:<T>:<m>”.
    • The <name> (string) names the column(s), <T> is a one of “S”, “I”, “R”, “L”, and indicates the type in the column, “string”, “integer”, “real”, “logical”, respectively. <m> is an integer > 0 specifying how many consecutive columns are being referred to.
    • The sum of the counts "m" must equal number of per-atom columns M (as defined in FRAME)
  • If after full parsing the key “Properties” is missing, the format is retroactively assumed to be plain xyz (4 columns, Z/species x y z), the entire second line is stored as a per-config “comment” property, and columns beyond the 4th are not read.

Per-atom data lines

Each column contains a sequence of primitive types, except string, which is replaced with simple string, separated by one or more whitespace characters, ending with EOL (optional for last line). The total number of columns in each row must be equal to the M and to the sum of the counts "m" in the "Properties" value string.

READING ase.atoms.Atoms FROM THIS FORMAT

Specific keys indicate special values, with specific order for overriding

Key-value pairs:

  • Lattice -> Atoms.cell, optional [do we want to accept "cell" also?]
    • 3x3 matrix - rows are cell vectors [preferred]
    • 9-vector - 3 cell vectors concatenated [only for backward compat]
    • 3-vector - diagonal entries of cell matrix [?]
  • pbc -> Atoms.pbc, optional
    • 3-vector of bool
    • default [False]*3 if no Lattice, otherwise [True]*3
  • Calculator results, used to set SinglePointCalculator.results dict
    • all per-config properties in ase.calculator.all_properties, with same name
    • scalars, vectors - directly stored
    • stress
      • 6-vector Voigt
      • 9-vector, 3x3 matrix, stored as stress Voigt-6, fail if not symmetric
    • virial -> stress (to convert multiply by -1/cell_vol), same format as stress [warn/fail if stress also present, perhaps only if inconsistent?]

Properties keys (all types are per-atom), types are simple

  • Atoms
    • Z -> numbers
    • species -> numbers, fail if not valid chemical symbol [warn/fail if conflict with Z?]
    • pos -> positions
    • mass -> masses
    • velo -> momenta (get mass from atomic number if missing)
    • same name: initial_charges, initial_magmoms
  • Calculator.results
    • local_energy -> energies
    • forces -> forces [also support “force”? What about overriding, complain if inconsistent?]
    • same name: magmoms (scalar or 3-vector), charges

WRITING ase.atoms.Atoms TO THIS FORMAT

General considerations

  • platform-appropriate EOL
  • [require some specific whitespace convention?]
  • scalars
    • all strings are quoted
    • otherwise stored unquoted
  • arrays
    • use {} [or []?] container marks, comma separated (not backward compatible " and space separated forms)
  • Definitely store (naming as described below)
    • all "first-class" Atoms properties (cell, pbc, numbers, masses, positions, momenta [any others?])
    • all info keys that are scalar, 1-D, 2-D array of prim type
    • all arrays that are scalar (Natoms x 1) or 1-D array( Natoms x (m > 1)) of prim type, shape[1] mapped to number of columns and space separated, not using regular array notation
    • [optionally warn about un-representable quantities?]
  • all Calculator.results key-value pairs, per-config same as info, per-atom same as arrays
  • Perhaps store
    • all info keys, per-config calculator results that are not representable (i.e. not prim type scalar, 1-D, or 2-D for per-config only) but can be mapped to JSON, as string starting with "_JSON "
    • same for arrays [?]
  • In general, keep ASE data type/dimension, invert mapping of names for reading. For quantities that have multiple possible names, use:
    • Lattice, not cell, 3x3 matrix
    • velo, not momenta
    • stress, not virial, as 3x3 matrix [are we OK with this?]

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

extxyz-0.2.0-cp313-cp313-win_amd64.whl (280.6 kB view details)

Uploaded CPython 3.13Windows x86-64

extxyz-0.2.0-cp313-cp313-manylinux_2_28_x86_64.whl (260.0 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

extxyz-0.2.0-cp313-cp313-macosx_15_0_x86_64.whl (285.6 kB view details)

Uploaded CPython 3.13macOS 15.0+ x86-64

extxyz-0.2.0-cp313-cp313-macosx_15_0_arm64.whl (266.2 kB view details)

Uploaded CPython 3.13macOS 15.0+ ARM64

extxyz-0.2.0-cp312-cp312-win_amd64.whl (280.6 kB view details)

Uploaded CPython 3.12Windows x86-64

extxyz-0.2.0-cp312-cp312-manylinux_2_28_x86_64.whl (260.0 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

extxyz-0.2.0-cp312-cp312-macosx_15_0_x86_64.whl (285.6 kB view details)

Uploaded CPython 3.12macOS 15.0+ x86-64

extxyz-0.2.0-cp312-cp312-macosx_15_0_arm64.whl (266.2 kB view details)

Uploaded CPython 3.12macOS 15.0+ ARM64

extxyz-0.2.0-cp311-cp311-win_amd64.whl (280.6 kB view details)

Uploaded CPython 3.11Windows x86-64

extxyz-0.2.0-cp311-cp311-manylinux_2_28_x86_64.whl (260.0 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

extxyz-0.2.0-cp311-cp311-macosx_15_0_x86_64.whl (285.6 kB view details)

Uploaded CPython 3.11macOS 15.0+ x86-64

extxyz-0.2.0-cp311-cp311-macosx_15_0_arm64.whl (266.2 kB view details)

Uploaded CPython 3.11macOS 15.0+ ARM64

extxyz-0.2.0-cp310-cp310-win_amd64.whl (280.6 kB view details)

Uploaded CPython 3.10Windows x86-64

extxyz-0.2.0-cp310-cp310-manylinux_2_28_x86_64.whl (260.0 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ x86-64

extxyz-0.2.0-cp310-cp310-macosx_15_0_x86_64.whl (285.6 kB view details)

Uploaded CPython 3.10macOS 15.0+ x86-64

extxyz-0.2.0-cp310-cp310-macosx_15_0_arm64.whl (266.2 kB view details)

Uploaded CPython 3.10macOS 15.0+ ARM64

File details

Details for the file extxyz-0.2.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: extxyz-0.2.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 280.6 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for extxyz-0.2.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 1d6ec3517ce3f85ffc45061c63170cef129c3929589af1258d0b70cb12525875
MD5 b2871100e7b3d0424c6f50a0a3fe2043
BLAKE2b-256 82bf771b9566466d391551e0ed2b576d269ff58c6a004576819dc83f39236bca

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7d2cb4bd17c3cd8b0a0ef134261f8932996a6a9fd6288600150a4b8ac2ad0513
MD5 8e62c6c4728b29857e03bc3adcdbb3ee
BLAKE2b-256 3ad921cc68d8caf164215aad767ab7200500fbaf9764afc7f38866fa1d068b6d

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp313-cp313-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp313-cp313-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 0f94fd3cdfb912d61c6677cc9a522c72faa1876e6c0abc066d990ee1bce5ff55
MD5 ed7f5e0a6d4b93306a32cf58bc1c32f5
BLAKE2b-256 27d8015a35d4654298c7743eeb56f3ac17afcf9f418a34bb3848f8f25e499dec

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp313-cp313-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp313-cp313-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 4b74e061a63f5361aed4db15719b9b7db336f36dbf482d013985eb9caf76fa72
MD5 240d5595001c99548e2d499ae40d8ea0
BLAKE2b-256 5094f5bb8c7f535934287b1aa686c393e6e8cc6b0645978de8ea3557977ad9f5

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: extxyz-0.2.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 280.6 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for extxyz-0.2.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 6351faf4bfef84135029721821b77df86b2b9d336a37a922d8c0af431943196f
MD5 360654cb8fb9bc33f15a804a0a3e3716
BLAKE2b-256 df600a113c868b09e5050cf9733ffcafa23743dc9c3120814140f820162ad188

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0da54fa5a75f4117ad6d5ccac10c5f8e42d9e6f665b0ce281b5849dcf9ed4c94
MD5 b9a524eca7e1fda66bf30e47eb68b59d
BLAKE2b-256 dd7ac73700cee236748d1511dae993f1dbf11323f5ffc52936bebea5802ee7dd

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp312-cp312-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp312-cp312-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 cf11d202e85eaa14852a9daac4380b419110d6bab60a7cf21d598d2cb167e3b9
MD5 82b793e4310f827c16bd46f582ebe27e
BLAKE2b-256 389f4677b7427d86e69099e5cabde857775c77b9bd36c3ce2a2bfa3b3a00909d

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp312-cp312-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp312-cp312-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 7995f56187311b74a01dd4ced9b3a3eeee6086eac722121ce0ebae566f11aa5a
MD5 d8f1f16a3002b6ab61e04a45071ac946
BLAKE2b-256 0892c722d2a11264b0fee597c313c513354a64125ea4b0215f9c0659d8e936ec

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: extxyz-0.2.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 280.6 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for extxyz-0.2.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 e53650a8b3c7ece8656c2544ee8beee5fe4ffb1bc6bfdc15e6a7b6ecd9182fe7
MD5 9faceb3c2fa7095ef1ca9eeb017d372f
BLAKE2b-256 00127452248e52d7fe90f7e2ca3e87aac3a4b07aba535709fc1c4e01fb342006

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d37acb88062b1ab37a3871dbe4bc6505c34b3c1767689de1934d03f658c3348c
MD5 0feccfc916168886bab75956804e44fa
BLAKE2b-256 c817b5c1d1272214f6be2e52104c5a0fd52ff1c3c295cf3f4420c05b404a74c3

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp311-cp311-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp311-cp311-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 550a81fae29450bf8598cec70e0e500ed82e531120e54ebda19191c73718018d
MD5 e016e7cbb6f90dedd6ab96b45077b5e8
BLAKE2b-256 34ce8e04ec1ce913d3b367c28e08a83a2135297e203025f180723da6d92fcf4a

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp311-cp311-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp311-cp311-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 fa07f1a47690bcdd8bd64d71f8a813efbc624dc28fcdb4d5dc0e00a09e01bf23
MD5 e84506b9f93adbe5b43f58fd025582cb
BLAKE2b-256 5cce8d79ad1d1d06e7e0ccef3f039de8f04d9d1dd3a42a63b69dc5d80e3f317b

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: extxyz-0.2.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 280.6 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for extxyz-0.2.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 21261d4b0a9fc068b3f82a6925d95555af2bd5132b19a524cbe39e37645f1052
MD5 d6017db444096f5fa5fb60ed528002df
BLAKE2b-256 f00339ec907edbbf5f4adea913f4c0b4419c79859ae34d5fd605693175f120a9

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp310-cp310-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 2f69557cb4cc02a41526a5ef803bc33df3707b13c8e9fec962ba5d64a6ba1700
MD5 56de792ecc766e3cb906b667fddf8221
BLAKE2b-256 7e917fba1d1d6c2c89be6fae295d38bb11109288377e0fff92caba4083b6397d

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp310-cp310-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp310-cp310-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 8ce82128de53cf6d8b9e5c91984b7e90b83f9bda1a1737713dafbf3a62ea5468
MD5 7144f4e86c7e985244b6b918b59dca6a
BLAKE2b-256 264b355b40c1f94974486a26b0c0fe2d8aa191c52a56ebb5a23bd2f81b458cb0

See more details on using hashes here.

File details

Details for the file extxyz-0.2.0-cp310-cp310-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for extxyz-0.2.0-cp310-cp310-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 02d69dc27989791d707b37ca04e54393ef427491012c05dc02d9e30ee8a95bd8
MD5 35ffeb033e19fcf4f89910bcf364edc0
BLAKE2b-256 b52ec0e8be7d610b5c41e6819b3c3849406e81219fc98278a51281994e706c11

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page