packages = [ 'pandas', 'jinja2', ] #import os #import asyncio import pandas as pd #import numpy as np # CHECK IF NEEDED from pandas import set_option, read_csv import io import gc import jinja2 #import pyperclip ######## Are those form js package ?? YES!!! ######## from js import document, Blob, URL # NECESSARY FOR FILE DOWNLOAD from js import Uint8Array from js import TextDecoder #from js import FileReader #from js import console ######## Are those form js package ?? ######## from pyscript import Element from pyscript import display from pyscript import create_proxy #### GLOBALS #### data = '' dload_df = pd.DataFrame() dload_df_ok = False Token = 'Version' header_line = [] # The way it was coded, it's a list, NOT string headerline_index = 0 # -1 for detecting invalid CSV file fileToAnalyse = '' sepr = 1 ele_id_title = Element('id_title') ele_accmin = Element('accmin') ele_content = Element('content') ele_rtables = Element('rtables') ele_tcrmax = Element('tcrmax') ele_filemsg = Element('file_msg') ## =============== PROCESS CALLBACK FOR FILE INPUT DIALOG ================ async def process_file(event): global headerline_index, fileToAnalyse, data, dload_df_ok dload_df_ok = False # INDICATES IF DOWNLOAD DATAFRAME IS ALLRIGHT headerline_index = 0 fileList = event.target.files.to_py() display('Please, choose an IRAP text datafile', target='file_msg', append=False) #ele_filemsg.write('ail') #print(type(file_buf)) for f in fileList: fileToAnalyse = f.name ##==## print('Input CSV file :' + fileToAnalyse) data = Uint8Array.new(await f.arrayBuffer()) ##==## print('after await') data = TextDecoder.new().decode(data) # display(type(data), target='msg', append=False) i = 0 line_list = [] flag = False data1 = data[0:1000000].splitlines() ## try: for line_list in data1: if flag: break if Token in line_list: header_line = data1[i + 1] flag = True else: i += 1 ## except: if not flag: display("Seems not to be a valid IRAP text file", target='file_msg', append=False) return display("This is a valid IRAP text file", target='file_msg', append=False) headerline_index = data1.index(header_line) # CLEAR TITLE OF RESULT TABLE : ele_rtables.clear() # CLEAR MEMORY SPACES FOR THOSE GUYS (ALBEIT GARBAGE COLLECTOR) ### data = '' # NOT THIS ONE !!! data1 = [] ## f.close() ## =============== PROCESS CALLBACK FOR STATISTCS_1 BUTTON ================ def bt_stats1(): global fileToAnalyse, dload_df, dload_df_ok global headerline_index, data # , state display('Success! You may now download your results.', target='file_msg', append=False) ele_rtables.clear() if headerline_index == 0: display('Please, choose a TXT file first.', target='file_msg', append=False) return buff = io.StringIO(data) # <<<<============ SOLUTION !!!!!! columns_to_use = ['participantCode', 'startingRule', 'isTestBlock', 'blockPairNumber', 'currentRule', 'trialNumber', 'trialType', 'timeToFirstAnswer', 'timeToCorrectResponse', 'accuracy'] PC='participantCode'; SRL='startingRule'; ITB='isTestBlock'; BPN='blockPairNumber'; CRL='currentRule'; TN='trialNumber'; TT='trialType'; TFA='timeToFirstAnswer'; TCR='timeToCorrectResponse'; ACU='accuracy' set_option('display.max_rows', None) set_option('display.max_columns', None) ## SETS THE FOALTING FORMAT FOR TWO DECINALS, ALTERNATIVELY USE THE .round(2) ## METHOD FOR THE mean VALUE : pd.options.display.float_format = '{:,.2f}'.format pd.set_option("display.colheader_justify","right") ### ============================================== df = read_csv(buff, sep='\t', header=headerline_index, index_col=False, usecols=columns_to_use, #on_bad_lines='warn', # 'error' , 'warn', 'skip' #error_bad_lines=False, #header=None, engine='python', # 'c' , 'python' , 'pyarrow' ) buff.close() df = df[df[ITB] == bool(1)] try: TCRMAX = int(ele_tcrmax.element.value) except: display("Not a valid float value. Using default.", target='msg', append=False) TCRMAX = 2000 df = df.groupby([PC, TT])[[TCR]].mean() ### .round(2) df = df[df[TCR] >= TCRMAX] # the means per partic per trial type that exceede TCRMAX # SAVE THE DATAFRAME TO A GLOBAL VARIABLE FOR DOWNLOADING: dload_df = df styles = [{'selector':"*", 'props':[ ("font-family" , 'Tahoma'), ("font-size" , '18px'), ("margin" , "15px auto"), ("border" , "4px solid #6C6C6C")]}, {"selector": "th", "props": [("text-align", "center"), ("background-color", "#FFE2D2")]}, {"selector": "td", "props": [("text-align", "center"), ("padding", "5px 7px")]}, ] df = df.style.set_table_styles(styles) ele_content.clear() #### (2024-04-17): CHANGE WRITE TO DISPLAY : SAME RESULTS: CHECK WHICH ONE HAS BETTER PERFORMANCE AND RESOURCE USAGE #ele_content.write(df, append=False) display(df, target='content', append = False) #### elem = Element('id_title') ele_id_title.write(f'Rule Violation: Means, per Participant and per Trial Type of each, considering only Test Blocks, of Time to Correct Response, identifying those > {TCRMAX} (Max Latency).', append=False) dload_df_ok = True del(df) gc.collect() ## =============== PROCESS CALLBACK FOR STATISTCS_2 BUTTON ================ def bt_stats2(): global fileToAnalyse, dload_df, dload_df_ok global headerline_index, data, ele_id_title, ele_accmin display('Success! You may now download your results.', target='file_msg', append=False) # CLEARS THE PREVIOUS MESSAGE buff = io.StringIO(data) ### display(dir(buff), target='msg') if headerline_index == 0: display('Please, choose a TXT data file first.', target='file_msg', append=False) return columns_to_use = ['participantCode', 'startingRule', 'isTestBlock', 'blockPairNumber', 'currentRule', 'trialNumber', 'trialType', 'timeToFirstAnswer', 'timeToCorrectResponse', 'accuracy'] PC='participantCode'; SRL='startingRule'; ITB='isTestBlock'; BPN='blockPairNumber'; CRL='currentRule'; TN='trialNumber'; TT='trialType'; TFA='timeToFirstAnswer'; TCR='timeToCorrectResponse'; ACU='accuracy' set_option('display.max_rows', None) set_option('display.max_columns', None) ## SETS THE FOALTING FORMAT FOR TWO DECINALS, ALTERNATIVELY USE THE .round(2) ## METHOD FOR THE mean VALUE : pd.options.display.float_format = '{:,.2f}'.format pd.set_option("display.colheader_justify","right") ## center" ### ============================================== df = read_csv(buff, sep='\t', header=headerline_index, index_col=False, usecols=columns_to_use, #on_bad_lines='warn', # 'error' , 'warn', 'skip' #error_bad_lines=False, #header=None, engine='python', # 'c' , 'python' , 'pyarrow' ) buff.close() df = df[df[ITB] == bool(1)] try: ACCMIN = float((ele_accmin).element.value) except: display("Not a valid float value. Using default.", target='msg', append=False) ACCMIN = 0.8 df = df.groupby([PC, TT])[[ACU]].mean() ### .round(2) df = df[df[ACU] <= ACCMIN] # the means per partic per trial type that fall bellow ACCMIN styles = [{'selector':"*", 'props':[ ("font-family" , 'Tahoma'), ("font-size" , '18px'), ("margin" , "15px auto"), ("border" , "4px solid #6C6C6C")]}, {"selector": "th", "props": [("text-align", "center"), ("background-color", "#FFE2D2")]}, {"selector": "td", "props": [("text-align", "center"), ("padding", "5px 7px")]}, ] # SAVE THE DATAFRAME IN A GLOBAL VARIABLE TO DWNLOAD IT LATER : dload_df = df df = df.style.set_table_styles(styles) ele_content.clear() display(df, target='content', append=False) ######## ele_id_title = Element('id_title') ele_id_title.write(f'Rule Violation: Means of Accuracy, per Participant and per Trial Type of each, considering only Test Blocks, of Accuracy, identifying those that fall bellow the Accuracy Threshold (ACCMIN) for Min Accuracy = {ACCMIN}.', append=False) dload_df_ok = True del(df) gc.collect() ## =============== PROCESS CALLBACK FOR STATISTCS_3 BUTTON ================ def bt_stats3(): global fileToAnalyse, dload_df, dload_df_ok global headerline_index, data, ele_id_title, ele_accmin, ele_tcrmax display('Success! You may now download your results.', target='file_msg', append=False) buff = io.StringIO(data) ### display(dir(buff), target='msg') if headerline_index == 0: display('Please, choose a TXT data file first.', target='file_msg', append=False) return columns_to_use = ['participantCode', 'startingRule', 'isTestBlock', 'blockPairNumber', 'currentRule', 'trialNumber', 'trialType', 'timeToFirstAnswer', 'timeToCorrectResponse', 'accuracy'] PC='participantCode'; SRL='startingRule'; ITB='isTestBlock'; BPN='blockPairNumber'; CRL='currentRule'; TN='trialNumber'; TT='trialType'; TFA='timeToFirstAnswer'; TCR='timeToCorrectResponse'; ACU='accuracy' set_option('display.max_rows', None) set_option('display.max_columns', None) ## SETS THE FOALTING FORMAT FOR TWO DECINALS, ALTERNATIVELY USE THE .round(2) ## METHOD FOR THE mean VALUE : pd.options.display.float_format = '{:,.2f}'.format pd.set_option("display.colheader_justify","right") ## center" ### ============================================== df = read_csv(buff, sep='\t', header=headerline_index, index_col=False, usecols=columns_to_use, #on_bad_lines='warn', # 'error' , 'warn', 'skip' #error_bad_lines=False, #header=None, engine='python', # 'c' , 'python' , 'pyarrow' ) buff.close() ####################################################### df = df.astype({ PC: 'int32', ITB: 'bool', TT: 'int32', TCR: 'float', ACU: 'float' }) ####################################################### df = df[df[ITB] == bool(1)] # GRAB AND FILTER TCRMAX : try: TCRMAX = int(ele_tcrmax.element.value) except: display("Not a valid float value. Using default.", target='msg', append=False) TCRMAX = 2000 # GRAB AND FILTER ACCMIN : try: ACCMIN = float((ele_accmin).element.value) except: display("Not a valid float value. Using default.", target='msg', append=False) ACCMIN = 0.8 df = df.groupby([PC, TT])[[TCR, ACU]].mean() df = df[df[TCR] >= TCRMAX] df = df[df[ACU] <= ACCMIN] styles = [{'selector':"*", 'props':[ ("font-family" , 'Tahoma'), ("font-size" , '18px'), ("margin" , "15px auto"), ("border" , "4px solid #6C6C6C")]}, {"selector": "th", "props": [("text-align", "center"), ("background-color", "#FFCFC0")]}, {"selector": "td", "props": [("text-align", "center"), ("padding", "5px 7px")]}, ] # SAVE THE DATAFRAME IN A GLOBAL VARIABLE TO DWNLOAD IT LATER : dload_df = df df = df.style.set_table_styles(styles) ele_content.clear() display(df, target='content', append=False) ele_id_title.write(f'Rule Breach 1 AND Rule Breach 2.', append=False) dload_df_ok = True del(df) gc.collect() ## =============== PROCESS CALLBACK FOR STATISTCS_4 BUTTON ================ def bt_stats4(): global fileToAnalyse, dload_df, dload_df_ok global headerline_index, data, ele_id_title, ele_accmin, ele_tcrmax display('Success! You may now download your results.', target='file_msg', append=False) buff = io.StringIO(data) if headerline_index == 0: display('Please, choose a TXT data file first.', target='file_msg', append=False) return columns_to_use = ['participantCode', 'startingRule', 'isTestBlock', 'blockPairNumber', 'currentRule', 'trialNumber', 'trialType', 'timeToFirstAnswer', 'timeToCorrectResponse', 'accuracy'] PC='participantCode'; SRL='startingRule'; ITB='isTestBlock'; BPN='blockPairNumber'; CRL='currentRule'; TN='trialNumber'; TT='trialType'; TFA='timeToFirstAnswer'; TCR='timeToCorrectResponse'; ACU='accuracy' set_option('display.max_rows', None) set_option('display.max_columns', None) ## SETS THE FOALTING FORMAT FOR TWO DECINALS, ALTERNATIVELY USE THE .round(2) ## METHOD FOR THE mean VALUE : pd.options.display.float_format = '{:,.2f}'.format pd.set_option("display.colheader_justify","right") ## center" ### ============================================== df = read_csv(buff, sep='\t', header=headerline_index, index_col=False, usecols=columns_to_use, #on_bad_lines='warn', # options: 'error' , 'warn', 'skip' #error_bad_lines=False, #header=None, engine='python', # options: 'c' (default) , 'python' , 'pyarrow' ) buff.close() ####################################################### df = df.astype({ PC: 'int32', ITB: 'bool', TT: 'int32', TCR: 'float', ACU: 'float' }) ####################################################### # GRAB AND VALIDATE TCRMAX : try: TCRMAX = int(ele_tcrmax.element.value) except: display("Not a valid float value. Using default.", target='msg', append=False) TCRMAX = 2000 # GRAB AND VALIDATE ACCMIN : try: ACCMIN = float((ele_accmin).element.value) except: display("Not a valid float value. Using default.", target='msg', append=False) ACCMIN = 0.8 df = df[df[ITB] == bool(1)] # STEP 1 df = df[df[ITB] <= 10000] # STEP 2 df = df.groupby([PC, CRL, TT])[[TCR, ACU]].mean() df = df[df[TCR] >= TCRMAX] df = df[df[ACU] <= ACCMIN] #print(df.head(50)) styles = [{'selector':"*", 'props':[ ("font-family" , 'Tahoma'), ("font-size" , '18px'), ("margin" , "15px auto"), ("border" , "4px solid #6C6C6C")]}, {"selector": "th", "props": [("text-align", "center"), ("background-color", "#FFD1B8")]}, {"selector": "td", "props": [("text-align", "center"), ("padding", "5px 7px")]}, ] # SAVE THE DATAFRAME IN A GLOBAL VARIABLE TO DWNLOAD IT LATER : dload_df = df df = df.style.set_table_styles(styles) ele_content.clear() display(df, target='content', append=False) ele_id_title.write(f'Rule Violation: Means of Accuracy and Latency, per Participant, per Trial Type, and per Current Rule (Con, Incon) of each, considering only Test Blocks, identifying those that fall bellow the Accuracy Threshold of {ACCMIN} and above the Latency threshold of {TCRMAX}. There may be more results here than when the means average out the two different types of block.', append=False) dload_df_ok = True del(df) gc.collect() ## =============== PROCESS CALLBACK FOR STATISTCS_5 BUTTON ================ def bt_stats5(): global fileToAnalyse, dload_df, dload_df_ok global headerline_index, data, ele_id_title, ele_accmin, ele_tcrmax display('Success! You may now download your results.', target='file_msg', append=False) buff = io.StringIO(data) if headerline_index == 0: display('Please, choose a TXT data file first.', target='file_msg', append=False) return columns_to_use = ['participantCode', 'startingRule', 'isTestBlock', 'blockPairNumber', 'currentRule', 'trialNumber', 'trialType', 'timeToFirstAnswer', 'timeToCorrectResponse', 'accuracy'] PC='participantCode'; SRL='startingRule'; ITB='isTestBlock'; BPN='blockPairNumber'; CRL='currentRule'; TN='trialNumber'; TT='trialType'; TFA='timeToFirstAnswer'; TCR='timeToCorrectResponse'; ACU='accuracy' set_option('display.max_rows', None) set_option('display.max_columns', None) ## SETS THE FOALTING FORMAT FOR TWO DECINALS, ALTERNATIVELY USE THE .round(2) ## METHOD FOR THE FLOAT TYPE VALUES : pd.options.display.float_format = '{:,.5f}'.format pd.set_option("display.colheader_justify","right") ## center" ### ============================================== df = read_csv(buff, sep='\t', header=headerline_index, index_col=False, usecols=columns_to_use, #on_bad_lines='warn', # 'error' , 'warn', 'skip' #error_bad_lines=False, #header=None, engine='python', # 'c' , 'python' , 'pyarrow' ).rename(columns={'participantCode': 'Part Code', 'isTestBlock': ITB, 'currentRule': CRL, \ 'trialType': 'Trial Type', 'timeToFirstAnswer': TFA, 'timeToCorrectResponse': TCR, 'accuracy': ACU}) buff.close() ####################################################### df = df.astype({ 'Part Code': 'int64', ITB: 'bool', CRL: 'int64', 'Trial Type': 'int64', TCR: 'float', ACU: 'float' }) ####################################################### #print(df.dtypes) # GRAB AND VALIDATE TCRMAX : try: TCRMAX = int(ele_tcrmax.element.value) except: display("Not a valid float value. Using default.", target='msg', append=False) TCRMAX = 2000 # GRAB AND VALIDATE ACCMIN : try: ACCMIN = float((ele_accmin).element.value) except: display("Not a valid float value. Using default.", target='msg', append=False) ACCMIN = 0.8 df = df[df[ITB] == bool(1)] # STEP 1 (MAYBE NOT NEEDED, CAUSE THE DATA IS ALREADY FILTERED BY THE ASTYPE() ABOVE. df = df[df[TCR] <= 10000] # STEP 2 df = df[['Part Code', BPN, CRL, 'Trial Type', TCR, ACU]] # STEP 3: # FROM CODEIUM SUGGESTION: (OK !!) ## ========================================= # Define a custom filter function def filter_groups(group): # Calculate the number of rows in the group where TCR <= 300.0 num_rows_tcr_less_equal_300 = group[group[TCR] <= 300.0].shape[0] # Check if this is greater than 10% of the total number of rows in the group if num_rows_tcr_less_equal_300 > 0.1 * group.shape[0]: return False # Exclude this group from the DataFrame return True # Include this group in the DataFrame # Apply the custom filter function to each group and transform the DataFrame df1 = df.groupby('Part Code').filter(filter_groups) ## ========================================= df1 = df1.groupby(['Part Code', 'blockPairNumber', 'Trial Type']).apply(lambda x: pd.DataFrame({ 'MeanTCR1': [x[TCR].loc[x[CRL] == 1].mean()], 'MeanTCR2': [x[TCR].loc[x[CRL] == 2].mean()], 'Std': [x[TCR].std(ddof=1)] })) # ================================================ df1['MeanTCR2_1'] = df1['MeanTCR2'] - df1['MeanTCR1'] # Note: some often, errors occur here. (recommesded: groupKeys=False) df1['DIRAP_Score'] = df1['MeanTCR2_1'] / df1['Std'] df1 = df1.groupby(['Part Code', 'Trial Type'])['DIRAP_Score'].mean().to_frame('D_Scores') # SAVE THE DATAFRAME IN A GLOBAL VARIABLE TO DOWNLOAD IT LATER : #dload_df = df1 df1 = df1.pivot_table(df1, index=['Part Code'], columns=['Trial Type']) # SAVE THE DATAFRAME IN A GLOBAL VARIABLE TO DOWNLOAD IT LATER : dload_df = df1 styles = [{'selector':"*", 'props':[ ("font-family" , 'Tahoma'), ("font-size" , '18px'), ("margin" , "15px auto"), ("border" , "4px solid #71797E")]}, {"selector": "th", "props": [("text-align", "center"), ("background-color", "#FFDACC")]}, {"selector": "td", "props": [("text-align", "center"), ("padding", "6px 8px")]}, ] df1 = df1.style.set_table_styles(styles) ele_content.clear() display(df1, target='content', append=False) ele_id_title.write(f'Overall D-IRAP Scores per Participant and per Trial Type of each, considering only Test Blocks.', append=False) dload_df_ok = True # JUST IN CASE, TO CLEAN UP THE MEMORY : del(df) del(df1) gc.collect() ## ======================================================== ## THIS FUNCTON BOUNDS THE ACTION OF PRESSING THE FILE SELECT BUTTON TO ITS ## CALLBACK FUNCTION "process_file()" def setup_button_inp_file(): ''' # Create a Python proxy for the callback function # process_file() is your function to process events from FileReader ''' file_event = create_proxy(process_file) # Set the listener to the callback e = document.getElementById("file_input") e.addEventListener("change", file_event, False) def setup_bt_stats1(): ### print('Inside setup_bt_stats1') # Create a Python proxy for the callback function """ This function to process events from the action of pressing bt_stats1, which has an id of "stats1" """ #button1_event = create_proxy(setup_bt_stats1) button1_event = create_proxy(bt_stats1) # Set the listener to the callback e = document.getElementById("stats1") e.addEventListener("click", button1_event, False) def setup_bt_stats2(): ### print('Inside setup_bt_stats2') # Create a Python proxy for the callback function ''' This function to process events from the action of pressing bt_stats2, which has an id of "stats2" ''' #button2_event = create_proxy(setup_bt_stats2) button2_event = create_proxy(bt_stats2) # Set the listener to the callback e = document.getElementById("stats2") e.addEventListener("click", button2_event, False) def setup_bt_stats3(): # Create a Python proxy for the callback function ''' This function to process events from the action of pressing bt_stats3, which has an id of "stats3" ''' button3_event = create_proxy(bt_stats3) #button3_event = create_proxy(setup_bt_stats3) # Set the listener to the callback e = document.getElementById("stats3") e.addEventListener("click", button3_event, False) def setup_bt_stats4(): # Create a Python proxy for the callback function ''' This function to process events from the action of pressing bt_stats4, which has an id of "stats4" ''' button4_event = create_proxy(bt_stats4) #button4_event = create_proxy(setup_bt_stats4) # Set the listener to the callback e = document.getElementById("stats4") e.addEventListener("click", button4_event, False) def setup_bt_stats5(): # Create a Python proxy for the callback function ''' This function to process events from the action of pressing bt_stats5, which has an id of "stats5" ''' button5_event = create_proxy(bt_stats5) #button5_event = create_proxy(setup_bt_stats5) # Set the listener to the callback e = document.getElementById("stats5") e.addEventListener("click", button5_event, False) def download_dataframe(df, sepr, default_filename='dataframe.csv'): #global sepr # Convert DataFrame to CSV string with necessary options for Excel compatibility if sepr == 1: csv_content = df.to_csv(index=True, \ sep=',', \ float_format='%.5f' \ ) else: csv_content = df.to_csv(index=True, \ sep='\t', \ float_format='%.5f' \ ) # Create a Blob object with the contents of the CSV blob = Blob.new([csv_content], {'type': 'text/csv'}) # Create a URL for the Blob object object_url = URL.createObjectURL(blob) # Create a temporary anchor element ('a') and trigger the download temp_link = document.createElement('a') temp_link.href = object_url temp_link.download = default_filename document.body.appendChild(temp_link) temp_link.click() # Cleanup: remove the temporary link and revoke the Blob URL document.body.removeChild(temp_link) URL.revokeObjectURL(object_url) def on_dload_button_click_1(event): global dload_df_ok, sepr sepr = 1 event.preventDefault() # Prevent default action which can cause page reload if not dload_df_ok: display('Please, create dataframe table first.', target='file_msg', append=False) return else: try: download_dataframe(dload_df, sepr, 'irap_tt_analysis.csv') display('Success! You may now download your results.', target='file_msg', append=False) except Exception as e: print(e, "Error downloading dataframe") def on_dload_button_click_2(event): global dload_df_ok, sepr sepr = 2 event.preventDefault() # Prevent default action which can cause page reload if not dload_df_ok: display('Please, create dataframe table first.', target='file_msg', append=False) return else: try: download_dataframe(dload_df, sepr, 'irap_tt_analysis.csv') display('Success! You may now download your results.', target='file_msg', append=False) except Exception as e: print(e, "Error downloading dataframe") # Add the event listener to the download button : def setup_dload_comma(): download_button_comma = document.getElementById('download_button_comma') download_button_comma.addEventListener('click', create_proxy(on_dload_button_click_1)) def setup_dload_tab(): download_button_tab = document.getElementById('download_button_tab') download_button_tab.addEventListener('click', create_proxy(on_dload_button_click_2)) setup_button_inp_file() setup_bt_stats1() setup_bt_stats2() setup_bt_stats3() setup_bt_stats4() setup_bt_stats5() setup_dload_comma() setup_dload_tab()

IRAP Trial-Type Policing

Messages:

Please, select an IRAP text datafile to start the analyses.



Select an IRAP Analysis :

Results:







Copyright © 2024 Rodrigo Vianna de Almeida (Ulster University) under a CC-BY-NC-ND 4.0 international license.


Intelectual property produced during the Ulster University PhD is linked to Ulster University. This institution should be contacted regarding reuse of the source material.

Any work that uses the present resource must cite:

de Almeida, R.V., Barnes-Holmes, D. & Leslie, J.C. (2024). Differential Trial-Type Effects in an Implicit Relational Assessment Procedure: Extending the DAARRE Model. The Psychological Record. DOI: 10.1007/s40732-024-00604-1.


Go back to the main page.