def test_temporal_and_frontal_hierarchy_reversal(self): """ test combined temporal and frontals """ patient = Semiology('Aphasia', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df patient.granular = False inspect_result, _ = patient.query_semiology() hierarchy_df = Hierarchy(inspect_result) hierarchy_df.temporal_hierarchy_reversal() # deafult max option hierarchy_df.frontal_hierarchy_reversal() inspect_result_reversed = hierarchy_df.new_df assert hierarchy_df.frontal_hr.equals(hierarchy_df.new_df) assert inspect_result.all().all() == inspect_result_reversed.all().all( ) assert not hierarchy_df.temporal_hr.equals(hierarchy_df.new_df) # ^ because self.new_df.copy() in the Hierarchy.temporal_hierarchy_reversal() method, so order matters. assert (inspect_result_reversed['TL'].sum() == 3) assert (inspect_result_reversed['Anterior (temporal pole)'].sum() == 5) assert (inspect_result_reversed['Lateral Temporal'].sum() == 0) assert (inspect_result_reversed['ITG'].sum() == 4) assert (inspect_result_reversed['Mesial Temporal'].sum() == 5) assert (inspect_result_reversed['FL'].sum() == 0) assert (inspect_result_reversed['IFG (F3)\n(BA 44,45,47)'].sum() == 1) print('\n10 combined T & F hierarchy reversals\n')
def test_MappingsCalibration_HierarchyReversal_SemioBrainBeta_TLd(self): """ Test the mappings TL for mapping calibration visualisation in the systReview (SemioBrain Database - beta version) i.e. not dummy data """ patient = Semiology('mappings TLd', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.use_SemioBrainBeta_notDummyData() patient.granular = False inspect_result, _ = patient.query_semiology() hierarchy_df = Hierarchy(inspect_result) hierarchy_df.all_hierarchy_reversal() # deafult max option inspect_result_reversed = hierarchy_df.new_df # test postcodes assert (inspect_result['TL'].sum() == 1) assert (inspect_result['Lateral Temporal'].sum() == 1) assert (inspect_result[ 'STG (includes Transverse Temporal Gyrus, Both Planum)'].sum() == 1 ) assert 'Planum Temporale' not in inspect_result # test hierarchy reversal assert (inspect_result_reversed['TL'].sum() == 0) assert (inspect_result_reversed['Lateral Temporal'].sum() == 0) assert (inspect_result_reversed[ 'STG (includes Transverse Temporal Gyrus, Both Planum)'].sum() == 1 ) assert 'Planum Temporale' not in inspect_result assert 'Planum Polare' not in inspect_result
def factor_ql(self, term, normalise_to_localising_values=False): """ factor function. NB normalise_to_localising_values default is False in semiology.py """ patient = Semiology(term, Laterality.LEFT, Laterality.LEFT) patient.data_frame = self.df patient.normalise_to_localising_values = normalise_to_localising_values all_combined_gifs = patient.query_lateralisation(one_map_dummy) return all_combined_gifs
def test_NegativeLookBehind_Regex(self): """ Test the NLB regex used in differentiating Tonic vs Asymmetric Tonic, atonic, generalised tonic, tonic-clonic etc in SemioDict. Note also that the SemioDict is the live one unless specifically specified: e.g. as an argument to QUERY_SEMIOLOGY(semiology_dict_path=dummy_semiology_dict_path=dummy_semiology_dict_path) """ patient = Semiology('Tonic', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df tonic_result, num_query_loc = patient.query_semiology() self.assertIs(type(tonic_result), pd.DataFrame) assert not tonic_result.empty assert (tonic_result['Localising'].sum() == 1 + 10) assert (tonic_result['Lateralising'].sum() == 1) # Now test for Atonic patient_two = Semiology('Atonic', Laterality.NEUTRAL, Laterality.NEUTRAL) patient_two.data_frame = self.df atonic_result, num_query_loc = patient_two.query_semiology() self.assertIs(type(atonic_result), pd.DataFrame) assert not atonic_result.empty assert (atonic_result['Localising'].sum() == 999) assert (atonic_result['Lateralising'].sum() == 2) print('\n9 negative lookbehind regex\n')
def test_paed_exclusions_query_semio(self): """ Test query_semiology then exclude paediatric cases. """ patient = Semiology('spasm', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df inspect_result, num_query_loc = patient.query_semiology() inspect_result = exclude_paediatric_cases(inspect_result) self.assertIs(type(inspect_result), pd.DataFrame) assert not inspect_result.empty assert (inspect_result['Localising'].sum() == 5 + 1) assert (inspect_result['Lateralising'].sum() == 0) print('\n8 paed exclusions query_semio()\n')
def test_prelim2_dummy_ILV_control(self): """ Preliminary test as per issues #169 on GitHub. This uses "ILV_4" as semiology term, which is Example 2 on GitHub: https://github.com/thenineteen/Semiology-Visualisation-Tool/issues/169 """ patient = Semiology('ILV_4', Laterality.LEFT, Laterality.LEFT) patient.data_frame = self.df inspect_result, _ = patient.query_semiology() self.assertIs(type(inspect_result), pd.DataFrame) assert not inspect_result.empty assert (inspect_result['Localising'].sum() == 4) assert (inspect_result['Lateralising'].sum() == 0)
def test_toplevel_aphasia_parentheses_and_caps(self): """ test query_semiology which calls QUERY_SEMIOLOGY Need to change the call to the semiology_dictionary to make it the dummy_semio_dict """ patient = Semiology('Aphasia', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df inspect_result, num_query_loc = patient.query_semiology() self.assertIs(type(inspect_result), pd.DataFrame) assert not inspect_result.empty # deafult excludes postictals assert (inspect_result['Localising'].sum() == 14 - 1) assert (inspect_result['Lateralising'].sum() == 6 - 1)
def test_prelim5_ql_50_50(self): """ Pipeline sequence test of ql: lateralises 50% CL and 50%IL. """ patient = Semiology('pipeline_50_50_laateralises_semioC', symptoms_side=Laterality.LEFT, dominant_hemisphere=Laterality.LEFT) patient.data_frame = self.df # returns the results from Q_L pipeline all_combined_gifs = patient.query_lateralisation( one_map_dummy) self.assertIs(type(all_combined_gifs), pd.DataFrame) assert not all_combined_gifs.empty return all_combined_gifs
def test_prelim4_ql_doesnot_lateralise(self): """ """ patient = Semiology('pipeline_notlaat_semioB', symptoms_side=Laterality.LEFT, dominant_hemisphere=Laterality.LEFT) patient.data_frame = self.df # as no lateralising data, the below will run a manual pipeline # involving melt_then_pivot_query and pivot_result_to_one_map: all_combined_gifs = patient.query_lateralisation( one_map_dummy) self.assertIs(type(all_combined_gifs), pd.DataFrame) assert not all_combined_gifs.empty return all_combined_gifs
def test_paed_default_query_semio(self): """ Test query_semiology for excluding paediatric cases. This test now shows that default query_semiology() DOES filter paediatric cases. """ patient = Semiology('spasm', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df # revert default paed exclusions patient.include_only_paediatric_cases = True inspect_result, num_query_loc = patient.query_semiology() self.assertIs(type(inspect_result), pd.DataFrame) assert not inspect_result.empty assert (inspect_result['Localising'].sum() == 10) assert (inspect_result['Lateralising'].sum() == 0) print('\n7 paed query_semio()\n')
def test_frontal_hierarchy_reversal(self): """ continuing testing reversal of postcode system for new class Hierarchy """ patient = Semiology('Aphasia', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df inspect_result, _ = patient.query_semiology() hierarchy_df = Hierarchy(inspect_result) hierarchy_df.frontal_hierarchy_reversal() # deafult max option inspect_result_reversed = hierarchy_df.frontal_hr # # note default is to exclude post ictals, otherwise add +1 to both below assert (inspect_result_reversed['FL'].sum() == 0) assert (inspect_result_reversed['IFG (F3)\n(BA 44,45,47)'].sum() == 1) print('\n9 frontal dictionary hierarchy reversal\n')
def test_prelim2_qs_doesnot_lateralise(self): """ Pipeline sequence testing of dummy data: does not lateralise. This is a standalone test to ensure qs/QS find dummy semiology. Test query_semiology which calls QUERY_SEMIOLOGY. The call to the semiology_dictionary is the dummy_semio_dict. """ patient = Semiology('pipeline_notlaat_semioB', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df inspect_result, _ = patient.query_semiology() self.assertIs(type(inspect_result), pd.DataFrame) assert not inspect_result.empty assert(inspect_result['Localising'].sum() == 10) assert(inspect_result['Lateralising'].sum() == 0)
def test_prelim3_ql_lateralises(self): """ Pipeline sequence test of ql: lateralises The call to the semiology_dictionary is the dummy_semio_dict as passed as an argument to q_l. Relies on mapping strategy as uses gifs. """ patient = Semiology('pipeline_laateralises_semioA', symptoms_side=Laterality.LEFT, dominant_hemisphere=Laterality.LEFT) patient.data_frame = self.df # returns the results from Q_L pipeline all_combined_gifs = patient.query_lateralisation( one_map_dummy) self.assertIs(type(all_combined_gifs), pd.DataFrame) assert not all_combined_gifs.empty return all_combined_gifs
def test_hierarchy(self): """ first tested postcode system which duplicates mapping before testing its reversal. """ patient = Semiology('Aphasia', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df # default behaviour of query_semiology changed to use granular hierarchy reversal: patient.granular = False inspect_result, _ = patient.query_semiology() assert (inspect_result['TL'].sum() == 12) assert (inspect_result['Anterior (temporal pole)'].sum() == 5) assert (inspect_result['Lateral Temporal'].sum() == 4) assert (inspect_result['ITG'].sum() == 4) assert (inspect_result['Mesial Temporal'].sum() == 5) # # by default postictal are excluded. Otherwise add +1 to both below assert (inspect_result['FL'].sum() == 1) assert (inspect_result['IFG (F3)\n(BA 44,45,47)'].sum() == 1) print('\n7 hierarchy\n')
def test_toplevel_query_lat_mappings(self): """ The call to the semiology_dictionary is the dummy_semio_dict as passed as an argument to q_l Relies on mapping strategy as uses gifs """ patient = Semiology('Aphasia', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df all_combined_gifs = patient.query_lateralisation(one_map_dummy) self.assertIs(type(all_combined_gifs), pd.DataFrame) assert not all_combined_gifs.empty labels = ['Gif Parcellations', 'pt #s'] all_combined_gifs = all_combined_gifs.astype({ 'Gif Parcellations': 'int32', 'pt #s': 'int32' }) new_all_combined_gifindexed = all_combined_gifs.loc[:, labels] new_all_combined_gifindexed.set_index('Gif Parcellations', inplace=True) # new_all_combined_gifindexed.to_csv(r'D:\aphasia_fixture.csv') # load fixture: fixture = pd.read_excel( dummy_data_path, header=0, usecols='A:B', sheet_name='fixture_aphasia', index_col=0, engine="openpyxl", ) # fixture.sort_index(inplace=True) assert ((new_all_combined_gifindexed.shape) == (fixture.shape)) # print('new_all_combined_gifindexed.shape is: ', # new_all_combined_gifindexed.shape) # print('fixture.shape.shape is: ', fixture.shape) assert (new_all_combined_gifindexed.index == fixture.index).all() assert (new_all_combined_gifindexed.values == fixture.values).all()
def test_temporal_hierarchy_reversal(self): """ now test reversal postcode system which duplicates mapping for new class Hierarchy """ patient = Semiology('Aphasia', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df patient.granular = False inspect_result, _ = patient.query_semiology() # # the three lines below were integrated into default query_semiology() using.granular = True hierarchy_df = Hierarchy(inspect_result) hierarchy_df.temporal_hierarchy_reversal() # deafult max option inspect_result_reversed = hierarchy_df.temporal_hr assert (inspect_result_reversed['TL'].sum() == 3) assert (inspect_result_reversed['Anterior (temporal pole)'].sum() == 5) assert (inspect_result_reversed['Lateral Temporal'].sum() == 0) assert (inspect_result_reversed['ITG'].sum() == 4) assert (inspect_result_reversed['Mesial Temporal'].sum() == 5) print('\n8 temporal hierarchy reversal\n')
def test_all_hierarchy_reversals(self): """ test all. """ patient = Semiology('Aphasia', Laterality.NEUTRAL, Laterality.NEUTRAL) patient.data_frame = self.df inspect_result, _ = patient.query_semiology() hierarchy_df = Hierarchy(inspect_result) hierarchy_df.all_hierarchy_reversal() # deafult max option inspect_result_reversed = hierarchy_df.new_df # assert object doesn't have any _hr aatribute: assert not hasattr(hierarchy_df, 'temporal_hr') assert (inspect_result_reversed['TL'].sum() == 3) assert (inspect_result_reversed['Anterior (temporal pole)'].sum() == 5) assert (inspect_result_reversed['Lateral Temporal'].sum() == 0) assert (inspect_result_reversed['ITG'].sum() == 4) assert (inspect_result_reversed['Mesial Temporal'].sum() == 5) # these two lines should be +1 if not excluding postictals assert (inspect_result_reversed['FL'].sum() == 0) assert (inspect_result_reversed['IFG (F3)\n(BA 44,45,47)'].sum() == 1) print('\n11 all_hierarchy reversals\n')
def test_latexceedsloc_3(self): """ Test capturing lateralisation value when it exceeds localising value (part1) and combining with lat_no_loc and lat_and_loc (part 2). Note that the default in Q_L of normalise_lat_to_loc = False and using norm_ratio = lower_value / higher_value results in capping of lateralisation influence on data visualisation. In the specific case of latexceedsloc semiology, despite 500 lat cumulative datapoints and 2 localising points, the GIF results are: {155: 2.0, 156:1.0} """ patient = Semiology('latexceedsloc', Laterality.LEFT, Laterality.LEFT) patient.data_frame = self.df # (part 1) test latexceedsloc alone using norm_ratio/oddsratio method of Q_L: heatmap, _ = patient.get_num_datapoints_dict(method='minmax') assert heatmap[156] == 200.0 assert heatmap[155] == 300.0 # (part 2) combine above with lat_not_loc and lat_and_loc: patient = Semiology('lat', Laterality.LEFT, Laterality.LEFT) patient.data_frame = self.df lat_allgifs = patient.query_lateralisation(one_map_dummy) # drop the zero entries - should be only the IL left ones which aren't MTG of TL: lat_allgifs = lat_allgifs[['Gif Parcellations', 'pt #s']].astype({ 'Gif Parcellations': 'int32', 'pt #s': 'int32' }) lat_allgifs.set_index('Gif Parcellations', inplace=True) lat_allgifs = lat_allgifs.loc[lat_allgifs['pt #s'] != 0, :] # assert using shape this not all are 1 so should not be the same: assert not lat_allgifs['pt #s'].sum() == lat_allgifs.shape[0] # check the MTG on the left (IL) GIF # 156 is == 3, # which it isn't due to the norm_ratio method in Q_L - as can be seen from part 1 # so instead we see in part 1 156 was 1, but in the spreadsheet it was 2. so will give 2. # 3 is better but lost due to norm_ratio method in Q_L assert (lat_allgifs.loc[156, 'pt #s'] == 201) # for the right sided GIF, 155, latexceedsloc gives 2 [/], # lat_not_loc gives 1 (CL) (See test_lat_not_loc_1)[/], and # lat_and_loc adds none [/] assert (lat_allgifs.loc[155, 'pt #s'] == 301)
def test_only_postictal_cases(self): """ Include only the single postictal aphasia. Note Dominant in dummy data. cf test_postictal_exclusions """ # Low level test df_postictal = only_postictal_cases(self.df) query, num_query_lat, num_query_loc = QUERY_SEMIOLOGY( df_postictal, semiology_term=['aphasia'], ignore_case=True, semiology_dict_path=None, col1='Reported Semiology', col2='Semiology Category', ) assert (query['Localising'].sum() == 1) assert (query['Lateralising'].sum() == 1) # High level test patient = Semiology('aphasia', Laterality.NEUTRAL, dominant_hemisphere=Laterality.LEFT) patient.data_frame = self.df patient.include_postictals = True patient.include_only_postictals = True patient.granular = True lat_allgifs = patient.query_lateralisation(one_map_dummy) lat_allgifs = lat_allgifs[['Gif Parcellations', 'pt #s']].astype({ 'Gif Parcellations': 'int32', 'pt #s': 'int32' }) lat_allgifs.set_index('Gif Parcellations', inplace=True) # note that dominant_hemisphere == Laterality.LEFT as set above. Just to clarify results change if dominace changes. Also 1's become 2's if not granular. assert (lat_allgifs.loc[164, 'pt #s'] == 1) assert (lat_allgifs.loc[166, 'pt #s'] == 1) assert (lat_allgifs.loc[163, 'pt #s'] == 0) assert (lat_allgifs.loc[165, 'pt #s'] == 0) lat_allgifs = lat_allgifs.loc[lat_allgifs['pt #s'] != 0, :] SVT_output, _ = patient.get_num_datapoints_dict(method='minmax') assert SVT_output == dict((lat_allgifs)['pt #s'])
def test_latnotloc_and_latandloc_2(self): """ Test capturing the lateralising but not localising data rather than skipping it. integrated with lat and loc data. """ patient = Semiology('lat_', Laterality.LEFT, Laterality.LEFT) patient.data_frame = self.df lat_not_loc_all_combined_gifs = patient.query_lateralisation( one_map_dummy) # inspect result lat_not_loc_result, _ = patient.query_semiology() self.assertIs(type(lat_not_loc_all_combined_gifs), pd.DataFrame) assert not lat_not_loc_all_combined_gifs.empty # drop the zero entries - should be only the IL left ones which aren't MTG of TL: lat_not_loc_all_combined_gifs = lat_not_loc_all_combined_gifs[[ 'Gif Parcellations', 'pt #s' ]].astype({ 'Gif Parcellations': 'int32', 'pt #s': 'int32' }) lat_not_loc_all_combined_gifs.set_index('Gif Parcellations', inplace=True) lat_not_loc_gifsclean = lat_not_loc_all_combined_gifs.loc[ lat_not_loc_all_combined_gifs['pt #s'] != 0, :] gifs_right, gifs_left = gifs_lat_factor() lat_not_loc_gifsclean_rights = (lat_not_loc_gifsclean.drop( index=156).index.isin(gifs_right).all()) # inspect result assertions assert (lat_not_loc_result.Localising.sum() == 1) assert (lat_not_loc_result['Lateralising'].sum() == 2) # all_combined_gifs assertions # all except GIF 156 (L MTG) are in the right GIFs: assert ((lat_not_loc_gifsclean_rights == True)) assert ((lat_not_loc_gifsclean.index.isin(gifs_left)).any() == True) # assert using shape as all pt #s are 1: assert (lat_not_loc_gifsclean['pt #s'].sum() == lat_not_loc_gifsclean.shape[0]) # check that latnotloc gives 1 and latandloc adds zero to right MTG GIF #155 heatmap, _ = patient.get_num_datapoints_dict(method='minmax') assert heatmap[155] == 1 # right
def test_lat_not_loc_1(self): """ Test capturing the lateralising but not localising data rather than skipping it. As implemented in QUERY_LATERALISATION in branch "Lateralising but no localising value". """ patient = Semiology('lat_not_loc', Laterality.LEFT, Laterality.LEFT) patient.data_frame = self.df lat_not_loc_all_combined_gifs = patient.query_lateralisation( one_map_dummy) # inspect result lat_not_loc_result, num_query_loc = patient.query_semiology() self.assertIs(type(lat_not_loc_all_combined_gifs), pd.DataFrame) assert not lat_not_loc_all_combined_gifs.empty # drop the zero entries as these are from the CL/IL zeros: lat_not_loc_all_combined_gifs = lat_not_loc_all_combined_gifs[[ 'Gif Parcellations', 'pt #s' ]].astype({ 'Gif Parcellations': 'int32', 'pt #s': 'int32' }) lat_not_loc_all_combined_gifs.set_index('Gif Parcellations', inplace=True) lat_not_loc_gifsclean = lat_not_loc_all_combined_gifs.loc[ lat_not_loc_all_combined_gifs['pt #s'] != 0, :] # now we know only the CL data remains in this dummy data, which is on the RIGHT. gifs_right, gifs_left = gifs_lat_factor() lat_not_loc_gifsclean_rights = ( lat_not_loc_gifsclean.index.isin(gifs_right).all()) # inspect result assertions assert (lat_not_loc_result.Localising.sum() == 0) assert (lat_not_loc_result['Lateralising'].sum() == 1) # all_combined_gifs assertions assert ((lat_not_loc_gifsclean_rights == True)) assert ((lat_not_loc_gifsclean.index.isin(gifs_left)).any() == False) assert (lat_not_loc_gifsclean['pt #s'].sum() == lat_not_loc_gifsclean.shape[0]) # test MTG on right 155 gif # gives 1: heatmap, _ = patient.get_num_datapoints_dict(method='minmax') assert 156 not in heatmap # left assert heatmap[155] == 1 # right
def p_GIFs( global_lateralisation=False, include_paeds_and_adults=True, include_only_postictals=False, symptom_laterality='NEUTRAL', dominance='NEUTRAL', hierarchy_reversal: bool = True, include_spontaneous_semiology: bool = False, # TS only ): """ Return the normalised/unnormalised marginal probabilities for each GIF parcellation. for ictal semiologies only (excluding postictals) see marginal_GIF_probabilities() for sensitivity analyses e.g. by adding include_concordance=False for data queries excluding concordance or changing laterality or age """ # normalised patient_all_semiology_norm = Semiology( ".*", symptoms_side=Laterality.NEUTRAL, dominant_hemisphere=Laterality.NEUTRAL, include_postictals=False, include_paeds_and_adults=include_paeds_and_adults, normalise_to_localising_values=True, global_lateralisation=global_lateralisation, include_spontaneous_semiology=include_spontaneous_semiology, ) if symptom_laterality == 'left': patient_all_semiology_norm.symptoms_side = Laterality.LEFT if dominance == 'left': patient_all_semiology_norm.dominant_hemisphere = Laterality.LEFT patient_all_semiology_norm.include_only_postictals = include_only_postictals patient_all_semiology_norm.granular = hierarchy_reversal all_combined_gifs_norm, _ = patient_all_semiology_norm.get_num_datapoints_dict( ) p_GIF_norm = marginal_GIF_probabilities(all_combined_gifs_norm) # now not normalised version patient_all_semiology_notnorm = Semiology( ".*", symptoms_side=Laterality.NEUTRAL, dominant_hemisphere=Laterality.NEUTRAL, include_postictals=False, include_paeds_and_adults=include_paeds_and_adults, normalise_to_localising_values=False, global_lateralisation=global_lateralisation, ) if symptom_laterality == 'left': patient_all_semiology_notnorm.symptoms_side = Laterality.LEFT if dominance == 'left': patient_all_semiology_notnorm.dominant_hemisphere = Laterality.LEFT patient_all_semiology_notnorm.include_only_postictals = include_only_postictals patient_all_semiology_notnorm.granular = hierarchy_reversal all_combined_gifs_notnorm, _ = patient_all_semiology_notnorm.get_num_datapoints_dict( ) p_GIF_notnorm = marginal_GIF_probabilities(all_combined_gifs_notnorm) return p_GIF_norm, p_GIF_notnorm