Skip to content
Snippets Groups Projects
Commit 803bea7a authored by Sean Fitzgibbon's avatar Sean Fitzgibbon
Browse files

updated documentation

parent 7f7b1ab6
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Fetch Data # Fetch Data
This notebook will download an open fMRI dataset (~50MB) for use in the MIGP demo. It also regresses confounds from the data and performs spatial smoothing with 10mm FWHM. This notebook will download an open fMRI dataset (~50MB) for use in the MIGP demo. It also regresses confounds from the data and performs spatial smoothing with 10mm FWHM.
This data is a derivative from the COBRE sample found in the International Neuroimaging Data-sharing Initiative (http://fcon_1000.projects.nitrc.org/indi/retro/cobre.html), originally released under Creative Commons - Attribution Non-Commercial. This data is a derivative from the COBRE sample found in the International Neuroimaging Data-sharing Initiative (http://fcon_1000.projects.nitrc.org/indi/retro/cobre.html), originally released under Creative Commons - Attribution Non-Commercial.
It comprises 10 preprocessed resting-state fMRI selected from 72 patients diagnosed with schizophrenia and 74 healthy controls (6mm isotropic, TR=2s, 150 volumes). It comprises 10 preprocessed resting-state fMRI selected from 72 patients diagnosed with schizophrenia and 74 healthy controls (6mm isotropic, TR=2s, 150 volumes).
* [Download the data](#download-the-data) * [Download the data](#download-the-data)
* [Clean the data](#clean-the-data) * [Clean the data](#clean-the-data)
* [Run `melodic`](#run-melodic) * [Run `melodic`](#run-melodic)
* [Plot group ICs](#plot-group-ics)
Firstly we will import the necessary packages for this notebook: Firstly we will import the necessary packages for this notebook:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
from nilearn import datasets from nilearn import datasets
from nilearn import image from nilearn import image
from nilearn import plotting from nilearn import plotting
import nibabel as nb import nibabel as nb
import numpy as np import numpy as np
import os.path as op import os.path as op
import os import os
import glob import glob
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
This function will be used to plot ICs later: This function will be used to plot ICs later:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def map_plot(d): def map_plot(d):
N = d.shape[-1] N = d.shape[-1]
fig, ax = plt.subplots(int(np.ceil((N/2))),2, figsize=(12, N)) fig, ax = plt.subplots(int(np.ceil((N/2))),2, figsize=(12, N))
for img, ax0 in zip(image.iter_img(d), ax.ravel()): for img, ax0 in zip(image.iter_img(d), ax.ravel()):
coord = plotting.find_xyz_cut_coords(img, activation_threshold=2.3) coord = plotting.find_xyz_cut_coords(img, activation_threshold=2.3)
plotting.plot_stat_map(img, cut_coords=coord, vmax=10, axes=ax0) plotting.plot_stat_map(img, cut_coords=coord, vmax=10, axes=ax0)
return fig return fig
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<a class="anchor" id="download-the-data"></a> <a class="anchor" id="download-the-data"></a>
## Download the data ## Download the data
Create a directory in the users home directory to store the downloaded data: Create a directory in the users home directory to store the downloaded data:
`expanduser` will expand the `~` to the be users home directory: `expanduser` will expand the `~` to the be users home directory:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
data_dir = op.expanduser('~/nilearn_data') data_dir = op.expanduser('~/nilearn_data')
if not op.exists(data_dir): if not op.exists(data_dir):
os.makedirs(data_dir) os.makedirs(data_dir)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Download the data (if not already downloaded). We use a method from [`nilearn`](https://nilearn.github.io/index.html) called `fetch_cobre` to download the fMRI data: Download the data (if not already downloaded). We use a method from [`nilearn`](https://nilearn.github.io/index.html) called `fetch_cobre` to download the fMRI data:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
d = datasets.fetch_cobre(data_dir=data_dir) d = datasets.fetch_cobre(data_dir=data_dir)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<a class="anchor" id="clean-the-data"></a> <a class="anchor" id="clean-the-data"></a>
## Clean the data ## Clean the data
We use methods from [`nilearn`](https://nilearn.github.io/index.html) to regress confounds from the data (```clean_img```) and to spatially smooth the data with a gaussian filter of 10mm FWHM (```smooth_img```): We use methods from [`nilearn`](https://nilearn.github.io/index.html) to regress confounds from the data (```clean_img```) and to spatially smooth the data with a gaussian filter of 10mm FWHM (```smooth_img```):
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# Create a list of filenames for cleaned and smoothed data # Create a list of filenames for cleaned and smoothed data
clean = [f.replace('.nii.gz', '_clean.nii.gz') for f in d.func] clean = [f.replace('.nii.gz', '_clean.nii.gz') for f in d.func]
smooth = [f.replace('.nii.gz', '_clean_smooth.nii.gz') for f in d.func] smooth = [f.replace('.nii.gz', '_clean_smooth.nii.gz') for f in d.func]
# loop through each subject, regress confounds and smooth # loop through each subject, regress confounds and smooth
for img, cleaned, smoothed, conf in zip(d.func, clean, smooth, d.confounds): for img, cleaned, smoothed, conf in zip(d.func, clean, smooth, d.confounds):
print(f'{img}: regress confounds: ', end='')
image.clean_img(img, confounds=conf).to_filename(cleaned) image.clean_img(img, confounds=conf).to_filename(cleaned)
print(f'smooth.')
image.smooth_img(img, 10).to_filename(smoothed) image.smooth_img(img, 10).to_filename(smoothed)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
To run ```melodic``` we will need a brain mask in MNI152 space at the same resolution as the fMRI. Here we use [`nilearn`](https://nilearn.github.io/index.html) methods to load the MNI152 mask (```load_mni152_brain_mask```), resample to the resolution of the fMRI (```resample_to_img```), and binarize (```math_img```): To run ```melodic``` we will need a brain mask in MNI152 space at the same resolution as the fMRI. Here we use [`nilearn`](https://nilearn.github.io/index.html) methods to load the MNI152 mask (```load_mni152_brain_mask```), resample to the resolution of the fMRI (```resample_to_img```), and binarize (```math_img```):
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# load a single fMRI dataset (func0) # load a single fMRI dataset (func0)
func0 = nb.load(d.func[0].replace('.nii.gz', '_clean_smooth.nii.gz')) func0 = nb.load(d.func[0].replace('.nii.gz', '_clean_smooth.nii.gz'))
# load MNI153 brainmask, resample to func0 resolution, binarize, and save to nifti # load MNI153 brainmask, resample to func0 resolution, binarize, and save to nifti
mask = datasets.load_mni152_brain_mask() mask = datasets.load_mni152_brain_mask()
mask = image.resample_to_img(mask, func0) mask = image.resample_to_img(mask, func0)
mask = image.math_img('img > 0.5', img=mask) mask = image.math_img('img > 0.5', img=mask)
mask.to_filename(op.join(data_dir, 'brain_mask.nii.gz')) mask.to_filename(op.join(data_dir, 'brain_mask.nii.gz'))
# plot brainmask to make sure it looks OK # plot brainmask to make sure it looks OK
disp = plotting.plot_anat(image.index_img(func0, 0)) disp = plotting.plot_anat(image.index_img(func0, 0))
disp.add_contours(mask, threshold=0.5) disp.add_contours(mask, threshold=0.5)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<a class="anchor" id="run-melodic"></a> <a class="anchor" id="run-melodic"></a>
### Run ```melodic``` ### Run ```melodic```
Generate a command line string and run group ```melodic``` on the smoothed fMRI with a dimension of 10 components: Generate a command line string and run group ```melodic``` on the smoothed fMRI with a dimension of 10 components:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# generate melodic command line string # generate melodic command line string
melodic_cmd = f"melodic -i {','.join(smooth)} --mask={op.join(data_dir, 'brain_mask.nii.gz')} -d 10 -v -o cobre.gica " melodic_cmd = f"melodic -i {','.join(smooth)} --mask={op.join(data_dir, 'brain_mask.nii.gz')} -d 10 -v -o cobre.gica "
print(melodic_cmd) print(melodic_cmd)
```
%% Cell type:code id: tags:
``` python
# run melodic # run melodic
! {melodic_cmd} ! {melodic_cmd}
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<a class="anchor" id="plot-group-ics"></a>
### Plot group ICs
Now we can load and plot the group ICs generated by ```melodic```. Now we can load and plot the group ICs generated by ```melodic```.
This function will be used to plot ICs:
%% Cell type:code id: tags:
``` python
def map_plot(d):
N = d.shape[-1]
fig, ax = plt.subplots(int(np.ceil((N/2))),2, figsize=(12, N))
for img, ax0 in zip(image.iter_img(d), ax.ravel()):
coord = plotting.find_xyz_cut_coords(img, activation_threshold=3.5)
plotting.plot_stat_map(img, cut_coords=coord, vmax=10, axes=ax0)
return fig
```
%% Cell type:markdown id: tags:
Hopefully you can see some familiar looking RSN spatial patterns: Hopefully you can see some familiar looking RSN spatial patterns:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# Load ICs
ics = nb.load('cobre.gica/melodic_IC.nii.gz') ics = nb.load('cobre.gica/melodic_IC.nii.gz')
# plot
fig = map_plot(ics) fig = map_plot(ics)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
``` ```
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Matlab MIGP ## Matlab MIGP
This notebook will load the dimension reduced data from Matlab MIGP, run group ICA, and then plot the group ICs. This notebook will load the dimension reduced data from Matlab MIGP, run group ICA, and then plot the group ICs.
* [Run `melodic`](#run-melodic) * [Run `melodic`](#run-matlab-melodic)
* [Plot group ICs](#plot-group-ics) * [Plot group ICs](#plot-matlab-group-ics)
Firstly we will import the necessary packages for this notebook: Firstly we will import the necessary packages for this notebook:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
from nilearn import plotting from nilearn import plotting
from nilearn import image from nilearn import image
import nibabel as nb import nibabel as nb
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
import os.path as op import os.path as op
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
It will be necessary to know the location where the data was stored so that we can load the brainmask. It will be necessary to know the location where the data was stored so that we can load the brainmask.
`expanduser` will expand the `~` to the be users home directory: `expanduser` will expand the `~` to the be users home directory:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
data_dir = op.expanduser('~/nilearn_data') data_dir = op.expanduser('~/nilearn_data')
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<a class="anchor" id="run-melodic"></a> <a class="anchor" id="run-matlab-melodic"></a>
### Run ```melodic``` ### Run ```melodic```
Generate a command line string and run group ```melodic``` on the Matlab MIGP dimension reduced data with a dimension of 10 components: Generate a command line string and run group ```melodic``` on the Matlab MIGP dimension reduced data with a dimension of 10 components:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# generate melodic command line string # generate melodic command line string
melodic_cmd = f"melodic -i matMIGP.nii.gz --mask={op.join(data_dir, 'brain_mask.nii.gz')} -d 10 -v --nobet --disableMigp -o matmigp.gica" melodic_cmd = f"melodic -i matMIGP.nii.gz --mask={op.join(data_dir, 'brain_mask.nii.gz')} -d 10 -v --nobet --disableMigp -o matmigp.gica"
print(melodic_cmd) print(melodic_cmd)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# run melodic # run melodic
! {melodic_cmd} ! {melodic_cmd}
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<a class="anchor" id="plot-group-ics"></a> <a class="anchor" id="plot-matlab-group-ics"></a>
### Plot group ICs ### Plot group ICs
Now we can load and plot the group ICs generated by ```melodic```. Now we can load and plot the group ICs generated by ```melodic```.
This function will be used to plot ICs: This function will be used to plot ICs:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def map_plot(d): def map_plot(d):
N = d.shape[-1] N = d.shape[-1]
fig, ax = plt.subplots(int(np.ceil((N/2))),2, figsize=(12, N)) fig, ax = plt.subplots(int(np.ceil((N/2))),2, figsize=(12, N))
for img, ax0 in zip(image.iter_img(d), ax.ravel()): for img, ax0 in zip(image.iter_img(d), ax.ravel()):
coord = plotting.find_xyz_cut_coords(img, activation_threshold=3.5) coord = plotting.find_xyz_cut_coords(img, activation_threshold=3.5)
plotting.plot_stat_map(img, cut_coords=coord, vmax=10, axes=ax0) plotting.plot_stat_map(img, cut_coords=coord, vmax=10, axes=ax0)
return fig return fig
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Hopefully you can see some familiar looking RSN spatial patterns: Hopefully you can see some familiar looking RSN spatial patterns:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
ics = nb.load('matmigp.gica/melodic_IC.nii.gz') ics = nb.load('matmigp.gica/melodic_IC.nii.gz')
fig = map_plot(ics) fig = map_plot(ics)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
``` ```
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Python MIGP ## Python MIGP
This notebook will perform *python* MIGP dimension reduction, run group ICA, and then plot the group ICs. This notebook will perform *python* MIGP dimension reduction, run group ICA, and then plot the group ICs.
* [Run python `MIGP`](#run-python-migp) * [Run python `MIGP`](#run-python-migp)
* [Run `melodic`](#run-melodic) * [Run `melodic`](#run-python-melodic)
* [Plot group ICs](#plot-group-ics) * [Plot group ICs](#plot-python-group-ics)
Firstly we will import the necessary packages for this notebook: Firstly we will import the necessary packages for this notebook:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
import glob import glob
import random import random
import nibabel as nb import nibabel as nb
import numpy as np import numpy as np
from scipy.sparse.linalg import svds, eigs from scipy.sparse.linalg import svds, eigs
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from nilearn import plotting from nilearn import plotting
from nilearn import image from nilearn import image
import os.path as op import os.path as op
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
It will be necessary to know the location where the data was stored so that we can load the brainmask. It will be necessary to know the location where the data was stored so that we can load the brainmask.
`expanduser` will expand the `~` to the be users home directory: `expanduser` will expand the `~` to the be users home directory:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
data_dir = op.expanduser('~/nilearn_data') data_dir = op.expanduser('~/nilearn_data')
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<a class="anchor" id="run-python-migp"></a> <a class="anchor" id="run-python-migp"></a>
### Run python `MIGP` ### Run python `MIGP`
Firstly we need to set the MIGP parameters: Firstly we need to set the MIGP parameters:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# create lists of (nibabel) image objects # create lists of (nibabel) image objects
in_list = [nb.load(f) for f in glob.glob(f'{data_dir}/cobre/fmri_*_smooth.nii.gz')] in_list = [nb.load(f) for f in glob.glob(f'{data_dir}/cobre/fmri_*_smooth.nii.gz')]
in_mask = nb.load(f'{data_dir}/brain_mask.nii.gz') in_mask = nb.load(f'{data_dir}/brain_mask.nii.gz')
# set user parameters (equivalent to melodic defaults) # set user parameters (equivalent to melodic defaults)
GO = 'pyMIGP.nii.gz' # output filename GO = 'pyMIGP.nii.gz' # output filename
dPCA_int = 299 # internal number of components - typically 2-4 times number of timepoints in each run (if you have enough RAM for that) dPCA_int = 299 # internal number of components - typically 2-4 times number of timepoints in each run (if you have enough RAM for that)
dPCA_out = 299 # number of eigenvectors to output - should be less than dPCAint and more than the final ICA dimensionality dPCA_out = 299 # number of eigenvectors to output - should be less than dPCAint and more than the final ICA dimensionality
sep_vn = False # switch on separate variance nomalisation for each input dataset sep_vn = False # switch on separate variance nomalisation for each input dataset
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# randomise the subject order # randomise the subject order
random.shuffle(in_list) random.shuffle(in_list)
# load and unravel brainmask # load and unravel brainmask
mask = in_mask.get_fdata().ravel() mask = in_mask.get_fdata().ravel()
# function to demean the data # function to demean the data
def demean(x): def demean(x):
return x - np.mean(x, axis=0) return x - np.mean(x, axis=0)
# loop through input files/subjects # loop through input files/subjects
for i, f in enumerate(in_list): for i, f in enumerate(in_list):
# read data # read data
print(f'Reading data file {f.get_filename()}') print(f'Reading data file {f.get_filename()}')
grot = f.get_fdata() grot = f.get_fdata()
grot = np.reshape(grot, [-1, grot.shape[-1]]) grot = np.reshape(grot, [-1, grot.shape[-1]])
grot = grot[mask!=0, :].T grot = grot[mask!=0, :].T
# demean # demean
print(f'\tRemoving mean image') print(f'\tRemoving mean image')
grot = demean(grot) grot = demean(grot)
# var-norm # var-norm
if sep_vn: if sep_vn:
print(f'\tNormalising by voxel-wise variance') print(f'\tNormalising by voxel-wise variance')
[uu, ss, vt] = svds(grot, k=30) [uu, ss, vt] = svds(grot, k=30)
vt[np.abs(vt) < (2.3 * np.std(vt))] = 0; vt[np.abs(vt) < (2.3 * np.std(vt))] = 0;
stddevs = np.maximum(np.std(grot - (uu @ np.diag(ss) @ vt), axis=0), 0.001) stddevs = np.maximum(np.std(grot - (uu @ np.diag(ss) @ vt), axis=0), 0.001)
grot = grot/stddevs grot = grot/stddevs
if i == 0: if i == 0:
W = demean(grot) W = demean(grot)
else: else:
# concat # concat
W = np.concatenate((W, demean(grot)), axis=0) W = np.concatenate((W, demean(grot)), axis=0)
# reduce W to dPCA_int eigenvectors # reduce W to dPCA_int eigenvectors
if W.shape[0]-10 > dPCA_int: if W.shape[0]-10 > dPCA_int:
print(f'\tReducing data matrix to a {dPCA_int} dimensional subspace') print(f'\tReducing data matrix to a {dPCA_int} dimensional subspace')
uu = eigs(W@W.T, dPCA_int)[1] uu = eigs(W@W.T, dPCA_int)[1]
uu = np.real(uu) uu = np.real(uu)
W = uu.T @ W W = uu.T @ W
# reshape and save # reshape and save
grot = np.zeros([mask.shape[0], dPCA_out]) grot = np.zeros([mask.shape[0], dPCA_out])
grot[mask!=0, :] = W[:dPCA_out, :].T grot[mask!=0, :] = W[:dPCA_out, :].T
grot = np.reshape(grot, in_list[0].shape[:3] + (dPCA_out,)) grot = np.reshape(grot, in_list[0].shape[:3] + (dPCA_out,))
print(f'Save to {GO}') print(f'Save to {GO}')
nb.Nifti1Image(grot, affine=in_list[0].affine).to_filename(GO) nb.Nifti1Image(grot, affine=in_list[0].affine).to_filename(GO)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<a class="anchor" id="run-melodic"></a> <a class="anchor" id="run-python-melodic"></a>
### Run ```melodic``` ### Run ```melodic```
Generate a command line string and run group ```melodic``` on the Python MIGP dimension reduced data with a dimension of 10 components: Generate a command line string and run group ```melodic``` on the Python MIGP dimension reduced data with a dimension of 10 components:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# generate melodic command line string # generate melodic command line string
melodic_cmd = f"melodic -i pyMIGP.nii.gz --mask={op.join(data_dir, 'brain_mask.nii.gz')} -d 10 -v --nobet --disableMigp -o pymigp.gica" melodic_cmd = f"melodic -i pyMIGP.nii.gz --mask={op.join(data_dir, 'brain_mask.nii.gz')} -d 10 -v --nobet --disableMigp -o pymigp.gica"
print(melodic_cmd) print(melodic_cmd)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# run melodic # run melodic
! {melodic_cmd} ! {melodic_cmd}
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<a class="anchor" id="plot-group-ics"></a> <a class="anchor" id="plot-python-group-ics"></a>
### Plot group ICs ### Plot group ICs
Now we can load and plot the group ICs generated by ```melodic```. Now we can load and plot the group ICs generated by ```melodic```.
This function will be used to plot ICs: This function will be used to plot ICs:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def map_plot(d): def map_plot(d):
N = d.shape[-1] N = d.shape[-1]
fig, ax = plt.subplots(int(np.ceil((N/2))),2, figsize=(12, N)) fig, ax = plt.subplots(int(np.ceil((N/2))),2, figsize=(12, N))
for img, ax0 in zip(image.iter_img(d), ax.ravel()): for img, ax0 in zip(image.iter_img(d), ax.ravel()):
coord = plotting.find_xyz_cut_coords(img, activation_threshold=3.5) coord = plotting.find_xyz_cut_coords(img, activation_threshold=3.5)
plotting.plot_stat_map(img, cut_coords=coord, vmax=10, axes=ax0) plotting.plot_stat_map(img, cut_coords=coord, vmax=10, axes=ax0)
return fig return fig
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Hopefully you can see some familiar looking RSN spatial patterns: Hopefully you can see some familiar looking RSN spatial patterns:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
ics = nb.load('pymigp.gica/melodic_IC.nii.gz') ics = nb.load('pymigp.gica/melodic_IC.nii.gz')
fig = map_plot(ics) fig = map_plot(ics)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
``` ```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment