noodles_vcf/variant/record_buf/
samples.rs

1//! Variant record samples.
2
3pub mod keys;
4pub mod sample;
5mod series;
6
7use std::io;
8
9use self::sample::Value;
10pub use self::{keys::Keys, sample::Sample, series::Series};
11use crate::Header;
12
13/// A variant record samples buffer.
14#[derive(Clone, Debug, Default, PartialEq)]
15pub struct Samples {
16    pub(crate) keys: Keys,
17    pub(crate) values: Vec<Vec<Option<Value>>>,
18}
19
20impl Samples {
21    /// Creates a variant record samples buffer.
22    ///
23    /// # Examples
24    ///
25    /// ```
26    /// use noodles_vcf::variant::record_buf::{samples::Keys, Samples};
27    /// let genotypes = Samples::new(Keys::default(), Vec::new());
28    /// ```
29    pub fn new(keys: Keys, values: Vec<Vec<Option<Value>>>) -> Self {
30        Self { keys, values }
31    }
32
33    /// Returns whether there are any samples.
34    ///
35    /// # Examples
36    ///
37    /// ```
38    /// use noodles_vcf::variant::record_buf::Samples;
39    /// let samples = Samples::default();
40    /// assert!(samples.is_empty());
41    /// ```
42    pub fn is_empty(&self) -> bool {
43        self.values.is_empty()
44    }
45
46    /// Removes all keys and samples.
47    ///
48    /// # Examples
49    ///
50    /// ```
51    /// use noodles_vcf::variant::{
52    ///     record::samples::keys::key,
53    ///     record_buf::{samples::{sample::Value, Keys}, Samples},
54    /// };
55    ///
56    /// let keys: Keys = [String::from(key::GENOTYPE)].into_iter().collect();
57    /// let mut samples = Samples::new(keys.clone(), vec![
58    ///     vec![Some(Value::from("0|0"))],
59    /// ]);
60    ///
61    /// assert!(!samples.is_empty());
62    ///
63    /// samples.clear();
64    /// assert!(samples.is_empty());
65    /// ```
66    pub fn clear(&mut self) {
67        self.keys.as_mut().clear();
68        self.values.clear();
69    }
70
71    /// Returns the keys.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use noodles_vcf::variant::{
77    ///     record::samples::keys::key,
78    ///     record_buf::{samples::Keys, Samples},
79    /// };
80    ///
81    /// let samples = Samples::default();
82    /// assert!(samples.keys().as_ref().is_empty());
83    ///
84    /// let keys: Keys = [String::from(key::GENOTYPE)].into_iter().collect();
85    /// let samples = Samples::new(keys.clone(), Vec::new());
86    /// assert_eq!(samples.keys(), &keys);
87    /// ```
88    pub fn keys(&self) -> &Keys {
89        &self.keys
90    }
91
92    /// Returns a mutable reference to the keys.
93    ///
94    /// # Examples
95    ///
96    /// ```
97    /// use noodles_vcf::variant::{
98    ///     record::samples::keys::key,
99    ///     record_buf::{samples::Keys, Samples},
100    /// };
101    ///
102    /// let keys: Keys = [String::from(key::GENOTYPE)].into_iter().collect();
103    ///
104    /// let mut samples = Samples::default();
105    /// *samples.keys_mut() = keys.clone();
106    ///
107    /// assert_eq!(samples.keys(), &keys);
108    /// ```
109    pub fn keys_mut(&mut self) -> &mut Keys {
110        &mut self.keys
111    }
112
113    /// Returns samples.
114    pub fn values(&self) -> impl Iterator<Item = Sample<'_>> {
115        self.values
116            .iter()
117            .map(|values| Sample::new(&self.keys, values))
118    }
119
120    /// Returns the sample with the given sample name.
121    ///
122    /// # Examples
123    ///
124    /// ```
125    /// use noodles_vcf::{
126    ///     self as vcf,
127    ///     variant::{
128    ///         record::samples::keys::key,
129    ///         record_buf::{samples::sample::Value, Samples},
130    ///     },
131    /// };
132    ///
133    /// let header = vcf::Header::builder()
134    ///     .add_sample_name("sample0")
135    ///     .add_sample_name("sample1")
136    ///     .add_sample_name("sample2")
137    ///     .build();
138    ///
139    /// let keys = [String::from(key::GENOTYPE)].into_iter().collect();
140    /// let samples = Samples::new(
141    ///     keys,
142    ///     vec![
143    ///         vec![Some(Value::from("0|0"))],
144    ///         vec![Some(Value::from("1/1"))],
145    ///         vec![],
146    ///     ],
147    /// );
148    ///
149    /// let sample = samples.get(&header, "sample0");
150    /// assert_eq!(sample.and_then(|s| s.values().get(0)), Some(&Some(Value::from("0|0"))));
151    /// ```
152    pub fn get(&self, header: &Header, sample_name: &str) -> Option<Sample<'_>> {
153        header
154            .sample_names()
155            .get_index_of(sample_name)
156            .and_then(|i| self.get_index(i))
157    }
158
159    /// Returns the sample at the given index.
160    pub fn get_index(&self, i: usize) -> Option<Sample<'_>> {
161        self.values
162            .get(i)
163            .map(|values| Sample::new(&self.keys, values))
164    }
165
166    /// Returns the series with the given column name.
167    ///
168    /// # Examples
169    ///
170    /// ```
171    /// use noodles_vcf::variant::{
172    ///     record::samples::keys::key,
173    ///     record_buf::{samples::sample::Value, Samples},
174    /// };
175    ///
176    /// let keys = [String::from(key::GENOTYPE)].into_iter().collect();
177    /// let samples = Samples::new(
178    ///     keys,
179    ///     vec![
180    ///         vec![Some(Value::from("0|0"))],
181    ///         vec![Some(Value::from("1/1"))],
182    ///         vec![],
183    ///     ],
184    /// );
185    ///
186    /// let series = samples.select(key::GENOTYPE).expect("missing genotype column");
187    /// assert_eq!(series.get(0), Some(Some(&Value::from("0|0"))));
188    /// assert_eq!(series.get(1), Some(Some(&Value::from("1/1"))));
189    /// assert_eq!(series.get(2), Some(None));
190    /// assert_eq!(series.get(3), None);
191    /// ```
192    pub fn select(&self, name: &str) -> Option<Series<'_>> {
193        self.keys()
194            .as_ref()
195            .get_full(name)
196            .map(|(i, name)| Series::new(name, &self.values[..], i))
197    }
198
199    /// Returns an iterator over series.
200    pub fn series(&self) -> impl Iterator<Item = Series<'_>> {
201        let column_names = self.keys();
202        let column_count = column_names.as_ref().len();
203
204        (0..column_count).map(|i| {
205            // SAFETY: `i` is < `column_count`.
206            let name = column_names.as_ref().get_index(i).unwrap();
207            Series::new(name, &self.values[..], i)
208        })
209    }
210}
211
212impl crate::variant::record::Samples for Samples {
213    fn is_empty(&self) -> bool {
214        self.values.is_empty()
215    }
216
217    fn len(&self) -> usize {
218        self.values.len()
219    }
220
221    fn column_names<'a, 'h: 'a>(
222        &'a self,
223        _: &'h Header,
224    ) -> Box<dyn Iterator<Item = io::Result<&'a str>> + 'a> {
225        Box::new(self.keys.as_ref().iter().map(|key| Ok(key.as_str())))
226    }
227
228    fn select<'a, 'h: 'a>(
229        &'a self,
230        _: &'h Header,
231        column_name: &str,
232    ) -> Option<io::Result<Box<dyn crate::variant::record::samples::Series + 'a>>> {
233        self.select(column_name)
234            .map(|series| Box::new(series) as Box<dyn crate::variant::record::samples::Series>)
235            .map(Ok)
236    }
237
238    fn series(
239        &self,
240    ) -> Box<
241        dyn Iterator<Item = io::Result<Box<dyn crate::variant::record::samples::Series + '_>>> + '_,
242    > {
243        Box::new(
244            self.series()
245                .map(|series| Box::new(series) as Box<dyn crate::variant::record::samples::Series>)
246                .map(Ok),
247        )
248    }
249
250    fn iter(
251        &self,
252    ) -> Box<dyn Iterator<Item = Box<dyn crate::variant::record::samples::Sample + '_>> + '_> {
253        Box::new(
254            self.values()
255                .map(|sample| Box::new(sample) as Box<dyn crate::variant::record::samples::Sample>),
256        )
257    }
258}
259
260impl crate::variant::record::Samples for &Samples {
261    fn is_empty(&self) -> bool {
262        self.values.is_empty()
263    }
264
265    fn len(&self) -> usize {
266        self.values.len()
267    }
268
269    fn column_names<'a, 'h: 'a>(
270        &'a self,
271        _: &'h Header,
272    ) -> Box<dyn Iterator<Item = io::Result<&'a str>> + 'a> {
273        Box::new(self.keys.as_ref().iter().map(|key| Ok(key.as_str())))
274    }
275
276    fn select<'a, 'h: 'a>(
277        &'a self,
278        _: &'h Header,
279        column_name: &str,
280    ) -> Option<io::Result<Box<dyn crate::variant::record::samples::Series + 'a>>> {
281        Samples::select(self, column_name)
282            .map(|series| Box::new(series) as Box<dyn crate::variant::record::samples::Series>)
283            .map(Ok)
284    }
285
286    fn series(
287        &self,
288    ) -> Box<
289        dyn Iterator<Item = io::Result<Box<dyn crate::variant::record::samples::Series + '_>>> + '_,
290    > {
291        Box::new(
292            Samples::series(self)
293                .map(|series| Box::new(series) as Box<dyn crate::variant::record::samples::Series>)
294                .map(Ok),
295        )
296    }
297
298    fn iter(
299        &self,
300    ) -> Box<dyn Iterator<Item = Box<dyn crate::variant::record::samples::Sample + '_>> + '_> {
301        Box::new(
302            self.values()
303                .map(|sample| Box::new(sample) as Box<dyn crate::variant::record::samples::Sample>),
304        )
305    }
306}
307
308impl From<Samples> for (Keys, Vec<Vec<Option<Value>>>) {
309    fn from(samples: Samples) -> Self {
310        (samples.keys, samples.values)
311    }
312}