Data Flow¶
This document describes the primary data flows through XPCS Viewer, from HDF5 file ingestion through computation to GUI visualization.
XPCS Analysis Pipeline¶
The main data flow for G2 correlation analysis:
flowchart TD
HDF5["HDF5 File<br/>/xpcs/ hierarchy"]
CP["HDF5ConnectionPool<br/>fileIO/hdf_reader.py"]
XF["XpcsFile<br/>In-memory data model"]
DC["DataCache<br/>LRU cache for arrays"]
VK["ViewerKernel<br/>Analysis coordinator"]
subgraph Backend["Backend Computation"]
BE["get_backend()<br/>JAX or NumPy"]
COMP["Array Operations<br/>backend.exp(), backend.mean(), ..."]
JIT["JIT Cache<br/>(JAX only)"]
end
subgraph Fitting["Fitting Pipeline"]
NLSQ["NLSQ 0.6.0<br/>Point estimates"]
NUTS["NumPyro NUTS<br/>Posterior samples"]
FRES["FitResult<br/>ArviZ diagnostics"]
end
subgraph Output["Output Boundaries"]
PQG["PyQtGraph<br/>Interactive plots"]
MPL["Matplotlib<br/>Publication plots"]
H5W["HDF5 Write<br/>Fit results"]
end
EN["ensure_numpy()<br/>I/O boundary conversion"]
HDF5 -->|"pool.get_connection()"| CP
CP -->|"np.ndarray (float64)"| XF
XF -->|"cached reads"| DC
XF -->|"g2_data, qmap"| VK
VK -->|"lazy module load"| COMP
VK -->|"fit request"| NLSQ
BE -->|"backend arrays"| COMP
COMP -->|"JIT-compiled"| JIT
NLSQ -->|"warm-start init"| NUTS
NUTS -->|"posterior samples"| FRES
COMP -->|"analysis results"| EN
FRES -->|"plot data"| EN
EN -->|"np.ndarray"| PQG
EN -->|"np.ndarray"| MPL
EN -->|"np.ndarray"| H5W
style EN fill:#f96,stroke:#333,color:#000
style BE fill:#69f,stroke:#333,color:#000
style NLSQ fill:#9c6,stroke:#333,color:#000
style NUTS fill:#9c6,stroke:#333,color:#000
Array Type Transitions¶
Stage |
Array Type |
Notes |
|---|---|---|
HDF5 read |
|
Always NumPy from h5py |
XpcsFile storage |
|
Cached as NumPy |
Backend computation |
JAX array or |
Depends on active backend |
JIT cache |
JAX array |
Compiled traces cached |
NLSQ fitting |
|
NLSQ operates on NumPy |
NumPyro NUTS |
JAX array |
Requires JAX backend |
I/O boundary |
|
|
PyQtGraph/Matplotlib |
|
Display libraries require NumPy |
SimpleMask Data Flow¶
Mask editing and Q-map computation flow:
flowchart TD
IMG["Detector Image<br/>np.ndarray (H, W)"]
SMW["SimpleMaskWindow<br/>User draws ROIs"]
SMK["SimpleMaskKernel<br/>Computation core"]
subgraph MaskOps["Mask Operations"]
AM["AreaMask<br/>Undo/redo history"]
DT["DrawingTools<br/>Rect, Circle, Polygon, ..."]
MASK["Final Mask<br/>int32, values 0/1"]
end
subgraph QMapComp["Q-Map Computation"]
GEO["GeometryMetadata<br/>bcx, bcy, det_dist, ..."]
QM["qmap.compute_qmap()<br/>JIT-compiled (JAX)"]
QRES["QMapSchema<br/>sqmap, dqmap, phis"]
end
subgraph Partition["Partition Generation"]
PG["utils.generate_partition()<br/>JIT-compiled (JAX)"]
PS["PartitionSchema<br/>partition_map, val_list, num_list"]
end
subgraph Export["Signal Export"]
SIG1["mask_exported<br/>Signal(np.ndarray)"]
SIG2["qmap_exported<br/>Signal(dict)"]
end
XV["XPCS Viewer<br/>apply_mask(), apply_qmap_result()"]
H5["HDF5 File<br/>Mask/Partition persistence"]
IMG --> SMW
SMW --> SMK
SMK --> AM
DT --> AM
AM --> MASK
SMK --> QM
GEO --> QM
QM --> QRES
QRES --> PG
MASK --> PG
PG --> PS
MASK --> SIG1
PS --> SIG2
SIG1 -.->|"loose coupling"| XV
SIG2 -.->|"loose coupling"| XV
SMK --> H5
style SIG1 fill:#f96,stroke:#333,color:#000
style SIG2 fill:#f96,stroke:#333,color:#000
Signal Payload Schemas¶
mask_exported(np.ndarray):
Shape:
(H, W), dtype:int32Values: 0 (masked) or 1 (valid)
qmap_exported(dict):
{
"partition_map": np.ndarray, # int32, (H, W), Q-bin indices
"num_pts": int, # Number of Q-bins
"val_list": list[float], # Q-bin center values
"num_list": list[int], # Pixels per Q-bin
}
Fitting Data Flow¶
The two-stage Bayesian fitting pipeline:
flowchart TD
G2["G2 Data<br/>delay_times, g2, g2_err"]
subgraph Stage1["Stage 1: NLSQ Warm-Start"]
NF["nlsq.nlsq_optimize()"]
NR["NLSQResult<br/>Point estimates + CurveFitResult"]
P0["Initial params<br/>tau, baseline, contrast"]
end
subgraph Stage2["Stage 2: Bayesian Inference"]
MC["NumPyro Model<br/>single_exp_model()"]
NU["NUTS Sampler<br/>4 chains x 1000 samples"]
PS["Posterior Samples<br/>dict[str, ndarray]"]
end
subgraph Diagnostics["Convergence Diagnostics"]
RH["R-hat < 1.01"]
ESS["ESS bulk/tail > 400"]
DIV["Divergences == 0"]
BF["BFMI >= 0.2"]
FD["FitDiagnostics"]
end
subgraph Results["Result Objects"]
FR["FitResult<br/>samples + diagnostics"]
AZ["xarray DataTree<br/>Posterior plots"]
end
G2 --> NF
NF --> NR
NR -->|"warm-start"| P0
P0 --> MC
MC --> NU
NU --> PS
PS --> RH
PS --> ESS
PS --> DIV
PS --> BF
RH --> FD
ESS --> FD
DIV --> FD
BF --> FD
PS --> FR
FD --> FR
FR --> AZ
style NR fill:#9c6,stroke:#333,color:#000
style FR fill:#69f,stroke:#333,color:#000
style FD fill:#f96,stroke:#333,color:#000
Convergence Thresholds¶
Diagnostic |
Threshold |
Meaning |
|---|---|---|
R-hat |
< 1.01 |
All chains converge to same distribution |
ESS bulk |
> 400 |
Sufficient effective samples for mean/variance |
ESS tail |
> 400 |
Sufficient effective samples for quantiles |
Divergences |
== 0 |
No divergent transitions |
BFMI |
>= 0.2 |
Adequate energy exploration |
HDF5 File Schema¶
The standard HDF5 file structure for XPCS data:
graph LR
subgraph HDF5["HDF5 File Structure"]
ROOT["/"]
XPCS["/xpcs/"]
QMAP["/xpcs/qmap/"]
G2["/xpcs/g2/"]
META["/xpcs/metadata/"]
SM["/simplemask/"]
SMMASK["/simplemask/mask/"]
SMPART["/simplemask/partition/"]
end
ROOT --> XPCS
ROOT --> SM
XPCS --> QMAP
XPCS --> G2
XPCS --> META
SM --> SMMASK
SM --> SMPART
subgraph QMapDS["Q-Map Datasets"]
SQ["sqmap<br/>float64, (H,W)"]
DQ["dqmap<br/>float64, (H,W)"]
PH["phis<br/>float64, (H,W)"]
MK["mask<br/>int32, (H,W)"]
PM["partition_map<br/>int32, (H,W)"]
end
subgraph G2DS["G2 Datasets"]
G2V["g2<br/>float64, (n_delay, n_q)"]
G2E["g2_err<br/>float64, (n_delay, n_q)"]
DT["delay_times<br/>float64, (n_delay,)"]
QV["q_values<br/>float64, (n_q,)"]
end
subgraph MetaDS["Metadata Attributes"]
BCX["bcx: float"]
BCY["bcy: float"]
DD["det_dist: float (mm)"]
LAM["lambda_: float (A)"]
PD["pix_dim: float (mm)"]
SHP["shape: (H, W)"]
end
QMAP --> QMapDS
G2 --> G2DS
META --> MetaDS
I/O Boundary Summary¶
All I/O boundaries where ensure_numpy() conversion occurs:
Boundary |
Direction |
Source Module |
Target |
|---|---|---|---|
PyQtGraph plotting |
Backend -> NumPy |
|
|
Matplotlib plotting |
Backend -> NumPy |
|
|
HDF5 write |
Backend -> NumPy |
|
|
HDF5 read |
NumPy -> Backend |
|
|
Signal export |
Backend -> NumPy |
|
|