File size: 12,633 Bytes
2406f66
 
 
 
 
 
 
4946383
 
 
 
 
 
8cbd013
 
4946383
 
 
 
 
8cbd013
 
 
 
 
 
 
 
 
 
4946383
 
8cbd013
4946383
b687b19
8cbd013
2b0bde5
4946383
7ccf8f2
4946383
 
 
 
 
 
 
 
 
 
8cbd013
4946383
 
 
8cbd013
4946383
 
 
 
8cbd013
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d1f1696
8cbd013
 
06b173c
8cbd013
 
06b173c
8cbd013
 
 
 
06b173c
 
 
 
 
 
d1f1696
8cbd013
06b173c
8cbd013
 
 
 
06b173c
8cbd013
 
 
 
 
06b173c
8cbd013
06b173c
d1f1696
06b173c
d1f1696
 
06b173c
d1f1696
 
 
06b173c
d1f1696
06b173c
d1f1696
 
 
 
 
 
 
 
06b173c
d1f1696
 
7ccf8f2
 
 
 
06b173c
4946383
 
8cbd013
06b173c
353fd37
8cbd013
06b173c
 
 
 
 
 
 
 
8cbd013
 
 
4946383
8cbd013
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4946383
8cbd013
4946383
 
8cbd013
 
 
 
 
4946383
8cbd013
 
 
 
 
 
 
4946383
 
8cbd013
4946383
 
 
8cbd013
 
 
 
 
 
 
 
4946383
8cbd013
 
 
4946383
8cbd013
06b173c
 
4946383
8cbd013
74ec8c4
06b173c
 
8cbd013
 
 
 
 
06b173c
 
887d87f
06b173c
887d87f
4946383
06b173c
4946383
887d87f
06b173c
 
 
 
 
 
 
887d87f
06b173c
 
 
 
 
 
 
887d87f
06b173c
 
 
 
 
 
 
887d87f
06b173c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8cbd013
4946383
8cbd013
 
 
 
06b173c
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
from transformers import pipeline
from lang_trans.arabic import buckwalter
from difflib import SequenceMatcher
import pandas as pd
import gradio as gr
import time

# Gradio application for learning Noorani Qaida

p = pipeline("automatic-speech-recognition", model="jonatasgrosman/wav2vec2-large-xlsr-53-arabic")

# Read excel file and store it in a dictionary
def read_excel_data(file_path, sheet_name):
    data_list = []

    try:
        # Read the Excel file
        df = pd.read_excel(file_path, sheet_name=sheet_name)
        # Iterate over the rows
        for index, row in df.iterrows():
            test = row['test']
            correct = row['correct']
            close = row['close']
            wrong = row['wrong']
            image = row["image"]
                     
            # Store close and wrong values as a tuple
            data_list.append((test, correct, close, wrong, image))            
        return data_list
        
    except Exception as e:
        print(f"Error reading Excel file: {e}")
    
# List of sample texts to read
excel_file_path = "ASR_live_test.xlsx"
sheet_name= 'sample_test(threshold=75%)'
full_test_list = read_excel_data(excel_file_path, sheet_name)

# Similarity function
def similar(a, b):
    return SequenceMatcher(None, a, b).ratio()

def transcribe(audio, reference_text):
    time.sleep(1)
    text = p(audio)["text"]
    text = buckwalter.untrans(text)
    state = text
    if state is not None:
        if similar(reference_text, state) > 0.75:
            score = "correct"
        elif similar(reference_text, state) > 0.50 and similar(reference_text, state) < 0.75:
            score = "close"
        else:
            score = "wrong"
        return state, score
    else : 
        print(" Null Object")

# Function to retrieve the list of unique categories
def get_unique_tests(data_list):
    tests=[]
    tests = [test for test, _, _, _, _ in data_list if test not in tests]
    return tests

# Function to retrieve close, wrong and image values for a given correct value
def get_values_image_for_test(tests, test):
    for t, correct, close, wrong, image in tests:
        if t == test:
            return correct, close, wrong, image

# Counting completed tests
def completed_tests(test):
    global completed_tests_list
    if completed_tests_list is None:
        completed_tests_list = []
    
    if test and test not in completed_tests_list :
        completed_tests_list.append(test)

    # elif test and test in completed_tests_list:
    #     gr.Warning("Test alreday done! Please select another test.")   
    
    total_completed_tests = len(completed_tests_list)
    return total_completed_tests, completed_tests_list

# Tests distribution over users
import random

def assign_tests(num_tests):
    global remaining_tests
    assigned_tests = []
    tests = get_unique_tests(full_test_list)  
       
    # Shuffle tests 
    random.shuffle(tests)
    
    # Updating remaining_tests 
    if (len(remaining_tests) == 0) and (len(assigned_tests) == 0):
        remaining_tests = set(tests)
    # else:
    #     remaining_tests -= set(assigned_tests) 

    # Last remaining tests are assigned to the last user
    if num_tests > len(remaining_tests):
        assigned_tests = remaining_tests
    
    # Ensure we still have enough tests    
    if len(remaining_tests) == 0: 
        print("***** Tests Completed *****")
        pass#return ["Tests Completed"]
    
    # Select tests that are not already assigned
    assigned_tests = [test for test in tests if test in remaining_tests][:num_tests]
    
    # Remove assigned tests from the set of all available tests
    remaining_tests -= set(assigned_tests) 
    return assigned_tests
    
# Tracking user progress 

def test_progress(test):
    global completed_tests_list
    global len_assigned_test

    # Get total completed tests
    total_completed_tests, completed_tests_list = completed_tests(test)

    # Test completed to be displayed to the user
    completed_tests_text = "\n".join(completed_tests_list)

    # Calculate how many tests are remaining
    total_remaining_tests = len_assigned_test - total_completed_tests

    if total_remaining_tests == 0:
        completed_tests_list.clear()
        progress_text = f"Congratulations! You have completed all tests"
    else:
        progress_text = f"Completed tests {total_completed_tests} . Remaining {total_remaining_tests}"
    return progress_text, completed_tests_text

# Authentication function
def update_message(request: gr.Request):
    return f"Welcome, {request.username}"


# Gradio apps

# Get test categories
data_list = full_test_list
image_path="all_imgs/"
completed_tests_list = []
remaining_tests = []

# Get a set of tests for each user
num_tests = 10
assigned_tests = assign_tests(num_tests)
len_assigned_test = len(assigned_tests)

print(assigned_tests)

# Flagging
callback = gr.CSVLogger()

# CSS
css = """
h1 { 
    text-align: center;
    color: #5756BB; 
    display:block;
}
p {
    text-align: left;
    display:block;
}
p.thick {
  font-weight: bold;
}
.drop_color {background-color: #e0eaff} 
img {
    height: auto; 
    width: auto;
    margin-left: auto;
    margin-right: auto;
    display: block;
}
.row {
    height: 90px; 
    width: auto;
}
progress_text {
    text-align: center;
    ont-weight: bold;
}
"""
js = """
    function change_color(){
    const test_text = document.getElementById("#test_color");
    const selectedtest = dropdown.options[dropdown.selectedIndex];
    selectedtest.style.color = "green";
    }
    """

demo = gr.Blocks(theme=gr.themes.Soft(), css=css)

with demo :
    # Add app title
    gr.Markdown(
        """
    # Noorani Qaida Test Interface"""
    )

    # User authentication
    with gr.Row():
        m = gr.Markdown()
        logout_button = gr.Button("Logout", link="/logout", scale=0, variant="primary")
        demo.load(update_message, None, m)

    # Add app description 
    gr.Markdown(
        """
    Select a category then a test from the list, read the text aloud, get the transcription and save it.
    """
    )

    # Assign value to each step 
    def get_test_text(test):
        correct, close, wrong, image = get_values_image_for_test(data_list, test)
        correct_text = gr.Textbox(label="Step 1", value=correct)
        close_text = gr.Textbox(label="Step 2", value=close)
        wrong_text = gr.Textbox(label="Step 3", value=wrong)
        image = gr.Image(value=(image_path+str(image)+".jpg"))
        return correct_text, close_text, wrong_text, image

    def update_completed_test(test):
        _, completed_tests = gr.TextArea(completed_tests(test))
        return completed_tests

    with gr.Row():
        # First big column
        with gr.Column(scale=1):
            
            # User progress
            progress_text = gr.Textbox(value="Completed tests 0. Remaining 10", interactive=False, show_label=False, container=True, elem_id="progress_text", elem_classes="drop_color")
            textarea_completed = gr.TextArea(info=" Your completed tests will appear here ", interactive=False, rtl=True, container=True, show_label=False, elem_classes="drop_color")

            # Test selection  
            tests_list = assigned_tests 
            test_dropdown = gr.Dropdown(tests_list, label="Tests",  info="Select a test", scale=1, elem_id="test_color", elem_classes="drop_color")
            test_dropdown.select(test_progress, test_dropdown, outputs=[progress_text, textarea_completed])

        # Second big column
        with gr.Column(scale=3):
            # First row for image
            with gr.Row():
                image =  gr.Image(elem_id="img", elem_classes="row", container=False, show_label=True, show_download_button=False, show_share_button=False) 

            # Second row for steps    
            with gr.Row():
                # First sub-column
                with gr.Column(): 
                    correct_text = gr.Textbox(label= "Step 1", info="Correct Text",  interactive=False, rtl=True)
                    correct_audio_record = gr.Audio(sources="microphone" ,type="filepath",  label="Record Audio", show_label=False)
                    correct_trans_text = gr.Textbox(info="Transcription",  interactive=False, rtl=True, show_label=False)
                    correct_score = gr.Textbox(label="Score", visible= False)    
                    correct_audio_record.stop_recording(fn=transcribe, inputs=[correct_audio_record, correct_text], outputs=[correct_trans_text, correct_score])

                # Second sub-column
                with gr.Column(): 
                    close_text = gr.Textbox(label="Step 2", info="Close Text",  interactive=False, rtl=True)
                    close_audio_record = gr.Audio(sources="microphone", type="filepath", label="Record Audio", show_label=False) 
                    close_trans_text = gr.Textbox(info="Transcription", interactive=False, rtl=True, show_label=False) 
                    close_score = gr.Textbox(label="Score", visible= False)
                    close_audio_record.stop_recording(fn=transcribe, inputs=[close_audio_record, close_text], outputs=[close_trans_text, close_score])

                # Third sub-column
                with gr.Column(): 
                    wrong_text = gr.Textbox(label="Step 3", info="Wrong Text",  interactive=False, rtl=True)
                    wrong_audio_record = gr.Audio(sources="microphone" ,type="filepath",  label="Record Audio", show_label=False) 
                    wrong_trans_text = gr.Textbox(info="Transcription",  interactive=False, rtl=True, show_label=False)
                    wrong_score = gr.Textbox(label="Score", visible= False)
                    wrong_audio_record.stop_recording(fn=transcribe, inputs=[wrong_audio_record, wrong_text], outputs=[wrong_trans_text, wrong_score])
            
                    # Row for flag
                    with gr.Row():
                        #user_name = gr.Request.username
                        def save_outputs(correct_text, correct_trans_text, correct_score, correct_audio_record,
                                        close_text, close_trans_text, close_score, close_audio_record,
                                        wrong_text, wrong_trans_text, wrong_score, wrong_audio_record):
                            if any(len(text)==0 for text in [correct_trans_text, close_trans_text, wrong_trans_text]):
                                return gr.Warning("Please complete the test before saving")
                            return (lambda *args: callback.flag(args, username="randa"))

                        flag_btn = gr.Button(value="Save this test", variant="primary", scale=2)
                        # Setup the components to flag
                        callback.setup([correct_text, correct_trans_text, correct_score, correct_audio_record,
                                        close_text, close_trans_text, close_score, close_audio_record,
                                        wrong_text, wrong_trans_text, wrong_score, wrong_audio_record], "flagged_data")
                        # We can choose which components to flag 
                        flag_btn.click(save_outputs, 
                                    [correct_text, correct_trans_text, correct_score, correct_audio_record,
                                        close_text, close_trans_text, close_score, close_audio_record,
                                        wrong_text, wrong_trans_text, wrong_score, wrong_audio_record],
                                        None, preprocess=False)
                        
                        # Update test values according to the selected test
                        test_dropdown.input(get_test_text, test_dropdown, [correct_text, close_text, wrong_text, image])
                
    
    # Clear the transcription after selecting a new test
    test_dropdown.select(lambda: [None]*10, None,
                                outputs=[correct_text, close_text, wrong_text, correct_audio_record, close_audio_record, wrong_audio_record, correct_trans_text, close_trans_text, wrong_trans_text, image],
                                queue=False)
#demo.launch(inbrowser=True)
if __name__ == "__main__":
    demo.launch(auth=[("randa", "randa"), ("randa1", "randa1"),("randa2", "randa2"), ("randa3", "randa3"),
                    ("karim1", "karim1"), ("karim2", "karim2"), ("karim3", "karim3"),
                    ("yassir1", "yassir1"), ("yassir2", "yassir2"), ("yassir3", "yassir3"),
                    ("mehdi", "mehdi")], 
                    share=True, inbrowser=True)