diff --git a/CHANGELOG b/CHANGELOG index 05e2c19..7ba1f17 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,16 @@ Changelog ========= +## [1.8.1] - 2021-11-04 +### Summary +This release provides one major bug fix in the FTLD follow-up packet, updated +installation instructions, and a few minor fixes for bugs in error logging +etc. + +### Updated + * Fix cappy install instructions in README + * Update FTLD FVP Z1X with fixed column spacing + + ## [1.8.0] - 2021-09-13 ### Summary diff --git a/README.md b/README.md index 23b97ab..5460b10 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,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 + $ python3 -m pip install git+https://github.com/ctsit/cappy.git@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: @@ -59,7 +59,7 @@ the `-file` flag._ [-lbd | -ftld] [-file FILE] [-meta FILTER_META] [-ptid PTID] [-vnum VNUM] [-vtype VTYPE] - Process redcap form output to nacculator. + Process redcap export data through nacculator. optional arguments: -h, --help show this help message and exit diff --git a/nacc/ftld/fvp/builder.py b/nacc/ftld/fvp/builder.py index 4dd39ee..5d8afb1 100644 --- a/nacc/ftld/fvp/builder.py +++ b/nacc/ftld/fvp/builder.py @@ -124,12 +124,12 @@ def add_z1x(record, packet): Z1X.B6LNOT = record['fu_b6lnot'] except KeyError: try: - if record['fu_lbudspch'] is not None: - Z1X.B2LSUB = '1' - Z1X.B2LNOT = '' - if record['fu_lbspcgim'] is not None: + if record['fu_lbudspch'] in ['0', '1']: Z1X.B2LSUB = '1' Z1X.B2LNOT = '' + if record['fu_lbspcgim'] in ['0', '1']: + Z1X.B6LSUB = '1' + Z1X.B6LNOT = '' # And leave the LBD fields blank if the project does not contain the # LBD module except KeyError: diff --git a/nacc/ftld/fvp/forms.py b/nacc/ftld/fvp/forms.py index 9a15a56..5aefe4a 100644 --- a/nacc/ftld/fvp/forms.py +++ b/nacc/ftld/fvp/forms.py @@ -46,21 +46,22 @@ def __init__(self): self.fields['LANGA4'] = nacc.uds3.Field(name='LANGA4', typename='Num', position=(61, 61), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=['Blank if Question 4b A4SUB = 0 (No)']) self.fields['A4SUB'] = nacc.uds3.Field(name='A4SUB', typename='Num', position=(63, 63), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) self.fields['A4NOT'] = nacc.uds3.Field(name='A4NOT', typename='Num', position=(65, 66), length=2, inclusive_range=None, allowable_values=['95', '96', '97', '98'], blanks=['Blank if Question 4b A4SUB = 1 (Yes)']) - self.fields['LANGB1'] = nacc.uds3.Field(name='LANGB1', typename='Num', position=(70, 70), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=['Blank if Question 6b B1SUB = 0 (No)']) - self.fields['B1SUB'] = nacc.uds3.Field(name='B1SUB', typename='Num', position=(72, 72), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) - self.fields['B1NOT'] = nacc.uds3.Field(name='B1NOT', typename='Num', position=(74, 75), length=2, inclusive_range=None, allowable_values=['95', '96', '97', '98'], blanks=['Blank if Question 6b B1SUB = 1 (Yes)']) - self.fields['LANGB4'] = nacc.uds3.Field(name='LANGB4', typename='Num', position=(77, 77), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=[]) - self.fields['LANGB5'] = nacc.uds3.Field(name='LANGB5', typename='Num', position=(79, 79), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=['Blank if Question 8b B5SUB = 0 (No)']) - self.fields['B5SUB'] = nacc.uds3.Field(name='B5SUB', typename='Num', position=(81, 81), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) - self.fields['B5NOT'] = nacc.uds3.Field(name='B5NOT', typename='Num', position=(83, 84), length=2, inclusive_range=None, allowable_values=['95', '96', '97', '98'], blanks=['Blank if Question 8b B5SUB = 1 (Yes)']) - self.fields['LANGB6'] = nacc.uds3.Field(name='LANGB6', typename='Num', position=(86, 86), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=['Blank if Question 9b B6SUB = 0 (No)']) - self.fields['B6SUB'] = nacc.uds3.Field(name='B6SUB', typename='Num', position=(88, 88), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) - self.fields['B6NOT'] = nacc.uds3.Field(name='B6NOT', typename='Num', position=(90, 91), length=2, inclusive_range=None, allowable_values=['95', '96', '97', '98'], blanks=['Blank if Question 9b B6SUB = 1 (Yes)']) - self.fields['LANGB7'] = nacc.uds3.Field(name='LANGB7', typename='Num', position=(93, 93), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=['Blank if Question 10b B7SUB = 0 (No)']) - self.fields['B7SUB'] = nacc.uds3.Field(name='B7SUB', typename='Num', position=(95, 95), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) - self.fields['B7NOT'] = nacc.uds3.Field(name='B7NOT', typename='Num', position=(97, 98), length=2, inclusive_range=None, allowable_values=['95', '96', '97', '98'], blanks=['Blank if Question 10b B7SUB = 1 (Yes)']) - self.fields['LANGB8'] = nacc.uds3.Field(name='LANGB8', typename='Num', position=(100, 100), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=[]) - self.fields['LANGB9'] = nacc.uds3.Field(name='LANGB9', typename='Num', position=(102, 102), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=[]) + self.fields['LANGB1'] = nacc.uds3.Field(name='LANGB1', typename='Num', position=(68, 68), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=['Blank if Question 6b B1SUB = 0 (No)']) + self.fields['B1SUB'] = nacc.uds3.Field(name='B1SUB', typename='Num', position=(70, 70), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) + self.fields['B1NOT'] = nacc.uds3.Field(name='B1NOT', typename='Num', position=(72, 73), length=2, inclusive_range=None, allowable_values=['95', '96', '97', '98'], blanks=['Blank if Question 6b B1SUB = 1 (Yes)']) + self.fields['LANGB4'] = nacc.uds3.Field(name='LANGB4', typename='Num', position=(75, 75), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=[]) + self.fields['LANGB5'] = nacc.uds3.Field(name='LANGB5', typename='Num', position=(77, 77), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=['Blank if Question 8b B5SUB = 0 (No)']) + self.fields['B5SUB'] = nacc.uds3.Field(name='B5SUB', typename='Num', position=(79, 79), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) + self.fields['B5NOT'] = nacc.uds3.Field(name='B5NOT', typename='Num', position=(81, 82), length=2, inclusive_range=None, allowable_values=['95', '96', '97', '98'], blanks=['Blank if Question 8b B5SUB = 1 (Yes)']) + self.fields['LANGB6'] = nacc.uds3.Field(name='LANGB6', typename='Num', position=(84, 84), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=['Blank if Question 9b B6SUB = 0 (No)']) + self.fields['B6SUB'] = nacc.uds3.Field(name='B6SUB', typename='Num', position=(86, 86), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) + self.fields['B6NOT'] = nacc.uds3.Field(name='B6NOT', typename='Num', position=(88, 89), length=2, inclusive_range=None, allowable_values=['95', '96', '97', '98'], blanks=['Blank if Question 9b B6SUB = 1 (Yes)']) + self.fields['LANGB7'] = nacc.uds3.Field(name='LANGB7', typename='Num', position=(91, 91), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=['Blank if Question 10b B7SUB = 0 (No)']) + self.fields['B7SUB'] = nacc.uds3.Field(name='B7SUB', typename='Num', position=(93, 93), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) + self.fields['B7NOT'] = nacc.uds3.Field(name='B7NOT', typename='Num', position=(95, 96), length=2, inclusive_range=None, allowable_values=['95', '96', '97', '98'], blanks=['Blank if Question 10b B7SUB = 1 (Yes)']) + self.fields['LANGB8'] = nacc.uds3.Field(name='LANGB8', typename='Num', position=(98, 98), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=[]) + self.fields['LANGB9'] = nacc.uds3.Field(name='LANGB9', typename='Num', position=(100, 100), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=[]) + self.fields['LANGC1'] = nacc.uds3.Field(name='LANGC1', typename='Num', position=(102, 102), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) self.fields['LANGC2'] = nacc.uds3.Field(name='LANGC2', typename='Num', position=(104, 104), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=[]) self.fields['LANGD1'] = nacc.uds3.Field(name='LANGD1', typename='Num', position=(106, 106), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=[]) self.fields['LANGD2'] = nacc.uds3.Field(name='LANGD2', typename='Num', position=(108, 108), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=[]) @@ -85,7 +86,6 @@ def __init__(self): self.fields['LANGE3F'] = nacc.uds3.Field(name='LANGE3F', typename='Num', position=(150, 150), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=[]) self.fields['LANGCLS'] = nacc.uds3.Field(name='LANGCLS', typename='Num', position=(152, 152), length=1, inclusive_range=(1, 2), allowable_values=['1', '2'], blanks=['Blank if Question 27b CLSSUB = 0 (No)']) self.fields['CLSSUB'] = nacc.uds3.Field(name='CLSSUB', typename='Num', position=(154, 154), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) - self.fields['CLSSUB'] = nacc.uds3.Field(name='CLSSUB', typename='Num', position=(154, 154), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) self.fields['B2LSUB'] = nacc.uds3.Field(name='B2LSUB', typename='Num', position=(156, 156), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) self.fields['B2LNOT'] = nacc.uds3.Field(name='B2LNOT', typename='Num', position=(158, 159), length=2, inclusive_range=None, allowable_values=['95', '96', '97', '98', '99'], blanks=['Blank if Question 28b B2LSUB = 1 (Yes)']) self.fields['B6LSUB'] = nacc.uds3.Field(name='B6LSUB', typename='Num', position=(161, 161), length=1, inclusive_range=(0, 1), allowable_values=['0', '1'], blanks=[]) diff --git a/nacc/ftld/ivp/builder.py b/nacc/ftld/ivp/builder.py index 61aaaeb..b617691 100644 --- a/nacc/ftld/ivp/builder.py +++ b/nacc/ftld/ivp/builder.py @@ -125,12 +125,12 @@ def add_z1x(record, packet): Z1X.B6LNOT = record['b6lnot'] except KeyError: try: - if record['lbudspch'] is not None: - Z1X.B2LSUB = '1' - Z1X.B2LNOT = '' - if record['lbspcgim'] is not None: + if record['lbudspch'] in ['0', '1']: Z1X.B2LSUB = '1' Z1X.B2LNOT = '' + if record['lbspcgim'] in ['0', '1']: + Z1X.B6LSUB = '1' + Z1X.B6LNOT = '' # And leave the LBD fields blank if the project does not contain the # LBD module except KeyError: diff --git a/nacc/redcap2nacc.py b/nacc/redcap2nacc.py index 983a0f2..94f3009 100755 --- a/nacc/redcap2nacc.py +++ b/nacc/redcap2nacc.py @@ -167,7 +167,7 @@ def check_for_bad_characters(field: Field) -> typing.List: return incompatible -def check_redcap_event(options, record) -> bool: +def check_redcap_event(options, record, out=sys.stdout, err=sys.stderr) -> bool: """ Determines if the record's redcap_event_name and filled forms match the options flag @@ -230,7 +230,7 @@ def check_redcap_event(options, record) -> bool: form_match_z1 = record['fvp_z1_complete'] except KeyError: form_match_z1 = '' - record['ivp_z1_complete'] = '' + record['fvp_z1_complete'] = '' form_match_z1x = record['fvp_z1x_complete'] if form_match_z1 in ['0', ''] and form_match_z1x in ['0', '']: return False @@ -256,7 +256,7 @@ def check_redcap_event(options, record) -> bool: if followup_match in ['', '0']: return False except KeyError: - print("Could not find a REDCap field for TFP Z1X form.") + print("Could not find a REDCap field for TFP Z1X form.", file=err) return False elif options.tfp3: event_name = 'tele' diff --git a/setup.py b/setup.py index dbfff76..15bc630 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools import setup, find_packages -VERSION = "1.8.0" +VERSION = "1.8.1" setup( name="nacculator", diff --git a/tests/test_skip_optional_forms_ftld.py b/tests/test_skip_optional_forms_ftld.py index c484a51..31347da 100644 --- a/tests/test_skip_optional_forms_ftld.py +++ b/tests/test_skip_optional_forms_ftld.py @@ -14,7 +14,7 @@ def test_a3a_ivp_skip(self): expected = record['ftdothis'] result = ivp_builder.build_ftld_ivp_form(record) - self.assertEqual(expected, result['FTDOThIS']) + self.assertEqual(expected, result['FTDOTHIS']) def test_a3a_fvp_skip(self): """ If the FVP A3a is not present in the csv, it should be skipped @@ -24,7 +24,7 @@ def test_a3a_fvp_skip(self): expected = record['fu_ftdothis'] result = fvp_builder.build_ftld_fvp_form(record) - self.assertEqual(expected, result['FTDOThIS']) + self.assertEqual(expected, result['FTDOTHIS']) def test_ivp_b3f_not_skipped(self): """ Form B3F is required and should never be skipped. """