Aerodynamic Particle Sizer (APS)
The APS is an instrument used for measuring aerodynamic particle size distributions in the micrometer range.
AeroViz.rawDataReader.script.APS.Reader
Bases: AbstractReader
APS (Aerodynamic Particle Sizer) Data Reader
A specialized reader for APS data files, which measure particle size distributions in the range of 542-1981 nm (aerodynamic diameter).
See docs/api/instruments/particle-sizers/APS.md for usage and
docs/guide/reader-reference.md for the
file layout, status codes and QC rules.
Attributes
STATUS_BITS
class-attribute
instance-attribute
STATUS_BITS = {1 << 0: 'Laser fault', 1 << 1: 'Total Flow out of range', 1 << 2: 'Sheath Flow out of range', 1 << 3: 'Excessive sample concentration', 1 << 4: 'Accumulator clipped', 1 << 5: 'Autocal failed', 1 << 6: 'Internal temperature < 10°C', 1 << 7: 'Internal temperature > 40°C', 1 << 8: 'Detector voltage out of range'}
DATE_FORMATS
class-attribute
instance-attribute
Methods:
__call__
Return the dN/dlogDp distribution; write S/V + a stats sidecar.
The parent pipeline produces the QC-applied, resampled dN/dlogDp frame
(diameters in µm as columns) and stamps df.attrs. We then write the
number / surface / volume distributions and a QC-aligned statistics file
next to the main output. Pass append_stats=True to also append the
statistics columns to the returned frame (default keeps it a clean PSD
matrix for psd_stats / merge_psd / SizeDist).
_raw_reader
Read and parse raw APS data files.
Returns all columns from the raw file. Column selection is deferred to _QC() and _process() stages.
Handles files with multiple concatenated headers (when multiple APS export files are merged into one). Header rows are identified and filtered out.
_QC
Perform quality control on APS data.
QC Rules Applied
- Status Error : Non-zero status flags indicate instrument error
- Insufficient : Less than 5 measurements per hour
- Invalid Number Conc : Total number concentration outside valid range (1-700 #/cm³)
_process
Return the QC'd dN/dlogDp size bins (plus QC_Flag).
The size distribution itself is the canonical APS product. Summary
statistics (total per size cut, GMD / GSD / mode) and the surface and
volume distributions are derived quantities — compute them on demand
with :func:AeroViz.psd_stats / :func:AeroViz.psd_distributions
rather than baking them into the reader output. This keeps the reader's
return type a plain dN/dlogDp DataFrame (diameters in µm as columns),
which is exactly what psd_stats / merge_psd / SizeDist consume.
Raw format
- File pattern:
*.txt, tab-delimited - Native frequency:
6minis the config fallback, but the file header carriesSample Time(115 s in the corpus) — not a whole number of minutes. The native grid follows the period detected per file, so scans are not lost to bin collisions;df.attrs['raw_freq']reports what was actually used. - Encoding: opened with
encoding='utf-8', errors='ignore' - Header layout: ~6 metadata lines (
Sample File,Sample Time,Density,Stokes Correction,Lower/Upper Channel Bound) then aSample #header row, found by scanning for that first cell (so files with several concatenated headers still locate it) - Time columns:
DateandStart Time - Size distribution data: columns 3–54 of the export (the under-range
<0.523column plus the 51 bins)
Parse recipe
- Transposed exports (
Sample #as a row rather than a column header) are rotated withset_index('Sample #').T; if that fails the reader raisesNotImplementedErrorwith the original exception attached and logs the first columns it saw. - Date from
Date+Start Time, formats%m/%d/%y %H:%M:%Sthen%m/%d/%Y %H:%M:%S; the winning format is logged, and a file matching neither raises with the list of known formats. - Size bins are the numeric column names in 0.5–20 (µm), converted to float
and rounded to 4 decimal places. Expected grid
(0.542, 19.81, 51 bins)(TSI 3321/3320 factory-fixed); a deviation warns loudly but does not reject — an 8-year × 4-station audit of 1 485 files showed zero drift, so a deviation means a firmware change, and concatenating it with other files would create NaN-poisoned columns. The under-range<0.523column is kept as metadata, not a bin. - The consumed index columns (
Date,Start Time,Sample #,Aerodynamic Diameter) are dropped; rows with an unparseable or duplicated timestamp are dropped; every other source column is kept through L1.
Measurement parameters
The APS provides aerodynamic particle size distribution measurements:
| Parameter | Value | Description |
|---|---|---|
| Size range | 0.542–19.81 µm (51 bins) | Aerodynamic diameter range |
| Output | dN/dlogDp | Number concentration per size bin |
| Unit | #/cm³ | Particle number concentration |
Status & error codes
Column Status Flags, mode binary_string (see
status modes).
OK is '0000 0000 0000 0000' (16-bit binary, all zeros); any bit still set
after clearing the whitelist mask is an error. A missing Status Flags
column is logged by check_status_columns and leaves the rule inert.
Bit meanings (from the TSI RF command):
- bit
0(0000 0000 0000 0001) — Laser fault - bit
1(0000 0000 0000 0010) — Total Flow out of range - bit
2(0000 0000 0000 0100) — Sheath Flow out of range - bit
3(0000 0000 0000 1000) — Excessive sample concentration - bit
4(0000 0000 0001 0000) — Accumulator clipped (> 65535) - bit
5(0000 0000 0010 0000) — Autocal failed - bit
6(0000 0000 0100 0000) — Internal temperature < 10°C - bit
7(0000 0000 1000 0000) — Internal temperature > 40°C - bit
8(0000 0001 0000 0000) — Detector voltage out of range (±10% Vb) - bit
9(0000 0010 0000 0000) — Reserved (unused)
Status Condition Register
The Status Flags column is a bitfield: the instrument OR-sums every
active condition and reports the sum, so one value can mean several things at
once. Reader.STATUS_BITS carries this table, and it is what turns a raw status
into df.attrs['status_conditions'] — a named condition instead of a number.
| Bit | Decimal | Condition |
|---|---|---|
| 8 | 256 |
Detector voltage out of range |
| 7 | 128 |
Internal temperature > 40°C |
| 6 | 64 |
Internal temperature < 10°C |
| 5 | 32 |
Autocal failed |
| 4 | 16 |
Accumulator clipped |
| 3 | 8 |
Excessive sample concentration |
| 2 | 4 |
Sheath Flow out of range |
| 1 | 2 |
Total Flow out of range |
| 0 | 1 |
Laser fault |
The register is written as a space-grouped bit string
('0000 0000 0000 0001' is bit 0, not the number one thousand). Bit 9 is
reserved. Every non-whitelisted bit counts as an error — this table names
the conditions, it does not decide which of them matter.
To stop treating one condition as an error, whitelist its decimal value:
QC rules
Before the rules run, the total number concentration is computed as
Σ (dN/dlogDp × dlogDp) over the per-bin widths. A natural log was used here
until 2026-09-09 where the data is dN/dlog₁₀Dp, inflating every total by
ln 10 = 2.303×; that mattered more for APS than for SMPS because the range is
tight — a MAX_TOTAL_CONC of 700 was really 304 /cm³, so valid high-loading
scans were being rejected.
| Rule | Condition | Severity |
|---|---|---|
| Status Error | Status Flags has any non-whitelisted bit set (see above) |
error |
| Insufficient | an hour holds < 50 % of the scans it could have held at the detected frequency (edge hours scaled by coverage) | advisory (WARNING) — recorded, data kept |
| Invalid Number Conc | total < 1 or > 700 #/cm³ (MIN_TOTAL_CONC / MAX_TOTAL_CONC); a NaN total is also flagged |
error |
Output
The L2 frame holds the dN/dlogDp matrix only (diameters in µm as
columns) plus the QC bookkeeping; Status Flags and the other metadata
columns are dropped in _process. Statistics are not in the frame.
| Column | Unit | Description |
|---|---|---|
| Size bins (0.542–19.81 µm) | dN/dlogDp | Number concentration for each size |
At L3 the same sidecars as SMPS are written next to the main output:
{prefix}_dNdlogDp.csv, {prefix}_dSdlogDp.csv (π·d²·dN),
{prefix}_dVdlogDp.csv (π·d³/6·dN) and {prefix}_stats.csv (from
psd_stats, QC-aligned; a failure there is logged and never fails the read).
Pass append_stats=True to also append the statistics columns to the
returned frame; the default keeps it a clean PSD matrix for psd_stats /
merge_psd / SizeDist.
Files written per read are listed in RawDataReader Reference §1.
Notes
- Measures aerodynamic particle diameter directly
- Complementary to SMPS for larger particle sizes
- Size range approximately 0.5–20 μm
- Logarithmic bin spacing in size distribution
- Counting efficiency: the APS under-counts at both ends — 85–99 % for solid particles, but falling from 75 % at 0.8 µm to 25 % at 10 µm for droplets (Volckens & Peters 2005). Not corrected for; see Counting Efficiency.