From dfed1e38d5e6b221ef681ca6cd721a734c99476c Mon Sep 17 00:00:00 2001
From: Ehsan Karimi <39439514+ehkarimi@users.noreply.github.com>
Date: Sat, 10 Dec 2022 08:03:08 -0500
Subject: [PATCH 1/4] Update io.py

there was a problem with reading the stats files
---
 nibabel/freesurfer/io.py | 56 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/nibabel/freesurfer/io.py b/nibabel/freesurfer/io.py
index e2f48d88eb..b7d294b120 100644
--- a/nibabel/freesurfer/io.py
+++ b/nibabel/freesurfer/io.py
@@ -1,10 +1,13 @@
-""" Read / write FreeSurfer geometry, morphometry, label, annotation formats
+""" Read / write FreeSurfer geometry, morphometry, label, stats, annotation formats
 """
+from __future__ import annotations
 
 import warnings
 import numpy as np
 import getpass
 import time
+import re 
+import pandas as pd
 
 from collections import OrderedDict
 from ..openers import Opener
@@ -622,3 +625,54 @@ def _serialize_volume_info(volume_info):
             strings.append(
                 f'{key:6s} = {val[0]:.10g} {val[1]:.10g} {val[2]:.10g}\n'.encode('utf-8'))
     return b''.join(strings)
+
+
+class StatsFileReader:
+
+    @staticmethod
+    def read_stats_file(file_path):
+        """Extracts stats from stats files except '*curv.stats' files
+
+        Parameters
+        ----------
+        file_path: str, required
+
+        Returns
+        -------
+
+        """
+        with open(file_path, 'r') as f:
+            for line in f:
+                if re.findall(r'ColHeaders .*', line):
+                    parameters = line.split()
+                    break
+        f.close()
+        stats = np.loadtxt(file_path, comments='#', dtype=str)
+        df_stats = pd.DataFrame(stats, columns=parameters[2:])
+        df_stats.set_index('StructName', drop=True, inplace=True)
+        return df_stats
+
+    @staticmethod
+    def read_stats_file_both_hemispheres(file_path: str):
+        """Extracts stats data of both hemisphers and merges them
+
+        Parameters
+        ----------
+        file_path: str, required
+            Path of the stats file belong to left (lh) or right(rh) hemisphere
+
+        Returns
+        -------
+        df_both_hemispheres: pd.DataFrame
+            Stats data of both hemisphers
+
+        Examples
+        --------
+        >>> df_stats_a2009 = StatsFileReader.read_stats_file(r'lh.aparc.a2009s.stats')
+
+        """
+        df_left = StatsFileReader.read_stats_file(file_path.replace('rh', 'lh'))
+        df_right = StatsFileReader.read_stats_file(file_path.replace('lh', 'rh'))
+        df_both_hemispheres = pd.merge(df_left, df_right, suffixes=('_lh', '_rh'), how='outer', left_index=True,
+                                       right_index=True)
+        return df_both_hemispheres

From 84d6e047cb4e928dc15b88ad8dc277bc12c87669 Mon Sep 17 00:00:00 2001
From: Ehsan Karimi <39439514+ehkarimi@users.noreply.github.com>
Date: Sat, 10 Dec 2022 12:04:20 -0500
Subject: [PATCH 2/4] Stats file reader functions are added

---
 nibabel/freesurfer/io.py | 100 +++++++++++++++++++--------------------
 1 file changed, 49 insertions(+), 51 deletions(-)

diff --git a/nibabel/freesurfer/io.py b/nibabel/freesurfer/io.py
index b7d294b120..048dd3bdfa 100644
--- a/nibabel/freesurfer/io.py
+++ b/nibabel/freesurfer/io.py
@@ -6,8 +6,7 @@
 import numpy as np
 import getpass
 import time
-import re 
-import pandas as pd
+import re
 
 from collections import OrderedDict
 from ..openers import Opener
@@ -626,53 +625,52 @@ def _serialize_volume_info(volume_info):
                 f'{key:6s} = {val[0]:.10g} {val[1]:.10g} {val[2]:.10g}\n'.encode('utf-8'))
     return b''.join(strings)
 
+def read_stats_file(file_path):
+    """Extracts stats from stats files except '*curv.stats' files
 
-class StatsFileReader:
-
-    @staticmethod
-    def read_stats_file(file_path):
-        """Extracts stats from stats files except '*curv.stats' files
-
-        Parameters
-        ----------
-        file_path: str, required
-
-        Returns
-        -------
-
-        """
-        with open(file_path, 'r') as f:
-            for line in f:
-                if re.findall(r'ColHeaders .*', line):
-                    parameters = line.split()
-                    break
-        f.close()
-        stats = np.loadtxt(file_path, comments='#', dtype=str)
-        df_stats = pd.DataFrame(stats, columns=parameters[2:])
-        df_stats.set_index('StructName', drop=True, inplace=True)
-        return df_stats
-
-    @staticmethod
-    def read_stats_file_both_hemispheres(file_path: str):
-        """Extracts stats data of both hemisphers and merges them
-
-        Parameters
-        ----------
-        file_path: str, required
-            Path of the stats file belong to left (lh) or right(rh) hemisphere
-
-        Returns
-        -------
-        df_both_hemispheres: pd.DataFrame
-            Stats data of both hemisphers
-
-        Examples
-        --------
-        >>> df_stats_a2009 = StatsFileReader.read_stats_file(r'lh.aparc.a2009s.stats')
-
-        """
-        df_left = StatsFileReader.read_stats_file(file_path.replace('rh', 'lh'))
-        df_right = StatsFileReader.read_stats_file(file_path.replace('lh', 'rh'))
-        df_both_hemispheres = pd.merge(df_left, df_right, suffixes=('_lh', '_rh'), how='outer', left_index=True,
-                                       right_index=True)
-        return df_both_hemispheres
+    Parameters
+    ----------
+    file_path: str, required
+
+    Examples
+    --------
+    >>> stats_a2009, column_names = read_stats_file(r'lh.aparc.a2009s.stats')
+
+    """
+    with open(file_path, 'r') as f:
+        for line in f:
+            if re.findall(r'ColHeaders .*', line):
+                parameters = line.split()
+                break
+    f.close()
+    stats = np.loadtxt(file_path, comments='#', dtype=str)
+    column_names = parameters[2:]
+    return stats, column_names
+
+
+def read_stats_file_both_hemispheres(file_path: str):
+    """Extracts stats data of both hemispheres and merges them
+
+    Parameters
+    ----------
+    file_path: str, required
+        Path of the stats file belong to left (lh) or right(rh) hemisphere
+
+    Returns
+    -------
+    stats_both_hemispheres: ndarray
+        Stats data of both hemisphers
+    column_naems: ndarray
+        Name of columns
+
+    Examples
+    --------
+    >>> stats_a2009, column_names = read_stats_file_both_hemispheres(r'lh.aparc.a2009s.stats')
+
+    """
+    stats_left, columns_left = read_stats_file(file_path.replace('rh', 'lh'))
+    stats_right, columns_right = read_stats_file(file_path.replace('lh', 'rh'))
+    stats_both_hemispheres = np.concatenate((stats_left, stats_right[:, 1:]), axis=1)
+    column_names = [col_name + '_left' for col_name in columns_left] + [col_name + '_right' for col_name in
+                                                                        columns_right[1:]]
+    return stats_both_hemispheres, column_names

From 8880a1ae4a2ead0cb3ff04e6ef633b4694dcbddf Mon Sep 17 00:00:00 2001
From: "Simon(Ehsan) Karimi" <39439514+simkarwin@users.noreply.github.com>
Date: Wed, 5 Apr 2023 03:53:57 -0400
Subject: [PATCH 3/4] Update nibabel/freesurfer/io.py

Co-authored-by: Chris Markiewicz <effigies@gmail.com>
---
 nibabel/freesurfer/io.py | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/nibabel/freesurfer/io.py b/nibabel/freesurfer/io.py
index 048dd3bdfa..bcf10ccdbd 100644
--- a/nibabel/freesurfer/io.py
+++ b/nibabel/freesurfer/io.py
@@ -639,13 +639,10 @@ def read_stats_file(file_path):
     """
     with open(file_path, 'r') as f:
         for line in f:
-            if re.findall(r'ColHeaders .*', line):
-                parameters = line.split()
+            if line.startswith('# ColHeaders '):
+                columns = line.split()[2:]
                 break
-    f.close()
-    stats = np.loadtxt(file_path, comments='#', dtype=str)
-    column_names = parameters[2:]
-    return stats, column_names
+        return np.genfromtxt(f, dtype=None, names=columns, encoding='utf-8')
 
 
 def read_stats_file_both_hemispheres(file_path: str):

From 97107b7b8ba71e385dc39db8d57e9883050922c3 Mon Sep 17 00:00:00 2001
From: "Simon(Ehsan) Karimi" <39439514+simkarwin@users.noreply.github.com>
Date: Wed, 5 Apr 2023 03:54:29 -0400
Subject: [PATCH 4/4] Update nibabel/freesurfer/io.py

Co-authored-by: Chris Markiewicz <effigies@gmail.com>
---
 nibabel/freesurfer/io.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/nibabel/freesurfer/io.py b/nibabel/freesurfer/io.py
index bcf10ccdbd..dda6117f5b 100644
--- a/nibabel/freesurfer/io.py
+++ b/nibabel/freesurfer/io.py
@@ -6,7 +6,6 @@
 import numpy as np
 import getpass
 import time
-import re
 
 from collections import OrderedDict
 from ..openers import Opener