Skip to content

Instantly share code, notes, and snippets.

@lukaspili
Last active October 1, 2019 15:00
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/b7930ee94874f21e8a9c65d65751b136 to your computer and use it in GitHub Desktop.
Save lukaspili/b7930ee94874f21e8a9c65d65751b136 to your computer and use it in GitHub Desktop.
import 'dart:math' as math;
// 1. MODELS
enum Gender { female, male }
class Activity {
Activity({this.id, this.category, this.hours, this.frequency, this.recordings});
final int id;
final int category;
// Number of hours per frequency
final int hours;
final ActivityFrequency frequency;
// Recordings attached to this activity
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});
// Duration in seconds
final int duration;
// The last value of leqA calculated the recording
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.round()} dbA';
}
}
// 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<double> aye({
Gender gender,
int age,
List<ActivityExposure> exposures,
}) {
const ISO_1999_NIPTS_3000 = [3000.0, 0.0120000000000000, 0.0370000000000000, 77.0];
const ISO_1999_alpha_3000 = [3000.0, 0.0115000000000000, 0.00750000000000000];
final sex = gender == Gender.male ? 0 : 1;
final currentAge = age;
final futureAge = List<int>();
for (int k = 1; k <= 5; ++k) {
futureAge.add(currentAge + k * 5);
}
final exposureData = exposures;
final lex8h = _lex8h(exposureData);
int beginAge = currentAge;
final a = List<double>();
for (int k = 1; k <= futureAge.length; ++k) {
double value;
if (lex8h < ISO_1999_NIPTS_3000[_indexFor(4)]) {
value = 0.0;
} else {
if (futureAge[_indexFor(k)] - beginAge > 10) {
final a = ISO_1999_NIPTS_3000[_indexFor(2)];
final b = ISO_1999_NIPTS_3000[_indexFor(3)];
final c = log10(futureAge[_indexFor(k)].toDouble() - beginAge);
final d = lex8h - ISO_1999_NIPTS_3000[_indexFor(4)];
final e = math.pow(d, 2);
final f = ISO_1999_alpha_3000[_indexFor(sex + 2)];
final g = ((a + b * c) * e) / f;
final h = math.sqrt(g);
final result = h - futureAge[_indexFor(k)] + 18;
value = result;
} else {
final a = log10(futureAge[_indexFor(k)] - beginAge + 1.0) / log10(11.0);
final b = ISO_1999_NIPTS_3000[_indexFor(2)] + ISO_1999_NIPTS_3000[_indexFor(3)] * log10(10.0);
final c = lex8h - ISO_1999_NIPTS_3000[_indexFor(4)];
final d = math.pow(c, 2);
final e = ISO_1999_alpha_3000[_indexFor(sex + 2)];
final f = a * (b * d) / e;
final g = math.sqrt(f);
final result = g - futureAge[_indexFor(k)] + 18;
value = result;
}
if (value < 0) {
value = 0.0;
}
}
a.add(value);
}
return a;
}
// Matlab array indexes start at 1, while in Dart it starts at 0
int _indexFor(int index) => index - 1;
double _lex8h(List<ActivityExposure> exposures) {
final totalDuration = exposures.fold(0, (it1, it2) => it1 + it2.normalizedDailyDuration);
final LAeq = _calculateLAeq(exposures);
return LAeq + 10 * log10(totalDuration / 8.0);
}
// 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<double> aye1 = aye(age: 30, gender: Gender.male, exposures: exposures);
printList('AYE for male, 30:', aye1);
final List<double> aye2 = aye(age: 30, gender: Gender.female, exposures: exposures);
printList('AYE for female, 30:', aye2);
final List<double> aye3 = aye(age: 50, gender: Gender.male, exposures: exposures);
printList('AYE for male, 50:', aye3);
final List<double> aye4 = aye(age: 50, gender: Gender.female, exposures: exposures);
printList('AYE for female, 50:', aye4);
}
// 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