Table of contents
For the third Decibels Challenge, the prompt for data is personal data. I decided to use data from 10 workouts I did and use SonicPi to sonify the process and Python to clean it up.
Wanted the sounds to represent the various stages a heart goes through in a workout. This explains some of the chaotic tension/feelings that can be heard in this track
Sounds
IllestPreacha · Decibels 2023 March Challenge ; Personal Data : Heart Edition
Data
Table
HR_AVG | HR_MAX | HR_MIN | Calories | CardioLoad | Zone3 | Zone2 | HR_Max-MIn | Zone2+3 | Other Zones | CaloLoad | |
0 | 147 | 174 | 98 | 554 | 71 | 0.44 | 0.1 | 76 | 0.54 | 0.46 | 7.802816901 |
1 | 123 | 156 | 108 | 876 | 80 | 0.36 | 0.37 | 48 | 0.73 | 0.27 | 10.95 |
2 | 110 | 135 | 74 | 44 | 3 | 0.16 | 0.61 | 61 | 0.77 | 0.23 | 14.66666667 |
3 | 100 | 126 | 80 | 224 | 16 | 0 | 0.12 | 46 | 0.12 | 0.88 | 14 |
4 | 130 | 156 | 74 | 292 | 29 | 0.56 | 0.38 | 82 | 0.94 | 0.06 | 10.06896552 |
5 | 116 | 140 | 95 | 137 | 11 | 0.05 | 0.72 | 45 | 0.77 | 0.23 | 12.45454545 |
6 | 126 | 158 | 93 | 434 | 42 | 0.34 | 0.49 | 65 | 0.83 | 0.17 | 10.33333333 |
7 | 123 | 154 | 86 | 593 | 58 | 0.44 | 0.31 | 68 | 0.75 | 0.25 | 10.22413793 |
8 | 136 | 136 | 85 | 570 | 69 | 0.24 | 0.17 | 51 | 0.41 | 0.59 | 8.260869565 |
9 | 90 | 123 | 73 | 157 | 12 | 0 | 0.15 | 50 | 0.15 | 0.85 | 13.08333333 |
10 | 138 | 172 | 108 | 497 | 57 | 0.64 | 0.16 | 64 | 0.8 | 0.2 | 8.719298246 |
Column Names
HR_AVG - Average Heart Rate
HR_Max - Max Heart Rate
HR_Min - Min Heart Rate
Calories - Calories Burnt
CardioLoad - the cardio intensity given for that workout
Zone2, Zone3, Other Zones - Refer to the Five Heart zones
CaloLoad - Is the ratio of Calories Burnt: Cardio Load
These columns are used in the SonicPi Code to make the sounds and can be used to understand which columns are affecting which part
Code
SonicPi Code
Comments in Code for more information
require 'csv'
#naming the Dataset DipInCode and going to read the file
Heart = CSV.parse(File.read("C:/Creatuve Code Challenges/Sonification Challenges/March 2023/HeartRatePrep.csv"), headers: true)
i = 0
live_loop :HeartZone do
#these effects are going to be affected by the zones, since they are between 0 and 1, which is the range for the mix function
with_fx :echo, mix: Heart[i]['Other Zones'].to_f do
with_fx :ixi_techno, mix: Heart[i]['Zone3'].to_f do
with_fx :krush, mix: Heart[i]['Zone2+3'].to_f do
#a trio of synths to add more musicality/variance to the listening experience
use_synth [:organ_tonewheel,:mod_sine,:mod_sine].choose
#Corresponds to the note being played
play Heart[i]['HR_MIN'].to_f, decay: Heart[i]['Other Zones'].to_f, amp: dice(12)
#We can even pass a list of times which it will treat as a circle of times:
play_pattern_timed chord(Heart[i]['HR_MIN'].to_f, :m13), [Heart[i]['Zone2+3'].to_f, Heart[i]['Other Zones'].to_f ,Heart[i]['HR_MAX'].to_f/ Heart[i]['HR_MIN'].to_f]
end
end
end
i += 1 #counter
if i == Heart.length #make the loop nonstop
i = 0
end
#spacing
sleep Math.sin(Heart[i]['HR_MAX'].to_f/ Heart[i]['HR_MIN'].to_f)
end
live_loop :HeartBeat do
#same as the previous loop, with the difference being a random choosing of 3 effects instead of 3 synths in this portion
with_fx :flanger, depth: Heart[i]['Other Zones'].to_f do
with_fx :echo, mix: Heart[i]['Zone2+3'].to_f do
with_fx [:ping_pong,:vowel,:whammy].choose, mix: Heart[i]['Other Zones'].to_f do
sample :ambi_piano,beat_stretch: Heart[i]['Zone2'].to_f ,pitch: Heart[i]['CaloLoad'].to_f
sample :perc_impact1,beat_stretch: Math.cos(Heart[i]['Other Zones'].to_f), decay: Heart[i]['CaloLoad'].to_f
end
end
end
i += 1
if i == Heart.length #make the loop nonstop
i = 0
end
sleep Heart[i]['HR_MAX'].to_f/ Heart[i]['HR_MIN'].to_f
end
Python Code
import pandas as pd
df = pd.read_csv('Jan16_23_heart - Sheet1.csv')
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 11 entries, 0 to 10 Data columns (total 7 columns): # Column Non-Null Count Dtype
--- ------ -------------- -----
0 HR_AVG 11 non-null int64
1 HR_MAX 11 non-null int64
2 HR_MIN 11 non-null int64
3 Calories 11 non-null int64
4 CardioLoad 11 non-null int64
5 Zone3 11 non-null float64 6 Zone2 11 non-null float64 dtypes: float64(2), int64(5) memory usage: 744.0 bytes
df. describe()
HR_AVG | HR_MAX | HR_MIN | Calories | CardioLoad | Zone3 | Zone2 | |
count | 11.000000 | 11.000000 | 11.000000 | 11.000000 | 11.000000 | 11.000000 | 11.000000 |
mean | 121.727273 | 148.181818 | 88.545455 | 398.000000 | 40.727273 | 0.293636 | 0.325455 |
std | 16.870631 | 17.325231 | 12.902431 | 249.911184 | 27.756408 | 0.222003 | 0.210778 |
min | 90.000000 | 123.000000 | 73.000000 | 44.000000 | 3.000000 | 0.000000 | 0.100000 |
25% | 113.000000 | 135.500000 | 77.000000 | 190.500000 | 14.000000 | 0.105000 | 0.155000 |
50% | 123.000000 | 154.000000 | 86.000000 | 434.000000 | 42.000000 | 0.340000 | 0.310000 |
75% | 133.000000 | 157.000000 | 96.500000 | 562.000000 | 63.500000 | 0.440000 | 0.435000 |
max | 147.000000 | 174.000000 | 108.000000 | 876.000000 | 80.000000 | 0.640000 | 0.720000 |
#time to make new columns based on the information provided and get more Numbers for the sonification
#HeartRate Max-MIn , getting the difference between Heart Rates
df['HR_Max-MIn'] = df['HR_MAX']- df['HR_MIN']
#Total percentage of HeartRatein Zone3 + Zone2
df['Zone2+3'] = df['Zone2'] + df['Zone3']
#Total percentage of Other Heart Zones
df['Other Zones'] = 1 - df['Zone2'] - df['Zone3']
#Calories divided by Cardio Load
df['CaloLoad'] = df['Calories'] / df['CardioLoad']
df
HR_AVG | HR_MAX | HR_MIN | Calories | CardioLoad | Zone3 | Zone2 | HR_Max-MIn | Zone2+3 | Other Zones | CaloLoad | |
0 | 147 | 174 | 98 | 554 | 71 | 0.44 | 0.10 | 76 | 0.54 | 0.46 | 7.802817 |
1 | 123 | 156 | 108 | 876 | 80 | 0.36 | 0.37 | 48 | 0.73 | 0.27 | 10.950000 |
2 | 110 | 135 | 74 | 44 | 3 | 0.16 | 0.61 | 61 | 0.77 | 0.23 | 14.666667 |
3 | 100 | 126 | 80 | 224 | 16 | 0.00 | 0.12 | 46 | 0.12 | 0.88 | 14.000000 |
4 | 130 | 156 | 74 | 292 | 29 | 0.56 | 0.38 | 82 | 0.94 | 0.06 | 10.068966 |
5 | 116 | 140 | 95 | 137 | 11 | 0.05 | 0.72 | 45 | 0.77 | 0.23 | 12.454545 |
6 | 126 | 158 | 93 | 434 | 42 | 0.34 | 0.49 | 65 | 0.83 | 0.17 | 10.333333 |
7 | 123 | 154 | 86 | 593 | 58 | 0.44 | 0.31 | 68 | 0.75 | 0.25 | 10.224138 |
8 | 136 | 136 | 85 | 570 | 69 | 0.24 | 0.17 | 51 | 0.41 | 0.59 | 8.260870 |
9 | 90 | 123 | 73 | 157 | 12 | 0.00 | 0.15 | 50 | 0.15 | 0.85 | 13.083333 |
10 | 138 | 172 | 108 | 497 | 57 | 0.64 | 0.16 | 64 | 0.80 | 0.20 | 8.719298 |
df.to_csv('HeartRatePrep.csv')