Validation of remote multimodal AI screening for Parkinson disease across diverse settings.
The 18 matches
- [1] § Methods › Statistics and reproducibility ↔ code/analyses/statistical_analysis.ipynb, lines 471–519 · score 0.73 · logistic regression, Benjamini Hochberg, variables, FDR, race, age
- [2] § Methods › Dataset splits ↔ code/analyses/figure_1_dataset_details.ipynb, lines 394–516 · score 0.71 · ROOSTER PD, ROUTE PD, Cluster PD, Parktest, training, model
- [3] § Methods › Model selection and performance reporting ↔ code/unimodal_models/quick_brown_fox/unimodal_fox_wavlm_baal.py, lines 428–496 · score 0.69 · min max, PD samples, minority oversampling, configurations, SMOTE, shallow
- [4] § Methods › Model selection and performance reporting ↔ code/unimodal_models/facial_expression_smile/unimodal_smile_baal.py, lines 388–455 · score 0.69 · min max, PD samples, minority oversampling, configurations, SMOTE, shallow
- [5] § Methods › Model training ↔ code/fusion_models/ufnet/UFNet_withhold_predictions.py, lines 447–495 · score 0.68 · withhold predictions, ReLU, layer normalization, linear, networks, dropout
- [6] § Methods › Model training ↔ code/fusion_models/ufnet/YoutubePD/uncertainty_aware_fusion_no_drop_youtubePD.py, lines 438–486 · score 0.65 · ReLU, layer normalization, uncertainty aware, linear, networks, dropout
- [7] § Methods › Dataset splits ↔ code/performance_analysis/bias_analysis.py, lines 199–258 · score 0.64 · SuperPD, InMotion, Cluster PD
- [8] § Methods › Model selection and performance reporting ↔ code/fusion_models/ufnet/analysis/draw_final_plots.py, lines 125–176 · score 0.63 · Expected Calibration Error, Brier Score, Negative Predictive, Positive Predictive, F1 score, Curve
- [9] § Methods › Statistics and reproducibility ↔ code/analyses/statistical_analysis.ipynb, lines 471–519 · score 0.62 · Benjamini Hochberg, FDR correction, coefficient, predicted, model
- [10] § Methods › Explainability analysis with SHAP ↔ code/analyses/figure_10_interpretability_shap.ipynb, lines 192–236 · score 0.62 · feature block, features predictions, flat, modality, unimodal, matrix
- [11] § Results › Study participants ↔ code/analyses/figure_1_dataset_details.ipynb, lines 394–516 · score 0.61 · ROOSTER PD, ROUTE PD, Cluster PD, train, models
- [12] § Methods › Extracting computational features ↔ code/feature_extraction_pipeline/facial_expression_smile/smile_feature_extraction.py, lines 146–230 · score 0.57 · MediaPipe, facial features, facial expressions, eye, Smile, videos
- [13] § Methods › Video quality analysis ↔ code/analyses/figure_5_9_clinical_comparison_error_analysis.ipynb, lines 590–695 · score 0.57 · finger tapping videos, poor quality, visibility, positioning, smile
- [14] § Results › Consistency with clinician evaluation ↔ code/analyses/statistical_analysis.ipynb, lines 549–619 · score 0.55 · Mann Whitney, FDR adjusted, clinicians, bootstrapped, PPV, sensitivity
- [15] § Methods › Extracting computational features ↔ code/feature_extraction_pipeline/finger_tapping/feature_extraction.py, lines 611–723 · score 0.52 · MediaPipe, interruptions, Finger tapping, speed, amplitude
- [16] § Results › Predictive performance ↔ code/analyses/figures_2_3_4_table_1_predictive_performance.ipynb, lines 1406–1482 · score 0.52 · predictive uncertainty, Fair, bins, 1.5 %, NPV, PPV
- [17] § Results › Investigation of model errors ↔ code/analyses/figure_5_9_clinical_comparison_error_analysis.ipynb, lines 418–526 · score 0.51 · finger tapping model, speech model, incorrect, errors, smile, accuracy
- [18] § Results › Investigation of model errors ↔ code/analyses/figure_9_c_d_error_analyses.ipynb, lines 82–108 · score 0.50 · unexplained error, PD symptoms, video quality, instructions
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Jupyter notebook · 634 lines · 18 KB · MIT · 3 matches
- # %%
- import pandas as pd
- import numpy as np
- from sklearn.metrics import roc_auc_score, confusion_matrix, accuracy_score
- from sklearn.utils import resample
- # %%
- df_test_results = pd.read_csv('../../data/test_data_big.csv')
- df_test_results['pred_park'] = (df_test_results['pred_score_fusion'] >= 0.5).astype(int)
- df_test_results.head()
- # %%
- import pandas as pd
- import numpy as np
- from sklearn.metrics import roc_auc_score, accuracy_score, confusion_matrix
- from sklearn.utils import resample
- def calculate_metrics_bootstrapped(true_labels, pred_labels, n_bootstraps=100):
- rng = np.random.RandomState(seed=42)
- # Convert to numpy arrays
- true_labels = np.array(true_labels)
- pred_labels = np.array(pred_labels)
- # Lists to store bootstrap results
- boot_auroc, boot_acc, boot_ppv, boot_npv, boot_sens, boot_spec, boot_f1 = [], [], [], [], [], [], []
- boot_count = 0
- while boot_count < n_bootstraps:
- # Sample indices with replacement
- indices = rng.choice(len(true_labels), size=len(true_labels), replace=True)
- # Sample labels
- y_true = true_labels[indices]
- y_pred = pred_labels[indices]
- try:
- auroc = roc_auc_score(y_true, y_pred)
- except ValueError:
- continue # Retry this bootstrap
- acc = accuracy_score(y_true, y_pred)
- try:
- tn, fp, fn, tp = confusion_matrix(y_true, y_pred, labels=[0, 1]).ravel()
- except ValueError:
- continue # Retry this bootstrap
- # Compute metrics safely
- ppv = tp / (tp + fp) if (tp + fp) > 0 else np.nan
- npv = tn / (tn + fn) if (tn + fn) > 0 else np.nan
- sensitivity = tp / (tp + fn) if (tp + fn) > 0 else np.nan
- specificity = tn / (tn + fp) if (tn + fp) > 0 else np.nan
- f1_score = 2 * (ppv * sensitivity) / (ppv + sensitivity) if (ppv + sensitivity) > 0 else np.nan
- if np.isnan([ppv, npv, sensitivity, specificity, f1_score]).any():
- continue # Retry this bootstrap
- # Append to result lists
- boot_auroc.append(auroc)
- boot_acc.append(acc)
- boot_ppv.append(ppv)
- boot_npv.append(npv)
- boot_sens.append(sensitivity)
- boot_spec.append(specificity)
- boot_f1.append(f1_score)
- boot_count += 1 # only increment if the sample is valid
- # Aggregate results
- bootstrap_results = {
- 'AUROC': boot_auroc,
- 'Accuracy': boot_acc,
- 'PPV': boot_ppv,
- 'NPV': boot_npv,
- 'Sensitivity': boot_sens,
- 'Specificity': boot_spec,
- 'F1 Score': boot_f1
- }
- # Summary with mean ± 95% CI
- summary = {}
- for metric, values in bootstrap_results.items():
- mean_val = np.nanmean(values)
- lower_ci = np.nanpercentile(values, 2.5)
- upper_ci = np.nanpercentile(values, 97.5)
- margin = (upper_ci - lower_ci) / 2
- summary[metric] = f"{round(mean_val * 100, 1)} ± {round(margin * 100, 1)}"
- summary_df = pd.DataFrame.from_dict(summary, orient='index', columns=['Mean ± 95% CI'])
- return summary_df, bootstrap_results
- # %%
- df_test_results['test_split'].value_counts()
- # %%
- df_global = df_test_results[df_test_results['test_split'] == 'global']
- true_labels_global = np.asarray(df_global['true_label'])
- pred_labels_global = np.asarray(df_global['pred_park'])
- summary_df_global, bootstrap_results_global = calculate_metrics_bootstrapped(true_labels_global, pred_labels_global)
- summary_df_global
- # %%
- df_val_1 = df_test_results[df_test_results['test_split'] == 'validation_1']
- true_labels_val_1 = np.asarray(df_val_1['true_label'])
- pred_labels_val_1 = np.asarray(df_val_1['pred_park'])
- summary_df_val_1, bootstrap_results_val_1 = calculate_metrics_bootstrapped(true_labels_val_1, pred_labels_val_1)
- summary_df_val_1
- # %%
- df_val_2 = df_test_results[df_test_results['test_split'] == 'validation_2']
- true_labels_val_2 = np.asarray(df_val_2['true_label'])
- pred_labels_val_2 = np.asarray(df_val_2['pred_park'])
- summary_df_val_2, bootstrap_results_val_2 = calculate_metrics_bootstrapped(true_labels_val_2, pred_labels_val_2)
- summary_df_val_2
- # %%
- from scipy.stats import mannwhitneyu
- # from statsmodels.stats.multitest import multipletests
- import itertools
- # Define the distributions (re-using group_a, group_b, group_c as stand-ins)
- distribution_sets = [
- bootstrap_results_global,
- bootstrap_results_val_1,
- bootstrap_results_val_2
- ]
- labels = ['Balanced Test Set', 'Validation Study 1', 'Validation Study 2']
- metric_name = 'PPV'
- # Perform pairwise Mann-Whitney U tests
- results = []
- for (i, j) in itertools.combinations(range(len(distribution_sets)), 2):
- group1 = distribution_sets[i][metric_name]
- group2 = distribution_sets[j][metric_name]
- label1 = labels[i]
- label2 = labels[j]
- stat, p = mannwhitneyu(group1, group2, alternative='two-sided')
- results.append({
- 'Comparison': f'{label1} vs {label2}',
- 'U Statistic': stat,
- 'p-value': p
- })
- # Convert results to a DataFrame
- results_df = pd.DataFrame(results)
- results_df
- # %%
- from scipy.stats import mannwhitneyu
- # Define the distributions (re-using group_a, group_b, group_c as stand-ins)
- distribution_sets = [
- bootstrap_results_global,
- bootstrap_results_val_1,
- bootstrap_results_val_2
- ]
- labels = ['Balanced Test Set', 'Validation Study 1', 'Validation Study 2']
- metric_name = 'Sensitivity'
- # Perform pairwise Mann-Whitney U tests
- results = []
- for (i, j) in itertools.combinations(range(len(distribution_sets)), 2):
- group1 = distribution_sets[i][metric_name]
- group2 = distribution_sets[j][metric_name]
- label1 = labels[i]
- label2 = labels[j]
- stat, p = mannwhitneyu(group1, group2, alternative='two-sided')
- results.append({
- 'Comparison': f'{label1} vs {label2}',
- 'U Statistic': stat,
- 'p-value': p
- })
- # Convert results to a DataFrame
- results_df = pd.DataFrame(results)
- results_df
- # %%
- df = df_test_results.copy()
- # %%
- import numpy as np
- import pandas as pd
- from scipy.stats import chi2_contingency
- np.random.seed(42)
- # Observed counts (correct, incorrect) per PD stage
- data = np.array([
- [11, 2], # Stage 1
- [43, 4], # Stage 2
- [8, 3] # Stage 3
- ])
- # Compute observed chi-square statistic
- observed_stat, _, _, _ = chi2_contingency(data, correction=False)
- print(observed_stat)
- # Flatten into array of 1s and 0s
- flat = np.concatenate([[1]*c + [0]*i for c, i in data])
- group_sizes = data.sum(axis=1)
- # Monte Carlo simulation
- n_sim = 10000
- simulated_stats = []
- for _ in range(n_sim):
- shuffled = np.random.permutation(flat)
- reshaped = []
- start = 0
- for size in group_sizes:
- group = shuffled[start:start+size]
- correct = (group == 1).sum()
- incorrect = size - correct
- reshaped.append([correct, incorrect])
- start += size
- reshaped = np.array(reshaped)
- stat, _, _, _ = chi2_contingency(reshaped, correction=False)
- simulated_stats.append(stat)
- simulated_stats = np.array(simulated_stats)
- p_mc = (simulated_stats >= observed_stat).mean()
- observed_stat, p_mc
- # %%
- summary = {'gender': [{'group': 'Female',
- 'mean': 0.22,
- 'se': 0.03,
- 'ci_lower': 0.16,
- 'ci_upper': 0.29,
- 'n_total': 171,
- 'n_wrong': 38},
- {'group': 'Male',
- 'mean': 0.17,
- 'se': 0.03,
- 'ci_lower': 0.11,
- 'ci_upper': 0.23,
- 'n_total': 147,
- 'n_wrong': 25},
- {'group': 'Unknown',
- 'mean': 0.0,
- 'se': 0.0,
- 'ci_lower': 0.0,
- 'ci_upper': 0.0,
- 'n_total': 2,
- 'n_wrong': 0},
- {'group': 'all',
- 'mean': 0.2,
- 'se': 0.02,
- 'ci_lower': 0.15,
- 'ci_upper': 0.24,
- 'n_total': 320,
- 'n_wrong': 63}],
- 'age_group': [{'group': '60 - 79',
- 'mean': 0.2,
- 'se': 0.03,
- 'ci_lower': 0.14,
- 'ci_upper': 0.25,
- 'n_total': 194,
- 'n_wrong': 39},
- {'group': '40 - 59',
- 'mean': 0.18,
- 'se': 0.04,
- 'ci_lower': 0.1,
- 'ci_upper': 0.26,
- 'n_total': 85,
- 'n_wrong': 15},
- {'group': 'Not Mentioned',
- 'mean': 0.0,
- 'se': 0.0,
- 'ci_lower': 0.0,
- 'ci_upper': 0.0,
- 'n_total': 3,
- 'n_wrong': 0},
- {'group': '>= 80',
- 'mean': 0.0,
- 'se': 0.0,
- 'ci_lower': 0.0,
- 'ci_upper': 0.0,
- 'n_total': 7,
- 'n_wrong': 0},
- {'group': '20 - 39',
- 'mean': 0.33,
- 'se': 0.09,
- 'ci_lower': 0.16,
- 'ci_upper': 0.5,
- 'n_total': 27,
- 'n_wrong': 9},
- {'group': '< 20',
- 'mean': 0.0,
- 'se': 0.0,
- 'ci_lower': 0.0,
- 'ci_upper': 0.0,
- 'n_total': 4,
- 'n_wrong': 0},
- {'group': 'all',
- 'mean': 0.2,
- 'se': 0.02,
- 'ci_lower': 0.15,
- 'ci_upper': 0.24,
- 'n_total': 320,
- 'n_wrong': 63}],
- 'race': [{'group': 'white',
- 'mean': 0.18,
- 'se': 0.03,
- 'ci_lower': 0.13,
- 'ci_upper': 0.23,
- 'n_total': 226,
- 'n_wrong': 40},
- {'group': 'Non-white',
- 'mean': 0.24,
- 'se': 0.06,
- 'ci_lower': 0.12,
- 'ci_upper': 0.35,
- 'n_total': 59,
- 'n_wrong': 14},
- {'group': 'Unknown',
- 'mean': 0.26,
- 'se': 0.07,
- 'ci_lower': 0.12,
- 'ci_upper': 0.4,
- 'n_total': 35,
- 'n_wrong': 9},
- {'group': 'all',
- 'mean': 0.2,
- 'se': 0.02,
- 'ci_lower': 0.15,
- 'ci_upper': 0.24,
- 'n_total': 320,
- 'n_wrong': 63}]}
- # %%
- from statsmodels.stats.proportion import proportions_ztest
- # Extract gender data for male and female only
- gender_data = summary['gender']
- female = next(g for g in gender_data if g['group'] == 'Female')
- male = next(g for g in gender_data if g['group'] == 'Male')
- # Gather counts
- counts = [female['n_wrong'], male['n_wrong']]
- totals = [female['n_total'], male['n_total']]
- props = [counts[i] / totals[i] for i in range(2)]
- # Check if sample size conditions are met for z-test
- conditions_met = all([
- totals[i] * props[i] >= 5 and totals[i] * (1 - props[i]) >= 5
- for i in range(2)
- ])
- # Perform test if valid
- if conditions_met:
- stat, pval = proportions_ztest(counts, totals)
- gender_result = {
- "test": "z-test for two proportions",
- "z_statistic": round(stat, 4),
- "p_value": round(pval, 4),
- "female_error_rate": round(props[0], 3),
- "male_error_rate": round(props[1], 3),
- "sample_size_conditions_met": True
- }
- else:
- result = {
- "error": "Sample size requirements not met for z-test",
- "sample_size_conditions_met": False
- }
- gender_result
- # %%
- # Extract race data for White and Non-White
- race_data = summary['race']
- white = next(r for r in race_data if r['group'].lower() == 'white')
- non_white = next(r for r in race_data if r['group'].lower() == 'non-white')
- # Gather counts
- counts = [white['n_wrong'], non_white['n_wrong']]
- totals = [white['n_total'], non_white['n_total']]
- props = [counts[i] / totals[i] for i in range(2)]
- # Check sample size conditions
- conditions_met_race = all([
- totals[i] * props[i] >= 5 and totals[i] * (1 - props[i]) >= 5
- for i in range(2)
- ])
- # Perform test if valid
- if conditions_met_race:
- stat, pval = proportions_ztest(counts, totals)
- race_result = {
- "test": "z-test for two proportions",
- "z_statistic": round(stat, 4),
- "p_value": round(pval, 4),
- "white_error_rate": round(props[0], 3),
- "non_white_error_rate": round(props[1], 3),
- "sample_size_conditions_met": True
- }
- else:
- race_result = {
- "error": "Sample size requirements not met for z-test",
- "sample_size_conditions_met": False
- }
- race_result
- # %%
- # Extract age group data and filter valid ones
- age_data = summary['age_group']
- valid_groups = [g for g in age_data if g['group'] in ['20 - 39', '40 - 59', '60 - 79']]
- # Create contingency table: [correct, incorrect] for each group
- age_contingency = []
- age_labels = []
- for group in valid_groups:
- correct = group['n_total'] - group['n_wrong']
- incorrect = group['n_wrong']
- age_contingency.append([correct, incorrect])
- age_labels.append(group['group'])
- # Run chi-square test of independence
- chi2_stat, p_val, dof, expected = chi2_contingency(age_contingency)
- # Create expected frequencies DataFrame and check for < 5
- expected_df = pd.DataFrame(expected, columns=['Correct_exp', 'Incorrect_exp'], index=age_labels)
- expected_check = (expected_df < 5).any(axis=1)
- any_cell_under_5 = expected_check.any()
- # Format result
- age_result = {
- "test": "Chi-square test of independence",
- "chi2_statistic": round(chi2_stat, 4),
- "p_value": round(p_val, 4),
- "degrees_of_freedom": dof,
- "age_groups_compared": age_labels,
- "all_expected_freqs_>=5": not any_cell_under_5
- }
- age_result
- # %%
- from statsmodels.stats.multitest import multipletests
- # Raw p-values from your tests
- pvals = [gender_result['p_value'], race_result['p_value'], age_result['p_value']]
- labels = ['Gender', 'Race', 'Age Group']
- # Apply FDR correction (Benjamini-Hochberg)
- reject, pvals_corrected, _, _ = multipletests(pvals, alpha=0.05, method='fdr_bh')
- # Display results
- for i in range(len(pvals)):
- print(f"{labels[i]}: raw p = {pvals[i]:.4f}, FDR-corrected p = {pvals_corrected[i]:.4f}, significant = {reject[i]}")
- # %%
- import pandas as pd
- import statsmodels.api as sm
- from statsmodels.stats.multitest import multipletests
- df['race_'] = df['race'].replace({
- 'White': 'white',
- 'Black or African American': 'Non-white',
- 'American Indian or Alaska Native': 'Non-white',
- 'Asian': 'Non-white',
- 'Others': 'Non-white',
- 'Not Mentioned': 'Unknown'
- })
- # Convert misclassified column to binary (1 = misclassified, 0 = correct)
- df['error'] = df['misclassified_fusion'].astype(int)
- # Filter rows to include only the desired levels
- df_filtered = df[
- df['gender'].isin(['Female', 'Male']) &
- df['race_'].isin(['white', 'Non-white']) &
- df['age_group'].isin(['20 - 39', '40 - 59', '60 - 79'])
- ].copy()
- # One-hot encode categorical predictors (drop_first avoids multicollinearity)
- X = pd.get_dummies(df_filtered[['gender', 'race_', 'age_group']], drop_first=True)
- X = sm.add_constant(X)
- # Ensure all X columns are numeric
- X = X.astype(float)
- y = df_filtered['error']
- # Fit logistic regression model
- model = sm.Logit(y, X).fit()
- pvals = model.pvalues
- # Apply Benjamini-Hochberg FDR correction
- reject, pvals_corrected, _, _ = multipletests(pvals, method='fdr_bh')
- # Display results in a table
- results = pd.DataFrame({
- 'Variable': X.columns,
- 'Coefficient': model.params.round(4),
- 'Raw p-value': pvals.round(4),
- 'FDR-adjusted p': pvals_corrected.round(4),
- 'Significant (FDR < 0.05)': reject
- })
- results
- # %%
- from statsmodels.stats.contingency_tables import cochrans_q
- df_clinician_ratings = df[~df['neurologist_label_ray'].isna()]
- # %%
- ray_preds = np.asarray(df_clinician_ratings['neurologist_label_ray'])
- ruth_preds = np.asarray(df_clinician_ratings['neurologist_label_ruth'])
- jamie_preds = np.asarray(df_clinician_ratings['neurologist_label_jamie'])
- group_prediction = (ray_preds + ruth_preds + jamie_preds >= 2).astype(int)
- # Then compare boots_park['PPV'] to boots_group['PPV']
- df_clinician_ratings['pred_park'] = (df_clinician_ratings['pred_score_fusion'] >= 0.5).astype(int)
- park_preds = np.asarray(df_clinician_ratings['pred_park'])
- true_labels = np.asarray(df_clinician_ratings['true_label'])
- summary_ray, boots_ray = calculate_metrics_bootstrapped(true_labels, ray_preds)
- summary_ruth, boots_ruth = calculate_metrics_bootstrapped(true_labels, ruth_preds)
- summary_jamie, boots_jamie = calculate_metrics_bootstrapped(true_labels, jamie_preds)
- summary_park, boots_park = calculate_metrics_bootstrapped(true_labels, park_preds)
- summary_group, boots_group = calculate_metrics_bootstrapped(true_labels, group_prediction)
- # %%
- from scipy.stats import mannwhitneyu
- from statsmodels.stats.multitest import multipletests
- def compare_park_to_clinicians(boots_park, boots_clinicians: dict, metrics: list):
- """
- Compare PARK's metrics to clinicians using one-sided Mann-Whitney U test (PARK < Clinician).
- Args:
- boots_park: dict of bootstrapped metrics for PARK
- boots_clinicians: dict of dicts (e.g., {'Ray': boots_ray, ...})
- metrics: list of metric names (e.g., ['PPV', 'Sensitivity'])
- Returns:
- A dictionary of test results and a printed summary message.
- """
- results = {}
- significantly_lower_metrics = []
- for metric in metrics:
- pvals = []
- pairs = []
- # inside the for metric loop
- for name, boots in boots_clinicians.items():
- dist_park = np.array(boots_park[metric])
- dist_clinician = np.array(boots[metric])
- # Check for valid data
- if np.all(np.isnan(dist_park)) or np.all(np.isnan(dist_clinician)):
- pvals.append(np.nan)
- else:
- try:
- stat = mannwhitneyu(dist_park, dist_clinician, alternative='less')
- pvals.append(stat.pvalue)
- except ValueError:
- pvals.append(np.nan)
- pairs.append(f"PARK vs {name}")
- # FDR correction
- if all(np.isfinite(pvals)):
- reject, pvals_fdr, _, _ = multipletests(pvals, method='fdr_bh')
- else:
- reject = [False] * len(pvals)
- pvals_fdr = [np.nan] * len(pvals)
- # Store result
- results[metric] = {
- 'pairs': pairs,
- 'raw_pvals': pvals,
- 'fdr_pvals': pvals_fdr,
- 'reject': reject
- }
- # Track significance
- if any(reject):
- significantly_lower_metrics.append(metric)
- # Print detailed result per metric
- print(f"\nMetric: {metric}")
- for i, pair in enumerate(pairs):
- print(f"{pair}: raw p = {pvals[i]:.4f}, FDR-adjusted p = {pvals_fdr[i]:.4f}, significant = {reject[i]}")
- # Summary message
- if significantly_lower_metrics:
- print(f"\n⚠️ PARK showed significantly lower performance (FDR < 0.05) than at least one clinician for: {', '.join(significantly_lower_metrics)}")
- else:
- print("\n✅ PARK did not show significantly lower performance than any clinician for any metric (FDR-adjusted p > 0.05).")
- return results
- # %%
- # Define the clinicians and the metrics to compare
- clinicians_boots = {
- 'Ray': boots_ray,
- 'Ruth': boots_ruth,
- 'Jamie': boots_jamie,
- 'Group': boots_group
- }
- metrics_to_compare = ['Accuracy', 'Specificity', 'Sensitivity', 'PPV', 'NPV', 'F1 Score']
- # Run the function
- results = compare_park_to_clinicians(boots_park, clinicians_boots, metrics_to_compare)
statistical_analysis.ipynb at commit 187b906, under MIT · at the source
Overview
- University of Rochester, Rochester, NY USA
- Bangladesh University of Engineering & Technology, Dhaka, Bangladesh
- Atria Health and Research Institute, New York, NY USA
- University of Rochester Medical Center, Rochester, NY USA
- InMotion, Beachwood, OH USA
- Harvard Medical School, Boston, MA USA
- Google Research, London, UK
- Ministry of Defense, Riyadh, Saudi Arabia
Abstract
Background: Timely detection of Parkinson’s disease (PD) remains limited by reliance on in-person neurological evaluations that are often costly and geographically inaccessible. To address these barriers, we develop PARK (Parkinson’s Analysis with Remote Kinetic-tasks) – a web-based artificial intelligence (AI) tool that screens for PD using short webcam recordings of facial expression, motor, and speech tasks.
Methods: Across eight independent studies (n = 1,865 participants; 670 with PD), participants completed three standardized tasks (smile mimicry, finger tapping, and pangram utterance) via webcam. Task-specific neural networks estimate PD risk and uncertainty, which are integrated through an uncertainty-calibrated fusion model (UFNet). Model performance is evaluated on one internal and two external test sets representing supervised and unsupervised real-world environments. Three movement disorder specialists also reviewed videos from 30 participants to benchmark clinical agreement of the PARK tool. User experience is assessed through structured surveys containing open-ended or multiple-choice questions.
Results: PARK achieves accuracies of 80.2–80.6% and AUROC of 0.85-0.87 across all evaluation cohorts, with 83.3–86.5% sensitivity and 71.2–78.4% specificity. Predictive performance remains stable across sex, age, and ethnicity. Agreement with clinician judgments reaches Cohen’s κ = 0.59. Uncertainty estimates reflect diagnostic confidence, and performance declines at high-uncertainty levels. Usability is rated highly (System Usability Scale > 70) in both supervised and unsupervised settings, with low perceived risk and strong user preference for remote screening.
Conclusions: PARK demonstrates promising accuracy and favorable user acceptance for remote PD screening, highlighting its potential as an accessible, equitable, and uncertainty-aware tool for neurological assessment when traditional care is challenging to obtain.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repositories
Its files are read in the Code ↔ Paper reader above, with 18 matches between paragraphs and lines of code.
ROC-HCI/UFNet
5ece2c65ba184faccf6c8cdccdc03132427c464b, 30 December 2024Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
52 files
- code/
constants.py , Python, 24 lines - code/
demographic_details/ , Python, 227 linesdemography_summary_table .py - code/
demographic_details/ , Python, 109 linesprepare_demographic_info _for_fusion_participants .py - code/
fusion_models/ , Python, 796 linesbaselines/ majority_voting.py - code/
fusion_models/ , Python, 805 linesbaselines/ majority_voting_drop_pre ds.py - code/
fusion_models/ , Python, 780 linesbaselines/ neural_early_fusion.py - code/
fusion_models/ , Python, 852 linesbaselines/ neural_hybrid_fusion.py - code/
fusion_models/ , Python, 890 linesbaselines/ neural_late_fusion.py - code/
fusion_models/ , Python, 978 linesufnet/ UFNet_no_withhold.py - code/
fusion_models/ , Python, 996 lines, 1 matchufnet/ UFNet_withhold_predictio ns.py - code/
fusion_models/ , Python, 988 lines, 1 matchufnet/ YoutubePD/ uncertainty_aware_fusion _no_drop_youtubePD.py - code/
fusion_models/ , Python, 1,018 linesufnet/ ablations/ lrformer_attention_fusio n_no_drops.py - code/
fusion_models/ , Python, 963 linesufnet/ ablations/ previous_attention_appro ach.py - code/
fusion_models/ , Python, 978 linesufnet/ ablations/ uncertainty_aware_early_ fusion.py - code/
fusion_models/ , Python, 979 linesufnet/ ablations/ uncertainty_aware_early_ fusion_no_drops.py - code/
fusion_models/ , Python, 1,072 linesufnet/ ablations/ uncertainty_aware_fusion _conformal_preds.py - code/
fusion_models/ , Python, 1,021 linesufnet/ ablations/ uncertainty_aware_fusion _label_smoothing.py - code/
fusion_models/ , Python, 1,109 linesufnet/ ablations/ uncertainty_aware_fusion _label_smoothing_conform al_prediction.py - code/
fusion_models/ , Python, 1,155 linesufnet/ ablations/ uncertainty_aware_fusion _label_smoothing_platt_s caling_conformal_predict ion.py - code/
fusion_models/ , Python, 1,031 linesufnet/ ablations/ uncertainty_aware_fusion _no_drop_ece_loss.py - code/
fusion_models/ , Python, 1,138 linesufnet/ ablations/ uncertainty_aware_fusion _platt_scaling_conformal _preds.py - code/
fusion_models/ , Python, 999 linesufnet/ analysis/ analysis.py - code/
fusion_models/ , Python, 326 lines, 1 matchufnet/ analysis/ draw_final_plots.py - code/
fusion_models/ , Python, 24 linesufnet/ constants.py - code/
fusion_models/ , Python, 880 linesufnet/ count_trainable_params.p y - code/
fusion_models/ , Python, 972 linesufnet/ multi_task_combinations. py - code/
performance_analysis/ , Python, 398 lines, 1 matchbias_analysis.py - code/
performance_analysis/ , Python, 38 linesconfidence_interval_usin g_random_seeds.py - code/
performance_analysis/ , Python, 91 linessensitivity_specificity. py - code/
performance_analysis/ , Python, 76 linesthreshold_vs_accuracy.py - code/
unimodal_models/ , Python, 19 linesfacial_expression_smile/ constants.py - code/
unimodal_models/ , Python, 19 linesfacial_expression_smile/ constants_baal.py - code/
unimodal_models/ , Python, 518 linesfacial_expression_smile/ count_final_model_parame ters.py - code/
unimodal_models/ , Python, 607 linesfacial_expression_smile/ unimodal_smile.py - code/
unimodal_models/ , Python, 595 linesfacial_expression_smile/ unimodal_smile_baal.py - code/
unimodal_models/ , Python, 706 linesfacial_expression_smile/ unimodal_smile_baal_yout ubePD.py - code/
unimodal_models/ , Python, 569 linesfacial_expression_smile/ unimodal_smile_video_emb edding.py - code/
unimodal_models/ , Python, 12 linesfinger_tapping/ constants.py - code/
unimodal_models/ , Python, 12 linesfinger_tapping/ constants_baal.py - code/
unimodal_models/ , Python, 561 linesfinger_tapping/ count_trainable_params.p y - code/
unimodal_models/ , Python, 652 linesfinger_tapping/ unimodal_finger.py - code/
unimodal_models/ , Python, 643 linesfinger_tapping/ unimodal_finger_baal.py - code/
unimodal_models/ , Python, 588 linesfinger_tapping/ unimodal_finger_video_em bedding.py - code/
unimodal_models/ , Python, 15 linesquick_brown_fox/ constants.py - code/
unimodal_models/ , Python, 15 linesquick_brown_fox/ constants_baal.py - code/
unimodal_models/ , Python, 541 linesquick_brown_fox/ count_trainable_params.p y - code/
unimodal_models/ , Python, 618 linesquick_brown_fox/ unimodal_fox.py - code/
unimodal_models/ , Python, 617 linesquick_brown_fox/ unimodal_fox_baal.py - code/
unimodal_models/ , Python, 610 linesquick_brown_fox/ unimodal_fox_baal_YouTub ePD.py - code/
unimodal_models/ , Python, 699 linesquick_brown_fox/ unimodal_fox_baal_YouTub ePD_k_fold.py - LICENSE, License, 21 lines
- README.md, Text, 49 lines
Zenodo 18940836
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
- 28 September 2026: the link answers (HTTP 200)
52 files
- code/
constants.py , Python, 24 lines - code/
demographic_details/ , Python, 227 linesdemography_summary_table .py - code/
demographic_details/ , Python, 109 linesprepare_demographic_info _for_fusion_participants .py - code/
fusion_models/ , Python, 796 linesbaselines/ majority_voting.py - code/
fusion_models/ , Python, 805 linesbaselines/ majority_voting_drop_pre ds.py - code/
fusion_models/ , Python, 780 linesbaselines/ neural_early_fusion.py - code/
fusion_models/ , Python, 852 linesbaselines/ neural_hybrid_fusion.py - code/
fusion_models/ , Python, 890 linesbaselines/ neural_late_fusion.py - code/
fusion_models/ , Python, 978 linesufnet/ UFNet_no_withhold.py - code/
fusion_models/ , Python, 996 linesufnet/ UFNet_withhold_predictio ns.py - code/
fusion_models/ , Python, 988 linesufnet/ YoutubePD/ uncertainty_aware_fusion _no_drop_youtubePD.py - code/
fusion_models/ , Python, 1,018 linesufnet/ ablations/ lrformer_attention_fusio n_no_drops.py - code/
fusion_models/ , Python, 963 linesufnet/ ablations/ previous_attention_appro ach.py - code/
fusion_models/ , Python, 978 linesufnet/ ablations/ uncertainty_aware_early_ fusion.py - code/
fusion_models/ , Python, 979 linesufnet/ ablations/ uncertainty_aware_early_ fusion_no_drops.py - code/
fusion_models/ , Python, 1,072 linesufnet/ ablations/ uncertainty_aware_fusion _conformal_preds.py - code/
fusion_models/ , Python, 1,021 linesufnet/ ablations/ uncertainty_aware_fusion _label_smoothing.py - code/
fusion_models/ , Python, 1,109 linesufnet/ ablations/ uncertainty_aware_fusion _label_smoothing_conform al_prediction.py - code/
fusion_models/ , Python, 1,155 linesufnet/ ablations/ uncertainty_aware_fusion _label_smoothing_platt_s caling_conformal_predict ion.py - code/
fusion_models/ , Python, 1,031 linesufnet/ ablations/ uncertainty_aware_fusion _no_drop_ece_loss.py - code/
fusion_models/ , Python, 1,138 linesufnet/ ablations/ uncertainty_aware_fusion _platt_scaling_conformal _preds.py - code/
fusion_models/ , Python, 999 linesufnet/ analysis/ analysis.py - code/
fusion_models/ , Python, 326 linesufnet/ analysis/ draw_final_plots.py - code/
fusion_models/ , Python, 24 linesufnet/ constants.py - code/
fusion_models/ , Python, 880 linesufnet/ count_trainable_params.p y - code/
fusion_models/ , Python, 972 linesufnet/ multi_task_combinations. py - code/
performance_analysis/ , Python, 398 linesbias_analysis.py - code/
performance_analysis/ , Python, 38 linesconfidence_interval_usin g_random_seeds.py - code/
performance_analysis/ , Python, 91 linessensitivity_specificity. py - code/
performance_analysis/ , Python, 76 linesthreshold_vs_accuracy.py - code/
unimodal_models/ , Python, 19 linesfacial_expression_smile/ constants.py - code/
unimodal_models/ , Python, 19 linesfacial_expression_smile/ constants_baal.py - code/
unimodal_models/ , Python, 518 linesfacial_expression_smile/ count_final_model_parame ters.py - code/
unimodal_models/ , Python, 607 linesfacial_expression_smile/ unimodal_smile.py - code/
unimodal_models/ , Python, 595 linesfacial_expression_smile/ unimodal_smile_baal.py - code/
unimodal_models/ , Python, 706 linesfacial_expression_smile/ unimodal_smile_baal_yout ubePD.py - code/
unimodal_models/ , Python, 569 linesfacial_expression_smile/ unimodal_smile_video_emb edding.py - code/
unimodal_models/ , Python, 12 linesfinger_tapping/ constants.py - code/
unimodal_models/ , Python, 12 linesfinger_tapping/ constants_baal.py - code/
unimodal_models/ , Python, 561 linesfinger_tapping/ count_trainable_params.p y - code/
unimodal_models/ , Python, 652 linesfinger_tapping/ unimodal_finger.py - code/
unimodal_models/ , Python, 643 linesfinger_tapping/ unimodal_finger_baal.py - code/
unimodal_models/ , Python, 588 linesfinger_tapping/ unimodal_finger_video_em bedding.py - code/
unimodal_models/ , Python, 15 linesquick_brown_fox/ constants.py - code/
unimodal_models/ , Python, 15 linesquick_brown_fox/ constants_baal.py - code/
unimodal_models/ , Python, 541 linesquick_brown_fox/ count_trainable_params.p y - code/
unimodal_models/ , Python, 618 linesquick_brown_fox/ unimodal_fox.py - code/
unimodal_models/ , Python, 617 linesquick_brown_fox/ unimodal_fox_baal.py - code/
unimodal_models/ , Python, 610 linesquick_brown_fox/ unimodal_fox_baal_YouTub ePD.py - code/
unimodal_models/ , Python, 699 linesquick_brown_fox/ unimodal_fox_baal_YouTub ePD_k_fold.py - LICENSE, License, 21 lines
- README.md, Text, 49 lines
saiful1105020/park_communications_medicine
187b90651e80d313169690f18d716d7466b15b0c, 11 March 2026Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
27 files
- code/
analyses/ , Jupyter, 278 linesbig_csv_generation.ipynb - code/
analyses/ , Python, 158 linescalculate_performance_me trics.py - code/
analyses/ , Jupyter, 369 linesdemographic_table_genera tion.ipynb - code/
analyses/ , Jupyter, 650 lines, 1 matchfigure_10_interpretabili ty_shap.ipynb - code/
analyses/ , Jupyter, 517 lines, 2 matchesfigure_1_dataset_details .ipynb - code/
analyses/ , Jupyter, 695 lines, 2 matchesfigure_5_9_clinical_comp arison_error_analysis.ip ynb - code/
analyses/ , Jupyter, 979 linesfigure_6_7_8_user_centri c_evaluation.ipynb - code/
analyses/ , Jupyter, 353 lines, 1 matchfigure_9_c_d_error_analy ses.ipynb - code/
analyses/ , Jupyter, 1,581 lines, 1 matchfigures_2_3_4_table_1_pr edictive_performance.ipy nb - code/
analyses/ , Jupyter, 634 lines, 3 matchesstatistical_analysis.ipy nb - code/
feature_extraction_pipel , Python, 380 lines, 1 matchine/ facial_expression_smile/ smile_feature_extraction .py - code/
feature_extraction_pipel , Python, 1,240 lines, 1 matchine/ finger_tapping/ feature_extraction.py - code/
feature_extraction_pipel , Python, 75 linesine/ quick_brown_fox/ extract_wavlm_features.p y - code/
feature_extraction_pipel , Python, 160 linesine/ quick_brown_fox/ helpers.py - code/
feature_extraction_pipel , Python, 1,010 linesine/ quick_brown_fox/ speech_utils.py - code/
feature_extraction_pipel , Python, 127 linesine/ quick_brown_fox/ video_preprocess.py - code/
fusion_model/ , Python, 24 linesconstants.py - code/
fusion_model/ , Python, 1,175 linesuncertainty_aware_fusion _wavlm.py - code/
unimodal_models/ , Python, 21 linesfacial_expression_smile/ constants_baal.py - code/
unimodal_models/ , Python, 666 lines, 1 matchfacial_expression_smile/ unimodal_smile_baal.py - code/
unimodal_models/ , Python, 14 linesfinger_tapping/ constants_baal.py - code/
unimodal_models/ , Python, 688 linesfinger_tapping/ unimodal_finger_baal.py - code/
unimodal_models/ , Python, 21 linesquick_brown_fox/ constants_baal.py - code/
unimodal_models/ , Python, 679 lines, 1 matchquick_brown_fox/ unimodal_fox_wavlm_baal. py - data/
validation_data/ , Python, 21 linesremove_identifiers.py - LICENSE, License, 21 lines
- README.md, Text, 276 lines
Zenodo 18940702
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
- 28 September 2026: the link answers (HTTP 200)
Code availability
All custom code used in this study, including scripts for video processing, feature extraction, model training and evaluation, statistical analyses, and figure generation, is publicly available via the GitHub repository: https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 4 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 125 scripts, each with its path and the digest of its content;
- 18 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
Datasets cited
- figshare:29410703, at figshare; found in the references
Data Availability Statement
The recorded videos are collected using a web-based tool. The tool is publicly accessible at https://
All custom code used in this study, including scripts for video processing, feature extraction, model training and evaluation, statistical analyses, and figure generation, is publicly available via the GitHub repository: https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 28 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 20 authors, 1 keyword, 1 funder, 42 references.
Cite
This paper
Islam, M. S., Adnan, T., Abdelkader, A., Liu, Z., Ma, E., Park, S., Azad, A., Liu, P., Pawlik, M., Hartman, E., Shelton, E., Larson, K. B., Rahman, M. S., Schwartz, C., Jaffe, K., Adams, J. L., Schneider, R. B., Freyberg, J., Dorsey, E. R., & Hoque, E. (2026). Validation of remote multimodal AI screening for Parkinson disease across diverse settings. Communications medicine, 6(1), 488. https://
BibTeX
@article{islam2026valida
author = {Islam, Md Saiful and Adnan, Tariq and Abdelkader, Abdelrahman and Liu, Zipei and Ma, Evelyn and Park, Sooyong and Azad, Asif and Liu, Pai and Pawlik, Meghan and Hartman, Emily and Shelton, Erin and Larson, Kristina B and Rahman, M Saifur and Schwartz, Cathe and Jaffe, Karen and Adams, Jamie L and Schneider, Ruth B and Freyberg, Jan and Dorsey, E Ray and Hoque, Ehsan},
title = {{Validation of remote multimodal AI screening for Parkinson disease across diverse settings}},
journal = {Communications medicine},
year = {2026},
month = may,
volume = {6},
number = {1},
pages = {488},
publisher = {Nature Publishing Group},
issn = {2730-664X},
doi = {10.1038/
url = {https://
pmid = {42092025},
pmcid = {PMC13586151}
}
RIS
TY - JOUR
AU - Islam, Md Saiful
AU - Adnan, Tariq
AU - Abdelkader, Abdelrahman
AU - Liu, Zipei
AU - Ma, Evelyn
AU - Park, Sooyong
AU - Azad, Asif
AU - Liu, Pai
AU - Pawlik, Meghan
AU - Hartman, Emily
AU - Shelton, Erin
AU - Larson, Kristina B
AU - Rahman, M Saifur
AU - Schwartz, Cathe
AU - Jaffe, Karen
AU - Adams, Jamie L
AU - Schneider, Ruth B
AU - Freyberg, Jan
AU - Dorsey, E Ray
AU - Hoque, Ehsan
TI - Validation of remote multimodal AI screening for Parkinson disease across diverse settings
T2 - Communications medicine
J2 - Commun Med (Lond)
PY - 2026
DA - 2026/
VL - 6
IS - 1
SP - 488
SN - 2730-664X
PB - Nature Publishing Group
DO - 10.1038/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1038/
"type": "article-journal",
"title": "Validation of remote multimodal AI screening for Parkinson disease across diverse settings",
"container-title": "Communications medicine",
"author": [
{
"family": "Islam",
"given": "Md Saiful"
},
{
"family": "Adnan",
"given": "Tariq"
},
{
"family": "Abdelkader",
"given": "Abdelrahman"
},
{
"family": "Liu",
"given": "Zipei"
},
{
"family": "Ma",
"given": "Evelyn"
},
{
"family": "Park",
"given": "Sooyong"
},
{
"family": "Azad",
"given": "Asif"
},
{
"family": "Liu",
"given": "Pai"
},
{
"family": "Pawlik",
"given": "Meghan"
},
{
"family": "Hartman",
"given": "Emily"
},
{
"family": "Shelton",
"given": "Erin"
},
{
"family": "Larson",
"given": "Kristina B"
},
{
"family": "Rahman",
"given": "M Saifur"
},
{
"family": "Schwartz",
"given": "Cathe"
},
{
"family": "Jaffe",
"given": "Karen"
},
{
"family": "Adams",
"given": "Jamie L"
},
{
"family": "Schneider",
"given": "Ruth B"
},
{
"family": "Freyberg",
"given": "Jan"
},
{
"family": "Dorsey",
"given": "E Ray"
},
{
"family": "Hoque",
"given": "Ehsan"
}
],
"container-title-short":
"volume": "6",
"issue": "1",
"page": "488",
"DOI": "10.1038/
"PMID": "42092025",
"PMCID": "PMC13586151",
"ISSN": "2730-664X",
"publisher": "Nature Publishing Group",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
6
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1038/s42003-026-10957-8 [code]
- Brain defence by the extracellular matrix protein Cochlin.Journal: Communications biologyIn common: imbalanced-learn, SHAP, Hugging Face Transformers, 11 other tools
- [2] doi:10.1016/j.isci.2026.116825 [code]
- Social hierarchy shapes behavioral and transcriptional responses to chronic stress and ketamine in male mice.Journal: iScienceIn common: imbalanced-learn, SHAP, Numba, 10 other tools
- [3] doi:10.1186/s13059-026-04125-8 [code]
- MLMarker: a machine learning framework for tissue inference and biomarker discovery.Journal: Genome biologyIn common: imbalanced-learn, SHAP, Plotly, 8 other tools
- [4] doi:10.1016/j.isci.2026.115329 [code]
- Brain metastases converge on shared geometric architecture and transcriptomic landscape yet remain distinct from gliomas.Journal: iScienceIn common: imbalanced-learn, SHAP, OpenCV, 7 other tools, clinical / translational
- [5] doi:10.1371/journal.pone.0348866 [code]
- Using deep learning to identify inherited retinal diseases based on wide-field retinal imaging data.Journal: PloS oneIn common: imbalanced-learn, Plotly, OpenCV, 7 other tools, clinical / translational
- [6] doi:10.1038/s41467-026-76837-1 [code]
- Drug screen and machine learning predict neuroprotective agents in a preclinical human model of childhood dementia.Journal: Nature communicationsIn common: SHAP, Hugging Face Transformers, OpenCV, 7 other tools
- [7] doi:10.1093/nargab/lqag050 [code]
- TSProm: deep learning framework to predict tissue-specific regulatory logic.Journal: NAR genomics and bioinformaticsIn common: SHAP, Hugging Face Transformers, statsmodels, 7 other tools
- [8] doi:10.1371/journal.pone.0346575 [code]
- Statistically valid explainable black-box machine learning: applications in sex classification across species using brain imaging.Journal: PloS oneIn common: Hugging Face Transformers, Numba, Plotly, 7 other tools
- [9] doi:10.7554/elife.109717 [code]
- Retrosplenial cortex enables context-dependent goal-directed sensorimotor transformation.Journal: eLifeIn common: SHAP, Numba, OpenCV, 7 other tools
- [10] doi:10.1038/s41467-026-74358-5 [code]
- Brain-inspired spatial intelligence for embodied agents.Journal: Nature communicationsIn common: Hugging Face Transformers, Numba, OpenCV, 7 other tools
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 4 repositories of the authors' code, each at its verified commit and with its license, 125 scripts, and 18 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:92c23d1311b5f76a…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
