janwinkler1 commited on
Commit
7235148
1 Parent(s): 40fa82b

eda jan, second push, adapted to wav files (#2)

Browse files
README.md CHANGED
@@ -1,7 +1,8 @@
1
  # Source of truth
2
 
3
  ## welcome and initial setup
4
- hi all,
 
5
  i think when we start with the EDA, it suffices if anyone just uses what they are used to (f.e. conda or whatever). However, afterwards, i think it could be helpful that everyone, always has exactly the same environment, same package/python versions, which is why i propose working with docker to minimize headaches and "but it works on my machine" issues. I think with this minimal setup below, we can fully focus on hacking while not having pain with painful stuff.
6
 
7
  please feel free to add / change / challenge things!
@@ -11,35 +12,39 @@ please feel free to add / change / challenge things!
11
  - read how to setup docker for mac [here](https://docs.docker.com/desktop/install/mac-install/)
12
 
13
  ### how docker compose works
14
- essentially, you just have to build the container with the services you want. if you're interested in it i can go into more detail just let me know.
 
15
 
16
  1. navigate to dc/dev and run:
17
 
18
  ```
19
- docker compose up -d --build
20
  ```
21
 
22
  only use the `--build` flag the first time around, or if you want to rebuild the container (e.g. when having added a package you need in the container). **NOTE:** the `-d` flag stands for `detach` which means that your docker container runs in the background and does not log everything into your console.
23
 
24
- 2. then, to check whether everything worked hit:
25
 
26
  ```
27
  docker ps
28
  ```
29
 
30
- 3. for this specific setup, you can head to `localhost:8888` where jupyterlab is running.
31
 
32
- 4. to create a new file (using jupytext, see below), just create a new .ipynb file, the .py file will be created automatically. all the changes you make in the notebook, will be reflected in the .py files which you then can use for your commits.
33
 
34
- now you shoold see the running docker containers.
 
 
35
 
36
- ### what about huggingface spaces:
37
  - [here](./docs/huggingface-spaces.md), you can see what huggingface spaces is and how we can complement our github repo with it (credits to chat-gpt)
38
 
39
  ### jupytext - nice versioning of jupyter notebooks
 
40
  since we are likely be working with jupyter notebooks alot, lets use jupytext. It automatically maps .ipynb to .py files with some magic. The .ipynb are in the gitignore, so we only have .py files nicely versioned in the repo. read more about it [here](https://jupytext.readthedocs.io/en/latest/)
41
 
42
  ### trunk based development
 
43
  lets stick to trunk based. if you dont know what it is, read all about it [here](https://trunkbaseddevelopment.com/)
44
 
45
  key take aways:
@@ -49,7 +54,7 @@ key take aways:
49
  1. **Single Main Branch**: All developers commit to the trunk or main branch.
50
  2. **Short-Lived Branches**: Branches, if used, are short-lived and quickly merged back.
51
  3. **Frequent Integrations**: Code changes are integrated frequently, often multiple times a day.
52
- 4. **Feature Flags**: Incomplete features are managed with feature flags to maintain trunk stability.
53
 
54
  #### Benefits
55
 
@@ -70,6 +75,9 @@ key take aways:
70
  - **Feature Flags**: Manage incomplete or experimental features.
71
  - **Code Reviews**: Maintain quality and knowledge sharing.
72
 
 
73
 
74
-
75
-
 
 
 
1
  # Source of truth
2
 
3
  ## welcome and initial setup
4
+
5
+ hi all,
6
  i think when we start with the EDA, it suffices if anyone just uses what they are used to (f.e. conda or whatever). However, afterwards, i think it could be helpful that everyone, always has exactly the same environment, same package/python versions, which is why i propose working with docker to minimize headaches and "but it works on my machine" issues. I think with this minimal setup below, we can fully focus on hacking while not having pain with painful stuff.
7
 
8
  please feel free to add / change / challenge things!
 
12
  - read how to setup docker for mac [here](https://docs.docker.com/desktop/install/mac-install/)
13
 
14
  ### how docker compose works
15
+
16
+ essentially, you just have to build the container with the services you want. if you're interested in it i can go into more detail just let me know.
17
 
18
  1. navigate to dc/dev and run:
19
 
20
  ```
21
+ docker compose up -d --build
22
  ```
23
 
24
  only use the `--build` flag the first time around, or if you want to rebuild the container (e.g. when having added a package you need in the container). **NOTE:** the `-d` flag stands for `detach` which means that your docker container runs in the background and does not log everything into your console.
25
 
26
+ 2. then, to check whether everything worked hit:
27
 
28
  ```
29
  docker ps
30
  ```
31
 
32
+ 3. for this specific setup, you can head to `localhost:8888` where jupyterlab is running.
33
 
34
+ 4. to create a new file (using jupytext, see below), just create a new .ipynb file, the .py file will be created automatically. all the changes you make in the notebook, will be reflected in the .py files which you then can use for your commits.
35
 
36
+ now you shoold see the running docker containers.
37
+
38
+ ### what about huggingface spaces:
39
 
 
40
  - [here](./docs/huggingface-spaces.md), you can see what huggingface spaces is and how we can complement our github repo with it (credits to chat-gpt)
41
 
42
  ### jupytext - nice versioning of jupyter notebooks
43
+
44
  since we are likely be working with jupyter notebooks alot, lets use jupytext. It automatically maps .ipynb to .py files with some magic. The .ipynb are in the gitignore, so we only have .py files nicely versioned in the repo. read more about it [here](https://jupytext.readthedocs.io/en/latest/)
45
 
46
  ### trunk based development
47
+
48
  lets stick to trunk based. if you dont know what it is, read all about it [here](https://trunkbaseddevelopment.com/)
49
 
50
  key take aways:
 
54
  1. **Single Main Branch**: All developers commit to the trunk or main branch.
55
  2. **Short-Lived Branches**: Branches, if used, are short-lived and quickly merged back.
56
  3. **Frequent Integrations**: Code changes are integrated frequently, often multiple times a day.
57
+ 4. **Feature Flags**: Incomplete features are managed with feature flags to maintain trunk stability.
58
 
59
  #### Benefits
60
 
 
75
  - **Feature Flags**: Manage incomplete or experimental features.
76
  - **Code Reviews**: Maintain quality and knowledge sharing.
77
 
78
+ ### code format
79
 
80
+ - lets stick to black for python and prettier for .md and other formats
81
+ - using docker for the purpose of formatting is really easy
82
+ - just `chmod +x format` so that the `format` is executable
83
+ - then simply use `./format` before adding your changes and all the files will be autoformatted
docs/docker-setup.md CHANGED
@@ -1,9 +1,11 @@
1
  # DockerSetup
2
 
3
  This is a short version of howto install Docker on Ubuntu 20.04. It is basically a summary of the following source:\
4
- * https://docs.docker.com/install/linux/docker-ce/ubuntu/#os-requirements
 
5
 
6
  ## Install Docker
 
7
  ```bash
8
  sudo apt update
9
  sudo apt-get install \
@@ -24,15 +26,19 @@ sudo apt install docker-ce
24
  ```
25
 
26
  ## Add user to "docker" group & re-login
 
27
  Add yourself to the docker group (to get access to the docker deamon socket)\
28
  note: beeing member of docker gives you root access via the docker deamon
29
- ```bash
 
30
  sudo usermod -a -G docker `whoami`
31
  ```
 
32
  Logout / Login to load the new group rights\
33
  Using Ubuntu Gnome it may be required to restart
34
 
35
  ## Install Docker-Compose
 
36
  ```bash
37
  sudo apt install python3-pip
38
  sudo pip3 install docker-compose
 
1
  # DockerSetup
2
 
3
  This is a short version of howto install Docker on Ubuntu 20.04. It is basically a summary of the following source:\
4
+
5
+ - https://docs.docker.com/install/linux/docker-ce/ubuntu/#os-requirements
6
 
7
  ## Install Docker
8
+
9
  ```bash
10
  sudo apt update
11
  sudo apt-get install \
 
26
  ```
27
 
28
  ## Add user to "docker" group & re-login
29
+
30
  Add yourself to the docker group (to get access to the docker deamon socket)\
31
  note: beeing member of docker gives you root access via the docker deamon
32
+
33
+ ```bash
34
  sudo usermod -a -G docker `whoami`
35
  ```
36
+
37
  Logout / Login to load the new group rights\
38
  Using Ubuntu Gnome it may be required to restart
39
 
40
  ## Install Docker-Compose
41
+
42
  ```bash
43
  sudo apt install python3-pip
44
  sudo pip3 install docker-compose
docs/huggingface-spaces.md CHANGED
@@ -3,6 +3,7 @@ Hugging Face Spaces and GitHub repositories serve different but complementary pu
3
  ### Comparison with GitHub Repositories
4
 
5
  - **GitHub Repository**:
 
6
  - **Purpose**: Primarily used for version control, collaboration, and sharing of code and projects.
7
  - **Capabilities**: Stores code, tracks changes, manages issues, and supports CI/CD pipelines.
8
  - **Usage**: Developers collaborate on software development projects, manage codebases, and deploy applications.
@@ -17,12 +18,15 @@ Hugging Face Spaces and GitHub repositories serve different but complementary pu
17
  You can import a GitHub repository into Hugging Face Spaces to deploy an application hosted on GitHub. Here’s how to do it:
18
 
19
  1. **Create a Space on Hugging Face**:
 
20
  - Go to the Hugging Face Spaces website and create a new Space.
21
 
22
  2. **Link to GitHub Repository**:
 
23
  - During the setup of the new Space, you can link it to a GitHub repository. This allows Hugging Face Spaces to pull the code from your GitHub repo.
24
 
25
  3. **Configure Your Space**:
 
26
  - Ensure your repository contains the necessary files for the framework you are using (Streamlit, Gradio, or HTML/CSS/JS).
27
  - For example, if you are using Streamlit, ensure you have a `requirements.txt` file for dependencies and a main Python script that runs the Streamlit app.
28
 
@@ -34,15 +38,17 @@ You can import a GitHub repository into Hugging Face Spaces to deploy an applica
34
 
35
  1. **Create a New Space**:
36
  - Navigate to Hugging Face Spaces and click on “New Space”.
37
-
38
  2. **Set Up Space**:
 
39
  - Choose a name for your Space, select the appropriate SDK (e.g., Streamlit, Gradio, or HTML), and choose the visibility (public or private).
40
 
41
  3. **Connect GitHub Repository**:
 
42
  - In the Space settings, you will find an option to link a GitHub repository. Provide the URL of your GitHub repository.
43
  - Hugging Face Spaces will clone your GitHub repository to use it as the source code for your Space.
44
 
45
  4. **Configure and Deploy**:
 
46
  - Make sure your GitHub repository is set up correctly for the chosen framework. For example, a Streamlit app should have a `requirements.txt` and an entry-point script like `app.py`.
47
  - Once everything is set up, your Space will be deployed and can be accessed via a URL provided by Hugging Face.
48
 
 
3
  ### Comparison with GitHub Repositories
4
 
5
  - **GitHub Repository**:
6
+
7
  - **Purpose**: Primarily used for version control, collaboration, and sharing of code and projects.
8
  - **Capabilities**: Stores code, tracks changes, manages issues, and supports CI/CD pipelines.
9
  - **Usage**: Developers collaborate on software development projects, manage codebases, and deploy applications.
 
18
  You can import a GitHub repository into Hugging Face Spaces to deploy an application hosted on GitHub. Here’s how to do it:
19
 
20
  1. **Create a Space on Hugging Face**:
21
+
22
  - Go to the Hugging Face Spaces website and create a new Space.
23
 
24
  2. **Link to GitHub Repository**:
25
+
26
  - During the setup of the new Space, you can link it to a GitHub repository. This allows Hugging Face Spaces to pull the code from your GitHub repo.
27
 
28
  3. **Configure Your Space**:
29
+
30
  - Ensure your repository contains the necessary files for the framework you are using (Streamlit, Gradio, or HTML/CSS/JS).
31
  - For example, if you are using Streamlit, ensure you have a `requirements.txt` file for dependencies and a main Python script that runs the Streamlit app.
32
 
 
38
 
39
  1. **Create a New Space**:
40
  - Navigate to Hugging Face Spaces and click on “New Space”.
 
41
  2. **Set Up Space**:
42
+
43
  - Choose a name for your Space, select the appropriate SDK (e.g., Streamlit, Gradio, or HTML), and choose the visibility (public or private).
44
 
45
  3. **Connect GitHub Repository**:
46
+
47
  - In the Space settings, you will find an option to link a GitHub repository. Provide the URL of your GitHub repository.
48
  - Hugging Face Spaces will clone your GitHub repository to use it as the source code for your Space.
49
 
50
  4. **Configure and Deploy**:
51
+
52
  - Make sure your GitHub repository is set up correctly for the chosen framework. For example, a Streamlit app should have a `requirements.txt` and an entry-point script like `app.py`.
53
  - Once everything is set up, your Space will be deployed and can be accessed via a URL provided by Hugging Face.
54
 
format ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ #! /bin/sh
2
+
3
+ # Run as root, otherwise the container cannot modify the mounted files.
4
+ docker run --rm --user root --volume $(pwd):/work tmknom/prettier prettier --loglevel warn --write .
5
+
6
+ # Format Python files using Black
7
+ docker run --rm --user root --volume $(pwd):/data cytopia/black:latest .
python/eda_jan.py CHANGED
@@ -20,7 +20,7 @@ import librosa.display
20
  import matplotlib.pyplot as plt
21
  from sklearn.cluster import KMeans
22
  from sklearn.decomposition import PCA
23
- from IPython.display import Audio, display
24
 
25
  # %%
26
  # Load the entire audio file
@@ -32,7 +32,7 @@ y, sr = librosa.load(file_path, sr=44100)
32
  # %%
33
  # split soundfile in to 10s chunks
34
  window_size = 10 # window size in seconds
35
- hop_size = 10 # hop size in seconds
36
 
37
  # Convert window and hop size to samples
38
  window_samples = int(window_size * sr)
@@ -47,13 +47,13 @@ print(f"Total number of windows: {num_windows}")
47
  # %%
48
  # Define frequency bands (in Hz)
49
  bands = {
50
- 'Sub-bass': (20, 60),
51
- 'Bass': (60, 250),
52
- 'Low Midrange': (250, 500),
53
- 'Midrange': (500, 2000),
54
- 'Upper Midrange': (2000, 4000),
55
- 'Presence': (4000, 6000),
56
- 'Brilliance': (6000, 20000)
57
  }
58
 
59
  # Initialize a list to hold the features
@@ -67,7 +67,7 @@ for i in range(num_windows):
67
  # Compute STFT
68
  S = librosa.stft(y_window)
69
  S_db = librosa.amplitude_to_db(np.abs(S))
70
-
71
  # Compute features for each band
72
  features = []
73
  for band, (low_freq, high_freq) in bands.items():
@@ -75,7 +75,7 @@ for i in range(num_windows):
75
  high_bin = int(np.ceil(high_freq * (S.shape[0] / sr)))
76
  band_energy = np.mean(S_db[low_bin:high_bin, :], axis=0)
77
  features.append(band_energy)
78
-
79
  # Flatten the feature array and add to all_features
80
  features_flat = np.concatenate(features)
81
  all_features.append(features_flat)
@@ -95,11 +95,13 @@ clusters = kmeans.fit_predict(features_reduced)
95
 
96
  # Plot the clusters
97
  plt.figure(figsize=(10, 6))
98
- scatter = plt.scatter(features_reduced[:, 0], features_reduced[:, 1], c=clusters, cmap='viridis')
99
- plt.title('Clustered Frequency Band Features')
100
- plt.xlabel('Principal Component 1')
101
- plt.ylabel('Principal Component 2')
102
- plt.colorbar(scatter, label='Cluster')
 
 
103
  plt.show()
104
 
105
 
@@ -108,12 +110,12 @@ plt.show()
108
  for cluster_label in np.unique(clusters):
109
  # Find the first data point in the cluster
110
  representative_index = np.where(clusters == cluster_label)[0][0]
111
-
112
  # Use the original audio window at the representative index
113
  start_sample = representative_index * hop_samples
114
  end_sample = start_sample + window_samples
115
  y_representative = y[start_sample:end_sample]
116
-
117
  print(f"Cluster {cluster_label} representative audio:")
118
  display(Audio(data=y_representative, rate=sr))
119
 
@@ -127,23 +129,36 @@ import numpy as np
127
  import librosa
128
  from sklearn.preprocessing import StandardScaler
129
  import joblib
 
 
 
 
 
 
 
 
 
130
 
 
131
  # Directory containing the audio files
132
- audio_dir = "data/soundscape_data"
 
 
 
133
 
134
  # Parameters for windowing
135
  window_size = 10 # window size in seconds
136
- hop_size = 10 # hop size in seconds
137
 
138
  # Define frequency bands (in Hz)
139
  bands = {
140
- 'Sub-bass': (20, 60),
141
- 'Bass': (60, 250),
142
- 'Low Midrange': (250, 500),
143
- 'Midrange': (500, 2000),
144
- 'Upper Midrange': (2000, 4000),
145
- 'Presence': (4000, 6000),
146
- 'Brilliance': (6000, 20000)
147
  }
148
 
149
  # Directory to save features
@@ -152,10 +167,10 @@ os.makedirs(features_dir, exist_ok=True)
152
 
153
  # Iterate over each audio file in the directory
154
  for filename in os.listdir(audio_dir):
155
- if filename.endswith(".flac"):
156
  file_path = os.path.join(audio_dir, filename)
157
  y, sr = librosa.load(file_path, sr=44100)
158
-
159
  # Convert window and hop size to samples
160
  window_samples = int(window_size * sr)
161
  hop_samples = int(hop_size * sr)
@@ -194,19 +209,17 @@ for filename in os.listdir(audio_dir):
194
  all_features = scaler.fit_transform(all_features)
195
 
196
  # Save features to disk
197
- feature_file = os.path.join(features_dir, f"{os.path.splitext(filename)[0]}_features.npy")
 
 
198
  joblib.dump((all_features, scaler), feature_file)
199
 
200
 
201
  # %%
202
- import numpy as np
203
- import joblib
204
- from sklearn.cluster import KMeans
205
- from sklearn.decomposition import PCA
206
- import matplotlib.pyplot as plt
207
-
208
  # Directory to load features
209
  features_dir = "features"
 
 
210
 
211
  # Load all features
212
  all_features = []
@@ -223,53 +236,50 @@ pca = PCA(n_components=2)
223
  features_pca = pca.fit_transform(all_features)
224
 
225
  # Perform k-means clustering
226
- kmeans = KMeans(n_clusters=5) # Example: 5 clusters
227
  clusters = kmeans.fit_predict(all_features)
228
 
229
  # Plot the PCA-reduced features with cluster labels
230
  plt.figure(figsize=(10, 6))
231
- scatter = plt.scatter(features_pca[:, 0], features_pca[:, 1], c=clusters, cmap='viridis')
232
- plt.title('PCA of Clustered Frequency Band Features')
233
- plt.xlabel('Principal Component 1')
234
- plt.ylabel('Principal Component 2')
235
- plt.colorbar(scatter, label='Cluster')
 
 
236
  plt.show()
237
 
238
  # Save clustering results
239
- clustering_results = {
240
- 'clusters': clusters,
241
- 'kmeans': kmeans,
242
- 'pca': pca
243
- }
244
- joblib.dump(clustering_results, 'clustering_results.pkl')
245
 
246
  # Plot the clusters
247
  plt.figure(figsize=(10, 6))
248
- for i in range(5):
249
- plt.plot(all_features[clusters == i].mean(axis=0), label=f'Cluster {i}')
250
  plt.legend()
251
- plt.title('Clustered Frequency Band Features')
 
 
252
  plt.show()
253
 
254
  # %%
255
- import os
256
- import numpy as np
257
- import librosa
258
- from IPython.display import Audio, display
259
- import joblib
260
-
261
  # Directory containing the audio files
262
- audio_dir = "data/soundscape_data"
 
 
 
263
  # Directory to load features
264
  features_dir = "features"
265
 
266
  # Parameters for windowing
267
  window_size = 10 # window size in seconds
268
- hop_size = 10 # hop size in seconds
269
 
270
  # Load clustering results
271
- clustering_results = joblib.load('clustering_results.pkl')
272
- clusters = clustering_results['clusters']
273
 
274
  # Load all features
275
  all_features = []
@@ -278,7 +288,7 @@ audio_segments = []
278
  for feature_file in os.listdir(features_dir):
279
  if feature_file.endswith("_features.npy"):
280
  features, scaler = joblib.load(os.path.join(features_dir, feature_file))
281
- filename = feature_file.replace('_features.npy', '.flac')
282
  file_path = os.path.join(audio_dir, filename)
283
  y, sr = librosa.load(file_path, sr=44100)
284
 
@@ -318,3 +328,79 @@ for cluster_label in np.unique(clusters):
318
 
319
 
320
  # %%
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  import matplotlib.pyplot as plt
21
  from sklearn.cluster import KMeans
22
  from sklearn.decomposition import PCA
23
+ from IPython.display import Audio, display
24
 
25
  # %%
26
  # Load the entire audio file
 
32
  # %%
33
  # split soundfile in to 10s chunks
34
  window_size = 10 # window size in seconds
35
+ hop_size = 10 # hop size in seconds
36
 
37
  # Convert window and hop size to samples
38
  window_samples = int(window_size * sr)
 
47
  # %%
48
  # Define frequency bands (in Hz)
49
  bands = {
50
+ "Sub-bass": (20, 60),
51
+ "Bass": (60, 250),
52
+ "Low Midrange": (250, 500),
53
+ "Midrange": (500, 2000),
54
+ "Upper Midrange": (2000, 4000),
55
+ "Presence": (4000, 6000),
56
+ "Brilliance": (6000, 20000),
57
  }
58
 
59
  # Initialize a list to hold the features
 
67
  # Compute STFT
68
  S = librosa.stft(y_window)
69
  S_db = librosa.amplitude_to_db(np.abs(S))
70
+
71
  # Compute features for each band
72
  features = []
73
  for band, (low_freq, high_freq) in bands.items():
 
75
  high_bin = int(np.ceil(high_freq * (S.shape[0] / sr)))
76
  band_energy = np.mean(S_db[low_bin:high_bin, :], axis=0)
77
  features.append(band_energy)
78
+
79
  # Flatten the feature array and add to all_features
80
  features_flat = np.concatenate(features)
81
  all_features.append(features_flat)
 
95
 
96
  # Plot the clusters
97
  plt.figure(figsize=(10, 6))
98
+ scatter = plt.scatter(
99
+ features_reduced[:, 0], features_reduced[:, 1], c=clusters, cmap="viridis"
100
+ )
101
+ plt.title("Clustered Frequency Band Features")
102
+ plt.xlabel("Principal Component 1")
103
+ plt.ylabel("Principal Component 2")
104
+ plt.colorbar(scatter, label="Cluster")
105
  plt.show()
106
 
107
 
 
110
  for cluster_label in np.unique(clusters):
111
  # Find the first data point in the cluster
112
  representative_index = np.where(clusters == cluster_label)[0][0]
113
+
114
  # Use the original audio window at the representative index
115
  start_sample = representative_index * hop_samples
116
  end_sample = start_sample + window_samples
117
  y_representative = y[start_sample:end_sample]
118
+
119
  print(f"Cluster {cluster_label} representative audio:")
120
  display(Audio(data=y_representative, rate=sr))
121
 
 
129
  import librosa
130
  from sklearn.preprocessing import StandardScaler
131
  import joblib
132
+ import numpy as np
133
+ from sklearn.cluster import KMeans
134
+ from sklearn.decomposition import PCA
135
+ import matplotlib.pyplot as plt
136
+ import librosa
137
+ from IPython.display import Audio, display
138
+ from sklearn.model_selection import cross_val_score
139
+ from sklearn.ensemble import RandomForestClassifier
140
+
141
 
142
+ # %%
143
  # Directory containing the audio files
144
+ # audio_dir = "data/soundscape_data"
145
+ audio_dir = (
146
+ "data/SoundMeters_Ingles_Primary-20240519T132658Z-002/SoundMeters_Ingles_Primary"
147
+ )
148
 
149
  # Parameters for windowing
150
  window_size = 10 # window size in seconds
151
+ hop_size = 10 # hop size in seconds
152
 
153
  # Define frequency bands (in Hz)
154
  bands = {
155
+ "Sub-bass": (20, 60),
156
+ "Bass": (60, 250),
157
+ "Low Midrange": (250, 500),
158
+ "Midrange": (500, 2000),
159
+ "Upper Midrange": (2000, 4000),
160
+ "Presence": (4000, 6000),
161
+ "Brilliance": (6000, 20000),
162
  }
163
 
164
  # Directory to save features
 
167
 
168
  # Iterate over each audio file in the directory
169
  for filename in os.listdir(audio_dir):
170
+ if filename.endswith(".wav"):
171
  file_path = os.path.join(audio_dir, filename)
172
  y, sr = librosa.load(file_path, sr=44100)
173
+
174
  # Convert window and hop size to samples
175
  window_samples = int(window_size * sr)
176
  hop_samples = int(hop_size * sr)
 
209
  all_features = scaler.fit_transform(all_features)
210
 
211
  # Save features to disk
212
+ feature_file = os.path.join(
213
+ features_dir, f"{os.path.splitext(filename)[0]}_features.npy"
214
+ )
215
  joblib.dump((all_features, scaler), feature_file)
216
 
217
 
218
  # %%
 
 
 
 
 
 
219
  # Directory to load features
220
  features_dir = "features"
221
+ n_clusters = 5
222
+
223
 
224
  # Load all features
225
  all_features = []
 
236
  features_pca = pca.fit_transform(all_features)
237
 
238
  # Perform k-means clustering
239
+ kmeans = KMeans(n_clusters=n_clusters) # Example: 5 clusters
240
  clusters = kmeans.fit_predict(all_features)
241
 
242
  # Plot the PCA-reduced features with cluster labels
243
  plt.figure(figsize=(10, 6))
244
+ scatter = plt.scatter(
245
+ features_pca[:, 0], features_pca[:, 1], c=clusters, cmap="viridis"
246
+ )
247
+ plt.title("PCA of Clustered Frequency Band Features")
248
+ plt.xlabel("Principal Component 1")
249
+ plt.ylabel("Principal Component 2")
250
+ plt.colorbar(scatter, label="Cluster")
251
  plt.show()
252
 
253
  # Save clustering results
254
+ clustering_results = {"clusters": clusters, "kmeans": kmeans, "pca": pca}
255
+ joblib.dump(clustering_results, "clustering_results.pkl")
 
 
 
 
256
 
257
  # Plot the clusters
258
  plt.figure(figsize=(10, 6))
259
+ for i in range(n_clusters):
260
+ plt.plot(all_features[clusters == i].mean(axis=0), label=f"Cluster {i}")
261
  plt.legend()
262
+ plt.title("Clustered Frequency Band Features")
263
+ plt.xlabel("Feature Index (Frequency Bands)")
264
+ plt.ylabel("Mean Feature Value (Energy in dB)")
265
  plt.show()
266
 
267
  # %%
 
 
 
 
 
 
268
  # Directory containing the audio files
269
+ # audio_dir = "data/soundscape_data"
270
+ audio_dir = (
271
+ "data/SoundMeters_Ingles_Primary-20240519T132658Z-002/SoundMeters_Ingles_Primary"
272
+ )
273
  # Directory to load features
274
  features_dir = "features"
275
 
276
  # Parameters for windowing
277
  window_size = 10 # window size in seconds
278
+ hop_size = 10 # hop size in seconds
279
 
280
  # Load clustering results
281
+ clustering_results = joblib.load("clustering_results.pkl")
282
+ clusters = clustering_results["clusters"]
283
 
284
  # Load all features
285
  all_features = []
 
288
  for feature_file in os.listdir(features_dir):
289
  if feature_file.endswith("_features.npy"):
290
  features, scaler = joblib.load(os.path.join(features_dir, feature_file))
291
+ filename = feature_file.replace("_features.npy", ".wav")
292
  file_path = os.path.join(audio_dir, filename)
293
  y, sr = librosa.load(file_path, sr=44100)
294
 
 
328
 
329
 
330
  # %%
331
+
332
+ # Fit PCA
333
+ pca = PCA().fit(all_features_scaled)
334
+
335
+ # Method 1: Variance Explained
336
+ explained_variance = pca.explained_variance_ratio_
337
+ cumulative_explained_variance = np.cumsum(explained_variance)
338
+
339
+ # Plot the cumulative explained variance
340
+ plt.figure(figsize=(10, 6))
341
+ plt.plot(cumulative_explained_variance, marker="o")
342
+ plt.xlabel("Number of Principal Components")
343
+ plt.ylabel("Cumulative Explained Variance")
344
+ plt.title("Explained Variance vs. Number of Principal Components")
345
+ plt.grid(True)
346
+ plt.show()
347
+
348
+
349
+ # %%
350
+ # Method 2: Scree Plot
351
+ plt.figure(figsize=(10, 6))
352
+ plt.plot(np.arange(1, len(explained_variance) + 1), explained_variance, marker="o")
353
+ plt.xlabel("Principal Component")
354
+ plt.ylabel("Explained Variance")
355
+ plt.title("Scree Plot")
356
+ plt.grid(True)
357
+ plt.show()
358
+
359
+
360
+ # %%
361
+ # Method 3: Kaiser Criterion
362
+ eigenvalues = pca.explained_variance_
363
+ kaiser_criterion = np.sum(eigenvalues > 1)
364
+
365
+
366
+ # IMO this doesnt make sense at the moment, we need to extract more features
367
+ print(f"Number of components selected by Kaiser Criterion: {kaiser_criterion}")
368
+
369
+
370
+ # %%
371
+ # Method 4: Cross-Validation
372
+ # Evaluate a classifier with different numbers of principal components
373
+
374
+ ## do not run if you dont have time, this takes forever.
375
+ # scores = []
376
+ # for n_components in range(1, len(explained_variance) + 1):
377
+ # pca = PCA(n_components=n_components)
378
+ # features_pca = pca.fit_transform(all_features_scaled)
379
+ # classifier = RandomForestClassifier() # Use your preferred model here
380
+ # score = np.mean(cross_val_score(classifier, features_pca, clusters, cv=n_clusters)) # Assuming `clusters` are your labels
381
+ # scores.append(score)
382
+
383
+ # # Plot cross-validation scores
384
+ # plt.figure(figsize=(10, 6))
385
+ # plt.plot(range(1, len(explained_variance) + 1), scores, marker='o')
386
+ # plt.xlabel('Number of Principal Components')
387
+ # plt.ylabel('Cross-Validation Score')
388
+ # plt.title('Cross-Validation Score vs. Number of Principal Components')
389
+ # plt.grid(True)
390
+ # plt.show()
391
+
392
+ # # Choosing the number of components that explain at least 95% of the variance
393
+ # n_components_variance = np.argmax(cumulative_explained_variance >= 0.95) + 1
394
+ # print(f"Number of components to retain 95% variance: {n_components_variance}")
395
+
396
+ # # Choose the optimal number of components based on your analysis
397
+ # optimal_n_components = n_components_variance # or based on the scree plot, cross-validation, etc.
398
+ # print(f"Optimal number of components: {optimal_n_components}")
399
+
400
+ # # Perform PCA with the selected number of components
401
+ # pca = PCA(n_components=optimal_n_components)
402
+ # features_pca = pca.fit_transform(all_features_scaled)
403
+
404
+ # %%
405
+
406
+ # %%
python/requirements.txt CHANGED
@@ -8,3 +8,5 @@ numpy
8
  opencv-python
9
  scipy
10
  librosa
 
 
 
8
  opencv-python
9
  scipy
10
  librosa
11
+ plotly
12
+ ipywidgets