Skip to content

Commit 3bdaf6b

Browse files
melhemrAbdulkadirA
authored andcommitted
Add statements to deal with derived volumes in harmonization model FIX #184
1 parent 51cb4e1 commit 3bdaf6b

File tree

2 files changed

+44
-14
lines changed

2 files changed

+44
-14
lines changed

NiBAx/core/model/datamodel.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,22 @@ def GetCompleteData(self):
107107
def GetModel(self):
108108
"""Returns harmonization model."""
109109
return self.harmonization_model
110+
111+
def GetMaxAgeOfMUSEHarmonizationModel(self):
112+
"""Returns model age maximum."""
113+
return self.harmonization_model['smooth_model']['bsplines_constructor'].knot_kwds[0]['upper_bound']
110114

115+
def GetMinAgeOfMUSEHarmonizationModel(self):
116+
"""Returns model age minimum."""
117+
return self.harmonization_model['smooth_model']['bsplines_constructor'].knot_kwds[0]['lower_bound']
118+
111119

112120
def GetNormativeRange(self,roi):
113121
"""Return normative range"""
114122

115123
# Constructig the visualization of the normative range based on GAM
116124
# model
117-
covariates = pd.DataFrame(np.linspace(25, 95, 200), columns=['Age'])
125+
covariates = pd.DataFrame(np.linspace(self.GetMinAgeOfMUSEHarmonizationModel(), self.GetMaxAgeOfMUSEHarmonizationModel(), 200), columns=['Age'])
118126
# Fix ICV roughly to population average
119127
covariates['ICV'] = 1450000 # mean ICV
120128
# Fix Sex variable

NiBAx/plugins/harmonization/harmonization.py

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
from NiBAx.core.baseplugin import BasePlugin
1313
from NiBAx.core.gui.SearchableQComboBox import SearchableQComboBox
1414

15+
from NiBAx.core import iStagingLogger
16+
17+
logger = iStagingLogger.get_logger(__name__)
18+
1519
class Harmonization(QtWidgets.QWidget,BasePlugin):
1620

1721
#constructor
@@ -112,6 +116,15 @@ def PopulateROI(self):
112116
roiList = list(set(self.datamodel.GetColumnHeaderNames()).intersection(set(MUSEDictDataFrame[MUSEDictDataFrame['ROI_LEVEL']=='SINGLE']['ROI_COL'])))
113117
roiList.sort()
114118
roiList = ['(MUSE) ' + list(map(MUSEDictIDtoNAME.get, [k]))[0] if k.startswith('MUSE_') else k for k in roiList]
119+
120+
if ('MUSE_Volume_301' in list(self.datamodel.harmonization_model['ROIs'])):
121+
logger.info('Model includes derived volumes')
122+
derivedROIs = list(set(self.datamodel.GetColumnHeaderNames()).intersection(set(MUSEDictDataFrame[MUSEDictDataFrame['ROI_LEVEL']=='DERIVED']['ROI_COL'])))
123+
derivedROIs.sort()
124+
derivedROIs = ['(MUSE) ' + list(map(MUSEDictIDtoNAME.get, [k]))[0] if k.startswith('MUSE_') else k for k in derivedROIs]
125+
roiList = roiList + derivedROIs
126+
else:
127+
logger.info('No derived volumes in model')
115128

116129
#add the list items to comboBox
117130
self.ui.comboBoxROI.blockSignals(True)
@@ -310,11 +323,17 @@ def plotMUSE(self,plotOptions):
310323

311324
def OnAddToDataFrame(self):
312325
print('Saving modified data to pickle file...')
313-
MUSEDictDataFrame= self.datamodel.GetMUSEDictDataFrame()
314-
Derived_numbers = list(MUSEDictDataFrame[MUSEDictDataFrame['ROI_LEVEL']=='DERIVED']['ROI_INDEX'])
315-
Derived_MUSE_Volumes = list('MUSE_Volume_' + str(x) for x in Derived_numbers)
316-
ROI_list = list(self.datamodel.harmonization_model['ROIs']) + Derived_MUSE_Volumes
317-
ROI_list.remove('MUSE_Volume_702')
326+
327+
ROI_list = list(self.datamodel.harmonization_model['ROIs'])
328+
if ('MUSE_Volume_301' not in ROI_list):
329+
logger.info('No derived volumes in model')
330+
MUSEDictDataFrame= self.datamodel.GetMUSEDictDataFrame()
331+
Derived_numbers = list(MUSEDictDataFrame[MUSEDictDataFrame['ROI_LEVEL']=='DERIVED']['ROI_INDEX'])
332+
Derived_MUSE_Volumes = list('MUSE_Volume_' + str(x) for x in Derived_numbers)
333+
ROI_list = ROI_list + Derived_MUSE_Volumes
334+
ROI_list.remove('MUSE_Volume_702')
335+
else:
336+
logger.info('Model includes derived volumes')
318337
H_ROIs = list('H_' + str(x) for x in ROI_list)
319338
ROIs_ICV_Sex_Residuals = ['RES_ICV_Sex_' + x for x in self.datamodel.harmonization_model['ROIs']]
320339
ROIs_Residuals = ['RES_' + x for x in self.datamodel.harmonization_model['ROIs']]
@@ -430,14 +449,17 @@ def DoHarmonization(self):
430449
else:
431450
muse = pd.concat([covars,pd.DataFrame(bayes_data, columns=['H_' + s for s in self.datamodel.harmonization_model['ROIs']])],axis=1)
432451

433-
# harmonize derived volumes
434-
MUSEDictDataFrame= self.datamodel.GetMUSEDictDataFrame()
435-
muse_mappings = self.datamodel.GetDerivedMUSEMap()
436-
for ROI in MUSEDictDataFrame[MUSEDictDataFrame['ROI_LEVEL']=='DERIVED']['ROI_INDEX']:
437-
single_ROIs = muse_mappings.loc[ROI].replace('NaN',np.nan).dropna().astype(np.float)
438-
single_ROIs = ['H_MUSE_Volume_%0d' % x for x in single_ROIs]
439-
muse['H_MUSE_Volume_%d' % ROI] = muse[single_ROIs].sum(axis=1,skipna=False)
440-
muse.drop(columns=['H_MUSE_Volume_702'], inplace=True)
452+
# harmonize derived volumes
453+
if ('MUSE_Volume_301' not in list(self.datamodel.harmonization_model['ROIs'])):
454+
logger.info('No derived volumes in model.')
455+
logger.info('Calculating using derived mapping dictionary.')
456+
MUSEDictDataFrame= self.datamodel.GetMUSEDictDataFrame()
457+
muse_mappings = self.datamodel.GetDerivedMUSEMap()
458+
for ROI in MUSEDictDataFrame[MUSEDictDataFrame['ROI_LEVEL']=='DERIVED']['ROI_INDEX']:
459+
single_ROIs = muse_mappings.loc[ROI].replace('NaN',np.nan).dropna().astype(np.float)
460+
single_ROIs = ['H_MUSE_Volume_%0d' % x for x in single_ROIs]
461+
muse['H_MUSE_Volume_%d' % ROI] = muse[single_ROIs].sum(axis=1,skipna=False)
462+
muse.drop(columns=['H_MUSE_Volume_702'], inplace=True)
441463

442464
start_index = len(self.datamodel.harmonization_model['SITE_labels'])
443465
sex_icv_effect = np.dot(muse[['Sex','DLICV_baseline']].copy(), self.datamodel.harmonization_model['B_hat'][start_index:(start_index+2),:])

0 commit comments

Comments
 (0)