-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
31bbaf6
commit d4f7fef
Showing
10 changed files
with
768 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,25 @@ | ||
# Displasias | ||
Concatenación Código Displasias | ||
# ratCortex-dMRIstreams | ||
|
||
Code to process dMRI volumes and create cortical streamlines in rat data. :information_source: [**Info & details**](https://hackmd.io/@servindc/ratCortex-dMRI) | ||
|
||
## Setup | ||
|
||
1. Install the [MINC](https://en.wikibooks.org/wiki/MINC) tools required for the code: | ||
```bash | ||
sudo apt install minc-tools | ||
``` | ||
|
||
2. Create a conda environment: | ||
```bash | ||
conda env create --file environment.yml | ||
``` | ||
|
||
3. Activate the environment: | ||
```bash | ||
conda activate cx-streams-env | ||
``` | ||
|
||
4. Display script help: | ||
```bash | ||
nii2streams.sh -h | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# run: conda env create --file environment.yml | ||
name: cx-streams-env | ||
channels: | ||
- conda-forge | ||
- anaconda | ||
- mrtrix3 | ||
dependencies: | ||
- python | ||
- matplotlib | ||
- numpy | ||
- nibabel | ||
- dipy | ||
- networkx | ||
- scipy | ||
- scikit-image | ||
- scikit-learn | ||
- mrtrix3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Adjust seed line | ||
@author: dcortex | ||
""" | ||
from os.path import join, basename | ||
from os import chdir | ||
import numpy as np | ||
import nibabel as nib | ||
from sklearn.neighbors import NearestNeighbors | ||
import networkx as nx | ||
from scipy.interpolate import splprep, splev | ||
|
||
def sort_points(seeds): | ||
""" | ||
Returns sorted 'seeds' (np.ndarray) by their nearest neighbors | ||
""" | ||
if len(seeds)==0: return np.array([]) | ||
clf = NearestNeighbors(n_neighbors=2).fit(seeds) | ||
G = clf.kneighbors_graph() # sparse N x N matrix | ||
|
||
T = nx.from_scipy_sparse_matrix(G) | ||
|
||
paths = [list(nx.dfs_preorder_nodes(T, i)) for i in range(len(seeds))] | ||
|
||
mindist = np.inf | ||
minidx = 0 | ||
|
||
for i in range(len(seeds)): | ||
p = paths[i] # order of nodes | ||
ordered = seeds[p] # ordered nodes | ||
# find cost of that order by the sum of euclidean distances between points (i) and (i+1) | ||
cost = (((ordered[:-1] - ordered[1:])**2).sum(1)).sum() | ||
if cost < mindist: | ||
mindist = cost | ||
minidx = i | ||
seeds = seeds[paths[minidx]] | ||
# Medial a lateral | ||
if seeds[0][1] < seeds[-1][1]: seeds = seeds[::-1] | ||
return seeds | ||
|
||
def smooth_curve(x, y, s=0.5): | ||
tck, u = splprep([x, y], s=s) | ||
smooth_points = np.array(splev(u, tck)).T | ||
return smooth_points | ||
|
||
def get_seeds_from_nii(f_name, subject, side='l', smooth=False, save=True, s=0.1, | ||
save_folder='~/Descargas',): | ||
lines_volume = nib.load(f_name).get_fdata() | ||
|
||
seeds_dict = {} | ||
for slice_n in range(10,16): | ||
|
||
sx, sy = np.array(np.nonzero(lines_volume[:,:,slice_n])) | ||
seeds = np.array([sx,sy]).T | ||
|
||
if len(seeds)==0: continue | ||
|
||
seeds = sort_points(seeds) | ||
if smooth: seeds = smooth_curve(*seeds.T, s=s) | ||
|
||
# Add z coordinate | ||
ones = np.ones([len(seeds), 1]) | ||
seeds = np.concatenate((seeds, slice_n*ones), axis=1)[1:,:] | ||
# remove first entry because of reasons ^ | ||
|
||
if save: | ||
seeds_name = f'{subject}_{side}_{slice_n}_seeds' | ||
if smooth: seeds_name += '_smooth' | ||
|
||
np.savetxt(join(save_folder, basename(seeds_name)+'.txt'), seeds) | ||
print(f'\n Created file: {basename(seeds_name)}.txt in: {save_folder}') | ||
|
||
seeds_dict[seeds_name] = seeds | ||
|
||
return seeds_dict | ||
|
||
#_____________________________________________________________________________ | ||
|
||
|
||
if __name__ == "__main__": | ||
import sys | ||
import subprocess | ||
from os.path import dirname | ||
|
||
#subject = sys.argv[1] # subject = '37A | ||
#side = 'l' | ||
|
||
#f_name = f'minc/{subject}_{side}_outline.nii' | ||
f_name = sys.argv[1] | ||
out_dir = sys.argv[2] | ||
prefix = sys.argv[3] | ||
try: | ||
n_seeds = sys.argv[4] | ||
except IndexError: | ||
n_seeds = 150 | ||
print(f'\n Using {n_seeds} seeds') | ||
|
||
#subject = basename(f_name).split('_')[0] | ||
side = basename(f_name).split('_')[1] | ||
seeds = get_seeds_from_nii(f_name, subject=prefix, side=side, smooth=True, save=True, | ||
s=10, save_folder=out_dir, ) | ||
|
||
#out_dir = dirname(f_name) | ||
for seeds_name in list(seeds.keys()): | ||
|
||
convert1 = (f"tckconvert {join(out_dir, seeds_name)}.txt" | ||
f" {join(out_dir, seeds_name)}.tck ") | ||
# -voxel2scanner ../{subject}_x2.nii | ||
resample = (f"tckresample -num_points {n_seeds} -nthreads 0" | ||
f" {join(out_dir, seeds_name)}.tck" | ||
f" {join(out_dir, seeds_name)}_resampled.tck") | ||
convert2 = (f"tckconvert {join(out_dir, seeds_name)}_resampled.tck" | ||
f" {join(out_dir, seeds_name)}_resampled_[].txt") | ||
rename = (f"mv {join(out_dir, seeds_name)}_resampled_0000000.txt" | ||
f" {join(out_dir, seeds_name)}_resampled.txt") | ||
for my_command in [convert1, resample, convert2, rename]: | ||
process = subprocess.Popen(my_command.split(), stdout=subprocess.PIPE) | ||
output, error = process.communicate() | ||
|
||
print((f"\n Created file: {join(out_dir, seeds_name)}_resampled" | ||
f"(txt & tck) in: {out_dir}\n")) | ||
|
||
#!tckconvert {seeds_name}.txt {seeds_name}.tck -voxel2scanner ../{subject}_x2.nii | ||
#!tckresample -num_points 150 -nthreads 0 {seeds_name}.tck {seeds_name}_resampled.tck | ||
#!tckconvert {seeds_name}_resampled.tck {seeds_name}_resampled_[].txt | ||
|
||
sys.exit() | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#!/bin/bash | ||
|
||
if [ "$1" == "-h" -o "$1" == "--help" -o "$1" == "" ]; then | ||
echo -e "\n Usage: `basename $0` grid_in grid_mid [output_path]" | ||
echo -e "\n Computes grid for the mincLaplace script." | ||
echo -e "\n Returns '_grid_123.nii.gz' & '_grid_123.mnc'.\n" | ||
exit 0 | ||
fi | ||
|
||
grid_in=$1 | ||
grid_mid=$2 | ||
out_folder=${3:-$(dirname $grid_in)} | ||
|
||
echo -e "\n Making new grid in: '$out_folder'" # -e enables interpretation of backslash escapes | ||
echo -e "\n Using: '$grid_in' & '$grid_mid'\n" | ||
|
||
# Area's default values: | ||
in0=${4:-1} | ||
mid=${5:-2} | ||
out=${6:-3} | ||
|
||
gridsufix=grid_${in0}${mid}${out} | ||
grid_name=$(basename ${grid_in%_grid_in*}) # e.g. 37A_l | ||
|
||
#echo $out_folder/${grid_name}_${gridsufix}.nii.gz | ||
|
||
#for side in l #r # left right | ||
|
||
#grid_in=$(find $out_folder -type f -iname "*_${side}_grid_in.nii.gz") | ||
#grid_mid=$(find $out_folder -type f -iname "*_${side}_grid_mid.nii.gz") | ||
|
||
#rat_id=$(basename ${grid_in%%_*}) | ||
|
||
#if [ -f "${out_folder}/${rat_id}_${side}_${gridsufix}.nii.gz" ] | ||
#then | ||
# echo -e "\n Archivo '${rat_id}_${side}_${gridsufix}.nii.gz' ya existe.\n\n" | ||
|
||
#elif [ -f "${rat_id}_${side}_grid_in.nii.gz" -a -f "${rat_id}_${side}_grid_mid.nii.gz" ] | ||
#elif [ -f $grid_in -a -f $grid_mid ] | ||
|
||
if [ -f "$out_folder/${grid_name}_${gridsufix}.nii.gz" ] | ||
then | ||
echo -e "\n File '${grid_name}_${gridsufix}.nii.gz' already exists.\n" | ||
elif [ -f $grid_in -a -f $grid_mid ] | ||
then | ||
#mrcalc ${rat_id}_${side}_grid_in.nii.gz 0 -mult $out -add base.nii | ||
mrcalc $grid_in 0 -mult $out -add ${out_folder}/base.nii | ||
|
||
mid_scalar="$(($mid-$out))" | ||
#mrcalc ${rat_id}_${side}_grid_mid.nii.gz $mid_scalar -mult base2.nii | ||
mrcalc $grid_mid $mid_scalar -mult ${out_folder}/base2.nii | ||
|
||
in_scalar="$(($in0-$out))" | ||
#mrcalc ${rat_id}_${side}_grid_in.nii.gz $in_scalar -mult base3.nii | ||
mrcalc $grid_in $in_scalar -mult ${out_folder}/base3.nii | ||
|
||
#mrcalc ${rat_id}_${side}_grid_in.nii.gz ${rat_id}_${side}_grid_mid.nii.gz -min $mid -mult base4.nii | ||
mrcalc $grid_in $grid_mid -min $mid -mult ${out_folder}/base4.nii | ||
|
||
#mrcalc base.nii base2.nii -add base3.nii -add base4.nii -add "${rat_id}_${side}_grid_${in0}${mid}${out}.nii.gz" | ||
a=${out_folder}/base.nii; b=${out_folder}/base2.nii | ||
c=${out_folder}/base3.nii; d=${out_folder}/base4.nii | ||
#mrcalc $a $b -add $c -add $d -add ${out_folder}/${rat_id}_${side}_${gridsufix}.nii.gz | ||
mrcalc $a $b -add $c -add $d -add $out_folder/${grid_name}_${gridsufix}.nii.gz | ||
|
||
gio trash ${out_folder}/base*.nii | ||
|
||
#nii2mnc ${out_folder}/${rat_id}_${side}_${gridsufix}.nii.gz ${out_folder}/${rat_id}_${side}_${gridsufix}.mnc | ||
nii2mnc $out_folder/${grid_name}_${gridsufix}.nii.gz $out_folder/${grid_name}_${gridsufix}.mnc | ||
|
||
echo -e "\n Grids '$out_folder/${grid_name}_${gridsufix}' (.mnc & .nii.gz) created in '$out_folder'\n" | ||
else | ||
echo -e "\n Error: files '$grid_in', '$grid_mid' missing.\n" | ||
fi | ||
|
||
|
Oops, something went wrong.