Skip to main content

Python package implemented in Rust to decode MOSS readout data

Project description

MOSS Decoder

CI PyPI - Downloads GitHub commit activity (branch)

Python module implemented in Rust for high-performance decoding of readout data from the MOSS chip (Stitched Monolithic Pixel Sensor prototype).

Installation

$ pip install moss-decoder

Import in python and use for decoding raw data.

Example

import moss_decoder

moss_packet = moss_decoder.decode_from_file("path/to/raw_data.raw")
print(moss_packet[0])
# Unit ID: 6 Hits: 44
#  [MossHit { region: 0, row: 3, column: 11 }, MossHit { region: 0, row: 18, column: 243 }, ...
print(moss_packet[0].hits[0])
# reg: 0 row: 3 col: 11

Features

See python types for the type information the package exposes to Python.

Two classes are provided: MossPacket & MossHit.

3 types of functions are provided

decode_event(arg: bytes)  -> tuple[MossPacket, int]: ...
# allows decoding a single event from an iterable of bytes

Returns: the decoded MossPacket and the index the unit frame trailer was found. Throws if no valid MossPacket is found.

decode_multiple_events(arg: bytes) -> tuple[list[MossPacket], int]: ...
# returns as many `MossPacket`s as can be decoded from the bytes iterable. 
# This is much more effecient than calling `decode_event` multiple times. 

Returns: A list of MossPackets and the index of the last observed unit frame trailer. Throws if no valid MossPackets are found.

decode_from_file(arg: str | Path) -> list[MossPacket]: ...
# takes a `Path` and returns as many `MossPacket` as can be decoded from file. 
# This is the most effecient way of decoding data from a file.

Returns: A list of MossPackets. Throws if the file is not found or no valid MossPackets are found.

Each function has a variant with a _fsm-suffix that uses an FSM based decoder, which is both faster and validates state transitions in the MOSS protocol.

MOSS event data packet protocol FSM

The a MOSS half-unit event data packet follows the states seen in the FSM below. The region header state is simplified here.

stateDiagram-v2
  frame_header : Unit Frame Header
  frame_trailer : Unit Frame Trailer
  region_header : Region Header
  data_0 : Data 0
  data_1 : Data 1
  data_2 : Data 2
  idle : Idle

    [*] --> frame_header
    
    frame_header --> region_header

    region_header --> region_header
    region_header --> frame_trailer
    region_header --> DATA

    state DATA {
      direction LR
      [*] --> data_0
      data_0 --> data_1
      data_1 --> data_2
      data_2 --> data_0
      data_2 --> [*]
    }
    
    DATA --> idle
    DATA --> region_header
    DATA --> frame_trailer


    idle --> DATA
    idle --> frame_trailer

    frame_trailer --> [*]

MOSS event data packet decoder FSM

The FSM based decoder uses the following FSM. The delimiter is expected to be 0xFA. The default Idle value 0xFF is also assumed.

stateDiagram-v2
direction LR
  delimiter : Event Delimiter
  frame_header : Unit Frame Header
  frame_trailer : Unit Frame Trailer

  
  [*] --> delimiter
  delimiter --> EVENT
  delimiter --> delimiter

  state EVENT {

    [*] --> frame_header

    frame_header --> HITS

    state HITS {
      [*] --> [*] : decode hits
    }

    HITS --> frame_trailer

    frame_trailer --> [*]

  }

Decoding hits takes place with the FSM in the next section.

Event packet hit decoder FSM

stateDiagram-v2

  region_header0 : Region Header 0
  region_header1 : Region Header 1
  region_header2 : Region Header 2
  region_header3 : Region Header 3
  data_0 : Data 0
  data_1 : Data 1
  data_2 : Data 2
  idle : Idle

  [*] --> region_header0
  region_header0 --> region_header1
  region_header0 --> DATA
  DATA --> region_header1
  region_header1 --> region_header2
  region_header1 --> DATA
  DATA --> region_header2
  region_header2 --> region_header3
  region_header2 --> DATA
  DATA --> region_header3
  region_header3 --> DATA
  DATA --> [*]
  region_header3 --> [*]

  
    state DATA {
      direction LR
      [*] --> data_0
      data_0 --> data_1
      data_1 --> data_2
      data_2 --> data_0
      data_2 --> idle
      idle --> [*]
      idle --> data_0
      data_2 --> [*]

    }

Decoding hits using the FSM above leads to higher performance and assures correct decoding by validating the state transitions.

Motivation & Purpose

Decoding in native Python is slow and the MOSS verification team at CERN got to a point where we needed more performance.

Earliest version of a Rust package gave massive improvements as shown in the benchmark below.

Decoding 10 MB MOSS readout data with 100k event data packets and ~2.7 million hits. Performed on CentOS Stream 9 with Python 3.11

Command Mean [s] Min [s] Max [s] Relative
python moss_test/util/decoder_native_python.py 36.319 ± 0.175 36.057 36.568 228.19 ± 2.70
python moss_test/util/decoder_rust_package.py 0.159 ± 0.002 0.157 0.165 1.00

@CERN Gitlab installation for CentOS and similar distributions from local build

If you update the package source code and want to build and install without publishing and fetching from PyPI, you can follow these steps.

The .CERN-gitlab-ci.yml file contains a build-centos manual job which will build the MOSS decoder package from source and saves the package as an artifact.

  1. Start the job, download the artifacts.
  2. Unzip the artifacts and you will find a wheels package in /target/wheels/ with the .whl extension
  3. Run python -m pip install <wheels package>.whl
  4. Confirm the installation with python -m pip freeze | grep moss, it should display something containing moss_decoder @ file:<your-path-to-wheels-package>

Troubleshooting

if you get ERROR: Could not find a version that satisfies the requirement ... make sure to add .whl when performing step 3 above.

if you don't see the expected message at step 4, try running the installation command in step 3 with any or all of these options --upgrade --no-cache-dir --force-reinstall.

Project details


Download files

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

Source Distribution

moss_decoder-0.5.0.tar.gz (2.4 MB view hashes)

Uploaded Source

Built Distributions

moss_decoder-0.5.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (599.8 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

moss_decoder-0.5.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (718.3 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

moss_decoder-0.5.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (604.3 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

moss_decoder-0.5.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (606.7 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

moss_decoder-0.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (595.0 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

moss_decoder-0.5.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl (610.0 kB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

moss_decoder-0.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (599.8 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

moss_decoder-0.5.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (718.3 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

moss_decoder-0.5.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (604.3 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

moss_decoder-0.5.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (606.7 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

moss_decoder-0.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (595.0 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

moss_decoder-0.5.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl (610.0 kB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

moss_decoder-0.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (599.9 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

moss_decoder-0.5.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (718.3 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

moss_decoder-0.5.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (604.4 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

moss_decoder-0.5.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (606.9 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

moss_decoder-0.5.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (594.9 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

moss_decoder-0.5.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl (610.1 kB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

moss_decoder-0.5.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (601.1 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

moss_decoder-0.5.0-pp37-pypy37_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (720.6 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

moss_decoder-0.5.0-pp37-pypy37_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (605.9 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

moss_decoder-0.5.0-pp37-pypy37_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (608.3 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

moss_decoder-0.5.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (596.6 kB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

moss_decoder-0.5.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl (611.0 kB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

moss_decoder-0.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (599.4 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

moss_decoder-0.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl (717.7 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ s390x

moss_decoder-0.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (603.9 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ppc64le

moss_decoder-0.5.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (606.4 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARMv7l

moss_decoder-0.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (594.7 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

moss_decoder-0.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl (609.8 kB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.5+ i686

moss_decoder-0.5.0-cp311-none-win_amd64.whl (129.6 kB view hashes)

Uploaded CPython 3.11 Windows x86-64

moss_decoder-0.5.0-cp311-none-win32.whl (123.1 kB view hashes)

Uploaded CPython 3.11 Windows x86

moss_decoder-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (599.4 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

moss_decoder-0.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl (717.7 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ s390x

moss_decoder-0.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (603.9 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ppc64le

moss_decoder-0.5.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (606.4 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARMv7l

moss_decoder-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (594.7 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

moss_decoder-0.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl (609.8 kB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.5+ i686

moss_decoder-0.5.0-cp311-cp311-macosx_11_0_arm64.whl (234.0 kB view hashes)

Uploaded CPython 3.11 macOS 11.0+ ARM64

moss_decoder-0.5.0-cp311-cp311-macosx_10_7_x86_64.whl (244.2 kB view hashes)

Uploaded CPython 3.11 macOS 10.7+ x86-64

moss_decoder-0.5.0-cp310-none-win_amd64.whl (129.6 kB view hashes)

Uploaded CPython 3.10 Windows x86-64

moss_decoder-0.5.0-cp310-none-win32.whl (123.1 kB view hashes)

Uploaded CPython 3.10 Windows x86

moss_decoder-0.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (599.4 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

moss_decoder-0.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl (717.7 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ s390x

moss_decoder-0.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (603.9 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ppc64le

moss_decoder-0.5.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (606.4 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARMv7l

moss_decoder-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (594.7 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

moss_decoder-0.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl (609.8 kB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.5+ i686

moss_decoder-0.5.0-cp310-cp310-macosx_11_0_arm64.whl (234.0 kB view hashes)

Uploaded CPython 3.10 macOS 11.0+ ARM64

moss_decoder-0.5.0-cp310-cp310-macosx_10_7_x86_64.whl (244.2 kB view hashes)

Uploaded CPython 3.10 macOS 10.7+ x86-64

moss_decoder-0.5.0-cp39-none-win_amd64.whl (129.7 kB view hashes)

Uploaded CPython 3.9 Windows x86-64

moss_decoder-0.5.0-cp39-none-win32.whl (123.3 kB view hashes)

Uploaded CPython 3.9 Windows x86

moss_decoder-0.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (599.7 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

moss_decoder-0.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl (718.2 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ s390x

moss_decoder-0.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (604.3 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ppc64le

moss_decoder-0.5.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (606.8 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARMv7l

moss_decoder-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (595.0 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

moss_decoder-0.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl (610.2 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.5+ i686

moss_decoder-0.5.0-cp38-none-win_amd64.whl (129.8 kB view hashes)

Uploaded CPython 3.8 Windows x86-64

moss_decoder-0.5.0-cp38-none-win32.whl (123.3 kB view hashes)

Uploaded CPython 3.8 Windows x86

moss_decoder-0.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (599.9 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

moss_decoder-0.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl (718.4 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ s390x

moss_decoder-0.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (604.3 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ppc64le

moss_decoder-0.5.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (607.0 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARMv7l

moss_decoder-0.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (595.3 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

moss_decoder-0.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl (610.3 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.5+ i686

moss_decoder-0.5.0-cp37-none-win_amd64.whl (129.8 kB view hashes)

Uploaded CPython 3.7 Windows x86-64

moss_decoder-0.5.0-cp37-none-win32.whl (123.3 kB view hashes)

Uploaded CPython 3.7 Windows x86

moss_decoder-0.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (600.0 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

moss_decoder-0.5.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl (718.5 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ s390x

moss_decoder-0.5.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (604.5 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ppc64le

moss_decoder-0.5.0-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (607.0 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARMv7l

moss_decoder-0.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (595.1 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64

moss_decoder-0.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl (610.3 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.5+ i686

Supported by

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