From e752ec3fc02da68f961d03edc3b9e1b93dc732e6 Mon Sep 17 00:00:00 2001 From: Samantha Emerson Date: Fri, 11 Dec 2020 17:05:52 -0500 Subject: [PATCH 1/6] Fix ftld fvp builder to take followup Z1X instead of initial --- nacc/ftld/fvp/builder.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nacc/ftld/fvp/builder.py b/nacc/ftld/fvp/builder.py index 4a69ca1..aa0dbcf 100644 --- a/nacc/ftld/fvp/builder.py +++ b/nacc/ftld/fvp/builder.py @@ -27,19 +27,19 @@ def build_ftld_fvp_form(record: dict, err=sys.stderr): # Forms B3F, B9F, C1F, C2F, C3F, E2F, and E3F are REQUIRED. # Forms A3A, C4F, C5F, and C6F are OPTIONAL and must be specifically # marked as present for nacculator to process them - if record['ivp_z1x_complete'] in ['1', '2']: - if record['ftda3afs'] == '1': + if record['fvp_z1x_complete'] in ['1', '2']: + if record['fu_ftda3afs'] == '1': add_a3a(record, packet) add_b3f(record, packet) add_b9f(record, packet) add_c1f(record, packet) add_c2f(record, packet) add_c3f(record, packet) - if record['ftdc4fs'] == '1': + if record['fu_ftdc4fs'] == '1': add_c4f(record, packet) - if record['ftdc5fs'] == '1': + if record['fu_ftdc5fs'] == '1': add_c5f(record, packet) - if record['ftdc6fs'] == '1': + if record['fu_ftdc6fs'] == '1': add_c6f(record, packet) else: print("ptid " + str(record['ptid']) + From 00aa177d5aeb1ba00645138f7a33b85248e43675 Mon Sep 17 00:00:00 2001 From: Samantha Emerson Date: Tue, 15 Dec 2020 15:21:10 -0500 Subject: [PATCH 2/6] Make all optional UDS3 forms optional in REDCap project --- nacc/redcap2nacc.py | 2 + nacc/uds3/fvp/builder.py | 98 ++++++++++++++++++++++++++++------------ nacc/uds3/ivp/builder.py | 98 ++++++++++++++++++++++++++++------------ 3 files changed, 142 insertions(+), 56 deletions(-) diff --git a/nacc/redcap2nacc.py b/nacc/redcap2nacc.py index 68c47cc..066acaa 100755 --- a/nacc/redcap2nacc.py +++ b/nacc/redcap2nacc.py @@ -198,6 +198,7 @@ def check_redcap_event(options, record) -> bool: form_match_z1 = record['ivp_z1_complete'] except KeyError: form_match_z1 = '' + record['ivp_z1_complete'] = '' form_match_z1x = record['ivp_z1x_complete'] if form_match_z1 in ['0', ''] and form_match_z1x in ['0', '']: return False @@ -207,6 +208,7 @@ def check_redcap_event(options, record) -> bool: form_match_z1 = record['fvp_z1_complete'] except KeyError: form_match_z1 = '' + record['ivp_z1_complete'] = '' form_match_z1x = record['fvp_z1x_complete'] if form_match_z1 in ['0', ''] and form_match_z1x in ['0', '']: return False diff --git a/nacc/uds3/fvp/builder.py b/nacc/uds3/fvp/builder.py index 1e95f79..de4dad8 100644 --- a/nacc/uds3/fvp/builder.py +++ b/nacc/uds3/fvp/builder.py @@ -19,37 +19,79 @@ def build_uds3_fvp_form(record, err=sys.stderr): add_z1_or_z1x(record, packet) add_a1(record, packet) if record['fvp_z1x_complete'] in ['1', '2']: - if record['fu_a2sub'] == '1': - add_a2(record, packet) - if record['fu_a3sub'] == '1': - add_a3(record, packet) - if record['fu_a4sub'] == '1': - add_a4(record, packet) - if record['fu_b1sub'] == '1': - add_b1(record, packet) + try: + if record['fu_a2sub'] == '1': + add_a2(record, packet) + except KeyError: + pass + try: + if record['fu_a3sub'] == '1': + add_a3(record, packet) + except KeyError: + print("KeyError in A3", file=err) + try: + if record['fu_a4sub'] == '1': + add_a4(record, packet) + except KeyError: + pass + try: + if record['fu_b1sub'] == '1': + add_b1(record, packet) + except KeyError: + pass add_b4(record, packet) - if record['fu_b5sub'] == '1': - add_b5(record, packet) - if record['fu_b6sub'] == '1': - add_b6(record, packet) - if record['fu_b7sub'] == '1': - add_b7(record, packet) + try: + if record['fu_b5sub'] == '1': + add_b5(record, packet) + except KeyError: + pass + try: + if record['fu_b6sub'] == '1': + add_b6(record, packet) + except KeyError: + pass + try: + if record['fu_b7sub'] == '1': + add_b7(record, packet) + except KeyError: + pass elif record['fvp_z1_complete'] in ['1', '2']: - if record['fu_a2_sub'] == '1': - add_a2(record, packet) - if record['fu_a3_sub'] == '1': - add_a3(record, packet) - if record['fu_a4_sub'] == '1': - add_a4(record, packet) - if record['fu_b1_sub'] == '1': - add_b1(record, packet) + try: + if record['fu_a2_sub'] == '1': + add_a2(record, packet) + except KeyError: + pass + try: + if record['fu_a3_sub'] == '1': + add_a3(record, packet) + except KeyError: + pass + try: + if record['fu_a4_sub'] == '1': + add_a4(record, packet) + except KeyError: + pass + try: + if record['fu_b1_sub'] == '1': + add_b1(record, packet) + except KeyError: + pass add_b4(record, packet) - if record['fu_b5_sub'] == '1': - add_b5(record, packet) - if record['fu_b6_sub'] == '1': - add_b6(record, packet) - if record['fu_b7_sub'] == '1': - add_b7(record, packet) + try: + if record['fu_b5_sub'] == '1': + add_b5(record, packet) + except KeyError: + pass + try: + if record['fu_b6_sub'] == '1': + add_b6(record, packet) + except KeyError: + pass + try: + if record['fu_b7_sub'] == '1': + add_b7(record, packet) + except KeyError: + pass else: print("ptid " + str(record['ptid']) + ": No Z1X or Z1 form found.", file=err) diff --git a/nacc/uds3/ivp/builder.py b/nacc/uds3/ivp/builder.py index 3dc977a..f433595 100644 --- a/nacc/uds3/ivp/builder.py +++ b/nacc/uds3/ivp/builder.py @@ -19,39 +19,81 @@ def build_uds3_ivp_form(record, err=sys.stderr): add_z1_or_z1x(record, packet) add_a1(record, packet) if record['ivp_z1x_complete'] in ['1', '2']: - if record['a2sub'] == '1': - add_a2(record, packet) - if record['a3sub'] == '1': - add_a3(record, packet) - if record['a4sub'] == '1': - add_a4(record, packet) + try: + if record['a2sub'] == '1': + add_a2(record, packet) + except KeyError: + pass + try: + if record['a3sub'] == '1': + add_a3(record, packet) + except KeyError: + pass + try: + if record['a4sub'] == '1': + add_a4(record, packet) + except KeyError: + pass add_a5(record, packet) - if record['b1sub'] == '1': - add_b1(record, packet) + try: + if record['b1sub'] == '1': + add_b1(record, packet) + except KeyError: + pass add_b4(record, packet) - if record['b5sub'] == '1': - add_b5(record, packet) - if record['b6sub'] == '1': - add_b6(record, packet) - if record['b7sub'] == '1': - add_b7(record, packet) + try: + if record['b5sub'] == '1': + add_b5(record, packet) + except KeyError: + pass + try: + if record['b6sub'] == '1': + add_b6(record, packet) + except KeyError: + pass + try: + if record['b7sub'] == '1': + add_b7(record, packet) + except KeyError: + pass elif record['ivp_z1_complete'] in ['1', '2']: - if record['a2_sub'] == '1': - add_a2(record, packet) - if record['a3_sub'] == '1': - add_a3(record, packet) - if record['a4_sub'] == '1': - add_a4(record, packet) + try: + if record['a2_sub'] == '1': + add_a2(record, packet) + except KeyError: + pass + try: + if record['a3_sub'] == '1': + add_a3(record, packet) + except KeyError: + pass + try: + if record['a4_sub'] == '1': + add_a4(record, packet) + except KeyError: + pass add_a5(record, packet) - if record['b1_sub'] == '1': - add_b1(record, packet) + try: + if record['b1_sub'] == '1': + add_b1(record, packet) + except KeyError: + pass add_b4(record, packet) - if record['b5_sub'] == '1': - add_b5(record, packet) - if record['b6_sub'] == '1': - add_b6(record, packet) - if record['b7_sub'] == '1': - add_b7(record, packet) + try: + if record['b5_sub'] == '1': + add_b5(record, packet) + except KeyError: + pass + try: + if record['b6_sub'] == '1': + add_b6(record, packet) + except KeyError: + pass + try: + if record['b7_sub'] == '1': + add_b7(record, packet) + except KeyError: + pass else: print("ptid " + str(record['ptid']) + ": No Z1X or Z1 form found.", file=err) From 115f6c59a0cfd933109957e64fda531ab3ed6d89 Mon Sep 17 00:00:00 2001 From: Samantha Emerson Date: Tue, 15 Dec 2020 15:23:34 -0500 Subject: [PATCH 3/6] Make optional forms for FTLD optional in REDCap project --- nacc/ftld/fvp/builder.py | 28 ++++++++++++++++++++-------- nacc/ftld/ivp/builder.py | 28 ++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/nacc/ftld/fvp/builder.py b/nacc/ftld/fvp/builder.py index aa0dbcf..2e0166c 100644 --- a/nacc/ftld/fvp/builder.py +++ b/nacc/ftld/fvp/builder.py @@ -28,19 +28,31 @@ def build_ftld_fvp_form(record: dict, err=sys.stderr): # Forms A3A, C4F, C5F, and C6F are OPTIONAL and must be specifically # marked as present for nacculator to process them if record['fvp_z1x_complete'] in ['1', '2']: - if record['fu_ftda3afs'] == '1': - add_a3a(record, packet) + try: + if record['fu_ftda3afs'] == '1': + add_a3a(record, packet) + except KeyError: + pass add_b3f(record, packet) add_b9f(record, packet) add_c1f(record, packet) add_c2f(record, packet) add_c3f(record, packet) - if record['fu_ftdc4fs'] == '1': - add_c4f(record, packet) - if record['fu_ftdc5fs'] == '1': - add_c5f(record, packet) - if record['fu_ftdc6fs'] == '1': - add_c6f(record, packet) + try: + if record['fu_ftdc4fs'] == '1': + add_c4f(record, packet) + except KeyError: + pass + try: + if record['fu_ftdc5fs'] == '1': + add_c5f(record, packet) + except KeyError: + pass + try: + if record['fu_ftdc6fs'] == '1': + add_c6f(record, packet) + except KeyError: + pass else: print("ptid " + str(record['ptid']) + ": No Z1X form found.", file=err) diff --git a/nacc/ftld/ivp/builder.py b/nacc/ftld/ivp/builder.py index b04ec96..6424265 100644 --- a/nacc/ftld/ivp/builder.py +++ b/nacc/ftld/ivp/builder.py @@ -28,19 +28,31 @@ def build_ftld_ivp_form(record: dict, err=sys.stderr): # Forms A3A, C4F, C5F, and C6F are OPTIONAL and must be specifically # marked as present for nacculator to process them if record['ivp_z1x_complete'] in ['1', '2']: - if record['ftda3afs'] == '1': - add_a3a(record, packet) + try: + if record['ftda3afs'] == '1': + add_a3a(record, packet) + except KeyError: + pass add_b3f(record, packet) add_b9f(record, packet) add_c1f(record, packet) add_c2f(record, packet) add_c3f(record, packet) - if record['ftdc4fs'] == '1': - add_c4f(record, packet) - if record['ftdc5fs'] == '1': - add_c5f(record, packet) - if record['ftdc6fs'] == '1': - add_c6f(record, packet) + try: + if record['ftdc4fs'] == '1': + add_c4f(record, packet) + except KeyError: + pass + try: + if record['ftdc5fs'] == '1': + add_c5f(record, packet) + except KeyError: + pass + try: + if record['ftdc6fs'] == '1': + add_c6f(record, packet) + except KeyError: + pass else: print("ptid " + str(record['ptid']) + ": No Z1X form found.", file=err) From 2ba0450f454a2d70e074bd76f4b67b628dd24140 Mon Sep 17 00:00:00 2001 From: Samantha Emerson Date: Tue, 15 Dec 2020 15:25:37 -0500 Subject: [PATCH 4/6] Update README to account for cappy install complication --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f863219..295ca7b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ HOW TO Convert from REDCap to NACC To install NACCulator, run: + $ python3 -m pip install git+https://github.com/ctsit/cappy.git@2.0.0#egg=cappy-2.0.0 $ pip3 install git+https://github.com/ctsit/nacculator.git Once the project data is exported from REDCap to the CSV file `data.csv`, run: From cfb887cdb10cf0b6bd0491cc864d2a9f931bf783 Mon Sep 17 00:00:00 2001 From: Samantha Emerson Date: Tue, 15 Dec 2020 16:45:33 -0500 Subject: [PATCH 5/6] Fix cruft in FVP builder --- nacc/uds3/fvp/builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nacc/uds3/fvp/builder.py b/nacc/uds3/fvp/builder.py index de4dad8..52a8224 100644 --- a/nacc/uds3/fvp/builder.py +++ b/nacc/uds3/fvp/builder.py @@ -28,7 +28,7 @@ def build_uds3_fvp_form(record, err=sys.stderr): if record['fu_a3sub'] == '1': add_a3(record, packet) except KeyError: - print("KeyError in A3", file=err) + pass try: if record['fu_a4sub'] == '1': add_a4(record, packet) From 75dbdb39080af69c50c50a16f1cb42aa1fc49501 Mon Sep 17 00:00:00 2001 From: Kevin Hanson Date: Tue, 15 Dec 2020 17:05:26 -0500 Subject: [PATCH 6/6] update CHANGELOG and setup.py for release 1.6.0 --- CHANGELOG | 21 +++++++++++++++++++++ setup.py | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index c45d1d0..d7491eb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,26 @@ Changelog ========= +## [1.6.0] - 2020-12-15 +### Summary +This change was implemented after getting feedback from OHSU. Some ADRCs do +not have the optional forms like A2 or A3 in their REDCap project at all, since +they will not be used for that center. NACCulator used to run with the +requirement that all forms be present in a REDCap project, whether they were +optional or not. This change is very similar to the one made previously that +made the CLS, Z1, and C1 forms optional for the REDCap csv input. +I also fixed a bug in the FTLD FVP builder that would cause it to look for the +IVP Z1X form. + +### added + * Make optional forms for FTLD optional in REDCap project + * Make all optional UDS3 forms optional in REDCap project + + +### changed +* Fix cruft in FVP builder (Samantha Emerson) +* Update README to account for cappy install complication +* Fix ftld fvp builder to take followup Z1X instead of initial + ## [1.5.0] - 2020-12-08 ### Summary diff --git a/setup.py b/setup.py index 8dc73df..11ce025 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools import setup, find_packages -VERSION = "1.5.0" +VERSION = "1.6.0" setup( name="nacculator",