{"action":"created","comment":{"url":"https://api.github.com/repos/mne-tools/mne-python/pulls/comments/26502117","id":26502117,"diff_hunk":"@@ -0,0 +1,256 @@\n+\"\"\"Compute a Recursively Applied and Projected MUltiple\n+Signal Classification (RAP-MUSIC).\n+\"\"\"\n+\n+# Authors: Yousra Bekhti <yousra.bekhti@gmail.com>\n+#          Alexandre Gramfort <alexandre.gramfort@telecom-paristech.fr>\n+#\n+# License: BSD (3-clause)\n+\n+import numpy as np\n+from scipy import linalg\n+\n+from ..io.pick import pick_channels_evoked\n+from ..minimum_norm.inverse import _check_reference\n+from ..cov import compute_whitener\n+from ..utils import logger, verbose\n+from ..dipole import Dipole\n+from ._lcmv import _prepare_beamformer_input, _setup_picks\n+\n+\n+@verbose\n+def _apply_rap_music(data, info, times, forward, noise_cov,\n+                     signal_ndim=15, n_dipoles=5, picks=None,\n+                     return_explained_data=False, verbose=None):\n+    \"\"\"RAP-MUSIC for evoked data\n+\n+    Parameters\n+    ----------\n+    data : array or list / iterable\n+        Evoked data.\n+    info : dict\n+        Measurement info.\n+    times : float\n+        Times.\n+    forward : dict\n+        Forward operator.\n+    noise_cov : Covariance\n+        The noise covariance.\n+    signal_ndim : int\n+        The dimension of the subspace spanning the signal.\n+        The default value is 15.\n+    n_dipoles : int\n+        The number of dipoles to estimate.\n+    picks : array-like of int | None\n+        Indices (in info) of data channels. If None, MEG and EEG data channels\n+        (without bad channels) will be used.\n+    return_explained_data : bool\n+        If True, the explained data is returned as an array.\n+    verbose : bool, str, int, or None\n+        If not None, override default verbose level (see mne.verbose).\n+\n+    Returns\n+    -------\n+    dipoles : list of instances of Dipole\n+        The dipole fits.\n+    explained_data : array\n+        Data explained by the dipoles using a least square fitting with the\n+        selected active dipoles and their estimated orientation.\n+        Computed only if return_explained_data is True.\n+    \"\"\"\n+    is_free_ori, ch_names, proj, vertno, G = _prepare_beamformer_input(\n+        info, forward, label=None, picks=picks, pick_ori=None)\n+\n+    gain = G.copy()\n+\n+    # Handle whitening + data covariance\n+    whitener, _ = compute_whitener(noise_cov, info, picks)\n+    if info['projs']:\n+        whitener = np.dot(whitener, proj)\n+\n+    # whiten the leadfield and the data\n+    G = np.dot(whitener, G)\n+    data = np.dot(whitener, data)\n+\n+    eig_values, eig_vectors = linalg.eigh(np.dot(data, data.T))\n+    phi_sig = eig_vectors[:, -signal_ndim:]\n+\n+    n_orient = 3 if is_free_ori else 1\n+    A = np.zeros((G.shape[0], n_dipoles))\n+    active_set = []\n+    oris = []\n+\n+    G_proj = G\n+    phi_sig_proj = phi_sig\n+\n+    for k in range(n_dipoles):\n+        subcorr_max = -1.\n+        source_idx = None\n+        for i_source in range(G.shape[1] // n_orient):\n+            Gk = G_proj[:, n_orient * i_source:\n+                        n_orient * i_source + n_orient]\n+\n+            subcorr, ori = _compute_subcorr(Gk, phi_sig_proj)\n+            if subcorr > subcorr_max:\n+                subcorr_max = subcorr\n+                source_idx = i_source\n+                A[:, k] = np.dot(Gk, ori)\n+                if n_orient == 1:\n+                    ori = [forward['src'][0]['nn'][vertno[0][i_source]]\n+                           if i_source <= vertno[0].size else\n+                           forward['src'][1]['nn'][vertno[1][i_source -\n+                                                             vertno[0].size]]]\n+                else:\n+                    ori = np.dot(forward['source_nn'][n_orient * i_source:\n+                                                      n_orient * i_source +\n+                                                      n_orient, :], ori)\n+\n+                if ori[-1] < 0:  # make sure ori is relative to surface ori\n+                    ori *= -1.\n+                source_ori = ori\n+\n+        active_set.append(source_idx)\n+        oris.append(source_ori)\n+\n+        logger.info(\"source %s found: p = %s\" % (k + 1, active_set[-1]))\n+        if n_orient == 3:\n+            logger.info(\"ori = %s %s %s\" % (source_ori[0], source_ori[1],\n+                                            source_ori[2]))\n+\n+        projection = _compute_proj(A[:, :k + 1])\n+        G_proj = np.dot(projection, G)\n+        phi_sig_proj = np.dot(projection, phi_sig)\n+\n+    sol = linalg.lstsq(A, data)[0]\n+\n+    active_set = np.sort(active_set)\n+    explained_data = None\n+    if return_explained_data:\n+        explained_data = np.dot(gain[:, active_set], sol)\n+\n+    vertno[1] = vertno[1][active_set[active_set > vertno[0].size] -\n+                          vertno[0].size]\n+    vertno[0] = vertno[0][active_set[active_set <= vertno[0].size]]\n+\n+    tstep = 1.0 / info['sfreq']\n+\n+    return _make_dipoles(times, tstep, forward['src'], vertno, active_set,\n+                         oris, sol), explained_data\n+\n+\n+def _make_dipoles(times, tstep, src, vertno, active_set, oris, sol):\n+    if vertno[0].size == 0:\n+        pos = np.array(src[1]['rr'][vertno[1]])\n+    elif vertno[1].size == 0:\n+        pos = np.array(src[0]['rr'][vertno[0]])\n+    else:\n+        pos = np.array((src[0]['rr'][vertno[0]][0],\n+                        src[1]['rr'][vertno[1]][0]))\n+    amplitude = sol * 1e09\n+    ori = np.array(oris)\n+    gof = []\n+\n+    dipoles = []\n+    for i_dip in range(pos.shape[0]):\n+        i_pos = pos[i_dip][np.newaxis, :].repeat(len(times), axis=0)\n+        i_ori = ori[i_dip][np.newaxis, :].repeat(len(times), axis=0)\n+        dipoles.append(Dipole(times * 1e3, i_pos, amplitude[i_dip],\n+                              i_ori, gof))\n+\n+    return dipoles\n+\n+\n+def _compute_subcorr(G, phi_sig):\n+    \"\"\" Compute the subspace correlation\n+    \"\"\"\n+    Ug = linalg.qr(G, mode='economic')[0]\n+    tmp = np.dot(Ug.T.conjugate(), phi_sig)\n+    subcorr = np.dot(tmp, tmp.T.conjugate()).real\n+    eig_vals, eig_vecs = linalg.eigh(subcorr)\n+    return np.sqrt(eig_vals[-1]), eig_vecs[:, -1]\n+\n+\n+def _compute_proj(A):\n+    \"\"\" Compute the orthogonal projection operation for\n+    a manifold vector A.\n+    \"\"\"\n+    Ah = A.T.conjugate()\n+    I = np.identity(A.shape[0])\n+    return I - np.dot(np.dot(A, linalg.pinv(np.dot(Ah, A))), Ah)\n+\n+\n+@verbose\n+def rap_music(evoked, forward, noise_cov, signal_ndim=15, n_dipoles=5,\n+              return_residual=False, picks=None, verbose=None):\n+    \"\"\"RAP-MUSIC source localization method.\n+\n+    Compute Recursively Applied and Projected MUltiple SIgnal Classification\n+    (RAP-MUSIC) on evoked data.\n+\n+    Parameters\n+    ----------\n+    evoked : Evoked\n+        Evoked data to localize.\n+    forward : dict","path":"mne/beamformer/_rap_music.py","position":194,"original_position":194,"commit_id":"fd577c265f420fdafd9e0fbccb368eed82d31e37","original_commit_id":"fd577c265f420fdafd9e0fbccb368eed82d31e37","user":{"login":"agramfort","id":161052,"avatar_url":"https://avatars.githubusercontent.com/u/161052?v=3","gravatar_id":"","url":"https://api.github.com/users/agramfort","html_url":"https://github.com/agramfort","followers_url":"https://api.github.com/users/agramfort/followers","following_url":"https://api.github.com/users/agramfort/following{/other_user}","gists_url":"https://api.github.com/users/agramfort/gists{/gist_id}","starred_url":"https://api.github.com/users/agramfort/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/agramfort/subscriptions","organizations_url":"https://api.github.com/users/agramfort/orgs","repos_url":"https://api.github.com/users/agramfort/repos","events_url":"https://api.github.com/users/agramfort/events{/privacy}","received_events_url":"https://api.github.com/users/agramfort/received_events","type":"User","site_admin":false},"body":"instance of Forward","created_at":"2015-03-16T16:36:25Z","updated_at":"2015-03-16T16:36:25Z","html_url":"https://github.com/mne-tools/mne-python/pull/1815#discussion_r26502117","pull_request_url":"https://api.github.com/repos/mne-tools/mne-python/pulls/1815","_links":{"self":{"href":"https://api.github.com/repos/mne-tools/mne-python/pulls/comments/26502117"},"html":{"href":"https://github.com/mne-tools/mne-python/pull/1815#discussion_r26502117"},"pull_request":{"href":"https://api.github.com/repos/mne-tools/mne-python/pulls/1815"}}},"pull_request":{"url":"https://api.github.com/repos/mne-tools/mne-python/pulls/1815","id":29715483,"html_url":"https://github.com/mne-tools/mne-python/pull/1815","diff_url":"https://github.com/mne-tools/mne-python/pull/1815.diff","patch_url":"https://github.com/mne-tools/mne-python/pull/1815.patch","issue_url":"https://api.github.com/repos/mne-tools/mne-python/issues/1815","number":1815,"state":"open","locked":false,"title":"Source Localization using Rap-Music","user":{"login":"yousrabk","id":4352445,"avatar_url":"https://avatars.githubusercontent.com/u/4352445?v=3","gravatar_id":"","url":"https://api.github.com/users/yousrabk","html_url":"https://github.com/yousrabk","followers_url":"https://api.github.com/users/yousrabk/followers","following_url":"https://api.github.com/users/yousrabk/following{/other_user}","gists_url":"https://api.github.com/users/yousrabk/gists{/gist_id}","starred_url":"https://api.github.com/users/yousrabk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yousrabk/subscriptions","organizations_url":"https://api.github.com/users/yousrabk/orgs","repos_url":"https://api.github.com/users/yousrabk/repos","events_url":"https://api.github.com/users/yousrabk/events{/privacy}","received_events_url":"https://api.github.com/users/yousrabk/received_events","type":"User","site_admin":false},"body":"Here is an implementation of the Rap-Music source localization @joewalter, @agramfort if I'm missing anything, let me know.\r\n","created_at":"2015-02-20T17:45:02Z","updated_at":"2015-03-16T16:36:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cff4bafd7a8edc1c23dc3212c4652519f3230c21","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mne-tools/mne-python/pulls/1815/commits","review_comments_url":"https://api.github.com/repos/mne-tools/mne-python/pulls/1815/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/1815/comments","statuses_url":"https://api.github.com/repos/mne-tools/mne-python/statuses/fd577c265f420fdafd9e0fbccb368eed82d31e37","head":{"label":"yousrabk:rapmusic","ref":"rapmusic","sha":"fd577c265f420fdafd9e0fbccb368eed82d31e37","user":{"login":"yousrabk","id":4352445,"avatar_url":"https://avatars.githubusercontent.com/u/4352445?v=3","gravatar_id":"","url":"https://api.github.com/users/yousrabk","html_url":"https://github.com/yousrabk","followers_url":"https://api.github.com/users/yousrabk/followers","following_url":"https://api.github.com/users/yousrabk/following{/other_user}","gists_url":"https://api.github.com/users/yousrabk/gists{/gist_id}","starred_url":"https://api.github.com/users/yousrabk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yousrabk/subscriptions","organizations_url":"https://api.github.com/users/yousrabk/orgs","repos_url":"https://api.github.com/users/yousrabk/repos","events_url":"https://api.github.com/users/yousrabk/events{/privacy}","received_events_url":"https://api.github.com/users/yousrabk/received_events","type":"User","site_admin":false},"repo":{"id":29482908,"name":"mne-python","full_name":"yousrabk/mne-python","owner":{"login":"yousrabk","id":4352445,"avatar_url":"https://avatars.githubusercontent.com/u/4352445?v=3","gravatar_id":"","url":"https://api.github.com/users/yousrabk","html_url":"https://github.com/yousrabk","followers_url":"https://api.github.com/users/yousrabk/followers","following_url":"https://api.github.com/users/yousrabk/following{/other_user}","gists_url":"https://api.github.com/users/yousrabk/gists{/gist_id}","starred_url":"https://api.github.com/users/yousrabk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yousrabk/subscriptions","organizations_url":"https://api.github.com/users/yousrabk/orgs","repos_url":"https://api.github.com/users/yousrabk/repos","events_url":"https://api.github.com/users/yousrabk/events{/privacy}","received_events_url":"https://api.github.com/users/yousrabk/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/yousrabk/mne-python","description":"MNE : Magnetoencephalography (MEG) and Electroencephalography (EEG) in Python","fork":true,"url":"https://api.github.com/repos/yousrabk/mne-python","forks_url":"https://api.github.com/repos/yousrabk/mne-python/forks","keys_url":"https://api.github.com/repos/yousrabk/mne-python/keys{/key_id}","collaborators_url":"https://api.github.com/repos/yousrabk/mne-python/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/yousrabk/mne-python/teams","hooks_url":"https://api.github.com/repos/yousrabk/mne-python/hooks","issue_events_url":"https://api.github.com/repos/yousrabk/mne-python/issues/events{/number}","events_url":"https://api.github.com/repos/yousrabk/mne-python/events","assignees_url":"https://api.github.com/repos/yousrabk/mne-python/assignees{/user}","branches_url":"https://api.github.com/repos/yousrabk/mne-python/branches{/branch}","tags_url":"https://api.github.com/repos/yousrabk/mne-python/tags","blobs_url":"https://api.github.com/repos/yousrabk/mne-python/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/yousrabk/mne-python/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/yousrabk/mne-python/git/refs{/sha}","trees_url":"https://api.github.com/repos/yousrabk/mne-python/git/trees{/sha}","statuses_url":"https://api.github.com/repos/yousrabk/mne-python/statuses/{sha}","languages_url":"https://api.github.com/repos/yousrabk/mne-python/languages","stargazers_url":"https://api.github.com/repos/yousrabk/mne-python/stargazers","contributors_url":"https://api.github.com/repos/yousrabk/mne-python/contributors","subscribers_url":"https://api.github.com/repos/yousrabk/mne-python/subscribers","subscription_url":"https://api.github.com/repos/yousrabk/mne-python/subscription","commits_url":"https://api.github.com/repos/yousrabk/mne-python/commits{/sha}","git_commits_url":"https://api.github.com/repos/yousrabk/mne-python/git/commits{/sha}","comments_url":"https://api.github.com/repos/yousrabk/mne-python/comments{/number}","issue_comment_url":"https://api.github.com/repos/yousrabk/mne-python/issues/comments{/number}","contents_url":"https://api.github.com/repos/yousrabk/mne-python/contents/{+path}","compare_url":"https://api.github.com/repos/yousrabk/mne-python/compare/{base}...{head}","merges_url":"https://api.github.com/repos/yousrabk/mne-python/merges","archive_url":"https://api.github.com/repos/yousrabk/mne-python/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/yousrabk/mne-python/downloads","issues_url":"https://api.github.com/repos/yousrabk/mne-python/issues{/number}","pulls_url":"https://api.github.com/repos/yousrabk/mne-python/pulls{/number}","milestones_url":"https://api.github.com/repos/yousrabk/mne-python/milestones{/number}","notifications_url":"https://api.github.com/repos/yousrabk/mne-python/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/yousrabk/mne-python/labels{/name}","releases_url":"https://api.github.com/repos/yousrabk/mne-python/releases{/id}","created_at":"2015-01-19T17:36:48Z","updated_at":"2015-01-19T21:21:48Z","pushed_at":"2015-03-16T12:13:39Z","git_url":"git://github.com/yousrabk/mne-python.git","ssh_url":"git@github.com:yousrabk/mne-python.git","clone_url":"https://github.com/yousrabk/mne-python.git","svn_url":"https://github.com/yousrabk/mne-python","homepage":"http://martinos.org/mne/","size":74075,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mne-tools:master","ref":"master","sha":"dfdd7db18ca471a2b86a610b0bb179d55fbdd454","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-03-16T15:44:51Z","pushed_at":"2015-03-16T15:44:51Z","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":162354,"stargazers_count":118,"watchers_count":118,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":106,"mirror_url":null,"open_issues_count":153,"forks":106,"open_issues":153,"watchers":118,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mne-tools/mne-python/pulls/1815"},"html":{"href":"https://github.com/mne-tools/mne-python/pull/1815"},"issue":{"href":"https://api.github.com/repos/mne-tools/mne-python/issues/1815"},"comments":{"href":"https://api.github.com/repos/mne-tools/mne-python/issues/1815/comments"},"review_comments":{"href":"https://api.github.com/repos/mne-tools/mne-python/pulls/1815/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/1815/commits"},"statuses":{"href":"https://api.github.com/repos/mne-tools/mne-python/statuses/fd577c265f420fdafd9e0fbccb368eed82d31e37"}}}}