create_mats - issue with normalization by ROI size

32 views
Skip to first unread message

kcampbell

unread,
Jun 23, 2020, 3:01:56 PM6/23/20
to brainGraph-help
Hi Chris, 

Thanks for the helpful User Guide for brainGraph R - it's been great so far! 
However, I've run into an issue with create_mats when trying to normalize connectivity matrices by ROI size (divisor = "size"). I have a "subj#_voxel_sizes.txt" file for each individual subject, which is a single column of numbers with each row corresponding to the number of voxels in a ROI (ncol=# ROIs, with rows same oder as connectivity matrices). Of note, create_mats appears to work fine when I remove the normalization arguments. 

mats <- create_mats(A.files = matfiles$A, modality = "dti", algo = "deterministic", inds = inds, divisor = "size", div.files = matfiles$region_sizes)
[1] Error in readLines(infiles[1]) : 'con' is not a connection.

It appears that there is an issue reading the connection to the region_size files. However, when I check the paths in my list with sapply(matfiles$region_sizes, file.exists), all outputs are 'TRUE'. I'm not sure how to troubleshoot this from here. Any help would be greatly appreciated! Thank you.


Chris Watson

unread,
Jun 23, 2020, 3:09:57 PM6/23/20
to brainGr...@googlegroups.com
Can you tell me:
* What version of the package you are using
* What is the output of "traceback()"
* Does the following return an array without error: (note there are 3 colons in a row)
div <- brainGraph:::read.array(matfiles$region_sizes, ncols=1)

If that last one returns an error, what is the output of "traceback()"


--
You received this message because you are subscribed to the Google Groups "brainGraph-help" group.
To unsubscribe from this group and stop receiving emails from it, send an email to brainGraph-he...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/brainGraph-help/ccc06e8d-6c4d-4c58-a033-f80abd976567n%40googlegroups.com.

kcampbell

unread,
Jun 23, 2020, 3:37:38 PM6/23/20
to brainGraph-help
Hi Chris, 

Version of R: 3.6.1; version of brainGraph package: 2.7.3.

Output of traceback()...
> traceback()
4: readLines(infiles[1])
3: read.array(div.files, ncols = 1)
2: normalize_mats(A.norm, div.files, Nv, kNumSubjs, P = 1)
1: create_mats(A.files = matfiles$A, modality = modality, 
       divisor = "size", div.files = matfiles$region_size, 
       inds = inds, algo = algo)

div <- brainGraph:::read.array(matfiles$region_sizes, ncols=1) # produces same error...
[1] Error in readLines(infiles[1]) : 'con' is not a connection

Output of traceback() again...
> traceback()
2: readLines(infiles[1])
1: brainGraph:::read.array(matfiles$region_sizes, ncols = 1)

Chris Watson

unread,
Jun 23, 2020, 3:49:03 PM6/23/20
to brainGr...@googlegroups.com
If you do "readLines(matfiles$region_sizes[1])" do you get the same error? What type of object is that, i.e., "str(matfiles$region_sizes)"

kcampbell

unread,
Jun 23, 2020, 4:03:48 PM6/23/20
to brainGraph-help
Quick update: I tried div <- brainGraph:::read.array(matfiles$region_size, ncols = 1) again with no error -  output is an array:
> str(div)
[1] num [1:64, 1, 1:75] # 64 regions, 75 subjects

The output of readLines(matfiles$region_size[1]) is a character vector of length n regions (n=64). 
> head(readLines(matfiles$region_size[1]))
[1] "3698" "4390" "1299" "1129" "464"  "450" 
>  class(readLines(matfiles$region_size[1]))
[1] "character"


Chris Watson

unread,
Jun 23, 2020, 4:57:55 PM6/23/20
to brainGr...@googlegroups.com
So it looks like there was a typo? If you use "matfiles$region_size" instead in the call to "create_mats", let me know if it works.
Chris

kcampbell

unread,
Jun 23, 2020, 5:12:58 PM6/23/20
to brainGraph-help
Apologies, the typo was from typing my question to you - this is why div <- brainGraph:::read.array(matfiles$region_sizes, ncols = 1) did not work the first time I tried it. (I removed the s at the end of 'sizes' and it worked - see the output of the in my previous response). "matfiles$region_size" is the correct name. 

So, it appears that the sizes.txt files are in the correct format, with the valid paths, but still 'create_mats' give the error I initially asked about. 

Chris Watson

unread,
Jun 23, 2020, 5:38:13 PM6/23/20
to brainGr...@googlegroups.com
I don't know why you would see that error, then, if there are no typos it should work given the traceback.
If you make sure that there are no typos or anything, then you can send me all the data and code I need to reproduce the issue and I will look into it.

Chris

kcampbell

unread,
Jun 25, 2020, 1:20:10 PM6/25/20
to brainGraph-help
Hello Chris, 

I have created an example of the Error I am receiving with create_mats when trying to normalize by ROI size. The attached .zip contains a folder with a script and example data to produce the error. 

Thank you very much for looking into this!
Kayleigh
Error_example.zip

Chris Watson

unread,
Jun 25, 2020, 4:19:24 PM6/25/20
to brainGr...@googlegroups.com
For me it runs without error although I am using a slightly newer, not-yet-released, version of the function (create_mats, that is). However, "read.array" is unchanged from the version you're using which is where your error originates. So I am not sure why you're getting an error. What OS are you using? Looks like Mac OS?

A few minor changes to your script that probably won't fix it, but you can try anyway:
* On line 8, remove the trailing slash from the string for the data directory
* On lines 11 and 14, change "paste0" to "file.path"



kcampbell

unread,
Jun 26, 2020, 2:58:59 PM6/26/20
to brainGraph-help
Hi Chris, 
Thanks for taking a look at my example code. 
Yes, I am using Mac OS 10.14.6.
I tried your suggested changes, and the same Error was produced. 

I explored this further with the brainGraph:::normalize_mats function in the source code. I was able to produce 'A.norm' matrices without any issue. 
> div <- brainGraph:::read.array(matfiles$region_size, ncols = 1)
> Nv <- nrow(brainGraph:::read.array(matfiles$A))
> P = 1 # because I used deterministic tractography
> A <- brainGraph:::read.array(matfiles$A)
> R <- array(apply(div, 3, function(x) cbind(sapply(seq_len(Nv), function(y) x + x[y]))), dim = dim(A))
> A.norm <- 2 * A/(P * R) # correct result 

I then looked through the create_mats function more closely...when I performed the following: 
> mats <- create_mats(A.files = matfiles$A, modality = "dti", divisor = "size", div.files = matfiles$region_size, inds = inds, algo = "probabilistic", P=1)
I did not receive an error. 
The resulting A.norm matrices matched those I produced when performing normalize_mats outside of the create_mats function. 

 It is possible there is an issue in create_mats when supplying this specific combination of parameters? (i.e. modality == "dti" & algo == "deterministic" & divisor == "size")?
And further, if I proceed with algo = "probabilistic" and P = 1, will I run into any issues later on? Is the thresholding computed the same? Or is this essentially the same as algo = "deterministic"?

Thanks again for your help!

Chris Watson

unread,
Jun 26, 2020, 3:05:46 PM6/26/20
to brainGr...@googlegroups.com
Ah, looking into it I have noticed a bug in the code. The problem is that the call to "normalize_mats" when using for deterministic tractography is missing its second argument, so all the function arguments get shifted. So yes, in your case changing to "probabilistic" and with P=1 is a good enough hack. I will make sure to fix this for the next release.

Chris

kcampbell

unread,
Jun 26, 2020, 3:29:04 PM6/26/20
to brainGraph-help
Glad we were able to identify this bug!
And thanks for confirming that changing to "probabilistic" and P=1 will work out for me here. 

One more quick question for for on this 'normalization by ROI size' topic -- what exactly does normalize_mats do to normalize by ROI size? I noticed that the values in array "R" are the average size of the corresponding two regions. Then, when computing 'A.norm' by:
> A.norm <- 2 * A/R
Why we do multiply by 2? 

Chris Watson

unread,
Jun 26, 2020, 3:44:56 PM6/26/20
to brainGr...@googlegroups.com
It is just another way of taking the average. The values in "R" are the sums of 2 numbers (2 regions), so you can think of it as
A.norm = A / mean(R)
==> A / (R1 + R2 / 2)
==> 2 * A / (R1 + R2)

kcampbell

unread,
Jun 26, 2020, 4:02:03 PM6/26/20
to brainGraph-help
Ah yes, that makes total sense! Thank you!
Reply all
Reply to author
Forward
0 new messages