Skip to main content

Stream-file parser for CrystFEL output

Project description

CFstreamparser

This is a simple Python library for parsing CrystFEL stream files, extracting global geometry, unit cell definitions, and per-frame indexing solutions.

Installation

pip install CFstreamparser

Usage Examples

from CFstreamparser import parse_stream_file

# 1. Parse a stream file

stream = parse_stream_file("path/to/your.stream")

# 2. Access global unit cell
print("Unit cell:", stream.uc)

# you can also query specific parameters, e.g. like this:

print("Unit cell:", stream.uc.a) # to get length of a.

# 3. Access global geometry parameters
print("Detector center-to-lens distance (clen):", stream.geom.params["clen"])

# 4. Retrieve a specific frame by its event number (e.g., 215)
chunk = stream.get_chunk_by_event(215)
if chunk:
    print(f"Frame {chunk.event} has {chunk.num_peaks} peaks")

    # 5. Iterate through all indexing solutions for this frame
    for sol_idx, sol in enumerate(chunk.crystals, start=1):
        print(f"Solution {sol_idx}: {sol.num_reflections} reflections, final residual {sol.predict_refine.final_residual:.3f}")

    # 6. Access the first solution's indexed reflections
    first_solution = chunk.crystals[0]

    print("First 5 indexed reflections:", first_solution.reflections[:5])
else:
    print("No chunk found for event 215")

Resolution limit analysis

The stream file contains a per-indexing-solution estimate of the diffraction resolution limit.

The library provides helpers to extract this information and generate histogram data. Values returned by these helpers are in Å.

import matplotlib.pyplot as plt
from CFstreamparser import (
    parse_stream_file,
    diffraction_resolution_limits,
    resolution_limit_histogram,
)

stream = parse_stream_file("path/to/your.stream")

# Get one resolution limit per image, selecting the best indexing solution
# (defined as the one with the most indexed reflections)
res_limits = diffraction_resolution_limits(
    stream,
    multi_solution="best",   # "best", "highest_res", or "lowest_res"
    per_image=True,
)

print("Number of images:", len(res_limits))
print("Median resolution limit (Å):", sorted(res_limits)[len(res_limits)//2])

# Build histogram data (counts and bin edges)
counts, edges = resolution_limit_histogram(
    stream,
    bins=50,
    multi_solution="best",
    per_image=True,
)

# Plot
plt.step(edges[:-1], counts, where="post")
plt.xlabel("Diffraction resolution limit (Å)")
plt.ylabel("Number of images")
plt.title("Resolution limit distribution")
plt.show()

If multiple indexing solutions exist per image, the multi_solution option controls how a single solution is selected:

  • "best": solution with the most indexed reflections (recommended default)
  • "highest_res": solution with the best (lowest Å) resolution limit
  • "lowest_res": solution with the worst (highest Å) resolution limit

Setting per_image=False returns one value per indexing solution instead of one per image, which can be useful for diagnosing multi-lattice or ambiguous indexing.

Indexing solution count statistics

CrystFEL stream files may contain zero, one, or multiple indexing solutions per image ("crystal" blocks within a chunk). The frequency of multiple solutions might be used as an indicator of indexing ambiguity, multi-lattice images, or overly permissive indexing parameters.

The library provides a helper to summarize how many solutions are found per image.

from CFstreamparser import parse_stream_file
from CFstreamparser.stats import solution_count_stats

stream = parse_stream_file("path/to/your.stream")

summary, histogram = solution_count_stats(stream)

print("Number of images:", summary.n_chunks)
print("Fraction with no solution:", summary.frac_with_0)
print("Fraction with exactly one solution:", summary.frac_with_1)
print("Fraction with multiple solutions:", summary.frac_with_2plus)
print("Maximum solutions in a single image:", summary.max_solutions_per_chunk)

print("Raw histogram (n_solutions -> n_images):")
print(histogram)

Interpretation guidelines:

  • A high fraction of images with 2+ solutions often indicates indexing ambiguity or multiple lattices in the same frame.
  • A large fraction of images with 0 solutions suggests weak diffraction, poor peak finding, or overly strict indexing thresholds.
  • Ideally, most indexed images fall into the exactly one solution category.

Unit cell parameter analysis

Stream files contain unit cell parameters for each indexing solution. The spread and clustering of these parameters are useful diagnostics for:

  • indexing stability,
  • detecting multiple phases,
  • identifying symmetry or indexing ambiguity.

The library provides helpers to extract unit cell parameters and generate histogram data for each parameter.

import matplotlib.pyplot as plt
from CFstreamparser import parse_stream_file, unit_cell_histograms

stream = parse_stream_file("path/to/your.stream")

# Compute histograms for unit cell parameters, selecting one solution per image
hists = unit_cell_histograms(
    stream,
    bins=50,
    multi_solution="best",  # most indexed reflections per image
    per_image=True,
)

# Note: lengths are returned in Å by default (nm -> Å conversion).

# Example: plot the a-axis distribution
counts_a, edges_a = hists["a"]

plt.step(edges_a[:-1], counts_a, where="post")
plt.xlabel("a (Å)")
plt.ylabel("Number of images")
plt.title("Unit cell a-parameter distribution")
plt.show()

Notes:

  • CrystFEL streams store unit cell lengths (a, b, c) in nm. By default, this library converts them to Å (via length_scale=10.0). Angles (alpha, beta, gamma) are always in degrees.
  • Broad or multi-modal distributions can indicate indexing ambiguity, incorrect symmetry assumptions, or multiple crystalline phases.
  • Setting per_image=False includes all indexing solutions and is useful for diagnosing multi-lattice images.

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

cfstreamparser-0.2.0.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

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

cfstreamparser-0.2.0-py3-none-any.whl (13.3 kB view details)

Uploaded Python 3

File details

Details for the file cfstreamparser-0.2.0.tar.gz.

File metadata

  • Download URL: cfstreamparser-0.2.0.tar.gz
  • Upload date:
  • Size: 13.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for cfstreamparser-0.2.0.tar.gz
Algorithm Hash digest
SHA256 9e7253793cea4142e012f1b70d0015fa4125392bfe1173f08eb7ecb5a687afae
MD5 c76b33aed68d20cfa744f4a6628efe53
BLAKE2b-256 d6cafeef6c3df3ec2de4765e581495a7aeb94ef1a252f035ccd70ac773e49eef

See more details on using hashes here.

File details

Details for the file cfstreamparser-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: cfstreamparser-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 13.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for cfstreamparser-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5604fed6279aab4de379159a6970e83031d2f2c48a36946f48669985abd49160
MD5 d51a5010bd4e537c87f01a66c41a6f5a
BLAKE2b-256 cad39aad8327fbcd0e9917b165a16f08d5c15f72607dc1be02805e6f407ef8f0

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