Harmonizing DTI data

Dear experts,

I’m trying to harmonize DTI maps across datasets and I came across neuroHarmonize. I was wondering if it is possible to fit non-linearly multiple covariates, or if not, if there are other methods out there that I can use for this? Thanks in advance.

Best regards,

Manuel

Hi @mblesac,

I’ve used neuroharmonize before but have only tried with one smooth term. Do you get an error when you try multiple?

Best,
Steven

Hi,

Thanks for your reply!

Using 2 smooth terms we found the following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/EBC/local/fsl/lib/python3.10/site-packages/neuroHarmonize/harmonizationLearn.py", line 130, in harmonizationLearn
    bs = BSplines(X_spline, df=[10] * len(smooth_cols), degree=[3] * len(smooth_cols),
  File "/EBC/local/fsl/lib/python3.10/site-packages/statsmodels/gam/smooth_basis.py", line 929, in __init__
    super(BSplines, self).__init__(x, include_intercept=include_intercept,
  File "/EBC/local/fsl/lib/python3.10/site-packages/statsmodels/gam/smooth_basis.py", line 757, in __init__
    self.smoothers = self._make_smoothers_list()
  File "/EBC/local/fsl/lib/python3.10/site-packages/statsmodels/gam/smooth_basis.py", line 935, in _make_smoothers_list
    kwds = self.knot_kwds[v] if self.knot_kwds else {}
IndexError: list index out of range

Then we tried with one smooth term and other linear term, the model was created but when we apply it to the data we found the following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/EBC/local/fsl/lib/python3.10/site-packages/neuroHarmonize/harmonizationNIFTI.py", line 152, in applyModelNIFTIs
    nifti_array_adj = applyModelOne(nifti_array, covarsSel, model)
  File "/EBC/local/fsl/lib/python3.10/site-packages/neuroHarmonize/harmonizationApply.py", line 176, in applyModelOne
    stand_mean += np.dot(tmp, B_hat).T
  File "<__array_function__ internals>", line 5, in dot
ValueError: shapes (1,6) and (14,33220) not aligned: 6 (dim 1) != 14 (dim 0)

Now I’m trying it with just one non-linear term and 0 linear terms. Any clue what is going on?

Best regards,

Manuel

I would need to know more about the data you are using and code you are running neuroharmonize with to be able to help. Neuroharmonize runs on plain numpy arrays too, so you can see if it runs on randomly generated test data.

Hi Manuel, we have a parametric version of ComBat implemented in our confounds package: GitHub - raamana/confounds: Conquering confounds and covariates in machine learning

its been tested well, but not thoroughly enough for us to start promoting it. if you are interested, I can show you how to use it.

Hi,

Thanks for your replies!

@Steven my data is a skeletonised WM images (TBSS-like) of two different neonatal studies. When I don’t use the sooth_terms flag it works perfectly.

Here is an example of my covers file:
image

They are 85 subjects from one site and 280 from another one.

The code is:

import pandas as pd
import numpy as np
from neuroHarmonize.harmonizationNIFTI import createMaskNIFTI
nifti_list = pd.read_csv('my_list.csv')
nifti_avg, nifti_mask, affine, hdr0 = createMaskNIFTI(nifti_list, threshold=0)
from neuroHarmonize.harmonizationNIFTI import flattenNIFTIs
nifti_array = flattenNIFTIs(nifti_list, 'thresholded_mask.nii.gz')
import neuroHarmonize as nh
covars = pd.read_csv('demographics.csv')
my_model, nifti_array_adj = nh.harmonizationLearn(nifti_array, covars)
nh.saveHarmonizationModel(my_model, 'MY_MODEL', smooth_terms=['AGE_B','AGE_S'])

@raamana thanks! I’ll give it a try!

Best regards,

Manuel

For more context,

What is the shape of this?

Shouldn’t your nh.harmonizationLearn command have the same smooth terms in it?

Which one of these lines is causing the error that you receive?

What is the reasoning behind two age regressors on a single image? Especially two that appear to largely covary?

Best,
Steven

you might need some orienting for this, as I designed the confounds library to emphasize the proper implementation of best practices fro cross-invalidation (separating training and test sets to avoid any overfitting or leakage etc): Usage — confounds 0.1.1 documentation

The focus is more on processed features, than images, as we can easily process images with numpy/nibabel/nilearn etc, and I think image processing should be separated from the harmonization

Please read the docs and play around with it and don’t hesitate to reach out if you have any questions.

Hi @Steven,

I mix some lines of the code, so apologies for that. I’ll reply to your questions and show you the final code. This is the correct code:

import pandas as pd
import numpy as np
from neuroHarmonize.harmonizationNIFTI import createMaskNIFTI
nifti_list = pd.read_csv('model_list.csv')
nifti_avg, nifti_mask, affine, hdr0 = createMaskNIFTI(nifti_list, threshold=0)
from neuroHarmonize.harmonizationNIFTI import flattenNIFTIs
nifti_array = flattenNIFTIs(nifti_list, 'thresholded_mask.nii.gz')
import neuroHarmonize as nh
covars = pd.read_csv('demographics_all.csv')
my_model, nifti_array_adj = nh.harmonizationLearn(nifti_array, covars, smooth_terms=['AGE_B'])
nh.saveHarmonizationModel(my_model, 'MY_MODEL')
from neuroHarmonize.harmonizationNIFTI import applyModelNIFTIs
# load pre-trained model
my_model = nh.loadHarmonizationModel('MY_MODEL')
applyModelNIFTIs(covars, my_model, nifti_list, 'thresholded_mask.nii.gz')

What is the shape of this?

The shape of the nifti array is: (373, 33220). Number of subjects, number of voxels.

You were right, see the corrected code at the beginning of the post.

The error is in this line:

applyModelNIFTIs(covars, my_model, nifti_list, 'thresholded_mask.nii.gz')

And is the following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/EBC/local/fsl/lib/python3.10/site-packages/neuroHarmonize/harmonizationNIFTI.py", line 152, in applyModelNIFTIs
    nifti_array_adj = applyModelOne(nifti_array, covarsSel, model)
  File "/EBC/local/fsl/lib/python3.10/site-packages/neuroHarmonize/harmonizationApply.py", line 176, in applyModelOne
    stand_mean += np.dot(tmp, B_hat).T
  File "<__array_function__ internals>", line 5, in dot
ValueError: shapes (1,6) and (14,33220) not aligned: 6 (dim 1) != 14 (dim 0)

For reference the shape of covars is: 373, 5.

This is quite common in neonatal imaging and they are not always that covaried. I can do a transformation and get rid of one of them.

Best regards,

Manuel

Will have to think more about the error, but it sounds like harmonization already ran fine in the line:

my_model, nifti_array_adj = nh.harmonizationLearn(nifti_array, covars, smooth_terms=['AGE_B'])

In that case, can you just save each row of the nifti_array_adj output as a new nifti?

Best,
Steven

Hi,

Ok thanks for your advise. I did that and something went wrong during the harmonization, it looks like the model didn’t converge.

Before harmonizing:

After harmonizing with linear covariates (the difference can not be appreciated but the values are different):

After harmonizing with non linear age at scan:

It looks like a mask, only with 0 and 1. the linear harmonization works correctly, so I think it should be something about the convergence of the model.

Best regards,

Manuel