We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
GClust bug
<img width="558" alt="Screen Shot 2019-06-22 at 3 46 06 PM" src="https://user-images.githubusercontent.com/25714207/59968259-eb346c80-9504-11e9-984c-8c13dff93a37.png">

should be `- self.min_components` rather than `- 1`

This causes an indexing error when `min_components` does not equal 1

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `graspy/cluster/gclust.py`
Content:
```
1 # Copyright 2019 NeuroData (http://neurodata.io)
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import numpy as np
16 import pandas as pd
17 from sklearn.metrics import adjusted_rand_score
18 from sklearn.mixture import GaussianMixture
19 from sklearn.model_selection import ParameterGrid
20 
21 from .base import BaseCluster
22 
23 
24 class GaussianCluster(BaseCluster):
25     r"""
26     Gaussian Mixture Model (GMM)
27 
28     Representation of a Gaussian mixture model probability distribution. 
29     This class allows to estimate the parameters of a Gaussian mixture 
30     distribution. It computes all possible models from one component to 
31     max_components. The best model is given by the lowest BIC score.
32 
33     Parameters
34     ----------
35     min_components : int, default=2. 
36         The minimum number of mixture components to consider (unless
37         max_components=None, in which case this is the maximum number of
38         components to consider). If max_componens is not None, min_components
39         must be less than or equal to max_components.
40 
41     max_components : int or None, default=None.
42         The maximum number of mixture components to consider. Must be greater 
43         than or equal to min_components.
44 
45     covariance_type : {'full' (default), 'tied', 'diag', 'spherical'}, optional
46         String or list/array describing the type of covariance parameters to use.
47         If a string, it must be one of:
48         
49         - 'full'
50             each component has its own general covariance matrix
51         - 'tied'
52             all components share the same general covariance matrix
53         - 'diag'
54             each component has its own diagonal covariance matrix
55         - 'spherical'
56             each component has its own single variance
57         - 'all'
58             considers all covariance structures in ['spherical', 'diag', 'tied', 'full']
59         If a list/array, it must be a list/array of strings containing only
60             'spherical', 'tied', 'diag', and/or 'spherical'.
61     
62     random_state : int, RandomState instance or None, optional (default=None)
63         If int, random_state is the seed used by the random number generator;
64         If RandomState instance, random_state is the random number generator;
65         If None, the random number generator is the RandomState instance used
66         by ``np.random``.
67 
68     Attributes
69     ----------
70     n_components_ : int
71         Optimal number of components based on BIC.
72     covariance_type_ : str
73         Optimal covariance type based on BIC.
74     model_ : GaussianMixture object
75         Fitted GaussianMixture object fitted with optimal numeber of components 
76         and optimal covariance structure.
77     bic_ : pandas.DataFrame
78         A pandas DataFrame of BIC values computed for all possible number of clusters
79         given by range(min_components, max_components + 1) and all covariance
80         structures given by covariance_type.
81     ari_ : pandas.DataFrame
82         Only computed when y is given. Pandas Dataframe containing ARI values computed
83         for all possible number of clusters given by range(min_components,
84         max_components) and all covariance structures given by covariance_type.
85     """
86 
87     def __init__(
88         self,
89         min_components=2,
90         max_components=None,
91         covariance_type="full",
92         random_state=None,
93     ):
94         if isinstance(min_components, int):
95             if min_components <= 0:
96                 msg = "min_components must be >= 1."
97                 raise ValueError(msg)
98         else:
99             msg = "min_components must be an integer, not {}.".format(
100                 type(min_components)
101             )
102             raise TypeError(msg)
103 
104         if isinstance(max_components, int):
105             if max_components <= 0:
106                 msg = "max_components must be >= 1 or None."
107                 raise ValueError(msg)
108             elif min_components > max_components:
109                 msg = "min_components must be less than or equal to max_components."
110                 raise ValueError(msg)
111         elif max_components is not None:
112             msg = "max_components must be an integer or None, not {}.".format(
113                 type(max_components)
114             )
115             raise TypeError(msg)
116 
117         if isinstance(covariance_type, (np.ndarray, list)):
118             covariance_type = np.unique(covariance_type)
119         elif isinstance(covariance_type, str):
120             if covariance_type == "all":
121                 covariance_type = ["spherical", "diag", "tied", "full"]
122             else:
123                 covariance_type = [covariance_type]
124         else:
125             msg = "covariance_type must be a numpy array, a list, or "
126             msg += "string, not {}".format(type(covariance_type))
127             raise TypeError(msg)
128 
129         for cov in covariance_type:
130             if cov not in ["spherical", "diag", "tied", "full"]:
131                 msg = (
132                     "covariance structure must be one of "
133                     + '["spherical", "diag", "tied", "full"]'
134                 )
135                 msg += " not {}".format(cov)
136                 raise ValueError(msg)
137 
138         new_covariance_type = []
139         for cov in ["spherical", "diag", "tied", "full"]:
140             if cov in covariance_type:
141                 new_covariance_type.append(cov)
142 
143         self.min_components = min_components
144         self.max_components = max_components
145         self.covariance_type = new_covariance_type
146         self.random_state = random_state
147 
148     def fit(self, X, y=None):
149         """
150         Fits gaussian mixure model to the data. 
151         Estimate model parameters with the EM algorithm.
152 
153         Parameters
154         ----------
155         X : array-like, shape (n_samples, n_features)
156             List of n_features-dimensional data points. Each row
157             corresponds to a single data point.
158         
159         y : array-like, shape (n_samples,), optional (default=None)
160             List of labels for X if available. Used to compute
161             ARI scores.
162 
163         Returns
164         -------
165         self
166         """
167 
168         # Deal with number of clusters
169         if self.max_components is None:
170             lower_ncomponents = 1
171             upper_ncomponents = self.min_components
172         else:
173             lower_ncomponents = self.min_components
174             upper_ncomponents = self.max_components
175 
176         n_mixture_components = upper_ncomponents - lower_ncomponents + 1
177 
178         if upper_ncomponents > X.shape[0]:
179             if self.max_components is None:
180                 msg = "if max_components is None then min_components must be >= "
181                 msg += "n_samples, but min_components = {}, n_samples = {}".format(
182                     upper_ncomponents, X.shape[0]
183                 )
184             else:
185                 msg = "max_components must be >= n_samples, but max_components = "
186                 msg += "{}, n_samples = {}".format(upper_ncomponents, X.shape[0])
187             raise ValueError(msg)
188         elif lower_ncomponents > X.shape[0]:
189             msg = "min_components must be <= n_samples, but min_components = "
190             msg += "{}, n_samples = {}".format(upper_ncomponents, X.shape[0])
191             raise ValueError(msg)
192 
193         # Get parameters
194         random_state = self.random_state
195 
196         param_grid = dict(
197             covariance_type=self.covariance_type,
198             n_components=range(lower_ncomponents, upper_ncomponents + 1),
199             random_state=[random_state],
200         )
201 
202         param_grid = list(ParameterGrid(param_grid))
203 
204         models = [[] for _ in range(n_mixture_components)]
205         bics = [[] for _ in range(n_mixture_components)]
206         aris = [[] for _ in range(n_mixture_components)]
207 
208         for i, params in enumerate(param_grid):
209             model = GaussianMixture(**params)
210             model.fit(X)
211             models[i % n_mixture_components].append(model)
212             bics[i % n_mixture_components].append(model.bic(X))
213             if y is not None:
214                 predictions = model.predict(X)
215                 aris[i % n_mixture_components].append(
216                     adjusted_rand_score(y, predictions)
217                 )
218 
219         self.bic_ = pd.DataFrame(
220             bics,
221             index=np.arange(lower_ncomponents, upper_ncomponents + 1),
222             columns=self.covariance_type,
223         )
224 
225         if y is not None:
226             self.ari_ = pd.DataFrame(
227                 aris,
228                 index=np.arange(lower_ncomponents, upper_ncomponents + 1),
229                 columns=self.covariance_type,
230             )
231         else:
232             self.ari_ = None
233 
234         # Get the best cov type and its index within the dataframe
235         best_covariance = self.bic_.min(axis=0).idxmin()
236         best_covariance_idx = self.covariance_type.index(best_covariance)
237 
238         # Get the index best component for best_covariance
239         best_component = self.bic_.idxmin()[best_covariance]
240 
241         self.n_components_ = best_component
242         self.covariance_type_ = best_covariance
243         self.model_ = models[best_component - 1][best_covariance_idx]
244 
245         return self
246
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/graspy/cluster/gclust.py b/graspy/cluster/gclust.py
--- a/graspy/cluster/gclust.py
+++ b/graspy/cluster/gclust.py
@@ -240,6 +240,6 @@
 
         self.n_components_ = best_component
         self.covariance_type_ = best_covariance
-        self.model_ = models[best_component - 1][best_covariance_idx]
+        self.model_ = models[best_component - self.min_components][best_covariance_idx]
 
         return self

{"golden_diff": "diff --git a/graspy/cluster/gclust.py b/graspy/cluster/gclust.py\n--- a/graspy/cluster/gclust.py\n+++ b/graspy/cluster/gclust.py\n@@ -240,6 +240,6 @@\n \n         self.n_components_ = best_component\n         self.covariance_type_ = best_covariance\n-        self.model_ = models[best_component - 1][best_covariance_idx]\n+        self.model_ = models[best_component - self.min_components][best_covariance_idx]\n \n         return self\n", "issue": "GClust bug\n<img width=\"558\" alt=\"Screen Shot 2019-06-22 at 3 46 06 PM\" src=\"https://user-images.githubusercontent.com/25714207/59968259-eb346c80-9504-11e9-984c-8c13dff93a37.png\">\r\n\r\nshould be `- self.min_components` rather than `- 1`\r\n\r\nThis causes an indexing error when `min_components` does not equal 1\n", "before_files": [{"content": "# Copyright 2019 NeuroData (http://neurodata.io)\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport numpy as np\nimport pandas as pd\nfrom sklearn.metrics import adjusted_rand_score\nfrom sklearn.mixture import GaussianMixture\nfrom sklearn.model_selection import ParameterGrid\n\nfrom .base import BaseCluster\n\n\nclass GaussianCluster(BaseCluster):\n    r\"\"\"\n    Gaussian Mixture Model (GMM)\n\n    Representation of a Gaussian mixture model probability distribution. \n    This class allows to estimate the parameters of a Gaussian mixture \n    distribution. It computes all possible models from one component to \n    max_components. The best model is given by the lowest BIC score.\n\n    Parameters\n    ----------\n    min_components : int, default=2. \n        The minimum number of mixture components to consider (unless\n        max_components=None, in which case this is the maximum number of\n        components to consider). If max_componens is not None, min_components\n        must be less than or equal to max_components.\n\n    max_components : int or None, default=None.\n        The maximum number of mixture components to consider. Must be greater \n        than or equal to min_components.\n\n    covariance_type : {'full' (default), 'tied', 'diag', 'spherical'}, optional\n        String or list/array describing the type of covariance parameters to use.\n        If a string, it must be one of:\n        \n        - 'full'\n            each component has its own general covariance matrix\n        - 'tied'\n            all components share the same general covariance matrix\n        - 'diag'\n            each component has its own diagonal covariance matrix\n        - 'spherical'\n            each component has its own single variance\n        - 'all'\n            considers all covariance structures in ['spherical', 'diag', 'tied', 'full']\n        If a list/array, it must be a list/array of strings containing only\n            'spherical', 'tied', 'diag', and/or 'spherical'.\n    \n    random_state : int, RandomState instance or None, optional (default=None)\n        If int, random_state is the seed used by the random number generator;\n        If RandomState instance, random_state is the random number generator;\n        If None, the random number generator is the RandomState instance used\n        by ``np.random``.\n\n    Attributes\n    ----------\n    n_components_ : int\n        Optimal number of components based on BIC.\n    covariance_type_ : str\n        Optimal covariance type based on BIC.\n    model_ : GaussianMixture object\n        Fitted GaussianMixture object fitted with optimal numeber of components \n        and optimal covariance structure.\n    bic_ : pandas.DataFrame\n        A pandas DataFrame of BIC values computed for all possible number of clusters\n        given by range(min_components, max_components + 1) and all covariance\n        structures given by covariance_type.\n    ari_ : pandas.DataFrame\n        Only computed when y is given. Pandas Dataframe containing ARI values computed\n        for all possible number of clusters given by range(min_components,\n        max_components) and all covariance structures given by covariance_type.\n    \"\"\"\n\n    def __init__(\n        self,\n        min_components=2,\n        max_components=None,\n        covariance_type=\"full\",\n        random_state=None,\n    ):\n        if isinstance(min_components, int):\n            if min_components <= 0:\n                msg = \"min_components must be >= 1.\"\n                raise ValueError(msg)\n        else:\n            msg = \"min_components must be an integer, not {}.\".format(\n                type(min_components)\n            )\n            raise TypeError(msg)\n\n        if isinstance(max_components, int):\n            if max_components <= 0:\n                msg = \"max_components must be >= 1 or None.\"\n                raise ValueError(msg)\n            elif min_components > max_components:\n                msg = \"min_components must be less than or equal to max_components.\"\n                raise ValueError(msg)\n        elif max_components is not None:\n            msg = \"max_components must be an integer or None, not {}.\".format(\n                type(max_components)\n            )\n            raise TypeError(msg)\n\n        if isinstance(covariance_type, (np.ndarray, list)):\n            covariance_type = np.unique(covariance_type)\n        elif isinstance(covariance_type, str):\n            if covariance_type == \"all\":\n                covariance_type = [\"spherical\", \"diag\", \"tied\", \"full\"]\n            else:\n                covariance_type = [covariance_type]\n        else:\n            msg = \"covariance_type must be a numpy array, a list, or \"\n            msg += \"string, not {}\".format(type(covariance_type))\n            raise TypeError(msg)\n\n        for cov in covariance_type:\n            if cov not in [\"spherical\", \"diag\", \"tied\", \"full\"]:\n                msg = (\n                    \"covariance structure must be one of \"\n                    + '[\"spherical\", \"diag\", \"tied\", \"full\"]'\n                )\n                msg += \" not {}\".format(cov)\n                raise ValueError(msg)\n\n        new_covariance_type = []\n        for cov in [\"spherical\", \"diag\", \"tied\", \"full\"]:\n            if cov in covariance_type:\n                new_covariance_type.append(cov)\n\n        self.min_components = min_components\n        self.max_components = max_components\n        self.covariance_type = new_covariance_type\n        self.random_state = random_state\n\n    def fit(self, X, y=None):\n        \"\"\"\n        Fits gaussian mixure model to the data. \n        Estimate model parameters with the EM algorithm.\n\n        Parameters\n        ----------\n        X : array-like, shape (n_samples, n_features)\n            List of n_features-dimensional data points. Each row\n            corresponds to a single data point.\n        \n        y : array-like, shape (n_samples,), optional (default=None)\n            List of labels for X if available. Used to compute\n            ARI scores.\n\n        Returns\n        -------\n        self\n        \"\"\"\n\n        # Deal with number of clusters\n        if self.max_components is None:\n            lower_ncomponents = 1\n            upper_ncomponents = self.min_components\n        else:\n            lower_ncomponents = self.min_components\n            upper_ncomponents = self.max_components\n\n        n_mixture_components = upper_ncomponents - lower_ncomponents + 1\n\n        if upper_ncomponents > X.shape[0]:\n            if self.max_components is None:\n                msg = \"if max_components is None then min_components must be >= \"\n                msg += \"n_samples, but min_components = {}, n_samples = {}\".format(\n                    upper_ncomponents, X.shape[0]\n                )\n            else:\n                msg = \"max_components must be >= n_samples, but max_components = \"\n                msg += \"{}, n_samples = {}\".format(upper_ncomponents, X.shape[0])\n            raise ValueError(msg)\n        elif lower_ncomponents > X.shape[0]:\n            msg = \"min_components must be <= n_samples, but min_components = \"\n            msg += \"{}, n_samples = {}\".format(upper_ncomponents, X.shape[0])\n            raise ValueError(msg)\n\n        # Get parameters\n        random_state = self.random_state\n\n        param_grid = dict(\n            covariance_type=self.covariance_type,\n            n_components=range(lower_ncomponents, upper_ncomponents + 1),\n            random_state=[random_state],\n        )\n\n        param_grid = list(ParameterGrid(param_grid))\n\n        models = [[] for _ in range(n_mixture_components)]\n        bics = [[] for _ in range(n_mixture_components)]\n        aris = [[] for _ in range(n_mixture_components)]\n\n        for i, params in enumerate(param_grid):\n            model = GaussianMixture(**params)\n            model.fit(X)\n            models[i % n_mixture_components].append(model)\n            bics[i % n_mixture_components].append(model.bic(X))\n            if y is not None:\n                predictions = model.predict(X)\n                aris[i % n_mixture_components].append(\n                    adjusted_rand_score(y, predictions)\n                )\n\n        self.bic_ = pd.DataFrame(\n            bics,\n            index=np.arange(lower_ncomponents, upper_ncomponents + 1),\n            columns=self.covariance_type,\n        )\n\n        if y is not None:\n            self.ari_ = pd.DataFrame(\n                aris,\n                index=np.arange(lower_ncomponents, upper_ncomponents + 1),\n                columns=self.covariance_type,\n            )\n        else:\n            self.ari_ = None\n\n        # Get the best cov type and its index within the dataframe\n        best_covariance = self.bic_.min(axis=0).idxmin()\n        best_covariance_idx = self.covariance_type.index(best_covariance)\n\n        # Get the index best component for best_covariance\n        best_component = self.bic_.idxmin()[best_covariance]\n\n        self.n_components_ = best_component\n        self.covariance_type_ = best_covariance\n        self.model_ = models[best_component - 1][best_covariance_idx]\n\n        return self\n", "path": "graspy/cluster/gclust.py"}], "after_files": [{"content": "# Copyright 2019 NeuroData (http://neurodata.io)\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport numpy as np\nimport pandas as pd\nfrom sklearn.metrics import adjusted_rand_score\nfrom sklearn.mixture import GaussianMixture\nfrom sklearn.model_selection import ParameterGrid\n\nfrom .base import BaseCluster\n\n\nclass GaussianCluster(BaseCluster):\n    r\"\"\"\n    Gaussian Mixture Model (GMM)\n\n    Representation of a Gaussian mixture model probability distribution. \n    This class allows to estimate the parameters of a Gaussian mixture \n    distribution. It computes all possible models from one component to \n    max_components. The best model is given by the lowest BIC score.\n\n    Parameters\n    ----------\n    min_components : int, default=2. \n        The minimum number of mixture components to consider (unless\n        max_components=None, in which case this is the maximum number of\n        components to consider). If max_componens is not None, min_components\n        must be less than or equal to max_components.\n\n    max_components : int or None, default=None.\n        The maximum number of mixture components to consider. Must be greater \n        than or equal to min_components.\n\n    covariance_type : {'full' (default), 'tied', 'diag', 'spherical'}, optional\n        String or list/array describing the type of covariance parameters to use.\n        If a string, it must be one of:\n        \n        - 'full'\n            each component has its own general covariance matrix\n        - 'tied'\n            all components share the same general covariance matrix\n        - 'diag'\n            each component has its own diagonal covariance matrix\n        - 'spherical'\n            each component has its own single variance\n        - 'all'\n            considers all covariance structures in ['spherical', 'diag', 'tied', 'full']\n        If a list/array, it must be a list/array of strings containing only\n            'spherical', 'tied', 'diag', and/or 'spherical'.\n    \n    random_state : int, RandomState instance or None, optional (default=None)\n        If int, random_state is the seed used by the random number generator;\n        If RandomState instance, random_state is the random number generator;\n        If None, the random number generator is the RandomState instance used\n        by ``np.random``.\n\n    Attributes\n    ----------\n    n_components_ : int\n        Optimal number of components based on BIC.\n    covariance_type_ : str\n        Optimal covariance type based on BIC.\n    model_ : GaussianMixture object\n        Fitted GaussianMixture object fitted with optimal numeber of components \n        and optimal covariance structure.\n    bic_ : pandas.DataFrame\n        A pandas DataFrame of BIC values computed for all possible number of clusters\n        given by range(min_components, max_components + 1) and all covariance\n        structures given by covariance_type.\n    ari_ : pandas.DataFrame\n        Only computed when y is given. Pandas Dataframe containing ARI values computed\n        for all possible number of clusters given by range(min_components,\n        max_components) and all covariance structures given by covariance_type.\n    \"\"\"\n\n    def __init__(\n        self,\n        min_components=2,\n        max_components=None,\n        covariance_type=\"full\",\n        random_state=None,\n    ):\n        if isinstance(min_components, int):\n            if min_components <= 0:\n                msg = \"min_components must be >= 1.\"\n                raise ValueError(msg)\n        else:\n            msg = \"min_components must be an integer, not {}.\".format(\n                type(min_components)\n            )\n            raise TypeError(msg)\n\n        if isinstance(max_components, int):\n            if max_components <= 0:\n                msg = \"max_components must be >= 1 or None.\"\n                raise ValueError(msg)\n            elif min_components > max_components:\n                msg = \"min_components must be less than or equal to max_components.\"\n                raise ValueError(msg)\n        elif max_components is not None:\n            msg = \"max_components must be an integer or None, not {}.\".format(\n                type(max_components)\n            )\n            raise TypeError(msg)\n\n        if isinstance(covariance_type, (np.ndarray, list)):\n            covariance_type = np.unique(covariance_type)\n        elif isinstance(covariance_type, str):\n            if covariance_type == \"all\":\n                covariance_type = [\"spherical\", \"diag\", \"tied\", \"full\"]\n            else:\n                covariance_type = [covariance_type]\n        else:\n            msg = \"covariance_type must be a numpy array, a list, or \"\n            msg += \"string, not {}\".format(type(covariance_type))\n            raise TypeError(msg)\n\n        for cov in covariance_type:\n            if cov not in [\"spherical\", \"diag\", \"tied\", \"full\"]:\n                msg = (\n                    \"covariance structure must be one of \"\n                    + '[\"spherical\", \"diag\", \"tied\", \"full\"]'\n                )\n                msg += \" not {}\".format(cov)\n                raise ValueError(msg)\n\n        new_covariance_type = []\n        for cov in [\"spherical\", \"diag\", \"tied\", \"full\"]:\n            if cov in covariance_type:\n                new_covariance_type.append(cov)\n\n        self.min_components = min_components\n        self.max_components = max_components\n        self.covariance_type = new_covariance_type\n        self.random_state = random_state\n\n    def fit(self, X, y=None):\n        \"\"\"\n        Fits gaussian mixure model to the data. \n        Estimate model parameters with the EM algorithm.\n\n        Parameters\n        ----------\n        X : array-like, shape (n_samples, n_features)\n            List of n_features-dimensional data points. Each row\n            corresponds to a single data point.\n        \n        y : array-like, shape (n_samples,), optional (default=None)\n            List of labels for X if available. Used to compute\n            ARI scores.\n\n        Returns\n        -------\n        self\n        \"\"\"\n\n        # Deal with number of clusters\n        if self.max_components is None:\n            lower_ncomponents = 1\n            upper_ncomponents = self.min_components\n        else:\n            lower_ncomponents = self.min_components\n            upper_ncomponents = self.max_components\n\n        n_mixture_components = upper_ncomponents - lower_ncomponents + 1\n\n        if upper_ncomponents > X.shape[0]:\n            if self.max_components is None:\n                msg = \"if max_components is None then min_components must be >= \"\n                msg += \"n_samples, but min_components = {}, n_samples = {}\".format(\n                    upper_ncomponents, X.shape[0]\n                )\n            else:\n                msg = \"max_components must be >= n_samples, but max_components = \"\n                msg += \"{}, n_samples = {}\".format(upper_ncomponents, X.shape[0])\n            raise ValueError(msg)\n        elif lower_ncomponents > X.shape[0]:\n            msg = \"min_components must be <= n_samples, but min_components = \"\n            msg += \"{}, n_samples = {}\".format(upper_ncomponents, X.shape[0])\n            raise ValueError(msg)\n\n        # Get parameters\n        random_state = self.random_state\n\n        param_grid = dict(\n            covariance_type=self.covariance_type,\n            n_components=range(lower_ncomponents, upper_ncomponents + 1),\n            random_state=[random_state],\n        )\n\n        param_grid = list(ParameterGrid(param_grid))\n\n        models = [[] for _ in range(n_mixture_components)]\n        bics = [[] for _ in range(n_mixture_components)]\n        aris = [[] for _ in range(n_mixture_components)]\n\n        for i, params in enumerate(param_grid):\n            model = GaussianMixture(**params)\n            model.fit(X)\n            models[i % n_mixture_components].append(model)\n            bics[i % n_mixture_components].append(model.bic(X))\n            if y is not None:\n                predictions = model.predict(X)\n                aris[i % n_mixture_components].append(\n                    adjusted_rand_score(y, predictions)\n                )\n\n        self.bic_ = pd.DataFrame(\n            bics,\n            index=np.arange(lower_ncomponents, upper_ncomponents + 1),\n            columns=self.covariance_type,\n        )\n\n        if y is not None:\n            self.ari_ = pd.DataFrame(\n                aris,\n                index=np.arange(lower_ncomponents, upper_ncomponents + 1),\n                columns=self.covariance_type,\n            )\n        else:\n            self.ari_ = None\n\n        # Get the best cov type and its index within the dataframe\n        best_covariance = self.bic_.min(axis=0).idxmin()\n        best_covariance_idx = self.covariance_type.index(best_covariance)\n\n        # Get the index best component for best_covariance\n        best_component = self.bic_.idxmin()[best_covariance]\n\n        self.n_components_ = best_component\n        self.covariance_type_ = best_covariance\n        self.model_ = models[best_component - self.min_components][best_covariance_idx]\n\n        return self\n", "path": "graspy/cluster/gclust.py"}]}