1use crate::{
2 data::*,
3 simulator::{Fa, Lag},
4 Censor,
5};
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9#[derive(Serialize, Deserialize, Debug, Clone, Default)]
38pub struct Data {
39 subjects: Vec<Subject>,
40}
41impl Data {
42 pub fn new(subjects: Vec<Subject>) -> Self {
50 Data { subjects }
51 }
52
53 pub fn subjects(&self) -> Vec<&Subject> {
59 self.subjects.iter().collect()
60 }
61
62 pub fn add_subject(&mut self, subject: Subject) {
68 self.subjects.push(subject);
69 }
70
71 pub fn get_subject(&self, id: &str) -> Option<&Subject> {
81 self.subjects.iter().find(|subject| subject.id() == id)
82 }
83
84 pub fn get_subject_mut(&mut self, id: &str) -> Option<&mut Subject> {
94 self.subjects.iter_mut().find(|subject| subject.id() == id)
95 }
96
97 pub fn filter_include(&self, include: &[String]) -> Data {
107 let subjects = self
108 .subjects
109 .iter()
110 .filter(|subject| include.iter().any(|id| id == subject.id()))
111 .cloned()
112 .collect();
113 Data::new(subjects)
114 }
115
116 pub fn filter_exclude(&self, exclude: Vec<String>) -> Data {
126 let subjects = self
127 .subjects
128 .iter()
129 .filter(|subject| !exclude.iter().any(|id| id == subject.id()))
130 .cloned()
131 .collect();
132 Data::new(subjects)
133 }
134
135 pub fn expand(&self, idelta: f64, tad: f64) -> Data {
149 if idelta <= 0.0 {
150 return self.clone();
151 }
152
153 let last_time = self
155 .subjects
156 .iter()
157 .flat_map(|subject| &subject.occasions)
158 .flat_map(|occasion| &occasion.events)
159 .filter_map(|event| match event {
160 Event::Observation(observation) => Some(observation.time()),
161 Event::Infusion(infusion) => Some(infusion.time() + infusion.duration()),
162 _ => None,
163 })
164 .max_by(|a, b| a.partial_cmp(b).unwrap())
165 .unwrap_or(0.0)
166 + tad;
167
168 let outeq_values = self.get_output_equations();
170
171 let new_subjects = self
173 .subjects
174 .iter()
175 .map(|subject| {
176 let new_occasions = subject
177 .occasions
178 .iter()
179 .map(|occasion| {
180 let old_events = occasion.process_events(None, true);
181
182 let existing_obs: std::collections::HashSet<(u64, usize)> = old_events
184 .iter()
185 .filter_map(|event| match event {
186 Event::Observation(obs) => {
187 let time_key = (obs.time() * 1e6).round() as u64;
189 Some((time_key, obs.outeq()))
190 }
191 _ => None,
192 })
193 .collect();
194
195 let mut new_events = Vec::new();
197 let mut time = 0.0;
198 while time < last_time {
199 let time_key = (time * 1e6).round() as u64;
200
201 for &outeq in &outeq_values {
202 if !existing_obs.contains(&(time_key, outeq)) {
204 let obs = Observation::new(
205 time,
206 None,
207 outeq,
208 None,
209 occasion.index,
210 Censor::None,
211 );
212 new_events.push(Event::Observation(obs));
213 }
214 }
215
216 time += idelta;
217 time = (time * 1e6).round() / 1e6;
218 }
219
220 new_events.extend(old_events);
222
223 let mut new_occasion = Occasion::new(occasion.index);
225 new_occasion.events = new_events;
226 new_occasion.covariates = occasion.covariates.clone();
227
228 new_occasion.sort();
229 new_occasion
230 })
231 .collect();
232
233 Subject::new(subject.id.clone(), new_occasions)
234 })
235 .collect();
236
237 Data::new(new_subjects)
238 }
239
240 pub fn iter(&'_ self) -> std::slice::Iter<'_, Subject> {
246 self.subjects.iter()
247 }
248
249 pub fn iter_mut(&'_ mut self) -> std::slice::IterMut<'_, Subject> {
255 self.subjects.iter_mut()
256 }
257
258 pub fn len(&self) -> usize {
264 self.subjects.len()
265 }
266
267 pub fn is_empty(&self) -> bool {
273 self.subjects.is_empty()
274 }
275
276 pub fn get_output_equations(&self) -> Vec<usize> {
278 let mut outeq_values: Vec<usize> = self
280 .subjects
281 .iter()
282 .flat_map(|subject| subject.get_output_equations())
283 .collect();
284 outeq_values.sort_unstable();
285 outeq_values.dedup();
286 outeq_values
287 }
288}
289
290impl IntoIterator for Data {
291 type Item = Subject;
292 type IntoIter = std::vec::IntoIter<Subject>;
293 fn into_iter(self) -> Self::IntoIter {
295 self.subjects.into_iter()
296 }
297}
298
299impl<'a> IntoIterator for &'a Data {
300 type Item = &'a Subject;
301 type IntoIter = std::slice::Iter<'a, Subject>;
302 fn into_iter(self) -> Self::IntoIter {
304 self.subjects.iter()
305 }
306}
307impl<'a> IntoIterator for &'a mut Data {
308 type Item = &'a mut Subject;
309 type IntoIter = std::slice::IterMut<'a, Subject>;
310 fn into_iter(self) -> Self::IntoIter {
312 self.subjects.iter_mut()
313 }
314}
315
316impl Into<Data> for Vec<Subject> {
317 fn into(self) -> Data {
319 Data::new(self)
320 }
321}
322
323impl Into<Data> for Subject {
324 fn into(self) -> Data {
326 Data::new(vec![self])
327 }
328}
329
330#[derive(Serialize, Debug, Deserialize, Clone)]
335pub struct Subject {
336 id: String,
337 occasions: Vec<Occasion>,
338}
339impl Subject {
340 pub(crate) fn new(id: String, occasions: Vec<Occasion>) -> Self {
347 let mut subject = Subject { id, occasions };
348 for occasion in subject.occasions.iter_mut() {
349 occasion.sort();
350 }
351 subject
352 }
353
354 pub fn occasions(&self) -> Vec<&Occasion> {
360 self.occasions.iter().collect()
361 }
362
363 pub fn id(&self) -> &String {
369 &self.id
370 }
371
372 pub fn from_occasions(id: String, occasions: Vec<Occasion>) -> Self {
386 Subject { id, occasions }
387 }
388
389 pub fn occasions_mut(&mut self) -> &mut Vec<Occasion> {
391 &mut self.occasions
392 }
393
394 pub fn occasions_iter_mut(&'_ mut self) -> std::slice::IterMut<'_, Occasion> {
396 self.occasions.iter_mut()
397 }
398
399 pub fn get_output_equations(&self) -> Vec<usize> {
400 let outeq_values: Vec<usize> = self
402 .occasions
403 .iter()
404 .flat_map(|occasion| {
405 occasion.events.iter().filter_map(|event| match event {
406 Event::Observation(obs) => Some(obs.outeq()),
407 _ => None,
408 })
409 })
410 .collect();
411 outeq_values
412 }
413
414 pub fn get_occasion_mut(&mut self, index: usize) -> Option<&mut Occasion> {
424 self.occasions.iter_mut().find(|occ| occ.index() == index)
425 }
426
427 pub fn iter(&'_ self) -> std::slice::Iter<'_, Occasion> {
433 self.occasions.iter()
434 }
435
436 pub fn iter_mut(&'_ mut self) -> std::slice::IterMut<'_, Occasion> {
442 self.occasions.iter_mut()
443 }
444
445 pub fn len(&self) -> usize {
451 self.occasions.len()
452 }
453
454 pub fn is_empty(&self) -> bool {
460 self.occasions.is_empty()
461 }
462}
463
464impl IntoIterator for Subject {
465 type Item = Occasion;
466 type IntoIter = std::vec::IntoIter<Occasion>;
467 fn into_iter(self) -> Self::IntoIter {
469 self.occasions.into_iter()
470 }
471}
472impl<'a> IntoIterator for &'a Subject {
473 type Item = &'a Occasion;
474 type IntoIter = std::slice::Iter<'a, Occasion>;
475 fn into_iter(self) -> Self::IntoIter {
477 self.occasions.iter()
478 }
479}
480impl<'a> IntoIterator for &'a mut Subject {
481 type Item = &'a mut Occasion;
482 type IntoIter = std::slice::IterMut<'a, Occasion>;
483 fn into_iter(self) -> Self::IntoIter {
485 self.occasions.iter_mut()
486 }
487}
488
489#[derive(Serialize, Debug, Deserialize, Clone)]
495pub struct Occasion {
496 pub(crate) events: Vec<Event>,
497 pub(crate) covariates: Covariates,
498 pub(crate) index: usize,
499}
500
501impl Occasion {
502 pub(crate) fn new(index: usize) -> Self {
510 Occasion {
511 events: Vec::new(),
512 covariates: Covariates::new(),
513 index,
514 }
515 }
516
517 pub fn events(&self) -> Vec<&Event> {
523 self.events.iter().collect()
524 }
525
526 pub fn index(&self) -> usize {
532 self.index
533 }
534
535 pub fn add_covariate(&mut self, name: String, covariate: Covariate) {
542 self.covariates.add_covariate(name, covariate);
543 }
544
545 pub(crate) fn set_covariates(&mut self, covariates: Covariates) {
547 self.covariates = covariates;
548 }
549
550 fn add_lagtime(&mut self, reorder: Option<(&Fa, &Lag, &Vec<f64>, &Covariates)>) {
551 if let Some((_, fn_lag, spp, covariates)) = reorder {
552 let spp = nalgebra::DVector::from_vec(spp.to_vec());
553 for event in self.events.iter_mut() {
554 let time = event.time();
555 if let Event::Bolus(bolus) = event {
556 let lagtime = fn_lag(&spp.clone().into(), time, covariates);
557 if let Some(l) = lagtime.get(&bolus.input()) {
558 *bolus.mut_time() += l;
559 }
560 }
561 }
562 }
563 self.sort();
564 }
565
566 fn add_bioavailability(&mut self, reorder: Option<(&Fa, &Lag, &Vec<f64>, &Covariates)>) {
567 if let Some((fn_fa, _, spp, covariates)) = reorder {
569 let spp = nalgebra::DVector::from_vec(spp.to_vec());
570 for event in self.events.iter_mut() {
571 let time = event.time();
572 if let Event::Bolus(bolus) = event {
573 let fa = fn_fa(&spp.clone().into(), time, covariates);
574 if let Some(f) = fa.get(&bolus.input()) {
575 bolus.set_amount(bolus.amount() * f);
576 }
577 }
578 }
579 }
580 }
581
582 pub(crate) fn sort(&mut self) {
584 self.events.sort_by(|a, b| {
585 #[inline]
587 fn event_type_order(event: &Event) -> u8 {
588 match event {
589 Event::Bolus(_) => 1,
590 Event::Infusion(_) => 2,
591 Event::Observation(_) => 3,
592 }
593 }
594
595 let time_cmp = a.time().partial_cmp(&b.time());
597
598 match time_cmp {
599 Some(std::cmp::Ordering::Equal) => {
600 event_type_order(a).cmp(&event_type_order(b))
602 }
603 Some(ordering) => ordering,
604 None => std::cmp::Ordering::Equal, }
606 });
607 }
608
609 pub(crate) fn process_events(
621 &self,
622 reorder: Option<(&Fa, &Lag, &Vec<f64>, &Covariates)>,
623 ignore: bool,
624 ) -> Vec<Event> {
625 let mut occ = self.clone();
626 occ.add_lagtime(reorder);
627 occ.add_bioavailability(reorder);
628
629 if ignore {
631 occ.events.iter().cloned().collect()
632 } else {
633 occ.events.clone()
634 }
635 }
636
637 pub fn covariates(&self) -> &Covariates {
643 &self.covariates
644 }
645
646 pub fn covariates_mut(&mut self) -> &mut Covariates {
652 &mut self.covariates
653 }
654
655 pub(crate) fn add_event(&mut self, event: Event) {
659 self.events.push(event);
660 self.sort();
661 }
662
663 pub fn add_observation(
665 &mut self,
666 time: f64,
667 value: f64,
668 outeq: usize,
669 errorpoly: Option<ErrorPoly>,
670 censored: Censor,
671 ) {
672 let observation =
673 Observation::new(time, Some(value), outeq, errorpoly, self.index, censored);
674 self.add_event(Event::Observation(observation));
675 }
676
677 pub fn add_missing_observation(&mut self, time: f64, outeq: usize) {
679 let observation = Observation::new(time, None, outeq, None, self.index, Censor::None);
680 self.add_event(Event::Observation(observation));
681 }
682
683 pub fn add_observation_with_error(
687 &mut self,
688 time: f64,
689 value: f64,
690 outeq: usize,
691 errorpoly: ErrorPoly,
692 censored: Censor,
693 ) {
694 let observation = Observation::new(
695 time,
696 Some(value),
697 outeq,
698 Some(errorpoly),
699 self.index,
700 censored,
701 );
702 self.add_event(Event::Observation(observation));
703 }
704
705 pub fn add_bolus(&mut self, time: f64, amount: f64, input: usize) {
707 let bolus = Bolus::new(time, amount, input, self.index);
708 self.add_event(Event::Bolus(bolus));
709 }
710
711 pub fn add_infusion(&mut self, time: f64, amount: f64, input: usize, duration: f64) {
713 let infusion = Infusion::new(time, amount, input, duration, self.index);
714 self.add_event(Event::Infusion(infusion));
715 }
716
717 pub fn events_mut(&mut self) -> &mut Vec<Event> {
719 &mut self.events
720 }
721
722 pub fn events_iter_mut(&'_ mut self) -> std::slice::IterMut<'_, Event> {
724 self.events.iter_mut()
725 }
726
727 pub(crate) fn initial_time(&self) -> f64 {
728 self.events
730 .iter()
731 .filter_map(|event| match event {
732 Event::Observation(observation) => Some(observation.time()),
733 Event::Bolus(bolus) => Some(bolus.time()),
734 Event::Infusion(infusion) => Some(infusion.time()),
735 })
736 .min_by(|a, b| a.partial_cmp(b).unwrap())
737 .unwrap_or(0.0)
738 }
739
740 pub(crate) fn infusions_ref(&self) -> Vec<&Infusion> {
741 self.events
743 .iter()
744 .filter_map(|event| match event {
745 Event::Infusion(infusion) => Some(infusion),
746 _ => None,
747 })
748 .collect()
749 }
750
751 pub fn iter(&'_ self) -> std::slice::Iter<'_, Event> {
757 self.events.iter()
758 }
759
760 pub fn iter_mut(&'_ mut self) -> std::slice::IterMut<'_, Event> {
766 self.events.iter_mut()
767 }
768
769 pub fn len(&self) -> usize {
775 self.events.len()
776 }
777
778 pub fn is_empty(&self) -> bool {
784 self.events.is_empty()
785 }
786}
787
788impl IntoIterator for Occasion {
789 type Item = Event;
790 type IntoIter = std::vec::IntoIter<Event>;
791 fn into_iter(self) -> Self::IntoIter {
793 self.events.into_iter()
794 }
795}
796impl<'a> IntoIterator for &'a Occasion {
797 type Item = &'a Event;
798 type IntoIter = std::slice::Iter<'a, Event>;
799 fn into_iter(self) -> Self::IntoIter {
801 self.events.iter()
802 }
803}
804impl<'a> IntoIterator for &'a mut Occasion {
805 type Item = &'a mut Event;
806 type IntoIter = std::slice::IterMut<'a, Event>;
807 fn into_iter(self) -> Self::IntoIter {
809 self.events.iter_mut()
810 }
811}
812
813impl<'a> IntoIterator for &'a Event {
815 type Item = &'a Event;
816 type IntoIter = std::option::IntoIter<&'a Event>;
817 fn into_iter(self) -> Self::IntoIter {
819 Some(self).into_iter()
820 }
821}
822impl<'a> IntoIterator for &'a mut Event {
823 type Item = &'a mut Event;
824 type IntoIter = std::option::IntoIter<&'a mut Event>;
825 fn into_iter(self) -> Self::IntoIter {
827 Some(self).into_iter()
828 }
829}
830
831impl fmt::Display for Data {
832 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
833 writeln!(f, "Data Overview: {} subjects", self.subjects.len())?;
834 for subject in &self.subjects {
835 writeln!(f, "{}", subject)?;
836 }
837 Ok(())
838 }
839}
840impl fmt::Display for Subject {
841 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
842 writeln!(f, "Subject ID: {}", self.id)?;
843 for occasion in &self.occasions {
844 writeln!(f, "{}", occasion)?;
845 }
846 Ok(())
847 }
848}
849impl fmt::Display for Occasion {
850 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
851 writeln!(f, "Occasion {}:", self.index)?;
852 for event in &self.events {
853 writeln!(f, " {}", event)?;
854 }
855
856 writeln!(f, " Covariates:\n{}", self.covariates)?;
857 Ok(())
858 }
859}
860
861#[cfg(test)]
862mod tests {
863 use super::*;
864 use crate::prelude::*;
865
866 fn create_sample_data() -> Data {
867 let subject1 = Subject::builder("subject1")
868 .observation(1.0, 10.0, 1)
869 .bolus(2.0, 50.0, 1)
870 .infusion(3.0, 100.0, 1, 1.0)
871 .covariate("age", 0.0, 30.0)
872 .covariate("weight", 0.0, 70.0)
873 .reset()
874 .observation(4.0, 20.0, 2)
875 .bolus(5.0, 60.0, 2)
876 .infusion(6.0, 120.0, 2, 2.0)
877 .covariate("age", 0.0, 31.0)
878 .covariate("weight", 0.0, 75.0)
879 .build();
880
881 let subject2 = Subject::builder("subject2")
882 .observation(1.5, 15.0, 1)
883 .bolus(2.5, 55.0, 1)
884 .infusion(3.5, 110.0, 1, 1.5)
885 .covariate("age", 0.0, 25.0)
886 .covariate("weight", 0.0, 65.0)
887 .reset()
888 .observation(4.5, 25.0, 2)
889 .bolus(5.5, 65.0, 2)
890 .infusion(6.5, 130.0, 2, 2.5)
891 .covariate("age", 0.0, 26.0)
892 .covariate("weight", 0.0, 68.0)
893 .build();
894
895 Data::new(vec![subject1, subject2])
896 }
897
898 #[test]
899 fn test_new_data() {
900 let data = create_sample_data();
901 assert_eq!(data.len(), 2);
902 }
903
904 #[test]
905 fn test_get_subjects() {
906 let data = create_sample_data();
907 let subjects = data.subjects();
908 assert_eq!(subjects.len(), 2);
909 assert_eq!(subjects[0].id(), "subject1");
910 assert_eq!(subjects[1].id(), "subject2");
911 }
912
913 #[test]
914 fn test_add_subject() {
915 let mut data = create_sample_data();
916 let new_subject = Subject::builder("subject3")
917 .observation(1.0, 10.0, 1)
918 .bolus(2.0, 50.0, 1)
919 .infusion(3.0, 100.0, 1, 1.0)
920 .covariate("age", 0.0, 30.0)
921 .covariate("weight", 0.0, 70.0)
922 .build();
923 data.add_subject(new_subject);
924 assert_eq!(data.len(), 3);
925 assert_eq!(data.subjects()[2].id(), "subject3");
926 }
927
928 #[test]
929 fn test_filter_include() {
930 let data = create_sample_data();
931 let include = vec!["subject1".to_string()];
932 let filtered_data = data.filter_include(&include);
933 assert_eq!(filtered_data.subjects().len(), 1);
934 assert_eq!(filtered_data.subjects()[0].id(), "subject1");
935 }
936
937 #[test]
938 fn test_filter_exclude() {
939 let data = create_sample_data();
940 let filtered_data = data.filter_exclude(vec!["subject1".to_string()]);
941 assert_eq!(filtered_data.len(), 1);
942 assert_eq!(filtered_data.subjects()[0].id(), "subject2");
943 }
944
945 #[test]
946 fn test_occasion_sort() {
947 let mut occasion = Occasion::new(0);
948 occasion.add_observation(2.0, 1.0, 1, None, Censor::None);
949 occasion.add_bolus(1.0, 100.0, 1);
950 occasion.sort();
951 let events = occasion.process_events(None, false);
952 match &events[0] {
953 Event::Bolus(b) => assert_eq!(b.time(), 1.0),
954 _ => panic!("First event should be a Bolus"),
955 }
956 match &events[1] {
957 Event::Observation(o) => assert_eq!(o.time(), 2.0),
958 _ => panic!("Second event should be an Observation"),
959 }
960 }
961
962 #[test]
963 fn test_data_iterators() {
964 let data = create_sample_data();
965 let mut count = 0;
966 for subject in data.iter() {
967 assert!(subject.id().starts_with("subject"));
968 count += 1;
969 }
970 assert_eq!(count, 2);
971
972 let mut data = create_sample_data();
973 for subject in data.iter_mut() {
974 subject.occasions_mut().push(Occasion::new(2));
975 }
976 assert_eq!(data.subjects()[0].occasions().len(), 3);
977 }
978
979 #[test]
980 fn test_subject_iterators() {
981 let subject = Subject::builder("test")
982 .observation(1.0, 10.0, 1)
983 .bolus(2.0, 50.0, 1)
984 .reset()
985 .observation(3.0, 20.0, 1)
986 .build();
987
988 let mut count = 0;
989 for occasion in subject.iter() {
990 assert!(occasion.index() < 2);
991 count += 1;
992 }
993 assert_eq!(count, 2);
994
995 let mut subject = subject;
996 for occasion in subject.iter_mut() {
997 occasion.add_observation(12.0, 100.0, 0, None, Censor::None);
998 }
999 assert_eq!(subject.occasions()[0].events().len(), 3);
1000 }
1001
1002 #[test]
1003 fn test_occasion_iterators() {
1004 let mut occasion = Occasion::new(0);
1005 occasion.add_observation(1.0, 10.0, 1, None, Censor::None);
1006 occasion.add_bolus(2.0, 50.0, 1);
1007 occasion.sort();
1008
1009 let mut count = 0;
1010 for event in occasion.iter() {
1011 match event {
1012 Event::Observation(_) => count += 1,
1013 Event::Bolus(_) => count += 2,
1014 _ => panic!("Unexpected event type"),
1015 }
1016 }
1017 assert_eq!(count, 3);
1018
1019 let mut occasion = occasion;
1020 for event in occasion.iter_mut() {
1021 event.inc_time(1.0);
1022 }
1023 assert_eq!(occasion.events()[0].time(), 2.0);
1024 }
1025
1026 #[test]
1027 fn test_data_intoiterator_refs() {
1028 let data = create_sample_data();
1029 let mut count = 0;
1030 for subject in &data {
1031 assert!(subject.id().starts_with("subject"));
1032 count += 1;
1033 }
1034 assert_eq!(count, 2);
1035 let mut data = create_sample_data();
1036 for subject in &mut data {
1037 subject.occasions_mut().push(Occasion::new(2));
1038 }
1039 assert_eq!(data.subjects()[0].occasions().len(), 3);
1040 }
1041 #[test]
1042 fn test_subject_intoiterator_all_forms() {
1043 let data = create_sample_data();
1044 let subject = data.get_subject("subject1").unwrap().clone();
1045
1046 let mut occasion_count = 0;
1048 let mut total_events = 0;
1049 for occasion in subject.clone() {
1050 assert_eq!(occasion.index(), occasion_count);
1051 total_events += occasion.events().len();
1052 occasion_count += 1;
1053 }
1054 assert_eq!(occasion_count, 2); assert_eq!(total_events, 6); let mut covariate_ages = Vec::new();
1059 for occasion in &subject {
1060 if let Some(age_cov) = occasion.covariates().get_covariate("age") {
1061 if let Ok(age_value) = age_cov.interpolate(0.1) {
1062 covariate_ages.push(age_value);
1063 }
1064 }
1065 }
1066 assert_eq!(covariate_ages, vec![30.0, 31.0]); let mut subject_mut = subject;
1070 for occasion in &mut subject_mut {
1071 occasion.add_missing_observation(10.0, 1); }
1073
1074 assert_eq!(subject_mut.occasions()[0].events().len(), 4);
1076 assert_eq!(subject_mut.occasions()[1].events().len(), 4);
1077 }
1078 #[test]
1079 fn test_occasion_intoiterator_all_forms() {
1080 let data = create_sample_data();
1081 let subject = data.get_subject("subject2").unwrap();
1082 let occasion = subject.occasions()[0].clone(); let mut event_types = Vec::new();
1086 let mut event_times = Vec::new();
1087 for event in occasion.clone() {
1088 event_times.push(event.time());
1089 match event {
1090 Event::Observation(_) => event_types.push("obs"),
1091 Event::Bolus(_) => event_types.push("bolus"),
1092 Event::Infusion(_) => event_types.push("infusion"),
1093 }
1094 }
1095 assert_eq!(event_times, vec![1.5, 2.5, 3.5]);
1097 assert_eq!(event_types, vec!["obs", "bolus", "infusion"]);
1098
1099 let mut total_dose = 0.0;
1101 for event in &occasion {
1102 match event {
1103 Event::Bolus(bolus) => total_dose += bolus.amount(),
1104 Event::Infusion(infusion) => total_dose += infusion.amount(),
1105 _ => {}
1106 }
1107 }
1108 assert_eq!(total_dose, 165.0); let mut occasion_mut = occasion;
1112 for event in &mut occasion_mut {
1113 event.inc_time(1.0);
1114 }
1115
1116 let shifted_times: Vec<f64> = occasion_mut.events().iter().map(|e| e.time()).collect();
1118 assert_eq!(shifted_times, vec![2.5, 3.5, 4.5]);
1119 }
1120 #[test]
1121 fn test_event_intoiterator_refs() {
1122 let data = create_sample_data();
1123 let subject = data.get_subject("subject1").unwrap();
1124 let occasion = &subject.occasions()[0];
1125
1126 if let Some(bolus_event) = occasion
1128 .events()
1129 .iter()
1130 .find(|e| matches!(e, Event::Bolus(_)))
1131 {
1132 let mut event_count = 0;
1133 for event in *bolus_event {
1134 assert_eq!(event.time(), 2.0); assert!(matches!(event, Event::Bolus(_)));
1136 if let Event::Bolus(bolus) = event {
1137 assert_eq!(bolus.amount(), 50.0); assert_eq!(bolus.input(), 1); }
1140 event_count += 1;
1141 }
1142 assert_eq!(event_count, 1);
1143 }
1144
1145 let mut infusion_event = Event::Infusion(Infusion::new(5.0, 200.0, 1, 2.0, 2));
1147 let original_time = infusion_event.time();
1148
1149 for event in &mut infusion_event {
1150 event.inc_time(3.0); }
1152
1153 assert_eq!(infusion_event.time(), original_time + 3.0);
1154
1155 if let Some(obs_event) = occasion
1157 .events()
1158 .iter()
1159 .find(|e| matches!(e, Event::Observation(_)))
1160 {
1161 for event in *obs_event {
1162 assert_eq!(event.time(), 1.0); if let Event::Observation(observation) = event {
1164 assert_eq!(observation.value(), Some(10.0)); assert_eq!(observation.outeq(), 1); }
1167 }
1168 }
1169 }
1170
1171 #[test]
1172 fn test_subject_builder_and_data_modification() {
1173 let mut subject = Subject::builder("test_subject")
1175 .bolus(0.0, 100.0, 1)
1176 .missing_observation(0.0, 1)
1177 .missing_observation(1.0, 1)
1178 .missing_observation(3.0, 1)
1179 .build();
1180
1181 assert_eq!(subject.id(), "test_subject");
1183 assert_eq!(subject.occasions().len(), 1);
1184
1185 let occasions = subject.occasions();
1186 let occasion = &occasions.first().unwrap();
1187 assert_eq!(occasion.events().len(), 4); if let Some(Event::Bolus(bolus)) = occasion
1191 .events()
1192 .iter()
1193 .find(|e| matches!(e, Event::Bolus(_)))
1194 {
1195 assert_eq!(bolus.amount(), 100.0);
1196 assert_eq!(bolus.time(), 0.0);
1197 assert_eq!(bolus.input(), 1);
1198 } else {
1199 panic!("Bolus event not found");
1200 }
1201
1202 let none_obs_count = occasion
1204 .events()
1205 .iter()
1206 .filter(|e| matches!(e, Event::Observation(obs) if obs.value().is_none()))
1207 .count();
1208 assert_eq!(none_obs_count, 3);
1209
1210 let occasion_mut = subject.get_occasion_mut(0).unwrap();
1212 for event in occasion_mut.events_iter_mut() {
1213 if let Event::Bolus(bolus) = event {
1214 let dose = bolus.mut_amount();
1215 *dose *= 2.0; }
1217 }
1218
1219 occasion_mut.add_missing_observation(12.0, 1);
1221
1222 let occasion = &subject.occasions()[0];
1224 assert_eq!(occasion.events().len(), 5); if let Some(Event::Bolus(bolus)) = occasion
1228 .events()
1229 .iter()
1230 .find(|e| matches!(e, Event::Bolus(_)))
1231 {
1232 assert_eq!(bolus.amount(), 200.0); } else {
1234 panic!("Bolus event not found after modification");
1235 }
1236
1237 if let Some(Event::Observation(obs)) = occasion
1239 .events()
1240 .iter()
1241 .find(|e| matches!(e, Event::Observation(obs) if obs.time() == 12.0))
1242 {
1243 assert_eq!(obs.time(), 12.0);
1244 assert_eq!(obs.value(), None);
1245 assert_eq!(obs.outeq(), 1);
1246 } else {
1247 panic!("Observation at time 12 not found");
1248 }
1249
1250 let none_obs_count = occasion
1252 .events()
1253 .iter()
1254 .filter(|e| matches!(e, Event::Observation(obs) if obs.value().is_none()))
1255 .count();
1256 assert_eq!(none_obs_count, 4); }
1258}