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}