From 43ca4d0d6545edd9e7ec30a6d33c7efb41870b80 Mon Sep 17 00:00:00 2001 From: Mathieu Boudreau Date: Mon, 5 Feb 2024 15:30:33 -0400 Subject: [PATCH] Update to structure --- content/index.ipynb | 322 ++++++++++++++++++++++---------------------- 1 file changed, 161 insertions(+), 161 deletions(-) diff --git a/content/index.ipynb b/content/index.ipynb index 8ae1a6b..9907d36 100644 --- a/content/index.ipynb +++ b/content/index.ipynb @@ -1134,7 +1134,164 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Plots" + "# 7     |     Paper figures" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Prepare RF shimming mask for figure\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "hide_input" + ] + }, + "outputs": [], + "source": [ + "# Select subject to show\n", + "subject = 'sub-05'\n", + "os.chdir(os.path.join(path_data, subject, \"fmap\"))\n", + "\n", + "# Create RF shimming mask from the segmentation (re-create the live RF shimming procedure)\n", + "file_mask = f\"{subject}_acq-anatCP_TB1TFL_mask-shimming.nii.gz\"\n", + "if notebook != 'figures':\n", + "\n", + " !sct_maths -i {subject}_acq-anatCP_TB1TFL_seg_labeled.nii.gz -thr 3 -uthr 9 -o {file_mask}\n", + " !sct_maths -i {file_mask} -bin 1 -o {file_mask}\n", + " !sct_create_mask -i {subject}_acq-anatCP_TB1TFL.nii.gz -p centerline,{file_mask} -size 28mm -f cylinder -o {file_mask}\n", + "\n", + " # Dilate mask\n", + " !sct_maths -i {file_mask} -dilate 2 -shape disk -dim 2 -o {subject}_acq-anatCP_TB1TFL_mask-shimming_dil.nii.gz\n", + " # Subtract dilated mask with mask to get the edge\n", + " !sct_maths -i {subject}_acq-anatCP_TB1TFL_mask-shimming_dil.nii.gz -sub {file_mask} -o {file_mask}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create figure of B1+ maps" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "hide_input", + "report_output" + ] + }, + "outputs": [], + "source": [ + "# Select subject to show\n", + "subject = 'sub-05'\n", + "os.chdir(os.path.join(path_data, subject, \"fmap\"))\n", + "file_mask = f\"{subject}_acq-anatCP_TB1TFL_mask-shimming.nii.gz\"\n", + "\n", + "# Load the statistics from the CSV file\n", + "stats_df = pd.read_csv(os.path.join(path_results, 'stats_b1plus.csv'))\n", + "\n", + "# Filter for the specific subject\n", + "subject_stats = stats_df[stats_df['Subject'] == subject]\n", + "\n", + "# Defining crop limits for resulting figure\n", + "xmin = 20\n", + "xmax = 110\n", + "ymin = 20\n", + "ymax = 150\n", + "\n", + "# Defining dynamic range\n", + "dynmin = 5 \n", + "dynmax = 30\n", + "\n", + "# Create a figure with multiple subplots\n", + "fig, axes = plt.subplots(2, 4, figsize=(8, 6))\n", + "font_size = 14\n", + "axes=axes.flatten()\n", + "\n", + "# First, plot the anatomical image with an overlay of the mask\n", + "\n", + "# Load data\n", + "CP_anat=nib.load(f\"{subject}_acq-anatCP_TB1TFL.nii.gz\")\n", + "CP_SC=nib.load(file_mask)\n", + "CP_nTpV=nib.load(f\"{subject}_acq-CP_TB1map.nii.gz\")\n", + "\n", + "# Defining mask based on the magnitude image intensity threshold\n", + "cslice=CP_anat.shape[2] // 2 -2 #shows the SC seg best\n", + "threshold=300\n", + "mask=CP_anat.get_fdata()[xmin:xmax,ymin:ymax, cslice]\n", + "mask=np.where(mask > threshold, 1, 0)\n", + "\n", + "# Cropping anat, SC, B1+\n", + "CP_anat=CP_anat.get_fdata()[xmin:xmax,ymin:ymax, cslice]\n", + "CP_anat=CP_anat*mask\n", + "CP_SC=CP_SC.get_fdata()[xmin:xmax,ymin:ymax, cslice]\n", + "CP_nTpV=CP_nTpV.get_fdata()[xmin:xmax,ymin:ymax, cslice]\n", + "CP_nTpV=CP_nTpV*mask\n", + "\n", + "# All opacity overalys look ugly: workaround, set the anat slice to a max value where the segmentation exists\n", + "CP_anat[CP_SC>0.5]=4000;\n", + "\n", + "# Plotting anat overlayed with SC\n", + "splot=axes[0]\n", + "splot.imshow((CP_anat.T), cmap='gray', origin='lower',vmin=0,vmax=2000)#, interpolation='spline36')\n", + "splot.set_title('Anat', size=font_size)\n", + "splot.axis('off')\n", + "\n", + "# Then, plot each B1+ map, with an overlay of the mean and CV inside the cord\n", + "for i,shim_mode in enumerate(shim_modes):\n", + " # Load data\n", + " B1map=nib.load(f\"{subject}_acq-{shim_mode}_TB1map.nii.gz\")\n", + " B1map=B1map.get_fdata()[xmin:xmax,ymin:ymax, cslice]\n", + " B1map=B1map*mask\n", + "\n", + " # Plot\n", + " splot=axes[i+1]\n", + " im = splot.imshow((B1map.T), cmap='viridis', origin='lower',vmin=dynmin,vmax=dynmax)#, interpolation='spline36')\n", + " splot.set_title(shim_mode, size=font_size)\n", + " splot.axis('off')\n", + "\n", + " # Find the statistics for the current shim mode\n", + " shim_stats = subject_stats[subject_stats['Shim_Mode'] == shim_mode]\n", + " if not shim_stats.empty:\n", + " mean_val = shim_stats.iloc[0]['Average']\n", + " std_val = shim_stats.iloc[0]['Standard_Deviation']\n", + " cv = std_val / mean_val * 100 # Coefficient of variation in percentage\n", + " annotation_text = f\"{mean_val:.2f} nT/V\\n{cv:.2f}%\"\n", + " splot.annotate(annotation_text, (0.05, 0.95), xycoords='axes fraction', \n", + " fontsize=10, color='white', \n", + " verticalalignment='top', horizontalalignment='left')\n", + "\n", + "plt.tight_layout()\n", + "plt.subplots_adjust(wspace=0.1, hspace=0, right=0.9)\n", + "\n", + "# Colorbar\n", + "# Assume that the colorbar should start at the bottom of the lower row of subplots and\n", + "# extend to the top of the upper row of subplots\n", + "cbar_bottom = 0.06 # This might need adjustment\n", + "cbar_height = 0.83 # This represents the total height of both rows of subplots\n", + "cbar_ax = fig.add_axes([0.93, cbar_bottom, 0.03, cbar_height])\n", + "cbar = plt.colorbar(im, cax=cbar_ax)\n", + "\n", + "# cbar_ax = fig.add_axes([0.95, 0.5, 0.04, 0.4])\n", + "# cbar = plt.colorbar(im, cax=cbar_ax)\n", + "cbar_ax.set_title('nT/V', size=12)\n", + "plt.savefig(os.path.join(path_results, 'fig_b1plus_map.png'), dpi=300, format='png')\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Figure 2.B1+ efficiency for one participant (sub-05) across all seven RF shimming conditions. The top left panel shows the tfl_b1map magnitude image with an overlay of the mask that was used to perform RF shimming. Text inserts show the mean (in nT/V) and CoV (in %) of B1+ efficiency along the spinal cord between C3 and T2. " ] }, { @@ -1218,7 +1375,7 @@ " t2_datasets[subject][shim_mode]={}\n", " b1_datasets[subject][shim_mode]={}\n", "\n", - " t2_data=go.Line(\n", + " t2_data=go.scatter.Line(\n", " x=x_grid,\n", " y=t2_data_plotly[subject][shim_mode][0],\n", " name=shim_mode,\n", @@ -1227,7 +1384,7 @@ " showlegend=False\n", " )\n", "\n", - " b1_data=go.Line(\n", + " b1_data=go.scatter.Line(\n", " x=x_grid,\n", " y=b1_data_plotly[subject][shim_mode],\n", " name=shim_mode,\n", @@ -1397,164 +1554,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Figure 3.B1+ efficiency (A) and CSF/Cord signal ratio from the GRE scan (B) across subjects and across different RF shimming conditions. Data werewas measured in the spinal cord from C3 to T2 vertebral levels. To match the x-ticks across subjects, the C2-C3 and the T2-T3 intervertebral discs of each subject were aligned with that of the PAM50 template {cite:p}`DELEENER2018170`, and the curves were linearly scaled." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Prepare RF shimming mask for figure\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "hide_input" - ] - }, - "outputs": [], - "source": [ - "# Select subject to show\n", - "subject = 'sub-05'\n", - "os.chdir(os.path.join(path_data, subject, \"fmap\"))\n", - "\n", - "# Create RF shimming mask from the segmentation (re-create the live RF shimming procedure)\n", - "file_mask = f\"{subject}_acq-anatCP_TB1TFL_mask-shimming.nii.gz\"\n", - "if notebook != 'figures':\n", - "\n", - " !sct_maths -i {subject}_acq-anatCP_TB1TFL_seg_labeled.nii.gz -thr 3 -uthr 9 -o {file_mask}\n", - " !sct_maths -i {file_mask} -bin 1 -o {file_mask}\n", - " !sct_create_mask -i {subject}_acq-anatCP_TB1TFL.nii.gz -p centerline,{file_mask} -size 28mm -f cylinder -o {file_mask}\n", - "\n", - " # Dilate mask\n", - " !sct_maths -i {file_mask} -dilate 2 -shape disk -dim 2 -o {subject}_acq-anatCP_TB1TFL_mask-shimming_dil.nii.gz\n", - " # Subtract dilated mask with mask to get the edge\n", - " !sct_maths -i {subject}_acq-anatCP_TB1TFL_mask-shimming_dil.nii.gz -sub {file_mask} -o {file_mask}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create figure of B1+ maps" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "hide_input", - "report_output" - ] - }, - "outputs": [], - "source": [ - "# Select subject to show\n", - "subject = 'sub-05'\n", - "os.chdir(os.path.join(path_data, subject, \"fmap\"))\n", - "file_mask = f\"{subject}_acq-anatCP_TB1TFL_mask-shimming.nii.gz\"\n", - "\n", - "# Load the statistics from the CSV file\n", - "stats_df = pd.read_csv(os.path.join(path_results, 'stats_b1plus.csv'))\n", - "\n", - "# Filter for the specific subject\n", - "subject_stats = stats_df[stats_df['Subject'] == subject]\n", - "\n", - "# Defining crop limits for resulting figure\n", - "xmin = 20\n", - "xmax = 110\n", - "ymin = 20\n", - "ymax = 150\n", - "\n", - "# Defining dynamic range\n", - "dynmin = 5 \n", - "dynmax = 30\n", - "\n", - "# Create a figure with multiple subplots\n", - "fig, axes = plt.subplots(2, 4, figsize=(8, 6))\n", - "font_size = 14\n", - "axes=axes.flatten()\n", - "\n", - "# First, plot the anatomical image with an overlay of the mask\n", - "\n", - "# Load data\n", - "CP_anat=nib.load(f\"{subject}_acq-anatCP_TB1TFL.nii.gz\")\n", - "CP_SC=nib.load(file_mask)\n", - "CP_nTpV=nib.load(f\"{subject}_acq-CP_TB1map.nii.gz\")\n", - "\n", - "# Defining mask based on the magnitude image intensity threshold\n", - "cslice=CP_anat.shape[2] // 2 -2 #shows the SC seg best\n", - "threshold=300\n", - "mask=CP_anat.get_fdata()[xmin:xmax,ymin:ymax, cslice]\n", - "mask=np.where(mask > threshold, 1, 0)\n", - "\n", - "# Cropping anat, SC, B1+\n", - "CP_anat=CP_anat.get_fdata()[xmin:xmax,ymin:ymax, cslice]\n", - "CP_anat=CP_anat*mask\n", - "CP_SC=CP_SC.get_fdata()[xmin:xmax,ymin:ymax, cslice]\n", - "CP_nTpV=CP_nTpV.get_fdata()[xmin:xmax,ymin:ymax, cslice]\n", - "CP_nTpV=CP_nTpV*mask\n", - "\n", - "# All opacity overalys look ugly: workaround, set the anat slice to a max value where the segmentation exists\n", - "CP_anat[CP_SC>0.5]=4000;\n", - "\n", - "# Plotting anat overlayed with SC\n", - "splot=axes[0]\n", - "splot.imshow((CP_anat.T), cmap='gray', origin='lower',vmin=0,vmax=2000)#, interpolation='spline36')\n", - "splot.set_title('Anat', size=font_size)\n", - "splot.axis('off')\n", - "\n", - "# Then, plot each B1+ map, with an overlay of the mean and CV inside the cord\n", - "for i,shim_mode in enumerate(shim_modes):\n", - " # Load data\n", - " B1map=nib.load(f\"{subject}_acq-{shim_mode}_TB1map.nii.gz\")\n", - " B1map=B1map.get_fdata()[xmin:xmax,ymin:ymax, cslice]\n", - " B1map=B1map*mask\n", - "\n", - " # Plot\n", - " splot=axes[i+1]\n", - " im = splot.imshow((B1map.T), cmap='viridis', origin='lower',vmin=dynmin,vmax=dynmax)#, interpolation='spline36')\n", - " splot.set_title(shim_mode, size=font_size)\n", - " splot.axis('off')\n", - "\n", - " # Find the statistics for the current shim mode\n", - " shim_stats = subject_stats[subject_stats['Shim_Mode'] == shim_mode]\n", - " if not shim_stats.empty:\n", - " mean_val = shim_stats.iloc[0]['Average']\n", - " std_val = shim_stats.iloc[0]['Standard_Deviation']\n", - " cv = std_val / mean_val * 100 # Coefficient of variation in percentage\n", - " annotation_text = f\"{mean_val:.2f} nT/V\\n{cv:.2f}%\"\n", - " splot.annotate(annotation_text, (0.05, 0.95), xycoords='axes fraction', \n", - " fontsize=10, color='white', \n", - " verticalalignment='top', horizontalalignment='left')\n", - "\n", - "plt.tight_layout()\n", - "plt.subplots_adjust(wspace=0.1, hspace=0, right=0.9)\n", - "\n", - "# Colorbar\n", - "# Assume that the colorbar should start at the bottom of the lower row of subplots and\n", - "# extend to the top of the upper row of subplots\n", - "cbar_bottom = 0.06 # This might need adjustment\n", - "cbar_height = 0.83 # This represents the total height of both rows of subplots\n", - "cbar_ax = fig.add_axes([0.93, cbar_bottom, 0.03, cbar_height])\n", - "cbar = plt.colorbar(im, cax=cbar_ax)\n", - "\n", - "# cbar_ax = fig.add_axes([0.95, 0.5, 0.04, 0.4])\n", - "# cbar = plt.colorbar(im, cax=cbar_ax)\n", - "cbar_ax.set_title('nT/V', size=12)\n", - "plt.savefig(os.path.join(path_results, 'fig_b1plus_map.png'), dpi=300, format='png')\n", - "plt.show()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Figure 2.B1+ efficiency for one participant (sub-05) across all seven RF shimming conditions. The top left panel shows the tfl_b1map magnitude image with an overlay of the mask that was used to perform RF shimming. Text inserts show the mean (in nT/V) and CoV (in %) of B1+ efficiency along the spinal cord between C3 and T2. " + "Figure 3.B1+ efficiency (A) and CSF/Cord signal ratio from the GRE scan (B) across subjects and across different RF shimming conditions. Data werewas measured in the spinal cord from C3 to T2 vertebral levels. To match the x-ticks across subjects, the C2-C3 and the T2-T3 intervertebral discs of each subject were aligned with that of the PAM50 template {cite:p}`DELEENER2018170`, and the curves were linearly scaled.\n" ] }, {