fcs

    Flow cytometry FCS file validation and reproducible data preparation

    Download zip
    Author
    Version
    0.2.1
    License
    MIT
    Last updated
    6 hours ago
    Downloads
    1

    #FCS 事件数据检查与选择后交换

    本项目仓库:尚未公开。当前只有本地源码;正式公开 URL 由对接团队创建后填写,不能提交旧 Forth 仓库充当本项目。

    模块 mawei2018/fcs,本地版本 0.2.1,MIT。当前评审状态:已选定 Forth 替换方向,待公开与办理换题。本文件是当前入口,旧轮次说明与详细用法保存在 历史/完整使用说明。

    #解决什么任务

    在导入前核对通道和事件矩阵,将选中的事件与通道写回可交换 FCS,避免只导出 CSV 后丢失通道元数据。

    已有 FCS 输入、需要事件/通道选择后继续交付格式文件时评估;不是为取代成熟 Python 科研工具而强造需求。

    #直接复现

    安装 MoonBit 和 Node.js 24,在本仓库根目录运行:

    moon build --target js --release node examples/run-use-case.mjs

    流程:事件选择后保留通道信息再交付 FCS。运行器创建新的系统临时目录,保留每一步的 stdout/stderr、产物及 report.json,打印实际目录;重复运行不会覆盖之前产物。它只执行仓库内的本地样例,不连接公网或发送消息。report.json 的 expected 是应观察的结果,实际结果在各步输出中;成功退出不替代内容核对。

    输入性质:原创 4 事件样例;输出是格式交换数据,不是临床分析或真实用户证明。

    应观察:选出 FSC-A 在 [15,35) 的两个事件并保留两个指定通道;CSV 和 FCS 均可交付。

    具体命令和输入路径见 使用任务 与 机器可读流程。只把这个脚本当复现入口,不把通用运行器计作核心技术贡献。

    #实现与已有项目的关系

    MoonBit 负责 FCS2/3/3.1 list-mode 字节解析、段/矩阵校验、显式缩放、统计、事件选择和 FCS3.1 写出;Node 负责文件与命令入口。

    FlowIO/FlowKit 等成熟 Python 工具已解决这类交换问题。本项目贡献是 MoonBit 可复用实现与 JS/WasmGC 数据准备接口,未发现同范围公开 MoonBit 包不等于证明生态空白。

    同类项目和检索边界见 DUPLICATION。查重用于避免错误的首创表述;关键词零结果不能证明生态空白,Node 宿主能力也不计为 MoonBit 原生 I/O。

    库使用从 公共 API 和根包源码开始;可在本 checkout 的消费包中导入 "mawei2018/fcs"。源码中的网络/文件宿主入口及完整参数仍见 完整使用说明。是否已发布到 Mooncakes 需另核实,本文不把 moon add 的下载成功作为已完成事项。

    #验证与边界

    0.2.0 增加显式 allow_text_padding 兼容选项,解决公开 G11.fcs 的 TEXT 尾部填充问题。默认仍拒绝,启用时报告忽略的字节数;只接受最终分隔符之后的 ASCII 空格,不修复偏移冲突、不改变段重叠检查,也不允许与 strict 同用。完整命令见 兼容与重写。同时修正分隔符范围,拒绝 ASCII NUL/DEL。

    本次 FlowIO1.4.0 对照重新执行:四个公开文件的 1,488,004 个值全量一致;G11 的 5,785×12 个值、重写 DATA 原始字节和选择后回读均核对。JS/WasmGC 核心各15项、CLI11组通过。见 当前独立对照 和 复现说明。

    0.1.0 的 独立对照 与 最小任务回执 保留原结果;其中 G11 拒绝记录描述的是旧版本。验证文件互通不等于全部厂商兼容或真实用户部署。

    常规核心检查可运行 moon check --target js、moon test --target js、moon test --target wasm-gc。专项命令:

    node tools/test_cli.mjs

    专项所需的固定参考版本、样本获取和命令见 TESTING。

    尚无明确实验室使用方;不做补偿应用、自动分类、FCS3.2 或临床分析。部分厂商文件明确不兼容,完整数据上限及拒绝样例见使用文档。

    #复审材料状态

    无明确实验室使用方,部分厂商样本不兼容;必须先由团队完成换题与公开地址,旧 Forth URL 不能充当新仓库。

    没有创建公开仓库、推送、发布 Mooncakes 或提交表单;当前可本地复查。

    申报草稿 已按当前功能修订,并单独标明本项目仓库;复核说明 区分材料错误、功能变化及尚未解决的问题。没有编造用户、设备接入、生产部署或评审认可。

    当前换题交接见 SWITCH-FROM-FORTH.md。本次新增格式兼容处理,仍未创建公开仓库。

    CI固定的编译器与标准库版本见 TOOLCHAIN.md;升级时需同时核对生成产物。

    #0.2.1 请求边界与公开文件交换

    修正 JS JSON 入口的小数事件/通道索引被通用整数解码器截断的问题;dataset/start/count/x/y/events/channels 必须是精确32位整数。多个事件选择器同时出现会拒绝,避免静默忽略 events。命令行选项采用严格 UTF-8 解码。MoonBit 格式解析、几何选择及写出算法未改动。

    新增固定公开 G11 的数值区间选择→三通道 FCS→FlowIO 回读任务,明确丢弃不适用的补偿和分析段,保留对应通道元数据,输出源/结果散列与完成清单。见 PUBLIC-SELECTION.md。区间仅用于可复现格式交换,不是生物学判定。当前证据在 evidence/request-20260927;0.2.0 报告保留历史语义。

    #本地验收与公开交付(2026-09-28)

    核心实现使用 MoonBit;固定编译器为 moonc 0.10.14+7d59c7ec9。先按本文安装宿主依赖、运行 moon update,再从仓库根目录执行以下与 CI 对齐的检查;可运行任务和适用边界见本文前面的示例与说明。

    moon check --target js --deny-warn moon test --target js --deny-warn moon test --target wasm-gc --deny-warn moon build --target js --release --deny-warn moon package

    跨平台复核(2026-09-28,本地 Ubuntu-D 26.04 WSL2):从当时的源码归档全新解包,固定 moonc 0.10.14+7d59c7ec9 下通过 moon update、moon fmt --check、moon info、严格检查、JS/Wasm-GC 测试及 JS release 构建;Node 24.21.0 跑通本仓一条宿主入口。本次补记仅修改文档,代码与 CI 未变;复核日志在本地交接包中,公开提交后的 GitHub Actions 仍须单独核对。

    本地核验:JS/Wasm-GC 各 15 项测试、release 构建、用例和 11 项 CLI 检查通过;严格检查无警告。moon package 已完成离线打包预检,它不等于已发布到 Mooncakes。

    公开交付(2026-09-28 核对):尚无本项目正式公开仓库 URL 或 Mooncakes 版本;当前模块名为 mawei2018/fcs;换题资格、仓库、公开 CI 和首次发布均待团队办理,不能沿用旧题仓库链接。相关远端 CI 与赛事结果仍需以实际记录核对。项目许可见 LICENSE;如使用第三方材料,其来源和许可见仓内相应说明。

    FcsError

    pub suberror FcsError {
    Invalid(String)
    Unsupported(String)
    Limit(String)
    } derive(
    Debug
    )

    FcsError::to_repr

    Bounds

    pub(all) struct Bounds {
    channel : Int
    lower : Double
    upper : Double
    } derive(
    Debug
    )

    Bounds::to_repr

    ByteOrder

    pub(all) enum ByteOrder {
    LittleEndian
    BigEndian
    } derive(Eq, ToJson,
    Debug
    )

    ByteOrder::equal

    fn ByteOrder::equal(ByteOrder, ByteOrder) -> Bool

    ByteOrder::not_equal

    fn ByteOrder::not_equal(x : ByteOrder, y : ByteOrder) -> Bool

    ByteOrder::to_json

    fn ByteOrder::to_json(ByteOrder) -> Json

    Channel

    pub struct Channel {
    name : String
    stain : String
    bits : Int
    range : Double
    decades : Double
    zero : Double
    gain : Double
    } derive(ToJson,
    Debug
    )

    Channel::to_json

    fn Channel::to_json(Channel) -> Json

    Channel::to_repr

    ChannelStats

    pub struct ChannelStats {
    count : Int
    nonfinite : Int
    minimum : Double?
    maximum : Double?
    mean : Double?
    variance : Double?
    } derive(ToJson,
    Debug
    )

    ChannelStats::to_json

    Dataset

    pub struct Dataset {
    version : String
    events : Int
    kind : NumberType
    order : ByteOrder
    file_offset : Int
    next_offset : Int
    // private fields
    } derive(
    Debug
    )

    Dataset::analysis_keywords

    fn Dataset::analysis_keywords(self : Dataset) -> Array[(String, String)]

    Dataset::channel_info

    fn Dataset::channel_info(self : Dataset) -> Array[Channel]

    Dataset::keyword

    fn Dataset::keyword(self : Dataset, key : String) -> String?

    Dataset::keywords

    fn Dataset::keywords(self : Dataset) -> Array[(String, String)]

    Dataset::polygon

    fn Dataset::polygon(self : Dataset, x_channel : Int, y_channel : Int, vertices : Array[(Double, Double)], scaled? : Bool) -> Array[Int] raise FcsError

    Even-odd polygon gate; exact floating-point edge points included, no epsilon.

    Dataset::rectangle

    fn Dataset::rectangle(self : Dataset, bounds : Array[Bounds], scaled? : Bool) -> Array[Int] raise FcsError

    Intersection of half-open intervals [lower, upper). NaN and infinities excluded.

    Dataset::spillover

    fn Dataset::spillover(self : Dataset) -> Spillover? raise FcsError

    Dataset::statistics

    fn Dataset::statistics(self : Dataset, channel : Int, scaled? : Bool) -> ChannelStats raise FcsError

    Welford sample variance (n-1); non-finite values are counted separately.

    Dataset::to_repr

    Dataset::value

    fn Dataset::value(self : Dataset, event : Int, channel : Int, scaled? : Bool) -> Double raise FcsError

    Raw instrument value; integer padding bits above ceil(log2(PnR)) are masked.

    Dataset::warnings

    fn Dataset::warnings(self : Dataset) -> Array[String]

    Dataset::write

    fn Dataset::write(self : Dataset, event_indices? : Array[Int], channel_indices? : Array[Int], updates? : Array[(String, String)], drop_spillover? : Bool, drop_analysis? : Bool) -> Bytes raise FcsError

    Creates a standalone canonical FCS 3.1 dataset. Event bytes are not decoded/re-encoded. Changing events/channels with ANALYSIS requires explicit drop_analysis=true.

    NumberType

    pub(all) enum NumberType {
    Integer
    Float32
    Float64
    } derive(Eq, ToJson,
    Debug
    )

    NumberType::equal

    fn NumberType::equal(NumberType, NumberType) -> Bool

    NumberType::not_equal

    fn NumberType::not_equal(x : NumberType, y : NumberType) -> Bool

    NumberType::to_json

    fn NumberType::to_json(NumberType) -> Json

    Spillover

    pub struct Spillover {
    channels : Array[String]
    coefficients : Array[Double]
    } derive(ToJson,
    Debug
    )

    Spillover::to_json

    fn Spillover::to_json(Spillover) -> Json

    create

    fn create(names : Array[String], values : Array[Double], double_precision? : Bool, order? : ByteOrder, metadata? : Array[(String, String)]) -> Bytes raise FcsError

    Event-major values. Input is finite; Float32 overflow is rejected.

    parse

    fn parse(data : Bytes, offset? : Int, strict? : Bool, allow_exclusive_end? : Bool, latin1? : Bool, allow_text_padding? : Bool) -> Dataset raise FcsError

    Reads one list-mode dataset. Offsets are relative to the dataset HEADER.

    parse_all

    fn parse_all(data : Bytes, strict? : Bool, allow_exclusive_end? : Bool, latin1? : Bool, allow_text_padding? : Bool) -> Array[Dataset] raise FcsError