codecov-io: # [Codecov](https://codecov.io/gh/kutaslab/fitgrid/pull/39?src=pr&el=h1) Report
> Merging [#39](https://codecov.io/gh/kutaslab/fitgrid/pull/39?src=pr&el=desc) into [master](https://codecov.io/gh/kutaslab/fitgrid/commit/06e5803882f11412adf99d32c57f04381d581ffa?src=pr&el=desc) will **increase** coverage by `0.19%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/kutaslab/fitgrid/pull/39/graphs/tree.svg?width=650&token=d9xVBW7gSn&height=150&src=pr)](https://codecov.io/gh/kutaslab/fitgrid/pull/39?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #39      +/-   ##
==========================================
+ Coverage   86.33%   86.52%   +0.19%     
==========================================
  Files           8        8              
  Lines         278      282       +4     
==========================================
+ Hits          240      244       +4     
  Misses         38       38
```


| [Impacted Files](https://codecov.io/gh/kutaslab/fitgrid/pull/39?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [fitgrid/epochs.py](https://codecov.io/gh/kutaslab/fitgrid/pull/39/diff?src=pr&el=tree#diff-Zml0Z3JpZC9lcG9jaHMucHk=) | `79.12% <100%> (ø)` | :arrow_up: |
| [fitgrid/tools.py](https://codecov.io/gh/kutaslab/fitgrid/pull/39/diff?src=pr&el=tree#diff-Zml0Z3JpZC90b29scy5weQ==) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/kutaslab/fitgrid/pull/39?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/kutaslab/fitgrid/pull/39?src=pr&el=footer). Last update [06e5803...107b849](https://codecov.io/gh/kutaslab/fitgrid/pull/39?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/fitgrid/epochs.py b/fitgrid/epochs.py
index d1f5b86..899298a 100644
--- a/fitgrid/epochs.py
+++ b/fitgrid/epochs.py
@@ -87,7 +87,7 @@ class Epochs:
         self.channels = channels
         self.table = table
         self._snapshots = snapshots
-        self._epoch_index = snapshots.get_group(0).index.copy()
+        self._epoch_index = tools.get_first_group(snapshots).index.copy()
 
     def _validate_LHS(self, LHS):
 
diff --git a/fitgrid/tools.py b/fitgrid/tools.py
index 114907f..a75d482 100644
--- a/fitgrid/tools.py
+++ b/fitgrid/tools.py
@@ -25,3 +25,10 @@ def get_index_duplicates_table(df, level):
         msg += '{0:<20} {1}\n'.format(value, ', '.join(locations))
 
     return msg
+
+
+def get_first_group(groupby):
+
+    first_group_name = list(groupby.groups)[0]
+    first_group = groupby.get_group(first_group_name)
+    return first_group

BUG: usage of `groupby.get_group(0)` is bad
`groupby.get_group(0)` gets the group with name `0`, not the first group.

Possible fix is to replace with 
```python
first_group_name = list(groupby.groups)[0]
first_group = groupby.get_group(first_group_name)
```
diff --git a/tests/test_fitgrid.py b/tests/test_fitgrid.py
index 43cb7e0..f14a93a 100644
--- a/tests/test_fitgrid.py
+++ b/tests/test_fitgrid.py
@@ -2,6 +2,7 @@ import pytest
 import numpy as np
 from .context import fitgrid
 from fitgrid.errors import FitGridError
+from fitgrid import tools
 import matplotlib
 
 matplotlib.use('Agg')
@@ -51,7 +52,8 @@ def test__residuals_have_long_form_and_correct_index():
         RHS='categorical + continuous',
     )
 
-    single_epoch = epochs._snapshots.get_group(0)
+    single_epoch = tools.get_first_group(epochs._snapshots)
+
     assert single_epoch.index.equals(grid.resid.index.levels[1])
 
 
@@ -69,7 +71,7 @@ def test__epoch_id_substitution():
     epochs = fitgrid.epochs_from_dataframe(data, channels)
 
     # remember epoch_index
-    epoch_index = epochs._snapshots.get_group(0).index
+    epoch_index = tools.get_first_group(epochs._snapshots).index
     assert (epoch_index == unusual_index).all()
 
     # take just two channels for speed

pip install -e .[dev]
parse_log_pytest
requirements.txt
black pytest pytest-cov
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
black==25.1.0
blosc2==2.5.1
click==8.1.8
contourpy==1.3.0
coverage==7.8.0
cycler==0.12.1
exceptiongroup==1.2.2
-e git+https://github.com/kutaslab/fitgrid.git@06e5803882f11412adf99d32c57f04381d581ffa#egg=fitgrid
fonttools==4.56.0
importlib_resources==6.5.2
iniconfig==2.1.0
kiwisolver==1.4.7
matplotlib==3.9.4
msgpack==1.1.0
mypy-extensions==1.0.0
ndindex==1.9.2
numexpr==2.10.2
numpy==2.0.2
packaging==24.2
pandas==2.2.3
pathspec==0.12.1
patsy==1.0.1
pillow==11.1.0
platformdirs==4.3.7
pluggy==1.5.0
py-cpuinfo==9.0.0
pyparsing==3.2.3
pytest==8.3.5
pytest-cov==6.0.0
python-dateutil==2.9.0.post0
pytz==2025.2
scipy==1.13.1
six==1.17.0
statsmodels==0.14.4
tables==3.9.2
tomli==2.2.1
tqdm==4.67.1
typing_extensions==4.13.0
tzdata==2025.2
zipp==3.21.0

name: fitgrid
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - black==25.1.0
      - blosc2==2.5.1
      - click==8.1.8
      - contourpy==1.3.0
      - coverage==7.8.0
      - cycler==0.12.1
      - exceptiongroup==1.2.2
      - fonttools==4.56.0
      - importlib-resources==6.5.2
      - iniconfig==2.1.0
      - kiwisolver==1.4.7
      - matplotlib==3.9.4
      - msgpack==1.1.0
      - mypy-extensions==1.0.0
      - ndindex==1.9.2
      - numexpr==2.10.2
      - numpy==2.0.2
      - packaging==24.2
      - pandas==2.2.3
      - pathspec==0.12.1
      - patsy==1.0.1
      - pillow==11.1.0
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - py-cpuinfo==9.0.0
      - pyparsing==3.2.3
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - scipy==1.13.1
      - six==1.17.0
      - statsmodels==0.14.4
      - tables==3.9.2
      - tomli==2.2.1
      - tqdm==4.67.1
      - typing-extensions==4.13.0
      - tzdata==2025.2
      - zipp==3.21.0
prefix: /opt/conda/envs/fitgrid

tests/test_fitgrid.py::test__residuals_have_long_form_and_correct_index
tests/test_fitgrid.py::test__epoch_id_substitution tests/test_fitgrid.py::test__smoke_influential_epochs
tests/test_fitgrid.py::test__correct_channels_in_fitgrid tests/test_fitgrid.py::test__method_returning_dataframe_expands_correctly tests/test_fitgrid.py::test__slicing tests/test_fitgrid.py::test__smoke_plot_betas tests/test_fitgrid.py::test__smoke_plot_adj_rsquared
fitgrid/tools.py fitgrid/epochs.py
fitgrid/tools.py fitgrid/epochs.py