rmayormartins commited on
Commit
701098c
1 Parent(s): a61fcf3

Resolve conflitos

Browse files
Files changed (2) hide show
  1. README.md +4 -4
  2. app.py +275 -53
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
- title: Speech-Scope
3
- emoji: 🎤
4
  colorFrom: gray
5
  colorTo: indigo
6
  sdk: gradio
@@ -10,9 +10,9 @@ pinned: false
10
  license: ecl-2.0
11
  ---
12
 
13
- ## Speech-Scope
14
 
15
- Análise de métricas de áudio.
16
 
17
  Confira a referência de configuração em [Hugging Face Spaces Config Reference](https://huggingface.co/docs/hub/spaces-config-reference).
18
 
 
1
  ---
2
+ title: AIA-Scope
3
+ emoji: 🔍
4
  colorFrom: gray
5
  colorTo: indigo
6
  sdk: gradio
 
10
  license: ecl-2.0
11
  ---
12
 
13
+ ## AIA-Scope
14
 
15
+ Análise do arquivo .aia gerado pelo MIT App Inventor
16
 
17
  Confira a referência de configuração em [Hugging Face Spaces Config Reference](https://huggingface.co/docs/hub/spaces-config-reference).
18
 
app.py CHANGED
@@ -1,83 +1,305 @@
1
  import gradio as gr
2
- import librosa
3
- import numpy as np
4
- import matplotlib.pyplot as plt
5
  import tempfile
6
- import librosa.display
 
 
 
 
 
 
7
 
8
 
9
- def calculate_basic_metrics(y, sr):
10
- pitches, magnitudes = librosa.piptrack(y=y, sr=sr)
11
- average_pitch = np.mean(pitches[pitches > 0])
12
- mfccs = librosa.feature.mfcc(y=y, sr=sr)
13
- energy = np.sum(y ** 2)
14
- zero_crossing_rate = np.mean(librosa.feature.zero_crossing_rate(y))
15
- spectral_centroid = np.mean(librosa.feature.spectral_centroid(y=y, sr=sr))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  return {
18
- 'Average Pitch': average_pitch,
19
- 'Number of MFCCs': mfccs.shape[1],
20
- 'Energy': energy,
21
- 'Zero Crossing Rate': zero_crossing_rate,
22
- 'Spectral Centroid': spectral_centroid
23
  }
24
 
25
 
26
- def calculate_advanced_metrics(y, sr):
27
- metrics = {}
28
 
29
- f0, _, _ = librosa.pyin(y, fmin=50, fmax=4000)
30
- if f0 is not None:
31
- metrics['Average F0 (YIN)'] = np.nanmean(f0)
32
 
33
- chroma = librosa.feature.chroma_stft(y=y, sr=sr)
34
- metrics['Average Chroma'] = np.mean(chroma)
35
 
36
- spectral_contrast = librosa.feature.spectral_contrast(y=y, sr=sr)
37
- metrics['Average Spectral Contrast'] = np.mean(spectral_contrast)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
- return metrics
 
 
 
40
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
- def generate_spectrogram(y, sr):
43
- plt.figure(figsize=(10, 4))
44
- librosa.display.specshow(librosa.amplitude_to_db(np.abs(librosa.stft(y)), ref=np.max), sr=sr, x_axis='time', y_axis='log')
45
- plt.colorbar(format='%+2.0f dB')
46
- plt.title('Spectrogram')
47
- plt.tight_layout()
48
 
 
 
 
 
 
49
 
50
- with tempfile.NamedTemporaryFile(delete=False, suffix='.png', mode='w+b') as f:
51
- plt.savefig(f.name, format='png')
52
- plt.close()
53
- return f.name
 
 
 
 
54
 
 
 
 
 
 
 
 
55
 
56
- def process_audio(file):
57
- if file is None:
58
- return {}, "placeholder.png"
59
 
60
- sr, y = file
 
 
 
61
 
62
- if y.dtype != np.float32:
63
- y = y.astype(np.float32) / np.iinfo(y.dtype).max
 
 
 
64
 
65
- basic_metrics = calculate_basic_metrics(y, sr)
66
- advanced_metrics = calculate_advanced_metrics(y, sr)
67
 
68
- metrics = {**basic_metrics, **advanced_metrics}
 
69
 
70
- image_path = generate_spectrogram(y, sr)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
- return metrics, image_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  iface = gr.Interface(
76
- fn=process_audio,
77
- inputs=gr.Audio(label="Upload Audio"),
78
- outputs=["json", "image"],
79
- title="Speech-Scope",
80
- description="Speech and audio Metrics Analysis"
 
81
  )
82
 
83
- iface.launch(debug=True)
 
 
 
 
 
1
  import gradio as gr
2
+ from zipfile import ZipFile, BadZipFile
 
 
3
  import tempfile
4
+ import os
5
+ import re
6
+ import pandas as pd
7
+ import collections
8
+ import json
9
+ import glob
10
+ from io import BytesIO
11
 
12
 
13
+
14
+ ai_patterns = [
15
+ "PIC*", "PersonalImageClassifier*", "Look*", "LookExtension*", "ChatBot", "ImageBot", "TMIC","TeachableMachine*",
16
+ "TeachableMachineImageClassifier*", "SpeechRecognizer*", "FaceExtension*","Pose*","Posenet","PosenetExtension", "Eliza*", "Alexa*"
17
+ ]
18
+
19
+
20
+ drawing_and_animation_patterns = ["Ball", "Canvas", "ImageSprite"]
21
+ maps_patterns = ["Map", "Marker", "Circle", "FeatureCollection", "LineString", "Navigation","Polygon", "Retangle" ]
22
+ sensors_patterns = ["AccelerometerSensor", "BarcodeScanner", "Barometer", "Clock", "GyroscopeSensor", "Hygrometer", "LightSensor", "LocationSensor", "MagneticFieldSensor", "NearField","OrientationSensor", "ProximitySensor","Thermometer", "Pedometer"]
23
+ social_patterns = ["ContactPicker", "EmailPicker", "PhoneCall", "PhoneNumberPicker", "Texting", "Twitter"]
24
+ storage_patterns = ["File", "CloudDB", "DataFile", "Spreadsheet", "FusiontablesControl", "TinyDB", "TinyWebDB"]
25
+ connectivity_patterns = ["BluetoothClient", "ActivityStarter", "Serial", "BluetoothServer", "Web"]
26
+
27
+
28
+ def extract_components_using_regex(scm_content):
29
+ pattern = r'"\$Type":"(.*?)"'
30
+ components = re.findall(pattern, scm_content)
31
+ if 'roboflow' in scm_content.lower():
32
+ components.append("Using Roboflow")
33
+ return components
34
+
35
+
36
+ def extract_category_components(components, patterns):
37
+ category_components = []
38
+ for component in components:
39
+ for pattern in patterns:
40
+ if component.startswith(pattern):
41
+ category_components.append(component)
42
+ return category_components
43
+
44
+
45
+ def extract_extensions_from_aia(file_path: str):
46
+ extensions = []
47
+ with ZipFile(file_path, 'r') as zip_ref:
48
+ for file_path in zip_ref.namelist():
49
+ if file_path.endswith('components.json') and 'assets/external_comps/' in file_path:
50
+ with zip_ref.open(file_path) as file:
51
+ components_json_content = file.read().decode('utf-8', errors='ignore')
52
+ components_data = json.loads(components_json_content)
53
+ for component in components_data:
54
+ extension_type = component.get("type", "")
55
+ if extension_type:
56
+ extensions.append(extension_type)
57
+ return extensions
58
+
59
+ def count_events_in_bky_file(bky_content):
60
+
61
+ return bky_content.count('<block type="component_event"')
62
+
63
+ def extract_app_name_from_scm_files(temp_dir):
64
+ scm_files = glob.glob(f"{temp_dir}/src/appinventor/*/*/*.scm")
65
+ for scm_file in scm_files:
66
+ with open(scm_file, 'r', encoding='utf-8', errors='ignore') as file:
67
+ content = file.read()
68
+
69
+
70
+ regex_patterns = [
71
+ r'"AppName"\s*:\s*"([^"]+)"',
72
+ r'"AppName"\s*:\s*\'([^\']+)\''
73
+ ]
74
+
75
+ for pattern in regex_patterns:
76
+ app_name_match = re.search(pattern, content)
77
+ if app_name_match:
78
+ return app_name_match.group(1)
79
+
80
+
81
+ print(f"Aviso: Nome do aplicativo não encontrado no diretório {temp_dir}")
82
+ return "N/A"
83
+
84
+ def extract_project_info_from_properties(file_path):
85
+
86
+ timestamp = "N/A"
87
+ app_name = "N/A"
88
+ app_version = "N/A"
89
+ authURL = "ai2.appinventor.mit.edu"
90
+
91
+
92
+ with tempfile.TemporaryDirectory() as temp_dir:
93
+ with ZipFile(file_path, 'r') as zip_ref:
94
+ zip_ref.extractall(temp_dir)
95
+
96
+ project_properties_file_path = 'youngandroidproject/project.properties'
97
+
98
+
99
+ if project_properties_file_path in zip_ref.namelist():
100
+ with zip_ref.open(project_properties_file_path) as file:
101
+ project_properties_lines = file.read().decode('utf-8').splitlines()
102
+
103
+
104
+ timestamp = project_properties_lines[1] if len(project_properties_lines) > 1 else "N/A"
105
+
106
+
107
+ for line in project_properties_lines:
108
+ app_name_match = re.match(r'aname=(.*)', line)
109
+ if app_name_match:
110
+ app_name = app_name_match.group(1)
111
+
112
+ app_version_match = re.match(r'versionname=(.*)', line)
113
+ if app_version_match:
114
+ app_version = app_version_match.group(1)
115
+
116
+
117
+ if app_name == "N/A":
118
+ print("O campo App Name não foi encontrado em project.properties. Tentando encontrar em arquivos .scm...")
119
+ app_name = extract_app_name_from_scm_files(temp_dir)
120
+ print(f"Nome do App encontrado nos arquivos .scm: {app_name}")
121
+
122
+ # ...
123
+
124
 
125
  return {
126
+ 'timestamp': timestamp,
127
+ 'app_name': app_name,
128
+ 'app_version': app_version,
129
+ 'authURL': authURL
 
130
  }
131
 
132
 
 
 
133
 
 
 
 
134
 
 
 
135
 
136
+ def extract_ai_components(components):
137
+ ai_components = []
138
+ for component in components:
139
+ for pattern in ai_patterns:
140
+ if '*' in pattern and component.startswith(pattern[:-1]):
141
+ ai_components.append(component)
142
+ elif component == pattern:
143
+ ai_components.append(component)
144
+ if "roboflow" in ' '.join(components).lower():
145
+ ai_components.append("Using Roboflow")
146
+ return ai_components
147
+
148
+ def extract_media_files(file_path: str):
149
+ media_files = []
150
+ with ZipFile(file_path, 'r') as zip_ref:
151
+ for file_path in zip_ref.namelist():
152
+ if 'assets/' in file_path and not file_path.endswith('/'):
153
+ media_files.append(os.path.basename(file_path))
154
+ return media_files
155
+
156
+ def list_components_in_aia_file(file_path):
157
+
158
+ results_df = pd.DataFrame(columns=[
159
+ 'aia_file', 'project_info', 'components', 'IA components', 'screens', 'operators',
160
+ 'variables', 'events', 'extensions', 'Media',
161
+ 'Drawing and Animation', 'Maps', 'Sensors', 'Social', 'Storage', 'Connectivity'])
162
 
163
+
164
+ pd.set_option('display.max_colwidth', None)
165
+ file_name = os.path.basename(file_path)
166
+
167
 
168
+ components_list = []
169
+ number_of_screens = 0
170
+ operators_count = 0
171
+ variables_count = 0
172
+ events_count = 0
173
+
174
+ media_files = extract_media_files(file_path)
175
+ media_summary = ', '.join(media_files)
176
+
177
+ project_info = extract_project_info_from_properties(file_path)
178
+ project_info_str = f"Timestamp: {project_info['timestamp']}, App Name: {project_info['app_name']}, Version: {project_info['app_version']}, AuthURL: {project_info['authURL']}"
179
 
 
 
 
 
 
 
180
 
181
+ with tempfile.TemporaryDirectory() as temp_dir:
182
+ with ZipFile(file_path, 'r') as zip_ref:
183
+ zip_ref.extractall(temp_dir)
184
+ scm_files = glob.glob(temp_dir + '/src/appinventor/*/*/*.scm')
185
+ bky_files = glob.glob(temp_dir + '/src/appinventor/*/*/*.bky')
186
 
187
+ number_of_screens = len(scm_files)
188
+ for scm_file in scm_files:
189
+ with open(scm_file, 'r', encoding='utf-8', errors='ignore') as file:
190
+ content = file.read()
191
+ components = extract_components_using_regex(content)
192
+ components_list.extend(components)
193
+ operators_count += len(re.findall(r'[+\-*/<>!=&|]', content))
194
+ variables_count += len(re.findall(r'"\$Name":"(.*?)"', content))
195
 
196
+
197
+ drawing_and_animation_summary = ', '.join(extract_category_components(components_list, drawing_and_animation_patterns))
198
+ maps_summary = ', '.join(extract_category_components(components_list, maps_patterns))
199
+ sensors_summary = ', '.join(extract_category_components(components_list, sensors_patterns))
200
+ social_summary = ', '.join(extract_category_components(components_list, social_patterns))
201
+ storage_summary = ', '.join(extract_category_components(components_list, storage_patterns))
202
+ connectivity_summary = ', '.join(extract_category_components(components_list, connectivity_patterns))
203
 
 
 
 
204
 
205
+
206
+
207
+ extensions_list = []
208
+ extensions_list = extract_extensions_from_aia(file_path)
209
 
210
+ for bky_file in bky_files:
211
+ with open(bky_file, 'r', encoding='utf-8', errors='ignore') as file:
212
+ bky_content = file.read()
213
+ events_count += count_events_in_bky_file(bky_content)
214
+
215
 
 
 
216
 
217
+
218
+ extensions_summary = ', '.join(list(set(extensions_list)))
219
 
220
+ components_count = collections.Counter(components_list)
221
+ components_summary = [f'{comp} ({count} x)' if count > 1 else comp for comp, count in components_count.items()]
222
+ ai_components_summary = extract_ai_components(components_list)
223
+ new_row = pd.DataFrame([{
224
+ 'aia_file': file_name,
225
+ 'project_info': project_info_str,
226
+ 'components': ', '.join(components_summary),
227
+ 'IA components': ', '.join(ai_components_summary),
228
+ 'screens': number_of_screens,
229
+ 'operators': operators_count,
230
+ 'variables': variables_count,
231
+ 'events': events_count,
232
+ 'extensions': extensions_summary,
233
+ 'Media': media_summary,
234
+ 'Drawing and Animation': drawing_and_animation_summary,
235
+ 'Maps': maps_summary,
236
+ 'Sensors': sensors_summary,
237
+ 'Social': social_summary,
238
+ 'Storage': storage_summary,
239
+ 'Connectivity': connectivity_summary
240
+ }])
241
 
242
+
243
+ results_df = pd.concat([results_df, new_row], ignore_index=True)
244
+ return results_df
245
+ #
246
+
247
+
248
+ output_style = """
249
+ <style>
250
+ .output-container {
251
+ max-height: 500px; /* Ajuste a altura máxima conforme necessário */
252
+ overflow: auto; /* Isso permite a rolagem vertical e horizontal se necessário */
253
+ display: block; /* Isso garante que o container seja renderizado abaixo do botão submit */
254
+ }
255
+ .output-container table {
256
+ width: 100%; /* Isso faz com que a tabela utilize toda a largura do container */
257
+ border-collapse: collapse;
258
+ }
259
+ .output-container th, .output-container td {
260
+ border: 1px solid #ddd; /* Isso adiciona bordas às células para melhor visualização */
261
+ text-align: left;
262
+ padding: 8px;
263
+ }
264
+ </style>
265
+ """
266
 
267
 
268
+ def analyze_aia(uploaded_file):
269
+ try:
270
+
271
+ file_path = uploaded_file.name if hasattr(uploaded_file, 'name') else None
272
+
273
+ if file_path and os.path.exists(file_path):
274
+ with ZipFile(file_path, 'r') as zip_ref:
275
+ with tempfile.TemporaryDirectory() as temp_dir:
276
+ zip_ref.extractall(temp_dir)
277
+ results_df = list_components_in_aia_file(file_path)
278
+
279
+ html_result = results_df.to_html(escape=False, classes="output-html")
280
+ return output_style + f'<div class="output-container">{html_result}</div>'
281
+
282
+
283
+ else:
284
+ return output_style + "Não foi possível localizar o arquivo .aia."
285
+
286
+ except BadZipFile:
287
+ return output_style + "Falha ao abrir o arquivo .aia como um arquivo zip. Ele pode estar corrompido ou não é um arquivo .aia válido."
288
+
289
+ except Exception as e:
290
+ return output_style + f"Erro ao processar o arquivo: {str(e)}"
291
+
292
  iface = gr.Interface(
293
+ fn=analyze_aia,
294
+ inputs=gr.File(),
295
+ outputs=gr.HTML(),
296
+ title="AIA-Scope",
297
+ description="Upload an .aia file to analyze its components.",
298
+ live=False
299
  )
300
 
301
+ if __name__ == "__main__":
302
+ iface.launch(debug=True)
303
+
304
+
305
+