library(shiny)
library(forcats)
library(tidyverse)
library(here)
library(hablar)
library(janitor)
library(gt)
Appendix H — QST CRF Data Quality Checks
This document goes over quality checks for the QST Case Report Form (CRF). The headings in the sidebar help the user navigate to their desired content.
H.1 Read in Data and write functions
H.1.1 Load Libraries
H.1.2 Function
Write a function to remove columns where all rows have NA, this is will remove duplicate columns for the the Thoracotomy/TKA cohort
<- function(x) any(!is.na(x)) not_all_na
H.2 CRF Quality checks
H.2.1 Quantitative Sensory Testing (QST)
Read in QST data, We will call this qst
<- read.csv(here("data", "qst", "qst-2024-11-06.csv")) %>%
qst retype()
We will also read in Imaging data since the information on recalibration is recorded in the Imaging CRF. We will later merge field names related to recalibration with the imaging data.
<- read.csv(here("data", "imaging", "imaging-2024-11-06.csv")) %>%
tka_img_4_qst filter(redcap_repeat_instrument == "imaging_mcc1_v09") %>%
select(
record_id,
redcap_event_name,
redcap_data_access_group,
redcap_repeat_instance,
fmricuffcontrarecal,
fmricuffcalfpressurerecal,
fmricuffipyn,
fmricuffcompletescl,
imaging_mcc1_v09_complete%>%
) filter(imaging_mcc1_v09_complete == 2 & !is.na(redcap_repeat_instance)) %>%
group_by(record_id, redcap_event_name) %>%
top_n(1, redcap_repeat_instance) %>%
ungroup() %>%
select(where(not_all_na))
Remove test records
<- c(
test_records "10000",
"15000",
"20000",
"25000",
"40000",
"50000",
"60000",
"70000",
"80000",
"90000",
"100000",
"110000",
"120000"
)
<- qst %>%
qst filter(!record_id %in% test_records)
Create a column for cohort type called “cohort”
<- qst %>%
qst mutate(
cohort = case_when(
>= 10000 & record_id < 15000 | record_id >= 25000 ~ "TKA",
record_id TRUE ~ "Thoracic"
) )
H.2.2 Data Dictionary
Read in data dictionary and remove duplicate field names
<- read_csv(here(
qst_dict "data",
"qst",
"qst-Data-Dictionary-2024-11-06.csv"
%>%
)) distinct(field_name, .keep_all = TRUE)
H.2.3 New field name(s):
Add the field name “cohort” to the data dictionary
# Create field names
<- data.frame(
cohort_new_row field_name = "cohort",
field_type = "Character",
field_note = "Type of surgical cohort",
select_choices_or_calculations = "TKA,Thoracic"
)
# Add the new row after the last row
<- qst_dict %>%
qst_dict slice(1:nrow(.)) %>%
add_row(.after = nrow(.), !!!cohort_new_row)
H.2.4 TKA QST
<- qst tka_qst
keep subjects from the TKA cohort, with the most recent baseline visit and merge with QST data.
<- tka_qst %>%
tka_qst filter(cohort == "TKA") %>%
filter(redcap_repeat_instrument == "qst_mcc1_v03") %>%
filter(qst_mcc1_v03_complete == 2 & !is.na(redcap_repeat_instance)) %>%
group_by(record_id, redcap_event_name) %>%
top_n(1, redcap_repeat_instance) %>%
ungroup() %>%
select(where(not_all_na))
<- left_join(
tka_qst
tka_qst,
tka_img_4_qst,by = intersect(names(tka_qst), names(tka_img_4_qst))
)
H.2.5 Pressure Pain Thresholds (PPT)
keep subjects with completed QST and PPT test completed.
<- tka_qst %>%
qdata2 filter(qst_mcc1_v03_complete == 2) %>%
filter(pptcompleteyn == 2 | pptcompleteyn == 1 | pptcompleteyn == 3)
H.2.5.0.1 Flag 1:
Check if the location of index site was entered [both sites =1 OR 3 = Index site (med/lat joint line)].
<- qdata2 %>%
qerror1 filter(pptcompleteyn == 1 | pptcompleteyn == 3) %>%
filter(is.na(pptpainlocation)) %>%
add_column(error_type = "Location of index site not entered") %>%
add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.2 Flag 2:
Remote site (contralateral deltoid)
Check for missing or mismatch in PPT ratings for Remote site.
Repetition 1:
<- qdata2 %>%
qerror2 filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
mutate(ppt_contr_diff1 = pptremote1val - pptremote1val1) %>%
filter(ppt_contr_diff1 != 0 | is.na(ppt_contr_diff1)) %>%
add_column(
error_type = "PPT Repetition 1:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.3 Flag 3:
Repetition 2:
<- qdata2 %>%
qerror3 filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
mutate(ppt_contr_diff2 = pptremote2val - pptremote2val1) %>%
filter(ppt_contr_diff2 != 0 | is.na(ppt_contr_diff2)) %>%
add_column(
error_type = "PPT repetition 2:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.4 Flag 4:
Repetition 3:
<- qdata2 %>%
qerror4 filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
mutate(ppt_contr_diff3 = pptremote3val - pptremote3val1) %>%
filter(ppt_contr_diff3 != 0 | is.na(ppt_contr_diff3)) %>%
add_column(
error_type = "PPT repetition 3:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.5 Flag 5:
Index site (med/lat joint line)
Check for missing or mismatch in PPT ratings for the index site.
Repetition 1:
<- qdata2 %>%
qerror5 filter(pptcompleteyn == 1 | pptcompleteyn == 3) %>%
mutate(ppt_index_diff1 = pptindex1val - pptindex1val1) %>%
filter(ppt_index_diff1 != 0 | is.na(ppt_index_diff1)) %>%
add_column(
error_type = "PPT Repetition 1:Missing or mismatch in PPT ratings for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.6 Flag 6:
Repetition 2:
<- qdata2 %>%
qerror6 filter(pptcompleteyn == 1 | pptcompleteyn == 3) %>%
mutate(ppt_index_diff2 = pptindex2val - pptindex2val1) %>%
filter(ppt_index_diff2 != 0 | is.na(ppt_index_diff2)) %>%
add_column(
error_type = "PPT Repetition 2:Missing or mismatch in PPT ratings for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.7 Flag 7:
Repetition 3:
<- qdata2 %>%
qerror7 filter(pptcompleteyn == 1 | pptcompleteyn == 3) %>%
mutate(ppt_index_diff3 = pptindex3val - pptindex3val1) %>%
filter(ppt_index_diff3 != 0 | is.na(ppt_index_diff3)) %>%
add_column(
error_type = "PPT Repetition 3:Missing or mismatch in PPT ratings for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.8 Flag 8:
Check if PPT was performed on remote site (pptcompleteyn == 2) but PPT information was filled out for the index site.
<- qdata2 %>%
qerror8 filter(pptcompleteyn == 2) %>%
mutate(
index1 = case_when(
!is.na(pptindex1val) & !is.na(pptindex1val1)) |
(!is.na(pptindex2val) & !is.na(pptindex2val1)) |
(!is.na(pptindex3val) & !is.na(pptindex3val1)) ~
(1,
TRUE ~ 0
)%>%
) filter(index1 == 1) %>%
add_column(
error_type = "PPT: Remote site was checked but PPT information was filled out for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.9 Flag 9:
Check if PPT was performed on both sites (pptcompleteyn == 1) but PPT information was not filled out for the index site.
<- qdata2 %>%
qerror9 filter(pptcompleteyn == 1) %>%
mutate(
index2 = case_when(
is.na(pptindex1val) & is.na(pptindex1val1)) |
(is.na(pptindex2val) & is.na(pptindex2val1)) |
(is.na(pptindex3val) & is.na(pptindex3val1)) ~
(1,
TRUE ~ 0
)%>%
) filter(index2 == 1) %>%
add_column(
error_type = "PPT: Both sites were checked but PPT information was not filled out for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.10 Flag 10:
Check if PPT was performed on the index site (pptcompleteyn == 3) but PPT information was filled out for the remote site
<- qdata2 %>%
qerror10 filter(pptcompleteyn == 3) %>%
mutate(
remote1 = case_when(
!is.na(pptremote1val) & !is.na(pptremote1val1)) |
(!is.na(pptremote2val) & !is.na(pptremote2val1)) |
(!is.na(pptremote3val) & !is.na(pptremote3val1)) ~
(1,
TRUE ~ 0
)%>%
) filter(remote1 == 1) %>%
add_column(
error_type = "PPT: Index site was checked but PPT information was filled out for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.11 Flag 11:
Check if PPT was performed on the both sites (pptcompleteyn == 1) but PPT information was not filled out for the remote site
<- qdata2 %>%
qerror11 filter(pptcompleteyn == 1) %>%
mutate(
remote2 = case_when(
is.na(pptremote1val) & is.na(pptremote1val1)) |
(is.na(pptremote2val) & is.na(pptremote2val1)) |
(is.na(pptremote3val) & is.na(pptremote3val1)) ~
(1,
TRUE ~ 0
)%>%
) filter(remote2 == 1) %>%
add_column(
error_type = "PPT: Both sites were checked but PPT information was not filled out for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.12 Flag 12:
Check if information was available to compute mean PPT values at the index site = primary data point (A2CPS: Site Manual of Procedures v3.0, pg. 154).
<- qdata2 %>%
qerror12 filter((pptcompleteyn == 1 | pptcompleteyn == 3)) %>%
rowwise() %>%
mutate(mean1 = mean(c(pptindex1val, pptindex2val, pptindex3val))) %>%
filter(is.na(mean1)) %>%
add_column(
error_type = "PPT: Not enough information was available to compute mean PPT values at the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.5.0.13 Flag 13:
Check if information was available to compute mean PPT values at the remote site = secondary data point (A2CPS: Site Manual of Procedures v3.0, pg. 154).
<- qdata2 %>%
qerror13 filter((pptcompleteyn == 1 | pptcompleteyn == 2)) %>%
rowwise() %>%
mutate(mean2 = mean(c(pptremote1val, pptremote2val, pptremote3val))) %>%
filter(is.na(mean2)) %>%
add_column(
error_type = "PPT: Not enough information was available to compute mean PPT values at the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6 Temporal Summation (TS):
Keep subjects with completed QST and TS test.
<- tka_qst %>%
tr.complete filter(qst_mcc1_v03_complete == 2) %>%
filter(tscompleted == 2 | tscompleted == 1 | tscompleted == 3)
If TS was completed for both sites then information on at least 1 repetition for both sites should be available.
Create a field name for each repetition (initial and final) and assign 1 if at least one repetition has information without mismatch errors or missingness.
<- tr.complete %>%
tka_ts_recoded mutate(ts_contr_init1 = tsrep1initialpainrem - tsrep1initialpainrem_d) %>%
mutate(ts_contr_fin1 = tsrep1finalpainrem - tsrep1finalpainrem_d) %>%
mutate(ts_contr_init2 = tsrep2initialpainrem - tsrep2initialpainrem_d) %>%
mutate(ts_contr_fin2 = tsrep2finalpainrem - tsrep2finalpainrem_d) %>%
mutate(ts_contr_init3 = tsinitialpainremsclr3 - tsinitialpainremscl1r3) %>%
mutate(ts_contr_fin3 = tsfinalpainremsclr3 - tsfinalpainremscl1r3) %>%
mutate(
trrep1 = case_when(
== 1 | tscompleted == 2) &
(tscompleted == 0 &
ts_contr_init1 == 0 ~
ts_contr_fin1 1,
TRUE ~ 0
)%>%
) mutate(
trrep2 = case_when(
== 1 | tscompleted == 2) &
(tscompleted == 0 &
ts_contr_init2 == 0 ~
ts_contr_fin2 1,
TRUE ~ 0
)%>%
) mutate(
trrep3 = case_when(
== 1 | tscompleted == 2) &
(tscompleted == 0 &
ts_contr_init3 == 0 ~
ts_contr_fin3 1,
TRUE ~ 0
)%>%
) mutate(ts_ind_init1 = tsrep1initialpainindex - tsrep1initialpainindex_d) %>%
mutate(ts_ind_fin1 = tsrep1finalpainindex - tsrep1finalpainindex_d) %>%
mutate(ts_ind_init2 = tsinitialpainindexsclr2 - tsinitialpainindexscl1r2) %>%
mutate(ts_ind_fin2 = tsfinalpainindexsclr2 - tsfinalpainindexscl1r2) %>%
mutate(ts_ind_init3 = tsinitialpainindexsclr3 - tsinitialpainindexscl1r3) %>%
mutate(ts_ind_fin3 = tsfinalpainindexsclr3 - tsfinalpainindexscl1r3) %>%
mutate(
indrep1 = case_when(
== 1 | tscompleted == 3) &
(tscompleted == 0 &
ts_ind_init1 == 0 ~
ts_ind_fin1 1,
TRUE ~ 0
)%>%
) mutate(
indrep2 = case_when(
== 1 | tscompleted == 3) &
(tscompleted == 0 &
ts_ind_init2 == 0 ~
ts_ind_fin2 1,
TRUE ~ 0
)%>%
) mutate(
indrep3 = case_when(
== 1 | tscompleted == 3) &
(tscompleted == 0 &
ts_ind_init3 == 0 ~
ts_ind_fin3 1,
TRUE ~ 0
)%>%
) mutate(
one_rem = case_when(trrep1 == 1 | trrep2 == 1 | trrep3 ~ 1, TRUE ~ 0)
%>%
) mutate(
one_ind = case_when(indrep1 == 1 | indrep2 == 1 | indrep3 ~ 1, TRUE ~ 0)
%>%
) mutate(one_rep = case_when(one_rem == 1 & one_ind == 1 ~ 1, TRUE ~ 0))
H.2.6.0.1 Flag 14:
Check if TS was completed for both sites and at least 1 repetition for both sites had no mismatch errors or missing data.
<- tka_ts_recoded %>%
qerror14 filter(tscompleted == 1 & one_rep == 0) %>%
add_column(
error_type = "TS:TS was completed for both sites and at least 1 repetition for both sites had no mismatch errors or missing data"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.2 Flag 15:
Check if TS was completed for the remote site and at least 1 repetition had no mismatch errors or missing data.
<- tka_ts_recoded %>%
qerror15 filter(tscompleted == 2 & one_rem == 0) %>%
add_column(
error_type = "TS:TS was completed for the remote site and at least 1 repetition had no mismatch errors or missing data"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.3 Flag 16:
Check if TS was completed for the index site and at least 1 repetition had no mismatch errors or missing data.
<- tka_ts_recoded %>%
qerror16 filter(tscompleted == 3 & one_ind == 0) %>%
add_column(
error_type = "TS:TS was completed for the index site and at least 1 repetition had no mismatch errors or missing data"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.4 Flag 17
Check for missing after sensation at 15 secs if TS Remote site (contralateral deltoid) was completed
<- tr.complete %>%
qerror17 filter(tscompleted == 1 | tscompleted == 2) %>%
filter(is.na(tsfinalpainremafts15)) %>%
add_column(
error_type = "TS: Missing after sensation at 15 secs if TS Remote site (contralateral deltoid) was completed"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.5 Flag 18
Check for missing after sensation at 30 secs if TS Remote site (contralateral deltoid) was completed
<- tr.complete %>%
qerror18 filter(tscompleted == 1 | tscompleted == 2) %>%
filter(is.na(tsfinalpainremafts30)) %>%
add_column(
error_type = "TS: Missing after sensation at 30 secs if TS Remote site (contralateral deltoid) was completed"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.6 Flag 19
Check for missing after sensation at 15 secs if TS Index site (med/lat knee) was completed
<- tr.complete %>%
qerror19 filter(tscompleted == 1 | tscompleted == 3) %>%
filter(is.na(tsfinalpainindafts15)) %>%
add_column(
error_type = "TS: Missing after sensation at 15 secs if TS Index site (med/lat knee) was completed"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.7 Flag 20
Check for missing after sensation at 30 secs if TS Index site (med/lat knee) was completed
<- tr.complete %>%
qerror20 filter(tscompleted == 1 | tscompleted == 3) %>%
filter(is.na(tsfinalpainindafts30)) %>%
add_column(
error_type = "TS: Missing after sensation at 30 secs if TS Index site (med/lat knee) was completed"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.8 Flag 21:
Check if TS was performed on the remote site but pain ratings were filled out for the index site.
<- tr.complete %>%
qerror19 filter(tscompleted == 2 & tscompleted != 3) %>%
mutate(
ts.index1 = case_when(
!is.na(tsrep1initialpainindex) & !is.na(tsrep1initialpainindex_d)) |
(!is.na(tsrep1finalpainindex) & !is.na(tsrep1finalpainindex_d)) |
(!is.na(tsinitialpainindexsclr2) & !is.na(tsinitialpainindexscl1r2)) |
(!is.na(tsfinalpainindexsclr2) & !is.na(tsfinalpainindexscl1r2)) |
(!is.na(tsinitialpainindexsclr3) & !is.na(tsinitialpainindexscl1r3)) |
(!is.na(tsfinalpainindexsclr3) & !is.na(tsfinalpainindexscl1r3)) ~
(1,
TRUE ~ 0
)%>%
) filter(ts.index1 == 1) %>%
add_column(
error_type = "TS:Remote site was checked but pain ratings were filled out for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.9 Flag 22:
Check if TS was performed on both sites but pain ratings were not filled out for the index site.
<- tr.complete %>%
qerror22 filter(tscompleted == 1) %>%
mutate(
ts.bothindex1 = case_when(
is.na(tsrep1initialpainindex) &
is.na(tsrep1initialpainindex_d) &
is.na(tsrep1finalpainindex) &
is.na(tsrep1finalpainindex_d) &
is.na(tsinitialpainindexsclr2) &
is.na(tsinitialpainindexscl1r2) &
is.na(tsfinalpainindexsclr2) &
is.na(tsfinalpainindexscl1r2) &
is.na(tsinitialpainindexsclr3) &
is.na(tsinitialpainindexscl1r3) &
is.na(tsfinalpainindexsclr3) &
is.na(tsfinalpainindexscl1r3) ~
1,
TRUE ~ 0
)%>%
) filter(ts.bothindex1 == 1) %>%
add_column(
error_type = "TS:Both sites were checked but pain ratings were not filled out for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.10 Flag 23:
Check if TS was performed on both sites but pain ratings were not filled out for the remote.
<- tr.complete %>%
qerror23 filter(tscompleted == 1) %>%
mutate(
ts.bothrem1 = case_when(
is.na(tsrep1initialpainrem) &
is.na(tsrep1initialpainrem_d) &
is.na(tsrep1finalpainrem) &
is.na(tsrep1finalpainrem_d) &
is.na(tsrep2initialpainrem) &
is.na(tsrep2initialpainrem_d) &
is.na(tsrep2finalpainrem) &
is.na(tsrep2finalpainrem_d) &
is.na(tsinitialpainremsclr3) &
is.na(tsinitialpainremscl1r3) &
is.na(tsfinalpainremsclr3) &
is.na(tsfinalpainremscl1r3) ~
1,
TRUE ~ 0
)%>%
) filter(ts.bothrem1 == 1) %>%
add_column(
error_type = "TS:Both sites were checked but pain ratings were not filled out for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.11 Flag 24:
Check if TS was performed on the index site but pain ratings were filled out for the remote site.
<- tr.complete %>%
qerror22 filter(tscompleted == 3 & tscompleted != 2) %>%
mutate(
ts.remote1 = case_when(
!is.na(tsrep1initialpainrem) & !is.na(tsrep1initialpainrem_d)) |
(!is.na(tsrep1finalpainrem) & !is.na(tsrep1finalpainrem_d)) |
(!is.na(tsrep2initialpainrem) & !is.na(tsrep2initialpainrem_d)) |
(!is.na(tsrep2finalpainrem) & !is.na(tsrep2finalpainrem_d)) |
(!is.na(tsinitialpainremsclr3) & !is.na(tsinitialpainremscl1r3)) |
(!is.na(tsfinalpainremsclr3) & !is.na(tsfinalpainremscl1r3)) ~
(1,
TRUE ~ 0
)%>%
) filter(ts.remote1 == 1) %>%
add_column(
error_type = "TS:index site was checked but pain ratings were filled out for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.12 Flag 25
Check if information was available to compute primary outcome: Mean of 3 MTS Difference scores computed (Max – initial), (A2CPS: Site Manual of Procedures v3.0, pg. 156). This is conditional on having 3 repetitions, if a record has < 3 repetitions, it will be flagged.
Primary outcome for the Index site.
<- tr.complete %>%
qerror25 filter(tscompleted == 1 | tscompleted == 3) %>%
mutate(
max.rep1.index = pmax(tsrep1finalpainindex, tsrep1initialpainindex)
%>%
) mutate(diff.rep1.index = max.rep1.index - tsrep1initialpainindex) %>%
mutate(
max.rep2.index = pmax(tsfinalpainindexsclr2, tsinitialpainindexsclr2)
%>%
) mutate(diff.rep2.index = max.rep2.index - tsinitialpainindexsclr2) %>%
mutate(
max.rep3.index = pmax(tsfinalpainindexsclr3, tsinitialpainindexsclr3)
%>%
) mutate(diff.rep3.index = max.rep3.index - tsinitialpainindexsclr3) %>%
mutate(diff.rep1.index = as.numeric(diff.rep1.index)) %>%
mutate(diff.rep2.index = as.numeric(diff.rep2.index)) %>%
mutate(diff.rep3.index = as.numeric(diff.rep3.index)) %>%
rowwise() %>%
mutate(
mean.index = mean(c(diff.rep1.index, diff.rep2.index, diff.rep3.index))
%>%
) filter(is.na(mean.index)) %>%
add_column(
error_type = "TS: Not enough information was available to compute primary outcome for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.13 Flag 26
Primary outcome for the Remote site.
<- tr.complete %>%
qerror26 filter(tscompleted == 1 | tscompleted == 2) %>%
mutate(max.rep1.remote = pmax(tsrep1initialpainrem, tsrep1finalpainrem)) %>%
mutate(diff.rep1.remote = max.rep1.remote - tsrep1initialpainrem) %>%
mutate(max.rep2.remote = pmax(tsrep2initialpainrem, tsrep2finalpainrem)) %>%
mutate(diff.rep2.remote = max.rep2.remote - tsrep2initialpainrem) %>%
mutate(max.rep3.remote = pmax(tsinitialpainremsclr3, tsfinalpainremsclr3)) %>%
mutate(diff.rep3.remote = max.rep3.remote - tsinitialpainremsclr3) %>%
mutate(diff.rep1.remote = as.numeric(diff.rep1.remote)) %>%
mutate(diff.rep2.remote = as.numeric(diff.rep2.remote)) %>%
mutate(diff.rep3.remote = as.numeric(diff.rep3.remote)) %>%
rowwise() %>%
mutate(
mean.remote = mean(c(diff.rep1.remote, diff.rep2.remote, diff.rep3.remote))
%>%
) filter(is.na(mean.remote)) %>%
add_column(
error_type = "TS: Not enough information was available to compute primary outcome for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.14 Flag 27
Check if information was available to compute secondary outcome: “Mean of 3 Wind-up ratios (WUR) computed ([Max +1]/ [initial +1]). (1 added to handle possibility of zero initial pain rating in denominator).” (A2CPS: Site Manual of Procedures v3.0, pg. 156). This is conditional on having 3 repetitions, if a record has < 3 repetitions, it will be flagged
Secondary outcome for the index site
<- tr.complete %>%
qerror27 filter(tscompleted == 1 | tscompleted == 3) %>%
mutate(
max.rep1.index1 = 1 + (pmax(tsrep1finalpainindex, tsrep1initialpainindex))
%>%
) mutate(init.rep1.index1 = 1 + (tsrep1initialpainindex)) %>%
mutate(div.rep1.index1 = max.rep1.index1 / init.rep1.index1) %>%
mutate(
max.rep2.index1 = 1 + (pmax(tsfinalpainindexsclr2, tsinitialpainindexsclr2))
%>%
) mutate(init.rep2.index1 = 1 + (tsinitialpainindexsclr2)) %>%
mutate(div.rep2.index1 = max.rep2.index1 / init.rep2.index1) %>%
mutate(
max.rep3.index1 = 1 + (pmax(tsfinalpainindexsclr3, tsinitialpainindexsclr3))
%>%
) mutate(init.rep3.index1 = 1 + (tsinitialpainindexsclr3)) %>%
mutate(div.rep3.index1 = max.rep3.index1 / init.rep3.index1) %>%
rowwise() %>%
mutate(
mean.sec.index = mean(c(div.rep1.index1, div.rep2.index1, div.rep3.index1))
%>%
) filter(is.na(mean.sec.index)) %>%
add_column(
error_type = "TS: Not enough information was available to compute secondary outcome for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.6.0.15 Flag 28
Secondary outcome for the Remote site.
<- tr.complete %>%
qerror28 filter(tscompleted == 1 | tscompleted == 2) %>%
mutate(
max.rep1.remote1 = 1 + (pmax(tsrep1initialpainrem, tsrep1finalpainrem))
%>%
) mutate(init.rep1.remote1 = 1 + (tsrep1initialpainrem)) %>%
mutate(div.rep1.remote1 = max.rep1.remote1 / init.rep1.remote1) %>%
mutate(
max.rep2.remote1 = 1 + (pmax(tsrep2initialpainrem, tsrep2finalpainrem))
%>%
) mutate(init.rep2.remote1 = 1 + (tsrep2initialpainrem)) %>%
mutate(div.rep2.remote1 = max.rep2.remote1 / init.rep2.remote1) %>%
mutate(
max.rep3.remote1 = 1 + (pmax(tsinitialpainremsclr3, tsfinalpainremsclr3))
%>%
) mutate(init.rep3.remote1 = 1 + (tsinitialpainremsclr3)) %>%
mutate(div.rep3.remote1 = max.rep3.remote1 / init.rep3.remote1) %>%
rowwise() %>%
mutate(
mean.sec.remote = mean(c(
div.rep1.remote1,
div.rep2.remote1,
div.rep3.remote1
))%>%
) filter(is.na(mean.sec.remote)) %>%
add_column(
error_type = "TS: Not enough information was available to compute secondary outcome for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.7 Conditioned Pain Modulation (CPM):
Keep records with “CPM test completed”
<- tka_qst %>%
trcpm.complete filter(qst_mcc1_v03_complete == 2) %>%
filter(!is.na(cpmcompleteyn) & cpmcompleteyn != 0)
H.2.7.0.1 Flag 29:
Check if water temperature was not checked:
<- trcpm.complete %>%
qerror29 filter(cpmcoldwatertempc != 1) %>%
add_column(error_type = "CPM: Water temperature not checked") %>%
add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.7.0.2 Flag 30:
Check for missing or mismatch in cold water pain ratings at 30 seconds.
<- trcpm.complete %>%
qerror30 filter(
== 1 | (cpmbathrangeyn == 2 & cpmoutrangetime >= 30)
cpmbathrangeyn %>%
) mutate(diff_30 = cpmcoldwaterpain30sscl - cpmcoldwaterpain30sscl1) %>%
filter(diff_30 != 0 | is.na(diff_30)) %>%
add_column(
error_type = "CPM: Missing or mismatch in cold water pain ratings at 30 sec"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.7.0.3 Flag 31:
Check for missing or mismatch in cold water pain ratings at 60 seconds.
<- trcpm.complete %>%
qerror31 filter(
== 1 | (cpmbathrangeyn == 2 & cpmoutrangetime >= 60)
cpmbathrangeyn %>%
) mutate(diff_60 = cpmcoldwaterpain60sscl - cpmcoldwaterpain60sscl1) %>%
filter(diff_60 != 0 | is.na(diff_60)) %>%
add_column(
error_type = "CPM: Missing or mismatch in cold water pain ratings at 60 sec"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.7.0.4 Flag 32:
Check for missing or mismatch in PPT ratings for Remote site (repetition 1).
<- trcpm.complete %>%
qerror32 mutate(diff_cpm1 = cpmppt1val - cpmppt1val1) %>%
filter(diff_cpm1 != 0 | is.na(diff_cpm1)) %>%
add_column(
error_type = "CPM PPT Rep1:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.7.0.5 Flag 33:
Check for missing or mismatch in PPT ratings for Remote site (repetition 2).
<- trcpm.complete %>%
qerror33 mutate(diff_cpm2 = cpmppt2val - cpmppt2val1) %>%
filter(diff_cpm2 != 0 | is.na(diff_cpm2)) %>%
add_column(
error_type = "CPM PPT Rep2:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.7.0.6 Flag 34:
Check for missing or mismatch in PPT ratings for Remote site (repetition 3).
<- trcpm.complete %>%
qerror34 mutate(diff_cpm3 = cpmppt3val - cpmppt3val1) %>%
filter(diff_cpm3 != 0 | is.na(diff_cpm3)) %>%
add_column(
error_type = "CPM PPT Rep3:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.7.0.7 Flag 35:
Check if information was available to compute primary outcome (A2CPS: Site Manual of Procedures v3.0, pg. 159) i.e. [(pre hand immersion PPT-post immersion PPT)/pre immersion PPT] *100
<- trcpm.complete %>%
qerror35 filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
rowwise() %>%
mutate(mean_pre = mean(c(pptremote1val, pptremote2val, pptremote3val))) %>%
rowwise() %>%
mutate(mean_post = mean(c(cpmppt1val, cpmppt2val, cpmppt3val))) %>%
mutate(cpm_change = ((mean_pre - mean_post) / mean_pre) * 100) %>%
filter(is.na(cpm_change)) %>%
add_column(
error_type = "CPM: Not enough information to compute primary outcome"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.7.0.8 Flag 36:
Check if information was available to compute secondary outcome (A2CPS: Site Manual of Procedures v3.0, pg. 159) i.e. CPM difference score computed as pre hand immersion PPT-post immersion PPT
<- trcpm.complete %>%
qerror36 filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
rowwise() %>%
mutate(mean_pre = mean(c(pptremote1val, pptremote2val, pptremote3val))) %>%
rowwise() %>%
mutate(mean_post = mean(c(cpmppt1val, cpmppt2val, cpmppt3val))) %>%
mutate(cpm_diff = mean_pre - mean_post) %>%
filter(is.na(cpm_diff)) %>%
add_column(
error_type = "CPM: Not enough information to compute secondary outcome"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.7.0.9 Flag 37:
Check If personalized pressure was performed during imaging and there were missing values for cuff Pressure to achieve 4/10 pain outside of scanner during QST as well as missing values for recalibration pressure during imaging.
<- tka_qst %>%
qerror37 mutate(
no.qst = case_when(
is.na(fmricuffcalfpressurerecal) & is.na(fmricuffcalfpressure) ~ 1,
TRUE ~ 0
)%>%
) mutate(
personal.cuff = case_when(
== 1 | fmricuffipyn == 1 ~ 1,
fmricuffcompletescl TRUE ~ 0
)%>%
) filter(personal.cuff == 1 & no.qst == 1) %>%
add_column(
error_type = "QST: Missing values for cuff Pressure to achieve 4/10 pain outside of scanner during QST as well as missing values for recalibration pressure during imaging"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.7.0.10 QST Biomarkers
H.2.7.0.10.1 PPT Biomarkers:
Mean PPT values at the index site = primary data point (A2CPS: Site Manual of Procedures v3.0, pg. 154).
<- qdata2 %>%
primary_ppt_tka filter((pptcompleteyn == 1 | pptcompleteyn == 3)) %>%
rowwise() %>%
mutate(mean1 = mean(c(pptindex1val, pptindex2val, pptindex3val))) %>%
rename(primary_ppt_tka = mean1) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
primary_ppt_tka )
Mean PPT values at the remote site = secondary data point (A2CPS: Site Manual of Procedures v3.0, pg. 154).
<- qdata2 %>%
secondary_ppt_tka filter((pptcompleteyn == 1 | pptcompleteyn == 2)) %>%
rowwise() %>%
mutate(mean2 = mean(c(pptremote1val, pptremote2val, pptremote3val))) %>%
rename(secondary_ppt_tka = mean2) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
secondary_ppt_tka )
H.2.7.0.10.2 TS Biomarkers:
Primary outcome: Mean of 3 MTS Difference scores computed (Max – initial), (A2CPS: Site Manual of Procedures v3.0, pg. 156). This is conditional on having 3 repetitions.
Primary outcome for the Index site.
<- tr.complete %>%
primary_ts_index_tka filter(tscompleted == 1 | tscompleted == 3) %>%
mutate(
max.rep1.index = pmax(tsrep1finalpainindex, tsrep1initialpainindex)
%>%
) mutate(diff.rep1.index = max.rep1.index - tsrep1initialpainindex) %>%
mutate(
max.rep2.index = pmax(tsfinalpainindexsclr2, tsinitialpainindexsclr2)
%>%
) mutate(diff.rep2.index = max.rep2.index - tsinitialpainindexsclr2) %>%
mutate(
max.rep3.index = pmax(tsfinalpainindexsclr3, tsinitialpainindexsclr3)
%>%
) mutate(diff.rep3.index = max.rep3.index - tsinitialpainindexsclr3) %>%
mutate(diff.rep1.index = as.numeric(diff.rep1.index)) %>%
mutate(diff.rep2.index = as.numeric(diff.rep2.index)) %>%
mutate(diff.rep3.index = as.numeric(diff.rep3.index)) %>%
rowwise() %>%
mutate(
mean.index = mean(c(diff.rep1.index, diff.rep2.index, diff.rep3.index))
%>%
) rename(primary_ts_index_tka = mean.index) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
primary_ts_index_tka )
Primary outcome for the Remote site.
<- tr.complete %>%
primary_ts_remote_tka filter(tscompleted == 1 | tscompleted == 2) %>%
mutate(max.rep1.remote = pmax(tsrep1initialpainrem, tsrep1finalpainrem)) %>%
mutate(diff.rep1.remote = max.rep1.remote - tsrep1initialpainrem) %>%
mutate(max.rep2.remote = pmax(tsrep2initialpainrem, tsrep2finalpainrem)) %>%
mutate(diff.rep2.remote = max.rep2.remote - tsrep2initialpainrem) %>%
mutate(max.rep3.remote = pmax(tsinitialpainremsclr3, tsfinalpainremsclr3)) %>%
mutate(diff.rep3.remote = max.rep3.remote - tsinitialpainremsclr3) %>%
mutate(diff.rep1.remote = as.numeric(diff.rep1.remote)) %>%
mutate(diff.rep2.remote = as.numeric(diff.rep2.remote)) %>%
mutate(diff.rep3.remote = as.numeric(diff.rep3.remote)) %>%
rowwise() %>%
mutate(
mean.remote = mean(c(diff.rep1.remote, diff.rep2.remote, diff.rep3.remote))
%>%
) rename(primary_ts_remote_tka = mean.remote) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
primary_ts_remote_tka )
Secondary outcome: Mean of 3 Wind-up ratios (WUR) computed ([Max +1]/ [initial +1]). (1 added to handle possibility of zero initial pain rating in denominator). (A2CPS: Site Manual of Procedures v3.0, pg. 156). This is conditional on having 3 repetitions, if a record has < 3 repetitions, it will be flagged
Secondary outcome for the index site
<- tr.complete %>%
secondary_ts_index_tka filter(tscompleted == 1 | tscompleted == 3) %>%
mutate(
max.rep1.index1 = 1 + (pmax(tsrep1finalpainindex, tsrep1initialpainindex))
%>%
) mutate(init.rep1.index1 = 1 + (tsrep1initialpainindex)) %>%
mutate(div.rep1.index1 = max.rep1.index1 / init.rep1.index1) %>%
mutate(
max.rep2.index1 = 1 + (pmax(tsfinalpainindexsclr2, tsinitialpainindexsclr2))
%>%
) mutate(init.rep2.index1 = 1 + (tsinitialpainindexsclr2)) %>%
mutate(div.rep2.index1 = max.rep2.index1 / init.rep2.index1) %>%
mutate(
max.rep3.index1 = 1 + (pmax(tsfinalpainindexsclr3, tsinitialpainindexsclr3))
%>%
) mutate(init.rep3.index1 = 1 + (tsinitialpainindexsclr3)) %>%
mutate(div.rep3.index1 = max.rep3.index1 / init.rep3.index1) %>%
rowwise() %>%
mutate(
mean.sec.index = mean(c(div.rep1.index1, div.rep2.index1, div.rep3.index1))
%>%
) rename(secondary_ts_index_tka = mean.sec.index) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
secondary_ts_index_tka )
Secondary outcome for the Remote site.
<- tr.complete %>%
secondary_ts_remote_tka filter(tscompleted == 1 | tscompleted == 2) %>%
mutate(
max.rep1.remote1 = 1 + (pmax(tsrep1initialpainrem, tsrep1finalpainrem))
%>%
) mutate(init.rep1.remote1 = 1 + (tsrep1initialpainrem)) %>%
mutate(div.rep1.remote1 = max.rep1.remote1 / init.rep1.remote1) %>%
mutate(
max.rep2.remote1 = 1 + (pmax(tsrep2initialpainrem, tsrep2finalpainrem))
%>%
) mutate(init.rep2.remote1 = 1 + (tsrep2initialpainrem)) %>%
mutate(div.rep2.remote1 = max.rep2.remote1 / init.rep2.remote1) %>%
mutate(
max.rep3.remote1 = 1 + (pmax(tsinitialpainremsclr3, tsfinalpainremsclr3))
%>%
) mutate(init.rep3.remote1 = 1 + (tsinitialpainremsclr3)) %>%
mutate(div.rep3.remote1 = max.rep3.remote1 / init.rep3.remote1) %>%
rowwise() %>%
mutate(
mean.sec.remote = mean(c(
div.rep1.remote1,
div.rep2.remote1,
div.rep3.remote1
))%>%
) rename(secondary_ts_remote_tka = mean.sec.remote) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
secondary_ts_remote_tka )
H.2.7.0.10.3 CPM Biomarkers:
Primary outcome (A2CPS: Site Manual of Procedures v3.0, pg. 159) i.e. [(pre hand immersion PPT-post immersion PPT)/pre immersion PPT] *100
<- trcpm.complete %>%
primary_cpm_tka filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
rowwise() %>%
mutate(mean_pre = mean(c(pptremote1val, pptremote2val, pptremote3val))) %>%
rowwise() %>%
mutate(mean_post = mean(c(cpmppt1val, cpmppt2val, cpmppt3val))) %>%
mutate(cpm_change = ((mean_pre - mean_post) / mean_pre) * 100) %>%
rename(primary_cpm_tka = cpm_change) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
primary_cpm_tka )
Secondary outcome (A2CPS: Site Manual of Procedures v3.0, pg. 159) i.e. CPM difference score computed as pre hand immersion PPT-post immersion PPT
<- trcpm.complete %>%
secondary_cpm_tka filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
rowwise() %>%
mutate(mean_pre = mean(c(pptremote1val, pptremote2val, pptremote3val))) %>%
rowwise() %>%
mutate(mean_post = mean(c(cpmppt1val, cpmppt2val, cpmppt3val))) %>%
mutate(cpm_diff = mean_pre - mean_post) %>%
rename(secondary_cpm_tka = cpm_diff) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
secondary_cpm_tka )
Merge computed biomarkers to the “tka_qst” dataset:
<- left_join(
tka_qst
tka_qst,
primary_ppt_tka,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
secondary_ppt_tka,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
primary_ts_index_tka,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
primary_ts_remote_tka,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
secondary_ts_index_tka,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
secondary_ts_remote_tka,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
primary_cpm_tka,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
secondary_cpm_tka,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
) )
H.2.7.0.11 New field name(s):
Add field names for the computed biomarkers to the QST data dictionary
# Create field names
<- data.frame(
primary_ppt_tka_new_row field_name = "primary_ppt_tka",
field_type = "numeric",
field_note = "PPT primary biomarker:TKA "
)
<- data.frame(
secondary_ppt_tka_new_row field_name = "secondary_ppt_tka",
field_type = "numeric",
field_note = "PPT secondary biomarker:TKA "
)
<- data.frame(
primary_ts_index_tka_new_row field_name = "primary_ts_index_tka",
field_type = "numeric",
field_note = "TS primary biomarker for the index site:TKA "
)
<- data.frame(
primary_ts_remote_tka_new_row field_name = "primary_ts_remote_tka",
field_type = "numeric",
field_note = "TS primary biomarker for the remote site:TKA "
)
<- data.frame(
secondary_ts_index_tka_new_row field_name = "secondary_ts_index_tka",
field_type = "numeric",
field_note = "TS secondary biomarker for the index site:TKA "
)
<- data.frame(
secondary_ts_remote_tka_new_row field_name = " secondary_ts_remote_tka",
field_type = "numeric",
field_note = "TS secondary biomarker for the remote site:TKA "
)
<- data.frame(
primary_cpm_tka_new_row field_name = " primary_cpm_tka",
field_type = "numeric",
field_note = "CPM primary biomarker:TKA "
)
<- data.frame(
secondary_cpm_tka_new_row field_name = " secondary_cpm_tka",
field_type = "numeric",
field_note = "CPM secondary biomarker:TKA "
)
# Add the new row after the last row
<- qst_dict %>%
qst_dict slice(1:nrow(.)) %>%
add_row(.after = nrow(.), !!!primary_ppt_tka_new_row) %>%
add_row(.after = nrow(.), !!!secondary_ppt_tka_new_row) %>%
add_row(.after = nrow(.), !!!primary_ts_index_tka_new_row) %>%
add_row(.after = nrow(.), !!!primary_ts_remote_tka_new_row) %>%
add_row(.after = nrow(.), !!!secondary_ts_index_tka_new_row) %>%
add_row(.after = nrow(.), !!!secondary_ts_remote_tka_new_row) %>%
add_row(.after = nrow(.), !!!primary_cpm_tka_new_row) %>%
add_row(.after = nrow(.), !!!secondary_cpm_tka_new_row)
H.2.7.0.12 Create QST error report for the TKA cohort.
# Specify the common prefix
<- "qerror"
qst_error
# Find data frames in the global environment with the specified prefix
<- mget(ls(pattern = paste0("^", qst_error)))
qst_list
# Combine the data frames using bind_rows
<- bind_rows(qst_list) %>%
qst_report as_tibble() %>%
mutate_all(as.character) %>%
pivot_wider(names_from = "error_type", values_from = "errors") %>%
mutate_all(~ replace_na(., ""))
%>%
qst_report gt() %>%
tab_header(
title = md("**TKA Cohort QST form Error Report**")
%>%
) tab_options(
table.font.size = px(12),
column_labels.font.size = px(12)
%>%
) tab_style(
style = list(cell_fill(color = "#F4F4F4")),
locations = cells_body(columns = record_id)
)
TKA Cohort QST form Error Report | |||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
record_id | redcap_data_access_group | redcap_repeat_instrument | redcap_repeat_instance | Location of index site not entered | PPT: Both sites were checked but PPT information was not filled out for the remote site | PPT: Not enough information was available to compute mean PPT values at the index site | PPT: Not enough information was available to compute mean PPT values at the remote site | TS:TS was completed for both sites and at least 1 repetition for both sites had no mismatch errors or missing data | TS: Missing after sensation at 15 secs if TS Remote site (contralateral deltoid) was completed | TS: Missing after sensation at 30 secs if TS Remote site (contralateral deltoid) was completed | TS:Remote site was checked but pain ratings were filled out for the index site | PPT Repetition 1:Missing or mismatch in PPT ratings for Remote site | TS: Missing after sensation at 30 secs if TS Index site (med/lat knee) was completed | TS:Both sites were checked but pain ratings were not filled out for the remote site | TS: Not enough information was available to compute primary outcome for the index site | TS: Not enough information was available to compute primary outcome for the remote site | TS: Not enough information was available to compute secondary outcome for the index site | TS: Not enough information was available to compute secondary outcome for the remote site | CPM: Water temperature not checked | PPT repetition 2:Missing or mismatch in PPT ratings for Remote site | CPM: Missing or mismatch in cold water pain ratings at 30 sec | CPM: Missing or mismatch in cold water pain ratings at 60 sec | CPM PPT Rep2:Missing or mismatch in PPT ratings for Remote site | CPM PPT Rep3:Missing or mismatch in PPT ratings for Remote site | CPM: Not enough information to compute primary outcome | CPM: Not enough information to compute secondary outcome | QST: Missing values for cuff Pressure to achieve 4/10 pain outside of scanner during QST as well as missing values for recalibration pressure during imaging | PPT repetition 3:Missing or mismatch in PPT ratings for Remote site | PPT Repetition 2:Missing or mismatch in PPT ratings for the index site | PPT Repetition 3:Missing or mismatch in PPT ratings for the index site | PPT: Both sites were checked but PPT information was not filled out for the index site |
10216 | rush_university_me | qst_mcc1_v03 | 1 | error | error | error | error | ||||||||||||||||||||||||
10222 | rush_university_me | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
25050 | university_of_mich | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10040 | uchicago | qst_mcc1_v03 | 1 | error | error | error | error | error | |||||||||||||||||||||||
10643 | uchicago | qst_mcc1_v03 | 1 | error | error | error | error | error | |||||||||||||||||||||||
10015 | rush_university_me | qst_mcc1_v03 | 1 | error | error | error | error | error | error | ||||||||||||||||||||||
10378 | uchicago | qst_mcc1_v03 | 1 | error | error | error | error | ||||||||||||||||||||||||
10637 | uchicago | qst_mcc1_v03 | 1 | error | error | ||||||||||||||||||||||||||
10679 | rush_university_me | qst_mcc1_v03 | 1 | error | error | error | error | ||||||||||||||||||||||||
10758 | uchicago | qst_mcc1_v03 | 1 | error | error | error | |||||||||||||||||||||||||
10147 | uchicago | qst_mcc1_v03 | 1 | error | error | error | error | error | error | error | error | ||||||||||||||||||||
10360 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10372 | uchicago | qst_mcc1_v03 | 1 | error | error | ||||||||||||||||||||||||||
25048 | university_of_mich | qst_mcc1_v03 | 1 | error | error | ||||||||||||||||||||||||||
10013 | rush_university_me | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10018 | rush_university_me | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10181 | rush_university_me | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10066 | uchicago | qst_mcc1_v03 | 1 | error | error | error | |||||||||||||||||||||||||
10283 | rush_university_me | qst_mcc1_v03 | 1 | error | error | error | |||||||||||||||||||||||||
10315 | uchicago | qst_mcc1_v03 | 1 | error | error | error | |||||||||||||||||||||||||
10418 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10436 | uchicago | qst_mcc1_v03 | 1 | error | error | error | |||||||||||||||||||||||||
10539 | uchicago | qst_mcc1_v03 | 1 | error | error | error | |||||||||||||||||||||||||
10684 | northshore | qst_mcc1_v03 | 1 | error | error | error | |||||||||||||||||||||||||
25136 | university_of_mich | qst_mcc1_v03 | 1 | error | error | error | |||||||||||||||||||||||||
10738 | uchicago | qst_mcc1_v03 | 1 | error | error | ||||||||||||||||||||||||||
10778 | rush_university_me | qst_mcc1_v03 | 1 | error | error | ||||||||||||||||||||||||||
10905 | rush_university_me | qst_mcc1_v03 | 1 | error | error | ||||||||||||||||||||||||||
10425 | uchicago | qst_mcc1_v03 | 1 | error | error | ||||||||||||||||||||||||||
10438 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10696 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10055 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
25157 | university_of_mich | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10363 | uchicago | qst_mcc1_v03 | 1 | error | error | ||||||||||||||||||||||||||
10613 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10698 | northshore | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10872 | northshore | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10899 | northshore | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
25051 | university_of_mich | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10201 | uchicago | qst_mcc1_v03 | 1 | error | error | error | error | error | |||||||||||||||||||||||
10655 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10703 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10006 | rush_university_me | qst_mcc1_v03 | 1 | error | error | error | |||||||||||||||||||||||||
10249 | rush_university_me | qst_mcc1_v03 | 1 | error | error | error | |||||||||||||||||||||||||
10077 | northshore | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10103 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10258 | northshore | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10297 | northshore | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10327 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10335 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10352 | northshore | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10442 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10483 | uchicago | qst_mcc1_v03 | 1 | error | |||||||||||||||||||||||||||
10487 | uchicago | qst_mcc1_v03 | 1 | error |
H.2.7.0.13 Save:
Save “tka_qst” and data dictionary as .csv files in the folder named “reformatted_QST”
write_csv(
tka_qst,file = here::here("data", "QST", "Reformatted", "reformatted_tka_qst.csv")
)
write_csv(
qst_dict,file = here::here("data", "QST", "Reformatted", "updated_qst_dict.csv")
)
H.2.8 QST: Thoracotomy cohort
<- qst thor_qst
We will also read in Imaging data since the information on recalibration is recorded in the Imaging CRF. We will later merge field names related to recalibration with the imaging data.
<- read_csv(here(
thor_img_4_qst "data",
"imaging",
"imaging-2024-11-06.csv"
%>%
)) filter(redcap_repeat_instrument == "imaging_mcc2_v01") %>%
select(
record_id,
redcap_event_name,
redcap_data_access_group,
redcap_repeat_instance,
fmricuffcontrarecal,
fmricuffcontrarecal,
fmricuffcalfpressurerecal,
fmricuffipyn,
fmricuffcompletescl,
imaging_mcc2_v01_complete%>%
) filter(imaging_mcc2_v01_complete == 2 & !is.na(redcap_repeat_instance)) %>%
group_by(record_id, redcap_event_name) %>%
top_n(1, redcap_repeat_instance) %>%
ungroup() %>%
select(where(not_all_na))
keep subjects from the Thoracotomy cohort, with the most recent baseline visit and merge with QST data.
<- thor_qst %>%
thor_qst filter(cohort == "Thoracic") %>%
filter(redcap_repeat_instrument == "qst_mcc1_v03") %>%
filter(qst_mcc1_v03_complete == 2 & !is.na(redcap_repeat_instance)) %>%
group_by(record_id, redcap_event_name) %>%
top_n(1, redcap_repeat_instance) %>%
ungroup() %>%
select(where(not_all_na))
<- left_join(
thor_qst
thor_qst,
thor_img_4_qst,by = intersect(names(thor_qst), names(thor_img_4_qst))
)
H.2.9 Pressure Pain Thresholds (PPT)
keep subjects with completed QST and PPT test.
<- thor_qst %>%
qdatam2 filter(qst_mcc1_v03_complete == 2) %>%
filter(pptcompleteyn == 2 | pptcompleteyn == 1 | pptcompleteyn == 3)
H.2.9.0.1 Flag 1:
Remote site: Shoulder (deltoid muscle), contralateral to surgical chest side.
Check for missing or mismatch in PPT ratings for Remote site.
Repetition 1:
<- qdatam2 %>%
m2qerror1 filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
mutate(ppt_contr_diff1 = pptremoter1val - pptremoter1val_d) %>%
filter(ppt_contr_diff1 != 0 | is.na(ppt_contr_diff1)) %>%
add_column(
error_type = "PPT Repetition 1:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.2 Flag 2:
Repetition 2:
<- qdatam2 %>%
m2qerror2 filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
mutate(ppt_contr_diff2 = pptremoter2val - pptremoter2val_d) %>%
filter(ppt_contr_diff2 != 0 | is.na(ppt_contr_diff2)) %>%
add_column(
error_type = "PPT repetition 2:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.3 Flag 3:
Repetition 3:
<- qdatam2 %>%
m2qerror3 filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
mutate(ppt_contr_diff3 = pptremoter3val - pptremoter3val_d) %>%
filter(ppt_contr_diff3 != 0 | is.na(ppt_contr_diff3)) %>%
add_column(
error_type = "PPT repetition 3:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.4 Flag 4:
Index site: Surgical site, lateral thorax on the midaxillary line in the intercostal space between the fifth and sixth rib
Check for missing or mismatch in PPT ratings for the index site.
Repetition 1:
<- qdatam2 %>%
m2qerror4 filter(pptcompleteyn == 1 | pptcompleteyn == 3) %>%
mutate(ppt_index_diff1 = pptindxr1val - pptindxr1val_d) %>%
filter(ppt_index_diff1 != 0 | is.na(ppt_index_diff1)) %>%
add_column(
error_type = "PPT Repetition 1:Missing or mismatch in PPT ratings for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.5 Flag 5:
Repetition 2:
<- qdatam2 %>%
m2qerror5 filter(pptcompleteyn == 1 | pptcompleteyn == 3) %>%
mutate(ppt_index_diff2 = pptindxr2val - pptindxr2val_d) %>%
filter(ppt_index_diff2 != 0 | is.na(ppt_index_diff2)) %>%
add_column(
error_type = "PPT Repetition 2:Missing or mismatch in PPT ratings for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.6 Flag 6:
Repetition 3:
<- qdatam2 %>%
m2qerror6 filter(pptcompleteyn == 1 | pptcompleteyn == 3) %>%
mutate(ppt_index_diff3 = pptindxr3val - pptindxr3val_d) %>%
filter(ppt_index_diff3 != 0 | is.na(ppt_index_diff3)) %>%
add_column(
error_type = "PPT Repetition 3:Missing or mismatch in PPT ratings for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.7 Flag 7:
Check if PPT was performed on remote site (pptcompleteyn == 2) but PPT information was filled out for the index site.
<- qdatam2 %>%
m2qerror7 filter(pptcompleteyn == 2) %>%
mutate(
index1 = case_when(
!is.na(pptindxr1val) & !is.na(pptindxr1val_d)) |
(!is.na(pptindxr2val) & !is.na(pptindxr2val_d)) |
(!is.na(pptindxr3val) & !is.na(pptindxr3val_d)) ~
(1,
TRUE ~ 0
)%>%
) filter(index1 == 1) %>%
add_column(
error_type = "PPT: Remote site was checked but PPT information was filled out for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.8 Flag 8:
Check if PPT was performed on both sites (pptcompleteyn == 1) but PPT information was not filled out for the index site.
<- qdatam2 %>%
m2qerror8 filter(pptcompleteyn == 1) %>%
mutate(
index2 = case_when(
is.na(pptindxr1val) & is.na(pptindxr1val_d)) |
(is.na(pptindxr2val) & is.na(pptindxr2val_d)) |
(is.na(pptindxr3val) & is.na(pptindxr3val_d)) ~
(1,
TRUE ~ 0
)%>%
) filter(index2 == 1) %>%
add_column(
error_type = "PPT: Both sites were checked but PPT information was not filled out for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.9 Flag 9:
Check if PPT was performed on the index site (pptcompleteyn == 3) but PPT information was filled out for the remote site
<- qdatam2 %>%
m2qerror9 filter(pptcompleteyn == 3) %>%
mutate(
remote1 = case_when(
!is.na(pptremoter1val) & !is.na(pptremoter1val_d)) |
(!is.na(pptremoter2val) & !is.na(pptremoter2val_d)) |
(!is.na(pptremoter3val) & !is.na(pptremoter3val_d)) ~
(1,
TRUE ~ 0
)%>%
) filter(remote1 == 1) %>%
add_column(
error_type = "PPT: Index site was checked but PPT information was filled out for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.10 Flag 10:
Check if PPT was performed on the both sites (pptcompleteyn == 1) but PPT information was not filled out for the remote site
<- qdatam2 %>%
m2qerror10 filter(pptcompleteyn == 1) %>%
mutate(
remote2 = case_when(
is.na(pptremoter1val) & is.na(pptremoter1val_d)) |
(is.na(pptremoter2val) & is.na(pptremoter2val_d)) |
(is.na(pptremoter3val) & is.na(pptremoter3val_d)) ~
(1,
TRUE ~ 0
)%>%
) filter(remote2 == 1) %>%
add_column(
error_type = "PPT: Both sites were checked but PPT information was not filled out for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.11 Flag 11:
Check if information was available to compute mean PPT values at the index site = primary data point (A2CPS: Site Manual of Procedures v3.0, pg. 154).
<- qdatam2 %>%
m2qerror11 filter((pptcompleteyn == 1 | pptcompleteyn == 3)) %>%
rowwise() %>%
mutate(mean1 = mean(c(pptindxr1val, pptindxr2val, pptindxr3val))) %>%
filter(is.na(mean1)) %>%
add_column(
error_type = "PPT: Not enough information was available to compute mean PPT values at the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.9.0.12 Flag 12:
Check if information was available to compute mean PPT values at the remote site = secondary data point (A2CPS: Site Manual of Procedures v3.0, pg. 154).
<- qdatam2 %>%
m2qerror12 filter((pptcompleteyn == 1 | pptcompleteyn == 2)) %>%
rowwise() %>%
mutate(mean2 = mean(c(pptremoter1val, pptremoter2val, pptremoter3val))) %>%
filter(is.na(mean2)) %>%
add_column(
error_type = "PPT: Not enough information was available to compute mean PPT values at the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10 Temporal Summation (TS):
Keep subjects with completed QST and TS test.
<- thor_qst %>%
m2tr.complete filter(qst_mcc1_v03_complete == 2) %>%
filter(tscompleted == 2 | tscompleted == 1 | tscompleted == 3)
If TS was completed for both sites then information on at least 1 repetition for both sites should be available.
Create a field name for each repetition (initial and final) and assign 1 if at least one repetition has information without mismatch errors.
<- m2tr.complete %>%
thor_ts_recoded mutate(ts_contr_init1 = tsremoter1initial - tsremoter1initial_d) %>%
mutate(ts_contr_fin1 = tsremoter1final - tsremoter1final_d) %>%
mutate(ts_contr_init2 = tsremoter2initial - tsremoter2initial_d) %>%
mutate(ts_contr_fin2 = tsremoter2final - tsremoter2final_d) %>%
mutate(ts_contr_init3 = tsremoter3initial - tsremoter3initial_d) %>%
mutate(ts_contr_fin3 = tsremoter3final - tsremoter3final_d) %>%
mutate(
trrep1 = case_when(
== 1 | tscompleted == 2) &
(tscompleted == 0 &
ts_contr_init1 == 0 ~
ts_contr_fin1 1,
TRUE ~ 0
)%>%
) mutate(
trrep2 = case_when(
== 1 | tscompleted == 2) &
(tscompleted == 0 &
ts_contr_init2 == 0 ~
ts_contr_fin2 1,
TRUE ~ 0
)%>%
) mutate(
trrep3 = case_when(
== 1 | tscompleted == 2) &
(tscompleted == 0 &
ts_contr_init3 == 0 ~
ts_contr_fin3 1,
TRUE ~ 0
)%>%
) mutate(ts_ind_init1 = tsindxr1initial - tsindxr1initial_d) %>%
mutate(ts_ind_fin1 = tsindxr1final - tsindxr1final_d) %>%
mutate(ts_ind_init2 = tsindxr2initial - tsindxr2initial_d) %>%
mutate(ts_ind_fin2 = tsindxr2final - tsindxr2final_d) %>%
mutate(ts_ind_init3 = tsindxr3initial - tsindxr3initial_d) %>%
mutate(ts_ind_fin3 = tsindxr3final - tsindxr3final_d) %>%
mutate(
indrep1 = case_when(
== 1 | tscompleted == 3) &
(tscompleted == 0 &
ts_ind_init1 == 0 ~
ts_ind_fin1 1,
TRUE ~ 0
)%>%
) mutate(
indrep2 = case_when(
== 1 | tscompleted == 3) &
(tscompleted == 0 &
ts_ind_init2 == 0 ~
ts_ind_fin2 1,
TRUE ~ 0
)%>%
) mutate(
indrep3 = case_when(
== 1 | tscompleted == 3) &
(tscompleted == 0 &
ts_ind_init3 == 0 ~
ts_ind_fin3 1,
TRUE ~ 0
)%>%
) mutate(
one_rem = case_when(trrep1 == 1 | trrep2 == 1 | trrep3 ~ 1, TRUE ~ 0)
%>%
) mutate(
one_ind = case_when(indrep1 == 1 | indrep2 == 1 | indrep3 ~ 1, TRUE ~ 0)
%>%
) mutate(one_rep = case_when(one_rem == 1 & one_ind == 1 ~ 1, TRUE ~ 0))
H.2.10.0.1 Flag 13:
Check if TS was completed for both sites and at least 1 repetition for both sites had no mismatch errors or missing data.
<- thor_ts_recoded %>%
m2qerror13 filter(tscompleted == 1 & one_rep == 0) %>%
add_column(
error_type = "TS: TS was completed for both sites and at least 1 repetition for both sites has no mismatch errors or missing data"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.2 Flag 14:
Check if TS was completed for the remote site and at least 1 repetition had no mismatch errors or missing data.
<- thor_ts_recoded %>%
m2qerror14 filter(tscompleted == 2 & one_rem == 0) %>%
add_column(
error_type = "TS: TS was completed for the remote site and at least 1 repetition had no mismatch errors or missing data"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.3 Flag 15:
Check if TS was completed for the index site and at least 1 repetition had no mismatch errors or missing data.
<- thor_ts_recoded %>%
m2qerror15 filter(tscompleted == 3 & one_ind == 0) %>%
add_column(
error_type = "TS: TS was completed for the index site and at least 1 repetition had no mismatch errors or missing data"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.4 Flag 16
Check for missing after sensation at 15 secs if TS Remote site (contralateral deltoid) was completed
<- m2tr.complete %>%
m2qerror16 filter(tscompleted == 1 | tscompleted == 2) %>%
filter(is.na(tsremoteafter15)) %>%
add_column(
error_type = "TS: Missing after sensation at 15 secs if TS Remote site (contralateral deltoid) was completed"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.5 Flag 17
Check for missing after sensation at 30 secs if TS Remote site (contralateral deltoid) was completed
<- m2tr.complete %>%
m2qerror17 filter(tscompleted == 1 | tscompleted == 2) %>%
filter(is.na(tsfinalpainremafts31)) %>%
add_column(
error_type = "TS: Missing after sensation at 30 secs if TS Remote site (contralateral deltoid) was completed"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.6 Flag 18
Check for missing after sensation at 15 secs if TS Index site was completed
<- m2tr.complete %>%
m2qerror18 filter(tscompleted == 1 | tscompleted == 3) %>%
filter(is.na(tsindxafter15)) %>%
add_column(
error_type = "TS: Missing after sensation at 15 secs if TS Index site was completed"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.7 Flag 19
Check for missing after sensation at 30 secs if TS Index site was completed
<- m2tr.complete %>%
m2qerror19 filter(tscompleted == 1 | tscompleted == 3) %>%
filter(is.na(tsindxafter30)) %>%
add_column(
error_type = "TS: Missing after sensation at 30 secs if TS Index site (med/lat knee) was completed"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.8 Flag 20:
Check if TS was performed on the remote site but pain ratings were filled out for the index site.
<- m2tr.complete %>%
m2qerror20 filter(tscompleted == 2 & tscompleted != 3) %>%
mutate(
ts.index1 = case_when(
!is.na(tsindxr1initial) & !is.na(tsindxr1initial_d)) |
(!is.na(tsindxr1final) & !is.na(tsindxr1final_d)) |
(!is.na(tsindxr2initial) & !is.na(tsindxr2initial_d)) |
(!is.na(tsindxr2final) & !is.na(tsindxr2final_d)) |
(!is.na(tsindxr3initial) & !is.na(tsindxr3initial_d)) |
(!is.na(tsindxr3final) & !is.na(tsindxr3final_d)) ~
(1,
TRUE ~ 0
)%>%
) filter(ts.index1 == 1) %>%
add_column(
error_type = "TS:Remote site was checked but pain ratings were filled out for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.9 Flag 21:
Check if TS was performed on both sites but pain ratings were not filled out for the index site.
<- m2tr.complete %>%
m2qerror21 filter(tscompleted == 1) %>%
mutate(
ts.bothindex1 = case_when(
is.na(tsindxr1initial) &
is.na(tsindxr1initial_d) &
is.na(tsindxr1final) &
is.na(tsindxr1final_d) &
is.na(tsindxr2initial) &
is.na(tsindxr2initial_d) &
is.na(tsindxr2final) &
is.na(tsindxr2final_d) &
is.na(tsindxr3initial) &
is.na(tsindxr3initial_d) &
is.na(tsindxr3final) &
is.na(tsindxr3final_d) ~
1,
TRUE ~ 0
)%>%
) filter(ts.bothindex1 == 1) %>%
add_column(
error_type = "TS:Both sites were checked but pain ratings were not filled out for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.10 Flag 22:
Check if TS was performed on both sites but pain ratings were not filled out for the remote.
<- m2tr.complete %>%
m2qerror22 filter(tscompleted == 1) %>%
mutate(
ts.bothrem1 = case_when(
is.na(tsremoter1initial) &
is.na(tsremoter1initial_d) &
is.na(tsremoter1final) &
is.na(tsremoter1final_d) &
is.na(tsremoter2initial) &
is.na(tsremoter2initial_d) &
is.na(tsremoter2final) &
is.na(tsremoter2final_d) &
is.na(tsremoter3initial) &
is.na(tsremoter3initial_d) &
is.na(tsremoter3final) &
is.na(tsremoter3final_d) ~
1,
TRUE ~ 0
)%>%
) filter(ts.bothrem1 == 1) %>%
add_column(
error_type = "TS:Both sites were checked but pain ratings were not filled out for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.11 Flag 23:
Check if TS was performed on the index site but pain ratings were filled out for the remote site.
<- m2tr.complete %>%
m2qerror23 filter(tscompleted == 3 & tscompleted != 2) %>%
mutate(
ts.remote1 = case_when(
!is.na(tsremoter1initial) & !is.na(tsremoter1initial_d)) |
(!is.na(tsremoter1final) & !is.na(tsremoter1final_d)) |
(!is.na(tsremoter2initial) & !is.na(tsremoter2initial_d)) |
(!is.na(tsremoter2final) & !is.na(tsremoter2final_d)) |
(!is.na(tsremoter3initial) & !is.na(tsremoter3initial_d)) |
(!is.na(tsremoter3final) & !is.na(tsremoter3final_d)) ~
(1,
TRUE ~ 0
)%>%
) filter(ts.remote1 == 1) %>%
add_column(
error_type = "TS:index site was checked but pain ratings were filled out for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.12 Flag 24
Check if information was available to compute primary outcome: Mean of 3 MTS Difference scores computed (Max – initial), (A2CPS: Site Manual of Procedures v3.0, pg. 156). This is conditional on having 3 repetitions, if a record has < 3 repetitions, it will be flagged.
Primary outcome for the Index site.
<- m2tr.complete %>%
m2qerror24 filter(tscompleted == 1 | tscompleted == 3) %>%
mutate(max.rep1.index = pmax(tsindxr1final, tsindxr1initial)) %>%
mutate(diff.rep1.index = max.rep1.index - tsindxr1initial) %>%
mutate(max.rep2.index = pmax(tsindxr2final, tsindxr2initial)) %>%
mutate(diff.rep2.index = max.rep2.index - tsindxr2initial) %>%
mutate(max.rep3.index = pmax(tsindxr3final, tsindxr3initial)) %>%
mutate(diff.rep3.index = max.rep3.index - tsindxr3initial) %>%
mutate(diff.rep1.index = as.numeric(diff.rep1.index)) %>%
mutate(diff.rep2.index = as.numeric(diff.rep2.index)) %>%
mutate(diff.rep3.index = as.numeric(diff.rep3.index)) %>%
rowwise() %>%
mutate(
mean.index = mean(c(diff.rep1.index, diff.rep2.index, diff.rep3.index))
%>%
) filter(is.na(mean.index)) %>%
add_column(
error_type = "TS: Not enough information was available to compute primary outcome for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.13 Flag 25
Primary outcome for the Remote site.
<- m2tr.complete %>%
m2qerror25 filter(tscompleted == 1 | tscompleted == 2) %>%
mutate(max.rep1.remote = pmax(tsremoter1initial, tsremoter1final)) %>%
mutate(diff.rep1.remote = max.rep1.remote - tsremoter1initial) %>%
mutate(max.rep2.remote = pmax(tsremoter2initial, tsremoter2final)) %>%
mutate(diff.rep2.remote = max.rep2.remote - tsremoter2initial) %>%
mutate(max.rep3.remote = pmax(tsremoter3initial, tsremoter3final)) %>%
mutate(diff.rep3.remote = max.rep3.remote - tsremoter3initial) %>%
mutate(diff.rep1.remote = as.numeric(diff.rep1.remote)) %>%
mutate(diff.rep2.remote = as.numeric(diff.rep2.remote)) %>%
mutate(diff.rep3.remote = as.numeric(diff.rep3.remote)) %>%
rowwise() %>%
mutate(
mean.remote = mean(c(diff.rep1.remote, diff.rep2.remote, diff.rep3.remote))
%>%
) filter(is.na(mean.remote)) %>%
add_column(
error_type = "TS: Not enough information was available to compute primary outcome for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.14 Flag 26
Check if information was available to compute secondary outcome: Mean of 3 Wind-up ratios (WUR) computed ([Max +1]/ [initial +1]). (1 added to handle possibility of zero initial pain rating in denominator). (A2CPS: Site Manual of Procedures v3.0, pg. 156). This is conditional on having 3 repetitions, if a record has < 3 repetitions, it will be flagged
Secondary outcome for the index site
<- m2tr.complete %>%
m2qerror26 filter(tscompleted == 1 | tscompleted == 3) %>%
mutate(max.rep1.index1 = 1 + (pmax(tsindxr1final, tsindxr1initial))) %>%
mutate(init.rep1.index1 = 1 + (tsindxr1initial)) %>%
mutate(div.rep1.index1 = max.rep1.index1 / init.rep1.index1) %>%
mutate(max.rep2.index1 = 1 + (pmax(tsindxr2final, tsindxr2initial))) %>%
mutate(init.rep2.index1 = 1 + (tsindxr2initial)) %>%
mutate(div.rep2.index1 = max.rep2.index1 / init.rep2.index1) %>%
mutate(max.rep3.index1 = 1 + (pmax(tsindxr3final, tsindxr3initial))) %>%
mutate(init.rep3.index1 = 1 + (tsindxr3initial)) %>%
mutate(div.rep3.index1 = max.rep3.index1 / init.rep3.index1) %>%
rowwise() %>%
mutate(
mean.sec.index = mean(c(div.rep1.index1, div.rep2.index1, div.rep3.index1))
%>%
) filter(is.na(mean.sec.index)) %>%
add_column(
error_type = "TS: Not enough information was available to compute secondary outcome for the index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.10.0.15 Flag 27
Secondary outcome for the Remote site.
<- m2tr.complete %>%
m2qerror28 filter(tscompleted == 1 | tscompleted == 2) %>%
mutate(max.rep1.remote1 = 1 + (pmax(tsremoter1initial, tsremoter1final))) %>%
mutate(init.rep1.remote1 = 1 + (tsremoter1initial)) %>%
mutate(div.rep1.remote1 = max.rep1.remote1 / init.rep1.remote1) %>%
mutate(max.rep2.remote1 = 1 + (pmax(tsremoter2initial, tsremoter2final))) %>%
mutate(init.rep2.remote1 = 1 + (tsremoter2initial)) %>%
mutate(div.rep2.remote1 = max.rep2.remote1 / init.rep2.remote1) %>%
mutate(max.rep3.remote1 = 1 + (pmax(tsremoter3initial, tsremoter3final))) %>%
mutate(init.rep3.remote1 = 1 + (tsremoter3initial)) %>%
mutate(div.rep3.remote1 = max.rep3.remote1 / init.rep3.remote1) %>%
rowwise() %>%
mutate(
mean.sec.remote = mean(c(
div.rep1.remote1,
div.rep2.remote1,
div.rep3.remote1
))%>%
) filter(is.na(mean.sec.remote)) %>%
add_column(
error_type = "TS: Not enough information was available to compute secondary outcome for the remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.11 Conditioned Pain Modulation (CPM):
Keep records with “CPM test completed”
<- thor_qst %>%
m2trcpm.complete filter(qst_mcc1_v03_complete == 2) %>%
filter(!is.na(cpmcompleteyn) & cpmcompleteyn != 0)
H.2.11.0.1 Flag 28:
Check if water temperature was not checked:
<- m2trcpm.complete %>%
m2qerror28 filter(cpmcoldwatertemp != 1) %>%
add_column(error_type = "CPM: Water temperature not checked") %>%
add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.11.0.2 Flag 29:
Check for missing or mismatch in cold water pain ratings at 30 seconds.
<- m2trcpm.complete %>%
m2qerror29 filter(
== 1 | (cpmbathrangeyn == 2 & cpmoutrangetime >= 30)
cpmbathrangeyn %>%
) mutate(diff_30 = cpmcoldwaterpain30 - cpmcoldwaterpain30_d) %>%
filter(diff_30 != 0 | is.na(diff_30)) %>%
add_column(
error_type = "CPM: Missing or mismatch in cold water pain ratings at 30 sec"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.11.0.3 Flag 30:
Check for missing or mismatch in cold water pain ratings at 60 seconds.
<- m2trcpm.complete %>%
m2qerror30 filter(
== 1 | (cpmbathrangeyn == 2 & cpmoutrangetime >= 60)
cpmbathrangeyn %>%
) mutate(diff_60 = cpmcoldwaterpain60 - cpmcoldwaterpain60_d) %>%
filter(diff_60 != 0 | is.na(diff_60)) %>%
add_column(
error_type = "CPM: Missing or mismatch in cold water pain ratings at 60 sec"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.11.0.4 Flag 31:
Check for missing or mismatch in PPT ratings for Remote site (repetition 1).
<- m2trcpm.complete %>%
m2qerror31 mutate(diff_cpm1 = cpmpptremr1val - cpmpptremr1val_d) %>%
filter(diff_cpm1 != 0 | is.na(diff_cpm1)) %>%
add_column(
error_type = "CPM PPT Rep1:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.11.0.5 Flag 32:
Check for missing or mismatch in PPT ratings for Remote site (repetition 2).
<- m2trcpm.complete %>%
m2qerror32 mutate(diff_cpm2 = cpmpptremr2val - cpmpptremr2val_d) %>%
filter(diff_cpm2 != 0 | is.na(diff_cpm2)) %>%
add_column(
error_type = "CPM PPT Rep2:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.11.0.6 Flag 33:
Check for missing or mismatch in PPT ratings for Remote site (repetition 3).
<- m2trcpm.complete %>%
m2qerror33 mutate(diff_cpm3 = cpmpptremr3val - cpmpptremr3val_d) %>%
filter(diff_cpm3 != 0 | is.na(diff_cpm3)) %>%
add_column(
error_type = "CPM PPT Rep3:Missing or mismatch in PPT ratings for Remote site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.11.0.7 Flag 34:
Check if information was available to compute primary outcome (A2CPS MOP v.3.0, pg. 159) i.e. [(pre hand immersion PPT-post immersion PPT)/pre immersion PPT] *100
<- m2trcpm.complete %>%
m2qerror34 filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
rowwise() %>%
mutate(mean_pre = mean(c(pptremoter1val, pptremoter2val, pptremoter3val))) %>%
rowwise() %>%
mutate(
mean_post = mean(c(cpmpptremr1val, cpmpptremr2val, cpmpptremr3val))
%>%
) mutate(cpm_change = ((mean_pre - mean_post) / mean_pre) * 100) %>%
filter(is.na(cpm_change)) %>%
add_column(
error_type = "CPM: Not enough information to compute primary outcome"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.11.0.8 Flag 35:
Check if information was available to compute secondary outcome (A2CPS MOP v.3.0, pg. 159) i.e. CPM difference score computed as pre hand immersion PPT-post immersion PPT
<- m2trcpm.complete %>%
m2qerror35 filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
rowwise() %>%
mutate(mean_pre = mean(c(pptremoter1val, pptremoter2val, pptremoter3val))) %>%
rowwise() %>%
mutate(
mean_post = mean(c(cpmpptremr1val, cpmpptremr2val, cpmpptremr3val))
%>%
) mutate(cpm_diff = mean_pre - mean_post) %>%
filter(is.na(cpm_diff)) %>%
add_column(
error_type = "CPM: Not enough information to compute secondary outcome"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.11.0.9 Flag 36:
Check If personalized pressure was performed during imaging and there were missing values for cuff Pressure to achieve 4/10 pain outside of scanner during QST as well as missing values for recalibration pressure during imaging.
<- thor_qst %>%
m2qerror36 mutate(
no.qst = case_when(
is.na(fmricuffcalfpressurerecal) & is.na(cuffpfmripressure) ~ 1,
TRUE ~ 0
)%>%
) mutate(
personal.cuff = case_when(
== 1 | fmricuffipyn == 1 ~ 1,
fmricuffcompletescl TRUE ~ 0
)%>%
) filter(personal.cuff == 1 & no.qst == 1) %>%
add_column(
error_type = "QST: Missing values for cuff Pressure to achieve 4/10 pain outside of scanner during QST as well as missing values for recalibration pressure during imaging"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12 Dynamic Mechanical Allodynia (DMA)
Keep records with “DMA test completed”
<- thor_qst %>%
m2dma.baseline filter(!is.na(dmatestcompyn) & dmatestcompyn != 0)
H.2.12.0.1 Flag 37:
If DMA was performed on both or either site but “DMA complete” was missing.
<- m2dma.baseline %>%
m2qerror37 filter(is.na(dmatestcompyn)) %>%
filter(
!is.na(
&
dmacontr1pain &
dmacontr1pain_d &
dmacontr2pain &
dmacontr2pain_d &
dmacontr3pain &
dmacontr3pain_d &
dmacontr4pain &
dmacontr4pain_d &
dmacontr5pain |
dmacontr5pain_d &
dmaindxr1pain &
dmaindxr1pain_d &
dmaindxr2pain &
dmaindxr2pain_d &
dmaindxr3pain &
dmaindxr3pain_d &
dmaindxr4pain &
dmaindxr4pain_d &
dmaindxr5pain &
dmaindxr5pain_d
dmasenscompare
)%>%
) add_column(
error_type = "DMA:DMA was performed on both or either site but DMA complete was missing"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.2 Flag 38:
Check if DMA was performed on all the sites and completion status for Standardized control site (contralateral) and Standardized index site (surgical) was also checked.
<- m2dma.baseline %>%
m2qerror38 filter(
== 1 & (dmatestcompwhich___1 == 1 | dmatestcompwhich___2 == 1)
dmatestcompyn %>%
) add_column(
error_type = "DMA:DMA was performed on all the sites and completion status for Standardized control site (contralateral) and Standardized index site (surgical) was also checked"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.3 Flag 39:
Check if DMA was performed on some sites and completion status for Standardized control site (contralateral) and Standardized index site (surgical) was not specified.
<- m2dma.baseline %>%
m2qerror39 filter(
== 2 &
(dmatestcompyn == 0 &
dmatestcompwhich___1 == 0) |
dmatestcompwhich___2 == 2 &
(dmatestcompyn == 0 &
dmatestcompwhich___1 == 0)
dmatestcompwhich___2 %>%
) add_column(
error_type = "DMA:DMA was performed on some sites and completion status for Standardized control site (contralateral) and Standardized index site (surgical) was not specified"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.4 Flag 40:
Check for mismatch in or missing pain data for Standardized control site (contralateral).
Repetition 1
<- m2dma.baseline %>%
m2qerror40 filter(
== 1 | (dmatestcompyn == 2 & dmatestcompwhich___1 == 1)
dmatestcompyn %>%
) mutate(dma_stand_cont_diff1 = dmacontr1pain - dmacontr1pain_d) %>%
filter(dma_stand_cont_diff1 != 0 | is.na(dma_stand_cont_diff1)) %>%
add_column(
error_type = "DMA: Repetition 1-Mismatch or missing pain data for standardized control site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.5 Flag 41:
Repetition 2
<- m2dma.baseline %>%
m2qerror41 filter(
== 1 | (dmatestcompyn == 2 & dmatestcompwhich___1 == 1)
dmatestcompyn %>%
) mutate(dma_stand_cont_diff2 = dmacontr2pain - dmacontr2pain_d) %>%
filter(dma_stand_cont_diff2 != 0 | is.na(dma_stand_cont_diff2)) %>%
add_column(
error_type = "DMA: Repetition 2-Mismatch or missing pain data for standardized control site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.6 Flag 42:
Repetition 3
<- m2dma.baseline %>%
m2qerror42 filter(
== 1 | (dmatestcompyn == 2 & dmatestcompwhich___1 == 1)
dmatestcompyn %>%
) mutate(dma_stand_cont_diff3 = dmacontr3pain - dmacontr3pain_d) %>%
filter(dma_stand_cont_diff3 != 0 | is.na(dma_stand_cont_diff3)) %>%
add_column(
error_type = "DMA: Repetition 3-Mismatch or missing pain data for standardized control site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.7 Flag 43:
Repetition 4
<- m2dma.baseline %>%
m2qerror43 filter(
== 1 | (dmatestcompyn == 2 & dmatestcompwhich___1 == 1)
dmatestcompyn %>%
) mutate(dma_stand_cont_diff4 = dmacontr4pain - dmacontr4pain_d) %>%
filter(dma_stand_cont_diff4 != 0 | is.na(dma_stand_cont_diff4)) %>%
add_column(
error_type = "DMA: Repetition 4-Mismatch or missing pain data for standardized control site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.8 Flag 44:
Repetition 5
<- m2dma.baseline %>%
m2qerror44 filter(
== 1 | (dmatestcompyn == 2 & dmatestcompwhich___1 == 1)
dmatestcompyn %>%
) mutate(dma_stand_cont_diff5 = dmacontr5pain - dmacontr5pain_d) %>%
filter(dma_stand_cont_diff5 != 0 | is.na(dma_stand_cont_diff5)) %>%
add_column(
error_type = "DMA: Repetition 5-Mismatch or missing pain data for standardized control site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.9 Flag 45:
Check for mismatch or missing pain data for standardized index site
Repetition 1
<- m2dma.baseline %>%
m2qerror45 filter(
== 1 | (dmatestcompyn == 2 & dmatestcompwhich___2 == 1)
dmatestcompyn %>%
) mutate(dma_stand_ind_diff1 = dmaindxr1pain - dmaindxr1pain_d) %>%
filter(dma_stand_ind_diff1 != 0 | is.na(dma_stand_ind_diff1)) %>%
add_column(
error_type = "DMA: Repetition 1-Mismatch or missing pain data for standardized index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.10 Flag 46:
Repetition 2
<- m2dma.baseline %>%
m2qerror46 filter(
== 1 | (dmatestcompyn == 2 & dmatestcompwhich___2 == 1)
dmatestcompyn %>%
) mutate(dma_stand_ind_diff2 = dmaindxr2pain - dmaindxr2pain_d) %>%
filter(dma_stand_ind_diff2 != 0 | is.na(dma_stand_ind_diff2)) %>%
add_column(
error_type = "DMA: Repetition 2-Mismatch or missing pain data for standardized index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.11 Flag 47:
Repetition 3
<- m2dma.baseline %>%
m2qerror47 filter(
== 1 | (dmatestcompyn == 2 & dmatestcompwhich___2 == 1)
dmatestcompyn %>%
) mutate(dma_stand_ind_diff3 = dmaindxr3pain - dmaindxr3pain_d) %>%
filter(dma_stand_ind_diff3 != 0 | is.na(dma_stand_ind_diff3)) %>%
add_column(
error_type = "DMA: Repetition 3-Mismatch or missing pain data for standardized index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.12 Flag 48:
Repetition 4
<- m2dma.baseline %>%
m2qerror48 filter(
== 1 | (dmatestcompyn == 2 & dmatestcompwhich___2 == 1)
dmatestcompyn %>%
) mutate(dma_stand_ind_diff4 = dmaindxr4pain - dmaindxr4pain_d) %>%
filter(dma_stand_ind_diff4 != 0 | is.na(dma_stand_ind_diff4)) %>%
add_column(
error_type = "DMA: Repetition 4-Mismatch or missing pain data for standardized index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.13 Flag 49:
Repetition 5
<- m2dma.baseline %>%
m2qerror49 filter(
== 1 | (dmatestcompyn == 2 & dmatestcompwhich___2 == 1)
dmatestcompyn %>%
) mutate(dma_stand_ind_diff5 = dmaindxr5pain - dmaindxr5pain_d) %>%
filter(dma_stand_ind_diff5 != 0 | is.na(dma_stand_ind_diff5)) %>%
add_column(
error_type = "DMA: Repetition 5-Mismatch or missing pain data for standardized index site"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.14 Flag 50:
Check if both sites were tested and standardized site comparison was not entered
<- m2dma.baseline %>%
m2qerror50 filter(dmatestcompyn == 1 & is.na(dmasenscompare)) %>%
add_column(
error_type = "If both sites were tested and standardized site comparison was not entered"
%>%
) add_column(errors = "error") %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
error_type,
errors )
H.2.12.0.15 QST Biomarkers
H.2.12.0.15.1 PPT Biomarkers:
Mean PPT values at the index site = primary data point (A2CPS: Site Manual of Procedures v3.0, pg. 154).
<- qdatam2 %>%
primary_ppt_thor filter((pptcompleteyn == 1 | pptcompleteyn == 3)) %>%
rowwise() %>%
mutate(mean1 = mean(c(pptindxr1val, pptindxr2val, pptindxr3val))) %>%
rename(primary_ppt_thor = mean1) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
primary_ppt_thor )
Mean PPT values at the remote site = secondary data point (A2CPS: Site Manual of Procedures v3.0, pg. 154).
<- qdatam2 %>%
secondary_ppt_thor filter((pptcompleteyn == 1 | pptcompleteyn == 2)) %>%
rowwise() %>%
mutate(mean2 = mean(c(pptremoter1val, pptremoter2val, pptremoter3val))) %>%
rename(secondary_ppt_thor = mean2) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
secondary_ppt_thor )
H.2.12.0.15.2 TS Biomarkers:
Primary outcome: Mean of 3 MTS Difference scores computed (Max – initial), (A2CPS: Site Manual of Procedures v3.0, pg. 156). This is conditional on having 3 repetitions.
Primary outcome for the Index site.
<- m2tr.complete %>%
primary_ts_index_thor filter(tscompleted == 1 | tscompleted == 3) %>%
mutate(max.rep1.index = pmax(tsindxr1final, tsindxr1initial)) %>%
mutate(diff.rep1.index = max.rep1.index - tsindxr1initial) %>%
mutate(max.rep2.index = pmax(tsindxr2final, tsindxr2initial)) %>%
mutate(diff.rep2.index = max.rep2.index - tsindxr2initial) %>%
mutate(max.rep3.index = pmax(tsindxr3final, tsindxr3initial)) %>%
mutate(diff.rep3.index = max.rep3.index - tsindxr3initial) %>%
mutate(diff.rep1.index = as.numeric(diff.rep1.index)) %>%
mutate(diff.rep2.index = as.numeric(diff.rep2.index)) %>%
mutate(diff.rep3.index = as.numeric(diff.rep3.index)) %>%
rowwise() %>%
mutate(
mean.index = mean(c(diff.rep1.index, diff.rep2.index, diff.rep3.index))
%>%
) rename(primary_ts_index_thor = mean.index) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
primary_ts_index_thor )
Primary outcome for the Remote site.
<- m2tr.complete %>%
primary_ts_remote_thor filter(tscompleted == 1 | tscompleted == 2) %>%
mutate(max.rep1.remote = pmax(tsremoter1initial, tsremoter1final)) %>%
mutate(diff.rep1.remote = max.rep1.remote - tsremoter1initial) %>%
mutate(max.rep2.remote = pmax(tsremoter2initial, tsremoter2final)) %>%
mutate(diff.rep2.remote = max.rep2.remote - tsremoter2initial) %>%
mutate(max.rep3.remote = pmax(tsremoter3initial, tsremoter3final)) %>%
mutate(diff.rep3.remote = max.rep3.remote - tsremoter3initial) %>%
mutate(diff.rep1.remote = as.numeric(diff.rep1.remote)) %>%
mutate(diff.rep2.remote = as.numeric(diff.rep2.remote)) %>%
mutate(diff.rep3.remote = as.numeric(diff.rep3.remote)) %>%
rowwise() %>%
mutate(
mean.remote = mean(c(diff.rep1.remote, diff.rep2.remote, diff.rep3.remote))
%>%
) rename(primary_ts_remote_thor = mean.remote) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
primary_ts_remote_thor )
Secondary outcome: Mean of 3 Wind-up ratios (WUR) computed ([Max +1]/ [initial +1]). (1 added to handle possibility of zero initial pain rating in denominator). (A2CPS: Site Manual of Procedures v3.0, pg. 156). This is conditional on having 3 repetitions, if a record has < 3 repetitions, it will be flagged
Secondary outcome for the index site
<- m2tr.complete %>%
secondary_ts_index_thor filter(tscompleted == 1 | tscompleted == 3) %>%
mutate(max.rep1.index1 = 1 + (pmax(tsindxr1final, tsindxr1initial))) %>%
mutate(init.rep1.index1 = 1 + (tsindxr1initial)) %>%
mutate(div.rep1.index1 = max.rep1.index1 / init.rep1.index1) %>%
mutate(max.rep2.index1 = 1 + (pmax(tsindxr2final, tsindxr2initial))) %>%
mutate(init.rep2.index1 = 1 + (tsindxr2initial)) %>%
mutate(div.rep2.index1 = max.rep2.index1 / init.rep2.index1) %>%
mutate(max.rep3.index1 = 1 + (pmax(tsindxr3final, tsindxr3initial))) %>%
mutate(init.rep3.index1 = 1 + (tsindxr3initial)) %>%
mutate(div.rep3.index1 = max.rep3.index1 / init.rep3.index1) %>%
rowwise() %>%
mutate(
mean.sec.index = mean(c(div.rep1.index1, div.rep2.index1, div.rep3.index1))
%>%
) rename(secondary_ts_index_thor = mean.sec.index) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
secondary_ts_index_thor )
Secondary outcome for the Remote site.
<- m2tr.complete %>%
secondary_ts_remote_thor filter(tscompleted == 1 | tscompleted == 2) %>%
mutate(max.rep1.remote1 = 1 + (pmax(tsremoter1initial, tsremoter1final))) %>%
mutate(init.rep1.remote1 = 1 + (tsremoter1initial)) %>%
mutate(div.rep1.remote1 = max.rep1.remote1 / init.rep1.remote1) %>%
mutate(max.rep2.remote1 = 1 + (pmax(tsremoter2initial, tsremoter2final))) %>%
mutate(init.rep2.remote1 = 1 + (tsremoter2initial)) %>%
mutate(div.rep2.remote1 = max.rep2.remote1 / init.rep2.remote1) %>%
mutate(max.rep3.remote1 = 1 + (pmax(tsremoter3initial, tsremoter3final))) %>%
mutate(init.rep3.remote1 = 1 + (tsremoter3initial)) %>%
mutate(div.rep3.remote1 = max.rep3.remote1 / init.rep3.remote1) %>%
rowwise() %>%
mutate(
mean.sec.remote = mean(c(
div.rep1.remote1,
div.rep2.remote1,
div.rep3.remote1
))%>%
) rename(secondary_ts_remote_thor = mean.sec.remote) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
secondary_ts_remote_thor )
H.2.12.0.15.3 CPM Biomarkers:
Primary outcome (A2CPS: Site Manual of Procedures v3.0, pg. 159) i.e. [(pre hand immersion PPT-post immersion PPT)/pre immersion PPT] *100
<- m2trcpm.complete %>%
primary_cpm_thor filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
rowwise() %>%
mutate(mean_pre = mean(c(pptremoter1val, pptremoter2val, pptremoter3val))) %>%
rowwise() %>%
mutate(
mean_post = mean(c(cpmpptremr1val, cpmpptremr2val, cpmpptremr3val))
%>%
) mutate(cpm_change = ((mean_pre - mean_post) / mean_pre) * 100) %>%
rename(primary_cpm_thor = cpm_change) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
primary_cpm_thor )
Secondary outcome (A2CPS: Site Manual of Procedures v3.0, pg. 159) i.e. CPM difference score computed as pre hand immersion PPT-post immersion PPT
<- m2trcpm.complete %>%
secondary_cpm_thor filter(pptcompleteyn == 1 | pptcompleteyn == 2) %>%
rowwise() %>%
mutate(mean_pre = mean(c(pptremoter1val, pptremoter2val, pptremoter3val))) %>%
rowwise() %>%
mutate(
mean_post = mean(c(cpmpptremr1val, cpmpptremr2val, cpmpptremr3val))
%>%
) mutate(cpm_diff = mean_pre - mean_post) %>%
rename(secondary_cpm_thor = cpm_diff) %>%
select(
record_id,
redcap_data_access_group,
redcap_repeat_instrument,
redcap_repeat_instance,
secondary_cpm_thor )
Merge computed biomarkers to the “thor_qst” dataset:
<- left_join(
thor_qst
thor_qst,
primary_ppt_thor,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
secondary_ppt_thor,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
primary_ts_index_thor,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
primary_ts_remote_thor,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
secondary_ts_index_thor,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
secondary_ts_remote_thor,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
primary_cpm_thor,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
)%>%
) left_join(
.,
secondary_cpm_thor,by = c(
"record_id",
"redcap_data_access_group",
"redcap_repeat_instrument",
"redcap_repeat_instance"
) )
H.2.12.0.16 New field name(s):
Add field names for the computed biomarkers to the QST data dictionary
# Create field names
<- data.frame(
primary_ppt_thor_new_row field_name = "primary_ppt_thor",
field_type = "numeric",
field_note = "PPT primary biomarker:thor "
)
<- data.frame(
secondary_ppt_thor_new_row field_name = "secondary_ppt_thor",
field_type = "numeric",
field_note = "PPT secondary biomarker:thoracic "
)
<- data.frame(
primary_ts_index_thor_new_row field_name = "primary_ts_index_thor",
field_type = "numeric",
field_note = "TS primary biomarker for the index site:thoracic "
)
<- data.frame(
primary_ts_remote_thor_new_row field_name = "primary_ts_remote_thor",
field_type = "numeric",
field_note = "TS primary biomarker for the remote site:thoracic "
)
<- data.frame(
secondary_ts_index_thor_new_row field_name = "secondary_ts_index_thor",
field_type = "numeric",
field_note = "TS secondary biomarker for the index site:thoracic "
)
<- data.frame(
secondary_ts_remote_thor_new_row field_name = "secondary_ts_remote_thor",
field_type = "numeric",
field_note = "TS secondary biomarker for the remote site:thoracic "
)
<- data.frame(
primary_cpm_thor_new_row field_name = "primary_cpm_thor",
field_type = "numeric",
field_note = "CPM primary biomarker:thoracic "
)
<- data.frame(
secondary_cpm_thor_new_row field_name = "secondary_cpm_thor",
field_type = "numeric",
field_note = "CPM secondary biomarker:thoracic "
)
# Add the new row after the last row
<- qst_dict %>%
qst_dict slice(1:nrow(.)) %>%
add_row(.after = nrow(.), !!!primary_ppt_thor_new_row) %>%
add_row(.after = nrow(.), !!!secondary_ppt_thor_new_row) %>%
add_row(.after = nrow(.), !!!primary_ts_index_thor_new_row) %>%
add_row(.after = nrow(.), !!!primary_ts_remote_thor_new_row) %>%
add_row(.after = nrow(.), !!!secondary_ts_index_thor_new_row) %>%
add_row(.after = nrow(.), !!!secondary_ts_remote_thor_new_row) %>%
add_row(.after = nrow(.), !!!primary_cpm_thor_new_row) %>%
add_row(.after = nrow(.), !!!secondary_cpm_thor_new_row)
H.2.12.0.17 Create QST error report for the Thoracotomy cohort.
# Specify the common prefix
<- "m2qerror"
m2qst_error
# Find data frames in the global environment with the specified prefix
<- mget(ls(pattern = paste0("^", m2qst_error)))
m2qst_list
# Combine the data frames using bind_rows
<- bind_rows(m2qst_list) %>%
m2qst_report as_tibble() %>%
mutate_all(as.character) %>%
pivot_wider(names_from = "error_type", values_from = "errors") %>%
mutate_all(~ replace_na(., ""))
%>%
m2qst_report gt() %>%
tab_header(
title = md("**Thoracotomy Cohort QST form Error Report**")
%>%
) tab_options(
table.font.size = px(12),
column_labels.font.size = px(12)
%>%
) tab_style(
style = list(cell_fill(color = "#F4F4F4")),
locations = cells_body(columns = record_id)
)
Thoracotomy Cohort QST form Error Report | |||||||
---|---|---|---|---|---|---|---|
record_id | redcap_data_access_group | redcap_repeat_instrument | redcap_repeat_instance | TS: Not enough information was available to compute primary outcome for the index site | TS: Not enough information was available to compute primary outcome for the remote site | TS: Not enough information was available to compute secondary outcome for the index site | CPM: Water temperature not checked |
20108 | spectrum_health | qst_mcc1_v03 | 1 | error | error | error | |
20133 | university_of_mich | qst_mcc1_v03 | 1 | error | error | ||
20337 | university_of_mich | qst_mcc1_v03 | 1 | error | error | ||
20028 | university_of_mich | qst_mcc1_v03 | 1 | error | |||
20054 | university_of_mich | qst_mcc1_v03 | 1 | error | |||
20144 | university_of_mich | qst_mcc1_v03 | 2 | error |
H.2.12.0.18 Save:
Save “thor_qst” and data dictionary as .csv files in the folder named “reformatted_QST”
write_csv(
thor_qst,file = here::here("data", "qst", "Reformatted", "reformatted_thor_qst.csv")
)
write_csv(
qst_dict,file = here::here("data", "qst", "Reformatted", "updated_qst_dict.csv")
)