Skip to content

Instantly share code, notes, and snippets.

@lukaspili
Created September 23, 2019 19:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lukaspili/a391dd05a25aec6f4f1a28e4a23cb229 to your computer and use it in GitHub Desktop.
Save lukaspili/a391dd05a25aec6f4f1a28e4a23cb229 to your computer and use it in GitHub Desktop.
dosimetry
import 'dart:math' as math;
// 1. MODELS
class Activity {
Activity(
{this.id, this.category, this.hours, this.frequency, this.recordings});
final int id;
final int category;
final int hours;
final ActivityFrequency frequency;
final List<Recording> recordings;
@override
String toString() {
return 'activity: $id, category: $category, recordings: ${recordings.length}';
}
}
enum ActivityFrequency { daily, weekly, monthly }
class Recording {
Recording({this.duration, this.leqA});
final int duration;
final double leqA;
}
class ActivityExposure {
ActivityExposure({this.activity, this.normalizedDailyDuration, this.leqA});
final Activity activity;
final double normalizedDailyDuration;
final double leqA;
@override
String toString() {
return 'activity: ${activity.id}, normalized daily duration: $normalizedDailyDuration, leqA: $leqA';
}
}
class ActivityDose {
ActivityDose({this.exposure, this.dose});
final ActivityExposure exposure;
final double dose;
@override
String toString() {
return 'activity: ${exposure.activity.id}, dose: $dose';
}
}
class CategoryDose {
CategoryDose({this.category, this.dose});
final int category;
final double dose;
@override
String toString() {
return 'category: $category, dose: $dose';
}
}
// 2. SAMPLE DATA
List<Activity> _createSampleData() {
return [
Activity(
id: 1,
category: 1,
hours: 8,
frequency: ActivityFrequency.weekly,
recordings: [
Recording(duration: 120, leqA: 50.0),
Recording(duration: 200, leqA: 40.0),
Recording(duration: 300, leqA: 80.0),
],
),
Activity(
id: 2,
category: 1,
hours: 5,
frequency: ActivityFrequency.daily,
recordings: [
Recording(duration: 500, leqA: 55.0),
Recording(duration: 200, leqA: 65.0),
],
),
Activity(
id: 3,
category: 2,
hours: 18,
frequency: ActivityFrequency.monthly,
recordings: [
Recording(duration: 120, leqA: 50.0),
Recording(duration: 200, leqA: 40.0),
Recording(duration: 300, leqA: 80.0),
Recording(duration: 300, leqA: 40.0),
Recording(duration: 300, leqA: 30.0),
],
),
Activity(
id: 4,
category: 2,
hours: 4,
frequency: ActivityFrequency.monthly,
recordings: [
Recording(duration: 500, leqA: 55.0),
Recording(duration: 250, leqA: 65.0),
Recording(duration: 700, leqA: 25.0),
Recording(duration: 100, leqA: 95.0),
],
),
];
}
// 3. MATH LAB CONVERTED FUNCTIONS
ActivityExposure _calculateExposurePerActivity(Activity activity) {
double normalizedDailyDuration;
switch (activity.frequency) {
case ActivityFrequency.daily:
normalizedDailyDuration = activity.hours.toDouble();
break;
case ActivityFrequency.weekly:
normalizedDailyDuration = activity.hours / 7;
break;
case ActivityFrequency.monthly:
normalizedDailyDuration = activity.hours / 7 / 4;
break;
}
final leqAs = activity.recordings.map((it) => it.leqA);
// 10*log10(sum((10.^(0.1* mesures)))/nb)
// a = (0.1* mesures)
final a = leqAs.map((it) => 0.1 * it);
// b = (10.^(0.1* mesures))
final b = a.map((it) => math.pow(10, it));
// c = sum((10.^(0.1* mesures)))
final c = b.fold(0, (it1, it2) => it1 + it2);
// d = sum((10.^(0.1* mesures)))/nb
final d = c / activity.recordings.length;
// e = log10(sum((10.^(0.1* mesures)))/nb)
final e = log10(d);
// averageLeqA = 10*log10(sum((10.^(0.1* mesures)))/nb)
final averageLeqA = 10 * e;
return ActivityExposure(
activity: activity,
normalizedDailyDuration: normalizedDailyDuration,
leqA: averageLeqA,
);
}
double _calculateLAeq(List<ActivityExposure> exposures) {
final totalDuration = exposures
.map((it) => it.normalizedDailyDuration)
.fold(0, (it1, it2) => it1 + it2);
// LAeq = 10*log10((1/total_duration)* sum((ActivityTab(:,1)).*10.^(0.1* ActivityTab(:,2))));
// (0.1* ActivityTab(:,2))
final a = exposures.map((it) => 0.1 * it.leqA).toList();
// 10.^(0.1* ActivityTab(:,2))
final b = a.map((it) => math.pow(10, it)).toList();
// (ActivityTab(:,1)).*10.^(0.1* ActivityTab(:,2))
final c = exposures
.asMap()
.map(
(index, it) => MapEntry(index, it.normalizedDailyDuration * b[index]))
.values
.toList();
// sum((ActivityTab(:,1)).*10.^(0.1* ActivityTab(:,2)))
final d = c.fold(0, (it1, it2) => it1 + it2);
// (1/total_duration)* sum((ActivityTab(:,1)).*10.^(0.1* ActivityTab(:,2)))
final e = (1 / totalDuration) * d;
// log10((1/total_duration)* sum((ActivityTab(:,1)).*10.^(0.1* ActivityTab(:,2))))
final f = log10(e);
// 10*log10((1/total_duration)* sum((ActivityTab(:,1)).*10.^(0.1* ActivityTab(:,2))))
final LAeq = 10 * f;
return LAeq;
}
List<ActivityDose> _calculateDosesPerActivityExposure(
List<ActivityExposure> exposures, double LAeq) {
final totalDuration = exposures
.map((it) => it.normalizedDailyDuration)
.fold(0, (it1, it2) => it1 + it2);
// dose=100*(ActivityTab(:,1)/total_duration).*10.^((ActivityTab(:,2)-LAeq)/10)
// (ActivityTab(:,2)-LAeq) / 10
final a = exposures.map((it) => (it.leqA - LAeq) / 10).toList();
// 10.^((ActivityTab(:,2)-LAeq)/10)
final b = a.map((it) => math.pow(10, it)).toList();
// (ActivityTab(:,1)/total_duration)
final c = exposures
.map((it) => it.normalizedDailyDuration / totalDuration)
.toList();
// (ActivityTab(:,1)/total_duration).*10.^((ActivityTab(:,2)-LAeq)/10)
final d = c
.asMap()
.map((index, it) => MapEntry(index, it * b[index]))
.values
.toList();
// 100*(ActivityTab(:,1)/total_duration).*10.^((ActivityTab(:,2)-LAeq)/10)
final doses = d.map((it) => 100 * it).toList();
// Associate each dose to its exposure activity
return doses
.asMap()
.map((index, it) {
return MapEntry(
index,
ActivityDose(
exposure: exposures[index],
dose: it,
),
);
})
.values
.toList();
}
List<CategoryDose> _groupDosesPerCategories(
List<ActivityDose> dosesPerActivity) {
// Group doses by categories, by making a sum of all doses of each category
return groupBy<ActivityDose, int>(
dosesPerActivity, (it) => it.exposure.activity.category)
.map((key, value) {
return MapEntry(
key,
CategoryDose(
category: key,
dose: value.fold(0, (it1, it2) => it1 + it2.dose),
),
);
})
.values
.toList();
}
// 4. RUN
void main() {
final List<Activity> activitiesWithRecordings = _createSampleData();
printList('Activities with recordings:', activitiesWithRecordings);
final List<ActivityExposure> exposures =
activitiesWithRecordings.map(_calculateExposurePerActivity).toList();
printList('Exposures for each activity:', exposures);
final double LAeq = _calculateLAeq(exposures);
print('LAeq: $LAeq');
print('');
final List<ActivityDose> dosesPerActivityExposure =
_calculateDosesPerActivityExposure(exposures, LAeq);
printList('Doses per activity exposure:', dosesPerActivityExposure);
final List<CategoryDose> dosesPerCategoryExposure =
_groupDosesPerCategories(dosesPerActivityExposure);
printList('Doses per category exposure:', dosesPerCategoryExposure);
}
// 5. DART UTILS
num log10(num x) => math.log(x) / math.log(10);
Map<T, List<S>> groupBy<S, T>(Iterable<S> values, T key(S element)) {
var map = <T, List<S>>{};
for (var element in values) {
var list = map.putIfAbsent(key(element), () => []);
list.add(element);
}
return map;
}
void printList(String title, List list) {
print(title);
list.forEach((it) => print(' * $it'));
print('');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment