{"action":"created","comment":{"url":"https://api.github.com/repos/mne-tools/mne-python/pulls/comments/33945695","id":33945695,"diff_hunk":"@@ -0,0 +1,463 @@\n+import numpy as np\n+from collections import defaultdict\n+from operator import add\n+from scipy.signal import welch, lfilter\n+from scipy.stats import kurtosis\n+from functools import reduce\n+from . import find_outliers\n+from ..utils import logger\n+from ..io.pick import pick_types, channel_type\n+\n+\n+def _by_ch_type(info, picks):\n+    \"\"\"Returns lists of channel indices, grouped by channel type.\"\"\"\n+    ch_types = defaultdict(list)\n+\n+    for ch in picks:\n+        ch_types[channel_type(info, ch)].append(ch)\n+\n+    return ch_types.items()\n+\n+\n+def _hurst(x):\n+    \"\"\"Estimate Hurst exponent on a timeseries.\n+\n+    The estimation is based on the second order discrete derivative.\n+\n+    Parameters\n+    ----------\n+    x : 1D numpy array\n+        The timeseries to estimate the Hurst exponent for.\n+\n+    Returns\n+    -------\n+    h : float\n+        The estimation of the Hurst exponent for the given timeseries.\n+    \"\"\"\n+    y = np.cumsum(np.diff(x, axis=1), axis=1)\n+\n+    b1 = [1, -2, 1]\n+    b2 = [1,  0, -2, 0, 1]\n+\n+    # second order derivative\n+    y1 = lfilter(b1, 1, y, axis=1)\n+    y1 = y1[:, len(b1) - 1:-1]  # first values contain filter artifacts\n+\n+    # wider second order derivative\n+    y2 = lfilter(b2, 1, y, axis=1)\n+    y2 = y2[:, len(b2) - 1:-1]  # first values contain filter artifacts\n+\n+    s1 = np.mean(y1 ** 2, axis=1)\n+    s2 = np.mean(y2 ** 2, axis=1)\n+\n+    return 0.5 * np.log2(s2 / s1)\n+\n+\n+def _efficient_welch(data, sfreq):\n+    \"\"\"Calls scipy.signal.welch with parameters optimized for greatest speed\n+    at the expense of precision. The window is set to ~10 seconds and windows\n+    are non-overlapping.\n+\n+    Parameters\n+    ----------\n+    data : N-D numpy array\n+        The timeseries to estimate signal power for. The last dimension\n+        is presumed to be time.\n+    sfreq : float\n+        The sample rate of the timeseries.\n+\n+    Returns\n+    -------\n+    fs : 1D numpy array\n+        The frequencies for which the power spectra was calculated.\n+    ps : ND numpy array\n+        The power spectra for each timeseries.\n+    \"\"\"\n+    nperseg = min(data.shape[-1],\n+                  2 ** int(np.log2(10 * sfreq) + 1))  # next power of 2\n+\n+    return welch(data, sfreq, nperseg=nperseg, noverlap=0, axis=-1)\n+\n+\n+def _freqs_power(data, sfreq, freqs):\n+    \"\"\"Estimate signal power at specific frequencies.\n+\n+    Parameters\n+    ----------\n+    data : N-D numpy array\n+        The timeseries to estimate signal power for. The last dimension\n+        is presumed to be time.\n+    sfreq : float\n+        The sample rate of the timeseries.\n+    freqs : list of float\n+        The frequencies to estimate signal power for.\n+\n+    Returns\n+    -------\n+    ps : list of float\n+        For each requested frequency, the estimated signal power.\n+    \"\"\"\n+    fs, ps = _efficient_welch(data, sfreq)\n+    try:\n+        return np.sum([ps[..., np.searchsorted(fs, f)] for f in freqs], axis=0)\n+    except IndexError:\n+        raise ValueError(\n+            (\"Insufficient sample rate to  estimate power at {} Hz for line \"\n+             \"noise detection. Use the 'metrics' parameter to disable the \"\n+             \"'line_noise' metric.\").format(freqs))\n+\n+\n+def _power_gradient(data, sfreq, prange):\n+    \"\"\"Estimate the gradient of the power spectrum at upper frequencies.\n+\n+    Parameters\n+    ----------\n+    data : N-D numpy array\n+        The timeseries to estimate signal power for. The last dimension\n+        is presumed to be time.\n+    sfreq : float\n+        The sample rate of the timeseries.\n+    prange : pair of floats\n+        The (lower, upper) frequency limits of the power spectrum to use. In\n+        the FASTER paper, they set these to the passband of the lowpass filter.\n+\n+    Returns\n+    -------\n+    grad : N-D numpy array\n+        The gradients of each timeseries.\n+    \"\"\"\n+    fs, ps = _efficient_welch(data, sfreq)\n+\n+    # Limit power spectrum to upper frequencies\n+    start, stop = (np.searchsorted(fs, p) for p in prange)\n+    if start >= ps.shape[1]:\n+        raise ValueError((\"Sample rate insufficient to estimate {} Hz power. \"\n+                          \"Use the 'power_gradient_range' parameter to tweak \"\n+                          \"the tested frequencies for this metric or use the \"\n+                          \"'metrics' parameter to disable the \"\n+                          \"'power_gradient' metric.\").format(prange[0]))\n+    ps = ps[:, start:stop]\n+\n+    # Compute mean gradients\n+    return np.mean(np.diff(ps), axis=1)\n+\n+\n+def _deviation(data):\n+    \"\"\"Computes the deviation from mean for each channel in a set of epochs.\n+\n+    This is not implemented as a lambda function, because the channel means\n+    should be cached during the computation.\n+\n+    Parameters\n+    ----------\n+    data : 3D numpy array\n+        The epochs (#epochs x #channels x #samples).\n+\n+    Returns\n+    -------\n+    dev : 1D numpy array\n+        For each epoch, the mean deviation of the channels.\n+    \"\"\"\n+    ch_mean = np.mean(data, axis=2)\n+    return ch_mean - np.mean(ch_mean, axis=0)\n+\n+\n+def faster_bad_channels(epochs, picks=None, thres=3, use_metrics=None,\n+                        max_iter=2, return_by_metric=False):\n+    \"\"\"Implements the first step of the FASTER algorithm.\n+\n+    This function attempts to automatically mark bad EEG channels by performing\n+    outlier detection. It operated on epoched data, to make sure only relevant\n+    data is analyzed.\n+\n+    Parameters\n+    ----------\n+    epochs : Instance of Epochs\n+        The epochs for which bad channels need to be marked\n+    picks : list of int | None\n+        Channels to operate on. Defaults to EEG channels.\n+    thres : float\n+        The threshold value, in standard deviations, to apply. A channel\n+        crossing this threshold value is marked as bad. Defaults to 3.\n+    use_metrics : list of str\n+        List of metrics to use. Can be any combination of:\n+            'variance', 'correlation', 'hurst', 'kurtosis', 'line_noise'\n+        Defaults to all of them.\n+    max_iter : int\n+        The maximum number of iterations performed during outlier detection\n+        (defaults to 2, original FASTER paper uses 1).\n+    return_by_metric : bool\n+        Whether to return the bad channels as a flat list (False, default) or\n+        as a dictionary with the names of the used metrics as keys and the\n+        bad channels found by this metric as values.\n+\n+    Returns\n+    -------\n+    bads : list of str\n+        The names of the bad EEG channels.\n+    \"\"\"\n+    metrics = {\n+        'variance': lambda x: np.var(x, axis=1),\n+        'correlation': lambda x: np.mean(\n+            np.ma.masked_array(np.corrcoef(x),\n+                               np.identity(len(x), dtype=bool)), axis=0),\n+        'hurst': lambda x: _hurst(x),\n+        'kurtosis': lambda x: kurtosis(x, axis=1),\n+        'line_noise': lambda x: _freqs_power(x, epochs.info['sfreq'],\n+                                             [50, 60]),\n+    }\n+\n+    if picks is None:\n+        picks = pick_types(epochs.info, meg=True, eeg=True, exclude=[])\n+    if use_metrics is None:\n+        use_metrics = metrics.keys()\n+\n+    # Concatenate epochs in time\n+    data = epochs.get_data()\n+    data = data.transpose(1, 0, 2).reshape(data.shape[1], -1)\n+    data = data[picks]\n+\n+    # Find bad channels\n+    bads = defaultdict(list)\n+    for ch_type, chs in _by_ch_type(epochs.info, picks):\n+        logger.info('Bad channel detection on %s channels:' % ch_type.upper())\n+        for m in use_metrics:\n+            s = metrics[m](data[chs])\n+            b = [epochs.ch_names[picks[chs[i]]]\n+                 for i in find_outliers(s, thres, max_iter)]\n+            logger.info('\\tBad by %s: %s' % (m, b))\n+            bads[m].append(b)\n+\n+    bads = dict([(k, np.concatenate(v).tolist()) for k, v in bads.items()])\n+    if return_by_metric:\n+        return bads\n+    else:\n+        return np.unique(np.concatenate(list(bads.values()))).tolist()\n+\n+\n+def faster_bad_epochs(epochs, picks=None, thres=3, use_metrics=None,\n+                      max_iter=2, return_by_metric=False):\n+    \"\"\"Implements the second step of the FASTER algorithm.\n+\n+    This function attempts to automatically mark bad epochs by performing\n+    outlier detection.\n+\n+    Parameters\n+    ----------\n+    epochs : Instance of Epochs\n+        The epochs to analyze.\n+    picks : list of int | None\n+        Channels to operate on. Defaults to EEG channels.\n+    thres : float","path":"mne/preprocessing/faster.py","position":251,"original_position":251,"commit_id":"d91cc67aeac912ed08297eb15f708baf3edf5cb8","original_commit_id":"d91cc67aeac912ed08297eb15f708baf3edf5cb8","user":{"login":"mainakjas","id":3817535,"avatar_url":"https://avatars.githubusercontent.com/u/3817535?v=3","gravatar_id":"","url":"https://api.github.com/users/mainakjas","html_url":"https://github.com/mainakjas","followers_url":"https://api.github.com/users/mainakjas/followers","following_url":"https://api.github.com/users/mainakjas/following{/other_user}","gists_url":"https://api.github.com/users/mainakjas/gists{/gist_id}","starred_url":"https://api.github.com/users/mainakjas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mainakjas/subscriptions","organizations_url":"https://api.github.com/users/mainakjas/orgs","repos_url":"https://api.github.com/users/mainakjas/repos","events_url":"https://api.github.com/users/mainakjas/events{/privacy}","received_events_url":"https://api.github.com/users/mainakjas/received_events","type":"User","site_admin":false},"body":"I mean a single function that calls all the FASTER steps in sequence. I've described it elsewhere. The arguments to the functions look very similar to me. No point in asking the user to write 5 lines when it can be done in one line.","created_at":"2015-07-06T15:22:09Z","updated_at":"2015-07-06T15:22:09Z","html_url":"https://github.com/mne-tools/mne-python/pull/1777#discussion_r33945695","pull_request_url":"https://api.github.com/repos/mne-tools/mne-python/pulls/1777","_links":{"self":{"href":"https://api.github.com/repos/mne-tools/mne-python/pulls/comments/33945695"},"html":{"href":"https://github.com/mne-tools/mne-python/pull/1777#discussion_r33945695"},"pull_request":{"href":"https://api.github.com/repos/mne-tools/mne-python/pulls/1777"}}},"pull_request":{"url":"https://api.github.com/repos/mne-tools/mne-python/pulls/1777","id":28726334,"html_url":"https://github.com/mne-tools/mne-python/pull/1777","diff_url":"https://github.com/mne-tools/mne-python/pull/1777.diff","patch_url":"https://github.com/mne-tools/mne-python/pull/1777.patch","issue_url":"https://api.github.com/repos/mne-tools/mne-python/issues/1777","number":1777,"state":"open","locked":false,"title":"WIP: Automatic artifact detection with FASTER","user":{"login":"wmvanvliet","id":428273,"avatar_url":"https://avatars.githubusercontent.com/u/428273?v=3","gravatar_id":"","url":"https://api.github.com/users/wmvanvliet","html_url":"https://github.com/wmvanvliet","followers_url":"https://api.github.com/users/wmvanvliet/followers","following_url":"https://api.github.com/users/wmvanvliet/following{/other_user}","gists_url":"https://api.github.com/users/wmvanvliet/gists{/gist_id}","starred_url":"https://api.github.com/users/wmvanvliet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wmvanvliet/subscriptions","organizations_url":"https://api.github.com/users/wmvanvliet/orgs","repos_url":"https://api.github.com/users/wmvanvliet/repos","events_url":"https://api.github.com/users/wmvanvliet/events{/privacy}","received_events_url":"https://api.github.com/users/wmvanvliet/received_events","type":"User","site_admin":false},"body":"The FASTER method consists of a series of algorithms designed to automatically detect various artifacts through outlier detection [1]. This PR implements the first four steps of the series:\r\n\r\n1. Detect bad MEG/EEG channels\r\n2. Detect bad epochs\r\n3. Detect bad ICA components\r\n4. Detect for each epoch, channels that are locally bad\r\n\r\nAn example is provided that takes the user through all four steps and demonstrates how to deal with the detected artifacts (bad channels can be interpolated, bad epochs can be rejected, bad ICA components can be zeroed out, ...)\r\n\r\n[1] Nolan H., Whelan R. and Reilly RB. FASTER: fully automated statistical thresholding for EEG artifact rejection. Journal of Neuroscience Methods, vol. 192, issue 1, pp. 152-162, 2010. http://doi.org/10.1016/j.jneumeth.2010.07.015\r\n","created_at":"2015-02-05T14:01:40Z","updated_at":"2015-07-06T15:22:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c4d53d7d9a6413b3913232c426f9fc31aea702b6","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mne-tools/mne-python/pulls/1777/commits","review_comments_url":"https://api.github.com/repos/mne-tools/mne-python/pulls/1777/comments","review_comment_url":"https://api.github.com/repos/mne-tools/mne-python/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mne-tools/mne-python/issues/1777/comments","statuses_url":"https://api.github.com/repos/mne-tools/mne-python/statuses/d91cc67aeac912ed08297eb15f708baf3edf5cb8","head":{"label":"wmvanvliet:faster","ref":"faster","sha":"d91cc67aeac912ed08297eb15f708baf3edf5cb8","user":{"login":"wmvanvliet","id":428273,"avatar_url":"https://avatars.githubusercontent.com/u/428273?v=3","gravatar_id":"","url":"https://api.github.com/users/wmvanvliet","html_url":"https://github.com/wmvanvliet","followers_url":"https://api.github.com/users/wmvanvliet/followers","following_url":"https://api.github.com/users/wmvanvliet/following{/other_user}","gists_url":"https://api.github.com/users/wmvanvliet/gists{/gist_id}","starred_url":"https://api.github.com/users/wmvanvliet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wmvanvliet/subscriptions","organizations_url":"https://api.github.com/users/wmvanvliet/orgs","repos_url":"https://api.github.com/users/wmvanvliet/repos","events_url":"https://api.github.com/users/wmvanvliet/events{/privacy}","received_events_url":"https://api.github.com/users/wmvanvliet/received_events","type":"User","site_admin":false},"repo":{"id":23457160,"name":"mne-python","full_name":"wmvanvliet/mne-python","owner":{"login":"wmvanvliet","id":428273,"avatar_url":"https://avatars.githubusercontent.com/u/428273?v=3","gravatar_id":"","url":"https://api.github.com/users/wmvanvliet","html_url":"https://github.com/wmvanvliet","followers_url":"https://api.github.com/users/wmvanvliet/followers","following_url":"https://api.github.com/users/wmvanvliet/following{/other_user}","gists_url":"https://api.github.com/users/wmvanvliet/gists{/gist_id}","starred_url":"https://api.github.com/users/wmvanvliet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wmvanvliet/subscriptions","organizations_url":"https://api.github.com/users/wmvanvliet/orgs","repos_url":"https://api.github.com/users/wmvanvliet/repos","events_url":"https://api.github.com/users/wmvanvliet/events{/privacy}","received_events_url":"https://api.github.com/users/wmvanvliet/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/wmvanvliet/mne-python","description":"MNE : Magnetoencephalography (MEG) and Electroencephalography (EEG) in Python","fork":true,"url":"https://api.github.com/repos/wmvanvliet/mne-python","forks_url":"https://api.github.com/repos/wmvanvliet/mne-python/forks","keys_url":"https://api.github.com/repos/wmvanvliet/mne-python/keys{/key_id}","collaborators_url":"https://api.github.com/repos/wmvanvliet/mne-python/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/wmvanvliet/mne-python/teams","hooks_url":"https://api.github.com/repos/wmvanvliet/mne-python/hooks","issue_events_url":"https://api.github.com/repos/wmvanvliet/mne-python/issues/events{/number}","events_url":"https://api.github.com/repos/wmvanvliet/mne-python/events","assignees_url":"https://api.github.com/repos/wmvanvliet/mne-python/assignees{/user}","branches_url":"https://api.github.com/repos/wmvanvliet/mne-python/branches{/branch}","tags_url":"https://api.github.com/repos/wmvanvliet/mne-python/tags","blobs_url":"https://api.github.com/repos/wmvanvliet/mne-python/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/wmvanvliet/mne-python/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/wmvanvliet/mne-python/git/refs{/sha}","trees_url":"https://api.github.com/repos/wmvanvliet/mne-python/git/trees{/sha}","statuses_url":"https://api.github.com/repos/wmvanvliet/mne-python/statuses/{sha}","languages_url":"https://api.github.com/repos/wmvanvliet/mne-python/languages","stargazers_url":"https://api.github.com/repos/wmvanvliet/mne-python/stargazers","contributors_url":"https://api.github.com/repos/wmvanvliet/mne-python/contributors","subscribers_url":"https://api.github.com/repos/wmvanvliet/mne-python/subscribers","subscription_url":"https://api.github.com/repos/wmvanvliet/mne-python/subscription","commits_url":"https://api.github.com/repos/wmvanvliet/mne-python/commits{/sha}","git_commits_url":"https://api.github.com/repos/wmvanvliet/mne-python/git/commits{/sha}","comments_url":"https://api.github.com/repos/wmvanvliet/mne-python/comments{/number}","issue_comment_url":"https://api.github.com/repos/wmvanvliet/mne-python/issues/comments{/number}","contents_url":"https://api.github.com/repos/wmvanvliet/mne-python/contents/{+path}","compare_url":"https://api.github.com/repos/wmvanvliet/mne-python/compare/{base}...{head}","merges_url":"https://api.github.com/repos/wmvanvliet/mne-python/merges","archive_url":"https://api.github.com/repos/wmvanvliet/mne-python/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/wmvanvliet/mne-python/downloads","issues_url":"https://api.github.com/repos/wmvanvliet/mne-python/issues{/number}","pulls_url":"https://api.github.com/repos/wmvanvliet/mne-python/pulls{/number}","milestones_url":"https://api.github.com/repos/wmvanvliet/mne-python/milestones{/number}","notifications_url":"https://api.github.com/repos/wmvanvliet/mne-python/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/wmvanvliet/mne-python/labels{/name}","releases_url":"https://api.github.com/repos/wmvanvliet/mne-python/releases{/id}","created_at":"2014-08-29T08:06:25Z","updated_at":"2015-05-08T07:28:50Z","pushed_at":"2015-06-08T20:22:52Z","git_url":"git://github.com/wmvanvliet/mne-python.git","ssh_url":"git@github.com:wmvanvliet/mne-python.git","clone_url":"https://github.com/wmvanvliet/mne-python.git","svn_url":"https://github.com/wmvanvliet/mne-python","homepage":"http://martinos.org/mne/","size":78825,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"mne-tools:master","ref":"master","sha":"e61db28bb5ac7bf0cf280ab01e97be47068e9e6d","user":{"login":"mne-tools","id":583875,"avatar_url":"https://avatars.githubusercontent.com/u/583875?v=3","gravatar_id":"","url":"https://api.github.com/users/mne-tools","html_url":"https://github.com/mne-tools","followers_url":"https://api.github.com/users/mne-tools/followers","following_url":"https://api.github.com/users/mne-tools/following{/other_user}","gists_url":"https://api.github.com/users/mne-tools/gists{/gist_id}","starred_url":"https://api.github.com/users/mne-tools/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mne-tools/subscriptions","organizations_url":"https://api.github.com/users/mne-tools/orgs","repos_url":"https://api.github.com/users/mne-tools/repos","events_url":"https://api.github.com/users/mne-tools/events{/privacy}","received_events_url":"https://api.github.com/users/mne-tools/received_events","type":"Organization","site_admin":false},"repo":{"id":1301584,"name":"mne-python","full_name":"mne-tools/mne-python","owner":{"login":"mne-tools","id":583875,"avatar_url":"https://avatars.githubusercontent.com/u/583875?v=3","gravatar_id":"","url":"https://api.github.com/users/mne-tools","html_url":"https://github.com/mne-tools","followers_url":"https://api.github.com/users/mne-tools/followers","following_url":"https://api.github.com/users/mne-tools/following{/other_user}","gists_url":"https://api.github.com/users/mne-tools/gists{/gist_id}","starred_url":"https://api.github.com/users/mne-tools/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mne-tools/subscriptions","organizations_url":"https://api.github.com/users/mne-tools/orgs","repos_url":"https://api.github.com/users/mne-tools/repos","events_url":"https://api.github.com/users/mne-tools/events{/privacy}","received_events_url":"https://api.github.com/users/mne-tools/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mne-tools/mne-python","description":"MNE : Magnetoencephalography (MEG) and Electroencephalography (EEG) in Python","fork":false,"url":"https://api.github.com/repos/mne-tools/mne-python","forks_url":"https://api.github.com/repos/mne-tools/mne-python/forks","keys_url":"https://api.github.com/repos/mne-tools/mne-python/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mne-tools/mne-python/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mne-tools/mne-python/teams","hooks_url":"https://api.github.com/repos/mne-tools/mne-python/hooks","issue_events_url":"https://api.github.com/repos/mne-tools/mne-python/issues/events{/number}","events_url":"https://api.github.com/repos/mne-tools/mne-python/events","assignees_url":"https://api.github.com/repos/mne-tools/mne-python/assignees{/user}","branches_url":"https://api.github.com/repos/mne-tools/mne-python/branches{/branch}","tags_url":"https://api.github.com/repos/mne-tools/mne-python/tags","blobs_url":"https://api.github.com/repos/mne-tools/mne-python/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mne-tools/mne-python/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mne-tools/mne-python/git/refs{/sha}","trees_url":"https://api.github.com/repos/mne-tools/mne-python/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mne-tools/mne-python/statuses/{sha}","languages_url":"https://api.github.com/repos/mne-tools/mne-python/languages","stargazers_url":"https://api.github.com/repos/mne-tools/mne-python/stargazers","contributors_url":"https://api.github.com/repos/mne-tools/mne-python/contributors","subscribers_url":"https://api.github.com/repos/mne-tools/mne-python/subscribers","subscription_url":"https://api.github.com/repos/mne-tools/mne-python/subscription","commits_url":"https://api.github.com/repos/mne-tools/mne-python/commits{/sha}","git_commits_url":"https://api.github.com/repos/mne-tools/mne-python/git/commits{/sha}","comments_url":"https://api.github.com/repos/mne-tools/mne-python/comments{/number}","issue_comment_url":"https://api.github.com/repos/mne-tools/mne-python/issues/comments{/number}","contents_url":"https://api.github.com/repos/mne-tools/mne-python/contents/{+path}","compare_url":"https://api.github.com/repos/mne-tools/mne-python/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mne-tools/mne-python/merges","archive_url":"https://api.github.com/repos/mne-tools/mne-python/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mne-tools/mne-python/downloads","issues_url":"https://api.github.com/repos/mne-tools/mne-python/issues{/number}","pulls_url":"https://api.github.com/repos/mne-tools/mne-python/pulls{/number}","milestones_url":"https://api.github.com/repos/mne-tools/mne-python/milestones{/number}","notifications_url":"https://api.github.com/repos/mne-tools/mne-python/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mne-tools/mne-python/labels{/name}","releases_url":"https://api.github.com/repos/mne-tools/mne-python/releases{/id}","created_at":"2011-01-28T03:31:13Z","updated_at":"2015-07-04T01:31:51Z","pushed_at":"2015-07-06T13:27:01Z","git_url":"git://github.com/mne-tools/mne-python.git","ssh_url":"git@github.com:mne-tools/mne-python.git","clone_url":"https://github.com/mne-tools/mne-python.git","svn_url":"https://github.com/mne-tools/mne-python","homepage":"http://martinos.org/mne/","size":178886,"stargazers_count":135,"watchers_count":135,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":128,"mirror_url":null,"open_issues_count":173,"forks":128,"open_issues":173,"watchers":135,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mne-tools/mne-python/pulls/1777"},"html":{"href":"https://github.com/mne-tools/mne-python/pull/1777"},"issue":{"href":"https://api.github.com/repos/mne-tools/mne-python/issues/1777"},"comments":{"href":"https://api.github.com/repos/mne-tools/mne-python/issues/1777/comments"},"review_comments":{"href":"https://api.github.com/repos/mne-tools/mne-python/pulls/1777/comments"},"review_comment":{"href":"https://api.github.com/repos/mne-tools/mne-python/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mne-tools/mne-python/pulls/1777/commits"},"statuses":{"href":"https://api.github.com/repos/mne-tools/mne-python/statuses/d91cc67aeac912ed08297eb15f708baf3edf5cb8"}}}}