flow_fcs/
version.rs

1use anyhow::Result;
2use serde::{Serialize, Serializer};
3use std::fmt::Display;
4
5/// An enum representing FCS file format versions
6///
7/// Each version has different required keywords and structural requirements.
8/// The library supports FCS versions 1.0 through 4.0, with 3.1 as the default.
9#[derive(Debug, Clone, Copy, Default, Hash)]
10pub enum Version {
11    V1_0,
12    V2_0,
13    V3_0,
14    #[default]
15    V3_1,
16    V3_2,
17    V4_0,
18}
19
20impl Display for Version {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        let version = match self {
23            Self::V1_0 => "FCS1.0",
24            Self::V2_0 => "FCS2.0",
25            Self::V3_0 => "FCS3.0",
26            Self::V3_1 => "FCS3.1",
27            Self::V3_2 => "FCS3.2",
28            Self::V4_0 => "FCS4.0",
29        };
30        write!(f, "{version}")
31    }
32}
33
34impl Serialize for Version {
35    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36    where
37        S: Serializer,
38    {
39        let version = match self {
40            Self::V1_0 => "FCS1.0",
41            Self::V2_0 => "FCS2.0",
42            Self::V3_0 => "FCS3.0",
43            Self::V3_1 => "FCS3.1",
44            Self::V3_2 => "FCS3.2",
45            Self::V4_0 => "FCS4.0",
46        };
47        serializer.serialize_str(version)
48    }
49}
50
51impl Version {
52    /// Returns the required *non-parameter* indexed keywords for the 'TEXT' segment in a given FCS version as a static array of strings
53    #[must_use]
54    pub fn get_required_keywords(&self) -> &[&str] {
55        const V1_0: [&str; 0] = [];
56        const V2_0: [&str; 5] = [
57            "$BYTEORD",  // byte order for data acquisition computer
58            "$DATATYPE", // type of data in data segment (ASCII, int, float)
59            "$MODE",     // data mode (list mode - preferred, histogram - deprecated)
60            "$NEXTDATA", // byte-offset to next data set in the file
61            "$PAR",      // number of parameters in an event
62        ];
63        const V3_0_V3_1: [&str; 12] = [
64            "$BEGINANALYSIS", // byte-offset to the beginning of analysis segment
65            "$BEGINDATA",     // byte-offset of beginning of data segment
66            "$BEGINSTEXT",    // byte-offset to beginning of text segment
67            "$BYTEORD",       // byte order for data acquisition computer
68            "$DATATYPE",      // type of data in data segment (ASCII, int, float)
69            "$ENDANALYSIS",   // byte-offset to end of analysis segment
70            "$ENDDATA",       // byte-offset to end of data segment
71            "$ENDSTEXT",      // byte-offset to end of text segment
72            "$MODE",          // data mode (list mode - preferred, histogram - deprecated)
73            "$NEXTDATA",      // byte-offset to next data set in the file
74            "$PAR",           // number of parameters in an event
75            "$TOT",           // total number of events in the data set
76        ];
77        const V3_2: [&str; 8] = [
78            "$BEGINDATA",
79            "$BYTEORD",
80            "$CYT",
81            "$DATATYPE",
82            "$ENDDATA",
83            "$NEXTDATA",
84            "$PAR",
85            "$TOT",
86        ];
87        const V4_0: [&str; 11] = [
88            "$BEGINDATA",
89            "$BYTEORD",
90            "$DATATYPE",
91            "$ENDDATA",
92            "$NEXTDATA",
93            "$PAR",
94            "$DATE",
95            "$ETIM",
96            "$CYT",
97            "$BTIM",
98            "$TOT",
99        ];
100
101        match self {
102            Self::V1_0 => &V1_0,
103            Self::V2_0 => &V2_0,
104            Self::V3_0 | Self::V3_1 => &V3_0_V3_1,
105            Self::V3_2 => &V3_2,
106            Self::V4_0 => &V4_0,
107        }
108    }
109}
110
111// Optional non-paramater indexed keywords
112// const OPTIONAL_KEYWORDS: [&str; 31] = [
113//     "$ABRT",          // events lost due to acquisition electronic coincidence
114//     "$BTIM",          // clock time at beginning of data acquisition
115//     "$CELLS",         // description of objects measured
116//     "$COM",           // comment
117//     "$CSMODE",        // cell subset mode, number of subsets an object may belong
118//     "$CSVBITS",       // number of bits used to encode cell subset identifier
119//     "$CYT",           // cytometer type
120//     "$CYTSN",         // cytometer serial number
121//     "$DATE",          // date of data acquisition
122//     "$ETIM",          // clock time at end of data acquisition
123//     "$EXP",           // investigator name initiating experiment
124//     "$FIL",           // name of data file containing data set
125//     "$GATE",          // number of gating parameters
126//     "$GATING",        // region combinations used for gating
127//     "$INST",          // institution where data was acquired
128//     "$LAST_MODIFIED", // timestamp of last modification
129//     "$LAST_MODIFIER", // person performing last modification
130//     "$LOST",          // number events lost due to computer busy
131//     "$OP",            // name of flow cytometry operator
132//     "$ORIGINALITY",   // information whether FCS data set has been modified or not
133//     "$PLATEID",       // plate identifier
134//     "$PLATENAME",     // plate name
135//     "$PROJ",          // project name
136//     "$SMNO",          // specimen (i.e., tube) label
137//     "$SPILLOVER",     // spillover matrix
138//     "$SRC",           // source of specimen (cell type, name, etc.)
139//     "$SYS",           // type of computer and OS
140//     "$TIMESTEP",      // time step for time parameter
141//     "$TR",            // trigger paramter and its threshold
142//     "$VOL",           // volume of sample run during data acquisition
143//     "$WELLID",        // well identifier
144// ];