Repository: graspologic-org/graspologic

Issue:
Documentation fixes
- Update Sklearn intersphinx, and make it the stable version instead of dev
- Fix the build warnings: 
```
11:02:00 AM: /opt/build/repo/graspy/cluster/gclust.py:docstring of graspy.cluster.GaussianCluster:35: WARNING: Bullet list ends without a blank line; unexpected unindent.
11:02:00 AM: /opt/build/repo/graspy/cluster/gclust.py:docstring of graspy.cluster.GaussianCluster:56: WARNING: Unexpected indentation.
11:02:00 AM: /opt/build/repo/graspy/embed/svd.py:docstring of graspy.embed.select_dimension:51: WARNING: Footnote [#] is not referenced.
11:02:00 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest:37: WARNING: Explicit markup ends without a blank line; unexpected unindent.
11:02:00 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest:40: WARNING: Explicit markup ends without a blank line; unexpected unindent.
11:02:00 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest:64: WARNING: Unknown target name: "p_value_1".
11:02:00 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest:64: WARNING: Unknown target name: "p_value_2".
11:02:00 AM: /opt/build/repo/docs/reference/utils.rst:28: WARNING: Unknown directive type "autofumction".
11:02:00 AM: .. autofumction:: get_multigraph_intersect_lcc
11:00:20 AM: intersphinx inventory has moved: http://scikit-learn.org/dev/objects.inv -> https://scikit-learn.org/dev/objects.inv
```



Discussion:
some of this may have been fixed by #408 
I can take this one!
Hey Pedigo, I'm a little confused with this issue.  Where are the 'build warnings' supposed to show up?  I didn't encounter them when I installed graspy from github.
@pauladkisson 
- Look at a [recent PR](https://github.com/neurodata/graspy/pull/421)
- Scroll down to bottom where it says "All checks have passed" and there are a bunch of lines that say "details" at the end. These are automated checks that run every time someone makes a PR. 
- Click on "details" next to where it says "mixed content - graspy" 
- Should bring you to something like [this](https://app.netlify.com/sites/graspy/deploys/5f525bb2dd0fc000072c437c) these are the logs from the build of our documentation
- If you scroll through you should see something like: 
```
8:27:56 AM: /opt/build/repo/graspy/cluster/gclust.py:docstring of graspy.cluster.GaussianCluster:38: WARNING: Bullet list ends without a blank line; unexpected unindent.
8:27:56 AM: /opt/build/repo/graspy/cluster/gclust.py:docstring of graspy.cluster.GaussianCluster:64: WARNING: Unexpected indentation.
/opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest:40: WARNING: Explicit markup ends without a blank line; unexpected unindent.
8:27:56 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest:43: WARNING: Explicit markup ends without a blank line; unexpected unindent.
8:27:56 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest.fit_predict:6: WARNING: Unexpected indentation.
8:27:56 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest.fit_predict:11: WARNING: Title underline too short.
8:27:56 AM: Returns
8:27:56 AM: ------
8:27:56 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest.fit_predict:11: WARNING: Unexpected section title.
8:27:56 AM: Returns
8:27:56 AM: ------
8:27:56 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest:72: WARNING: Unknown target name: "p_value_1".
8:27:56 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest:72: WARNING: Unknown target name: "p_value_2".
8:27:56 AM: /opt/build/repo/graspy/inference/latent_position_test.py:docstring of graspy.inference.LatentPositionTest.fit_predict:26: WARNING: Unknown target name: "p_value".
```
The goal is to fix the documentation generation to not have these warnings. I'd just focus on the ones for `LatentPositionTest` to start (or even just the ones about "unknown target name"), because that will let you just focus on one class in the code for now. You will have to learn a bit about how the documentation gets generated. There is something called a docstring in python (the one you will start with is [here](https://github.com/neurodata/graspy/blob/ca4001315b2d00d19437609afa6bdf96577fd7ce/graspy/inference/latent_position_test.py#L25)) which is in the code, but a tool called sphinx converts into out documentation pages. The warnings above are basically saying that when sphinx is run, there are some issues with how the docstrings get converted to documentation. 
Ok, this is definitely helpful.  I can see the warnings in the deploy details that you mentioned, and it should be easy enough to fix a few docstrings, but I've never worked on a project to this scale before.  How can I check my work to make sure that the issues are resolved?
@pauladkisson I think the easiest thing for you in this case will be to make a draft PR sooner rather than later. This will cause netlify (the thing that builds our docs) to trigger a build online, which will generate all of those logs, and will let you check your work to see if the errors stop.

Other option is to build the documentation locally on your machine. Instructions for that are [here](https://github.com/neurodata/graspy/tree/master/docs)
Thanks, yeah, I just found the instructions for installing sphinx and building the docs.  I was able to get it to run and display the appropriate warnings, but I also got a weird error that didn't show up in the netlify version:

```
Notebook error:
CellExecutionError in tutorials/inference/latent_distribution_test.ipynb:
------------------
ldt_dcorr = LatentDistributionTest("dcorr", metric="euclidean", n_bootstraps=100)
ldt_dcorr.fit(A1, A2)
------------------

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-04d99b26d852> in <module>
----> 1 ldt_dcorr = LatentDistributionTest("dcorr", metric="euclidean", n_bootstraps=100)
      2 ldt_dcorr.fit(A1, A2)

TypeError: __init__() got an unexpected keyword argument 'metric'
TypeError: __init__() got an unexpected keyword argument 'metric'

You can ignore this error by setting the following in conf.py:

    nbsphinx_allow_errors = True

make: *** [html] Error 2
```

Do you know what's going on?
So using the ignore error setting listed above, I am able to work on the documentation fixes.  When I get through them, I will remove the ignore error setting, submit a PR, and see if the error persists.
1. @pauladkisson feel free to @ me whenever anything concerning latent distribution test causes issues cuz much of it is my code, so i likely will know. 
2. wrap multiline code in ``` please
3. despite 1, i have no idea what's going on, since it passes for me.
actually, i have a conjecture: i think i changed an argument that used to be called distance to "metric" in #366 . so maybe it uses an outdated version of graspy. why / how to check? me not knows. Ben?
Hey @alyakin314! Yeah, I'm not sure what's going on with that since I just cloned the repo yesterday...

For the other warnings, most of it is fairly simple to fix (funky indents, skipped lines, etc.) but I did some digging on the internet, and it looks like sphinx itself has a bug where it doesn't recognize variables with a trailing underscore (p_value_1_, p_value_2_, etc.).  So, I could change the actual variable names to omit the underscore, but I don't know if I would need to change them elsewhere.  @bdpedigo lmk what you think.
@pauladkisson you should be careful with changing those. some of them are used in tutorial notebooks, so they may break if u change the names. furthremore, i think some of those variables, such as p_value and null_distribution follow the same convention between ldt and lpt, and are even mentioned in BaseInference's docs. so you should search through repo and change the names everywhere where apropriate, if you intend on changing 'em.
@pauladkisson actually, if you're using a local version to do this - can you verify that you indeed are using 0.3.0 graspy? just cuz you have a cloned repo doesn't mean you are using the updated version.
@pauladkisson have you tried running that notebook locally (not just building the docs)
I'm pretty sure that I'm using the current version.  Under the release folder in docs it says release_0.3.rst.  I'm not sure how else I would check.  

I did try running the problematic notebook locally, and I got the same error: in the fourth code block.   I also checked it against the tutorial live on the site, and they are the same as far as I can tell.  
can you post the full traceback from running the notebook locally?
other things: 
- can you lmk how you installed graspy locally? 
- if you installed locally from a cloned github repo, can you go into the repo and do git pull, and make sure you are also on master branch? 
Sure, I installed it by following the Installation Guide listed on https://github.com/neurodata/graspy, using these three lines of code:

`git clone https://github.com/neurodata/graspy
cd graspy
python3 setup.py install`

I did a git pull ., and got the message: "Already up to date."
I did a git show-branch and got the message: "[master] Tutorial fixes (#416)"
This is the exact error that I'm getting:
<img width="1110" alt="Screen Shot 2020-09-05 at 11 49 43 AM" src="https://user-images.githubusercontent.com/34703136/92308745-06569500-ef6e-11ea-80e0-9b60c32a061e.png">

thanks. can you show me output of
`help(LatentDistributionTest)`
and 
`print(LatentDistributionTest())`
can also try installing graspy by navigating to the directory where it was cloned and doing 
`pip install -e .`
but I don't think that's the issue

Output of help(LatentDistributionTest)

Help on class LatentDistributionTest in module graspy.inference.latent_distribution_test:

class LatentDistributionTest(graspy.inference.base.BaseInference)
 |  LatentDistributionTest(n_components=None, n_bootstraps=200, bandwidth=None)
 |  
 |  Two-sample hypothesis test for the problem of determining whether two random 
 |  dot product graphs have the same distributions of latent positions.
 |  
 |  This test can operate on two graphs where there is no known matching between
 |  the vertices of the two graphs, or even when the number of vertices is different. 
 |  Currently, testing is only supported for undirected graphs.
 |  
 |  Read more in the :ref:`tutorials <inference_tutorials>`
 |  
 |  Parameters
 |  ----------
 |  n_components : int or None, optional (default=None)
 |      Number of embedding dimensions. If None, the optimal embedding
 |      dimensions are found by the Zhu and Godsi algorithm.
 |  
 |  n_bootstraps : int (default=200)
 |      Number of bootstrap iterations.
 |  
 |  bandwidth : float, optional (default=0.5)
 |      Bandwidth to use for gaussian kernel. If None,
 |      the median heuristic will be used.
 |  
 |  Attributes
 |  ----------
 |  sample_T_statistic_ : float
 |      The observed difference between the embedded latent positions of the two 
 |      input graphs.
 |  
 |  p_ : float
 |      The overall p value from the test.
 |  
 |  null_distribution_ : ndarray, shape (n_bootstraps, )
 |      The distribution of T statistics generated under the null.
 |  
 |  References
 |  ----------
 |  .. [1] Tang, M., Athreya, A., Sussman, D. L., Lyzinski, V., & Priebe, C. E. (2017). 
 |      "A nonparametric two-sample hypothesis testing problem for random graphs."
 |      Bernoulli, 23(3), 1599-1630.
 |  
 |  Method resolution order:
 |      LatentDistributionTest
 |      graspy.inference.base.BaseInference
 |      sklearn.base.BaseEstimator
 |      builtins.object
 |  
 |  Methods defined here:
 |  
 |  __init__(self, n_components=None, n_bootstraps=200, bandwidth=None)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  fit(self, A1, A2)
 |      Fits the test to the two input graphs
 |      
 |      Parameters
 |      ----------
 |      A1, A2 : nx.Graph, nx.DiGraph, nx.MultiDiGraph, nx.MultiGraph, np.ndarray
 |          The two graphs to run a hypothesis test on.
 |      
 |      Returns
 |      -------
 |      p_ : float
 |          The p value corresponding to the specified hypothesis test
 |  
 |  ----------------------------------------------------------------------
 |  Methods inherited from sklearn.base.BaseEstimator:
 |  
 |  __getstate__(self)
 |  
 |  __repr__(self, N_CHAR_MAX=700)
 |      Return repr(self).
 |  
 |  __setstate__(self, state)
 |  
 |  get_params(self, deep=True)
 |      Get parameters for this estimator.
 |      
 |      Parameters
 |      ----------
 |      deep : bool, default=True
 |          If True, will return the parameters for this estimator and
 |          contained subobjects that are estimators.
 |      
 |      Returns
 |      -------
 |      params : mapping of string to any
 |          Parameter names mapped to their values.
 |  
 |  set_params(self, **params)
 |      Set the parameters of this estimator.
 |      
 |      The method works on simple estimators as well as on nested objects
 |      (such as pipelines). The latter have parameters of the form
 |      ``<component>__<parameter>`` so that it's possible to update each
 |      component of a nested object.
 |      
 |      Parameters
 |      ----------
 |      **params : dict
 |          Estimator parameters.
 |      
 |      Returns
 |      -------
 |      self : object
 |          Estimator instance.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from sklearn.base.BaseEstimator:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
Output of print(LatentDistributionTest()):

LatentDistributionTest(bandwidth=None, n_bootstraps=200, n_components=None)

yeah somehow the version of graspy you have installed is old. i'd try the `pip install -e .` thing I mentioned
and do make sure you're on the master and pull before ^
@pauladkisson 
fyi, the version of the package u're using can be checked like this:
```
>>> import graspy
>>> print grapy.__version__
```
it can very different from the version of the repo u cloned, if u did not istall it as `pip install --eidtable .`
Ok, I tried the pip install and it fixed the error.  Why would installing from github generate an old version tho?
Did you use pip to install the local version you have cloned? That's what I
was suggesting (look up what -e and . mean to pip install)

On Sat, Sep 5, 2020, 9:37 AM Paul Adkisson <notifications@github.com> wrote:

> Ok, I tried the pip install and it fixed the error. Why would installing
> from github generate an old version tho?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/neurodata/graspy/issues/291#issuecomment-687633529>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AGEF4HZHFH7XDKC37D3K2SDSEJSNBANCNFSM4JR2JFAA>
> .
>

Yes, I used pip install -e graspy
> Yes, I used pip install -e graspy

that’s not the same thing. you installed from pypi, as editable, which I’m not even sure what that means.
and this isn’t exactly what you want, for multiple reasons 
1) it’s behind
2) edits to the repo won’t be reflected in the code used by python 

can I ask you to uninstall graspy, and if u can - make a scratch environment, then do everything from the beginning and send us the log if it breaks. 

upd: where by log I mean the full log of how you’re installing.

upd 2: can you please, wrap the code in triple ``` when you post it here; it’s really hard to read otherwise. 

upd 3: when u do the above, also remove the repo and clone again plsplspls 
Hey guys, I uninstalled and reinstalled several times in different ways, but I couldn't recreate the error...At this point I'm willing to just chalk it up to some mistake on my end (due to unfamiliarity with git, etc.).  Although, I didn't remove the repo and reclone because I didn't want to have to redo fixing all the other warnings.

Sorry about the code, I was just using the <insert code> button on the comment box, but clearly it doesn't work that well.  I will try using triple quotes in the future.

Please let me know if there is some problem that I'm not understanding.
> Hey guys, I uninstalled and reinstalled several times in different ways, but I couldn't recreate the error...At this point I'm willing to just chalk it up to some mistake on my end (due to unfamiliarity with git, etc.). Although, I didn't remove the repo and reclone because I didn't want to have to redo fixing all the other warnings.

you know how git works, don’t you?

> Sorry about the code, I was just using the button on the comment box, but clearly it doesn't work that well. I will try using triple quotes in the future.

it assumes you’re going to enter just `an in-line piece`. if you paste and then highlight and click that it works.

> Please let me know if there is some problem that I'm not understanding.

how did you end up installing? what was the exact command and where were you located?



Resolving patch:
diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -82,7 +82,7 @@
 # -- Options for HTML output -------------------------------------------------
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ["_templates"]
-html_static_path = ["_static"]
+html_static_path = []
 modindex_common_prefix = ["graspy."]
 
 pygments_style = "sphinx"
diff --git a/graspy/cluster/gclust.py b/graspy/cluster/gclust.py
--- a/graspy/cluster/gclust.py
+++ b/graspy/cluster/gclust.py
@@ -45,8 +45,9 @@ class GaussianCluster(BaseCluster):
             each component has its own diagonal covariance matrix
         - 'spherical'
             each component has its own single variance
+
         If a list/array, it must be a list/array of strings containing only
-            'spherical', 'tied', 'diag', and/or 'spherical'.
+            'spherical', 'tied', 'diag', and/or 'full'.
 
     tol : float, defaults to 1e-3.
         The convergence threshold. EM iterations will stop when the
@@ -66,6 +67,7 @@ class GaussianCluster(BaseCluster):
         The method used to initialize the weights, the means and the
         precisions.
         Must be one of::
+
             'kmeans' : responsibilities are initialized using kmeans.
             'random' : responsibilities are initialized randomly.
 
diff --git a/graspy/embed/svd.py b/graspy/embed/svd.py
--- a/graspy/embed/svd.py
+++ b/graspy/embed/svd.py
@@ -86,7 +86,7 @@ def select_dimension(
 
     References
     ----------
-    .. [#1] Zhu, M. and Ghodsi, A. (2006).
+    .. [1] Zhu, M. and Ghodsi, A. (2006).
         Automatic dimensionality selection from the scree plot via the use of
         profile likelihood. Computational Statistics & Data Analysis, 51(2),
         pp.918-930.


Test patch:
diff --git a/graspy/inference/latent_position_test.py b/graspy/inference/latent_position_test.py
--- a/graspy/inference/latent_position_test.py
+++ b/graspy/inference/latent_position_test.py
@@ -47,9 +47,11 @@ class LatentPositionTest(BaseInference):
             .. math:: H_o: X_1 = X_2 R
         - 'scalar-rotation'
             .. math:: H_o: X_1 = c X_2 R
+
             where :math:`c` is a scalar, :math:`c > 0`
         - 'diagonal-rotation'
             .. math:: H_o: X_1 = D X_2 R
+
             where :math:`D` is an arbitrary diagonal matrix
 
     n_bootstraps : int, optional (default 500)
@@ -71,7 +73,7 @@ class LatentPositionTest(BaseInference):
         The p value estimated from the null distributions from sample 1 and sample 2.
 
     p_value_ : float
-        The overall p value from the test; this is the max of p_value_1_ and p_value_2_
+        The overall p value from the test; this is the max of ``p_value_1_`` and ``p_value_2_``
 
     See also
     --------