{"action":"created","comment":{"url":"https://api.github.com/repos/rice-bioe/fc/pulls/comments/46859923","id":46859923,"diff_hunk":"@@ -217,265 +52,152 @@ def clustering_gmm(data, n_clusters = 8, initialization = 'distance_sub',\n     Notes\n     -----\n     GMM finds clusters by fitting a linear combination of `n_clusters`\n-    Gaussian probability density functions (pdf) to `data`, by likelihood\n-    maximization.\n+    Gaussian probability density functions (pdf) to `data` using\n+    Expectation Maximization (EM).\n+\n+    GMM can be fairly sensitive to the initial parameter choice. To\n+    generate a reasonable set of initial conditions, `clustering_gmm`\n+    first divides all samples in `data` into `n_clusters` groups of the\n+    same size based on their Euclidean distance to the origin. Then, for\n+    each group, the 50% samples farther away from the mean are discarded.\n+    The mean and covariance are calculated from the remaining samples of\n+    each group, and used as initial conditions for the GMM EM algorithm.\n \n     `clustering_gmm` internally uses `GMM` from the ``scikit-learn``\n-    library. For more information, consult their documentation.\n+    library, with full covariance matrices for each cluster and a fixed,\n+    uniform set of weights. This means that `clustering_gmm` implicitly\n+    assumes that all bead subpopulations have roughly the same number of\n+    events. For more information, consult ``scikit-learn``'s documentation.\n \n     \"\"\"\n-    # Initialization method\n-    if initialization == 'distance':\n-        # Perform distance-based clustering\n-        labels = fc.mef.clustering_distance(data, n_clusters)\n-        labels_all = list(set(labels))\n-        data_clustered = [data[labels == i] for i in labels_all]\n-        \n-        # Initialize parameters for GMM\n-        weights = np.tile(1.0 / n_clusters,\n-                                        n_clusters)\n-        means = np.array([np.mean(di, axis = 0) \n-            for di in data_clustered])\n-        \n+    ###\n+    # Parameter initialization\n+    ###\n+    weights = np.tile(1.0 / n_clusters, n_clusters)\n+    means = []\n+    covars = []\n+\n+    # Get distance and sort based on it\n+    dist = np.sum(data**2., axis=1)\n+    sorted_i = np.argsort(dist)\n+\n+    # Expected number of elements per cluster\n+    n_per_cluster = data.shape[0]/float(n_clusters)\n+\n+    # Get means and covariances per cluster\n+    # We will just use a fraction of ``1 - 2*discard_frac`` of the data.\n+    # Data at the edges that actually corresponds to another cluster can\n+    # really mess up the final result.\n+    discard_frac = 0.25\n+    for i in range(n_clusters):\n+        il = int((i + discard_frac)*n_per_cluster)\n+        ih = int((i + 1 - discard_frac)*n_per_cluster)\n+        sorted_i_i = sorted_i[il:ih]\n+        data_i = data[sorted_i_i]\n+        means.append(np.mean(data_i, axis=0))\n         if data.shape[1] == 1:\n-            covars = [np.cov(di.T).reshape(1,1) for di in data_clustered]\n+            covars.append(np.cov(data_i.T).reshape(1,1))\n         else:\n-            covars = [np.cov(di.T) for di in data_clustered]\n-\n-        # Initialize GMM object\n-        gmm = GMM(n_components = n_clusters, tol = tol, min_covar = min_covar,\n-            covariance_type = 'full', params = 'mc', init_params = '')\n-        gmm.weight_ = weights\n-        gmm.means_ = means\n-        gmm.covars_ = covars\n-\n-    elif initialization == 'distance_sub':\n-        # Initialize parameters for GMM\n-        weights = np.tile(1.0 / n_clusters,\n-                                        n_clusters)\n-        means = []\n-        covars = []\n-\n-        # Get distance and sort based on it\n-        dist = np.sum(data**2., axis = 1)\n-        sorted_i = np.argsort(dist)\n-\n-        # Expected number of elements per cluster\n-        n_per_cluster = data.shape[0]/float(n_clusters)\n-\n-        # Get the means and covariances per cluster\n-        # We will just use a fraction of 1-2*discard_frac of the data.\n-        # Data at the edges that actually corresponds to another cluster can\n-        # really mess up the final result.\n-        discard_frac = 0.25\n-        for i in range(n_clusters):\n-            il = int((i+discard_frac)*n_per_cluster)\n-            ih = int((i+1-discard_frac)*n_per_cluster)\n-            sorted_i_i = sorted_i[il:ih]\n-            data_i = data[sorted_i_i]\n-            means.append(np.mean(data_i, axis = 0))\n-            if data.shape[1] == 1:\n-                covars.append(np.cov(data_i.T).reshape(1,1))\n-            else:\n-                covars.append(np.cov(data_i.T))\n-        means = np.array(means)\n-\n-        # Initialize GMM object\n-        gmm = GMM(n_components = n_clusters, tol = tol, min_covar = min_covar,\n-            covariance_type = 'full', params = 'mc', init_params = '')\n-        gmm.weight_ = weights\n-        gmm.means_ = means\n-        gmm.covars_ = covars\n-\n-    else:\n-        raise ValueError('Initialization method {} not implemented.'\\\n-            .format(initialization))\n+            covars.append(np.cov(data_i.T))\n+    means = np.array(means)\n+\n+    ###\n+    # Run Gaussian Mixture Model Clustering\n+    ###\n+\n+    # Initialize GMM object\n+    gmm = GMM(n_components=n_clusters,\n+              tol=tol,\n+              min_covar=min_covar,\n+              covariance_type='full',\n+              params='mc',\n+              init_params='')\n+\n+    # Set initial parameters\n+    gmm.weight_ = weights\n+    gmm.means_ = means\n+    gmm.covars_ = covars\n \n     # Fit \n     gmm.fit(data)\n-    # Get labels using the responsibilities\n+\n+    # Get labels by sampling from the responsibilities\n     # This avoids the complete elimination of a cluster if two or more clusters\n     # have very similar means.\n     resp = gmm.predict_proba(data)\n-    labels = [np.random.choice(range(n_clusters), p = ri) for ri in resp]\n+    labels = [np.random.choice(range(n_clusters), p=ri) for ri in resp]\n \n     return labels\n \n-def find_peaks_smoothed_mode(data, min_val = 0, max_val = 1023):\n+def selection_std(populations,\n+                  low=None,\n+                  high=None,\n+                  n_std_low=2.5,\n+                  n_std_high=2.5):\n     \"\"\"\n-    Find the mode of a dataset by finding the peak of a smoothed histogram.\n+    Select populations if most of their elements are between two values.\n \n-    This function finds the mode of a dataset by calculating the histogram,\n-    using a 1D Gaussian filter to smooth out the histogram, and identifying\n-    the maximum value of the smoothed histogram. The ``sigma`` parameter of\n-    the Gaussian filter is taken from the standard deviation of `data`.\n+    This function selects populations from `populations` if their means are\n+    more than `n_std_low` standard deviations greater than `low`, and\n+    `n_std_high` standard deviations lower than `high`.\n \n     Parameters\n     ----------\n-    data : array\n-        Nx1 array to calculate the mode from. `data` is assumed to contain\n-        only integers.\n-    min_val : int, optional\n-        Minimum possible value in `data`.\n-    max_val : int, optional\n-        Maximum possible value in `data`.\n+    populations : list of arrays or FCSData objects\n+        Populations to select or discard.\n+    low, high : int or float, optional\n+        Left and right threshold. If None, use 0.015 of the lowest value\n+        and 0.0985 of the highest value in the first population's `domain`,\n+        if available.\n+    n_std_low, n_std_high : float, optional\n+        Number of standard deviations from `low` and `high`, respectively,\n+        that a population's mean has to be closer than to be discarded.\n \n     Returns\n     -------\n-    peak : float\n-        Mode of `data`.\n-    hist_smooth : array\n-        ``(max_val - min_val + 1)``-long array containing the smoothed\n-        histogram.\n+    selected_mask : boolean array\n+        Set of flags indicating whether a population has been selected.\n \n     \"\"\"\n-    # Calculate bin edges and centers\n-    bin_edges = np.arange(min_val, max_val + 2) - 0.5\n-    bin_edges[0] = -np.inf\n-    bin_edges[-1] = np.inf\n-    bin_centers = np.arange(min_val, max_val + 1)\n-\n-    # Identify peak\n-    # Calculate sample mean and standard deviation\n-    # mu = np.mean(data)\n-    sigma = np.std(data)\n-    # Calculate histogram\n-    hist, __ = np.histogram(data, bin_edges)\n-    # Do Gaussian blur on histogram\n-    # We have found empirically that using one half of the distribution's \n-    # standard deviation results in a nice fit.\n-    hist_smooth = scipy.ndimage.filters.gaussian_filter1d(hist, sigma/2.)\n-    # Extract peak\n-    i_max = np.argmax(hist_smooth)\n-    peak = bin_centers[i_max]\n-\n-    return peak, hist_smooth\n-\n-def find_peaks_median(data):\n-    \"\"\"\n-    Find the median of a data array.\n+    # Default thresholds\n+    if low is None:\n+        low = 0.015*populations[0].domain(0)[0]\n+    if high is None:\n+        high = 0.985*populations[0].domain(0)[-1]\n \n-    Parameters\n-    ----------\n-    data : array\n-        Nx1 array to calculate the median from.\n+    # Calculate means and standard deviations\n+    pop_mean = np.array([fc.stats.mean(p) for p in populations])\n+    pop_std = np.array([fc.stats.std(p) for p in populations])\n \n-    Returns\n-    -------\n-    peak : int or float\n-        Median of `data`.\n-\n-    \"\"\"\n-    peak = np.median(data)\n-    return peak\n-\n-def select_peaks_proximity(peaks_ch,\n-                           peaks_mef,\n-                           peaks_ch_std,\n-                           peaks_ch_std_mult_l = 2.5,\n-                           peaks_ch_std_mult_r = 2.5,\n-                           peaks_ch_min = 0,\n-                           peaks_ch_max = 1023):\n-    \"\"\"\n-    Select bead subpopulations based on proximity to a minimum and maximum.\n-\n-    This function discards some values from `peaks_ch` if they're closer\n-    than `peaks_ch_std_mult_l` standard deviations to `peaks_ch_min`, or\n-    `peaks_ch_std_mult_r` standard deviations to `peaks_ch_max`. Standard\n-    deviations should be provided in `peaks_ch_std`. Then, it discards the\n-    corresponding values in `peaks_mef`. Finally, it discards the values in\n-    `peaks_mef` that have an undetermined value (NaN), and the\n-    corresponding values in peaks_ch.\n-\n-    Parameters\n-    ----------\n-    peaks_ch : array\n-        Sorted fluorescence values of bead populations in channel units.\n-    peaks_mef : array\n-        Sorted fluorescence values of bead populations in MEF units.\n-    peaks_ch_std_mult_l, peaks_ch_std_mult_r : float, optional\n-        Number of standard deviations from `peaks_ch_min` and\n-        `peaks_ch_max`, respectively, that a value in `peaks_ch` has to be\n-        closer than to be discarded.\n-    peaks_ch_min, peaks_ch_max : int, optional\n-        Minimum and maximum tolerable fluorescence value in channel units.\n-\n-    Returns\n-    -------\n-    sel_peaks_ch : array\n-        Selected fluorescence values of bead populations in channel units.\n-    sel_peaks_mef : array\n-        Selected fluorescence values of bead populations in MEF units.\n-\n-    \"\"\"\n-    # Minimum peak standard deviation will be 1.0\n+    # Set minimum standard deviation to one.\n     min_std = 1.0\n-    peaks_ch_std = peaks_ch_std.copy()\n-    peaks_ch_std[peaks_ch_std < min_std] = min_std\n-\n-    # Discard channel-space peaks\n-    if (peaks_ch[0] - peaks_ch_std[0]*peaks_ch_std_mult_l) <= peaks_ch_min and\\\n-        (peaks_ch[-1] + peaks_ch_std[-1]*peaks_ch_std_mult_r) >= peaks_ch_max:\n-        raise ValueError('Peaks are being cut off at both sides.')\n-    elif (peaks_ch[0] - peaks_ch_std[0]*peaks_ch_std_mult_l) <= peaks_ch_min:\n-        discard_ch = 'left'\n-        discard_ch_n = 1\n-        while (peaks_ch[discard_ch_n] - \n-            peaks_ch_std[discard_ch_n]*peaks_ch_std_mult_l) <= peaks_ch_min:\n-            discard_ch_n = discard_ch_n + 1\n-        sel_peaks_ch = peaks_ch[discard_ch_n:]\n-    elif (peaks_ch[-1] + peaks_ch_std[-1]*peaks_ch_std_mult_r) >= peaks_ch_max:\n-        discard_ch = 'right'\n-        discard_ch_n = 1\n-        while (peaks_ch[-1-discard_ch_n] +\n-            peaks_ch_std[-1-discard_ch_n]*peaks_ch_std_mult_r) >= peaks_ch_max:\n-            discard_ch_n = discard_ch_n + 1\n-        sel_peaks_ch = peaks_ch[:-discard_ch_n]\n-    else:\n-        discard_ch = False\n-        discard_ch_n = 0\n-        sel_peaks_ch = peaks_ch.copy()\n-\n-    # Discard MEF peaks\n-    discard_mef_n = len(peaks_mef) - len(sel_peaks_ch)\n-    if discard_ch == 'left':\n-        sel_peaks_mef = peaks_mef[discard_mef_n:]\n-    elif discard_ch == 'right':\n-        sel_peaks_mef = peaks_mef[:-discard_mef_n]\n-    elif discard_ch == False and discard_mef_n == 0:\n-        sel_peaks_mef = peaks_mef.copy()\n-    else:\n-        ValueError('Number of MEF values and channel peaks does not match.')\n-    \n-    # Discard unknown (NaN) peaks\n-    unknown_mef = np.isnan(sel_peaks_mef)\n-    n_unknown_mef = np.sum(unknown_mef)\n-    if n_unknown_mef > 0:\n-        sel_peaks_ch = sel_peaks_ch[np.invert(unknown_mef)]\n-        sel_peaks_mef = sel_peaks_mef[np.invert(unknown_mef)]\n+    pop_std[pop_std < min_std] = min_std\n \n-    return sel_peaks_ch, sel_peaks_mef\n+    # Return populations that don't cross either threshold\n+    selected_mask = np.logical_and((pop_mean - n_std_low*pop_std) > low,\n+                                   (pop_mean - n_std_high*pop_std) < high)\n+    return selected_mask\n \n-def fit_standard_curve(peaks_ch, peaks_mef):\n+def fit_beads_autofluorescence(fl_channel, fl_mef):\n     \"\"\"\n-    Fit a standard curve to known fluorescence values of calibration beads.\n+    Fit a standard curve using a beads model with autofluorescence.\n \n     Parameters\n     ----------\n-    peaks_ch : array\n+    fl_channel : array\n         Fluorescence values of bead populations in channel units.\n-    peaks_mef : array\n+    fl_mef : array\n         Fluorescence values of bead populations in MEF units.\n \n     Returns\n     -------\n-    sc : function\n+    std_crv : function\n         Standard curve that transforms fluorescence from channel units to\n         MEF units.","path":"fc/mef.py","position":557,"original_position":557,"commit_id":"bf2581e42c2227533df5e00f2f2f7ebfa9c8f04e","original_commit_id":"bf2581e42c2227533df5e00f2f2f7ebfa9c8f04e","user":{"login":"JS3xton","id":2179825,"avatar_url":"https://avatars.githubusercontent.com/u/2179825?v=3","gravatar_id":"","url":"https://api.github.com/users/JS3xton","html_url":"https://github.com/JS3xton","followers_url":"https://api.github.com/users/JS3xton/followers","following_url":"https://api.github.com/users/JS3xton/following{/other_user}","gists_url":"https://api.github.com/users/JS3xton/gists{/gist_id}","starred_url":"https://api.github.com/users/JS3xton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JS3xton/subscriptions","organizations_url":"https://api.github.com/users/JS3xton/orgs","repos_url":"https://api.github.com/users/JS3xton/repos","events_url":"https://api.github.com/users/JS3xton/events{/privacy}","received_events_url":"https://api.github.com/users/JS3xton/received_events","type":"User","site_admin":false},"body":"Might be nice to indicate the function signature here.","created_at":"2015-12-07T18:54:08Z","updated_at":"2015-12-07T18:54:08Z","html_url":"https://github.com/rice-bioe/fc/pull/165#discussion_r46859923","pull_request_url":"https://api.github.com/repos/rice-bioe/fc/pulls/165","_links":{"self":{"href":"https://api.github.com/repos/rice-bioe/fc/pulls/comments/46859923"},"html":{"href":"https://github.com/rice-bioe/fc/pull/165#discussion_r46859923"},"pull_request":{"href":"https://api.github.com/repos/rice-bioe/fc/pulls/165"}}},"pull_request":{"url":"https://api.github.com/repos/rice-bioe/fc/pulls/165","id":52799217,"html_url":"https://github.com/rice-bioe/fc/pull/165","diff_url":"https://github.com/rice-bioe/fc/pull/165.diff","patch_url":"https://github.com/rice-bioe/fc/pull/165.patch","issue_url":"https://api.github.com/repos/rice-bioe/fc/issues/165","number":165,"state":"open","locked":false,"title":"MEF module cleanup","user":{"login":"castillohair","id":1529481,"avatar_url":"https://avatars.githubusercontent.com/u/1529481?v=3","gravatar_id":"","url":"https://api.github.com/users/castillohair","html_url":"https://github.com/castillohair","followers_url":"https://api.github.com/users/castillohair/followers","following_url":"https://api.github.com/users/castillohair/following{/other_user}","gists_url":"https://api.github.com/users/castillohair/gists{/gist_id}","starred_url":"https://api.github.com/users/castillohair/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/castillohair/subscriptions","organizations_url":"https://api.github.com/users/castillohair/orgs","repos_url":"https://api.github.com/users/castillohair/repos","events_url":"https://api.github.com/users/castillohair/events{/privacy}","received_events_url":"https://api.github.com/users/castillohair/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-12-07T02:13:42Z","updated_at":"2015-12-07T18:54:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3d492db0216d43ccb99079391a453b2d884b55d1","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/rice-bioe/fc/pulls/165/commits","review_comments_url":"https://api.github.com/repos/rice-bioe/fc/pulls/165/comments","review_comment_url":"https://api.github.com/repos/rice-bioe/fc/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rice-bioe/fc/issues/165/comments","statuses_url":"https://api.github.com/repos/rice-bioe/fc/statuses/bf2581e42c2227533df5e00f2f2f7ebfa9c8f04e","head":{"label":"rice-bioe:mef-improvements","ref":"mef-improvements","sha":"bf2581e42c2227533df5e00f2f2f7ebfa9c8f04e","user":{"login":"rice-bioe","id":2345009,"avatar_url":"https://avatars.githubusercontent.com/u/2345009?v=3","gravatar_id":"","url":"https://api.github.com/users/rice-bioe","html_url":"https://github.com/rice-bioe","followers_url":"https://api.github.com/users/rice-bioe/followers","following_url":"https://api.github.com/users/rice-bioe/following{/other_user}","gists_url":"https://api.github.com/users/rice-bioe/gists{/gist_id}","starred_url":"https://api.github.com/users/rice-bioe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rice-bioe/subscriptions","organizations_url":"https://api.github.com/users/rice-bioe/orgs","repos_url":"https://api.github.com/users/rice-bioe/repos","events_url":"https://api.github.com/users/rice-bioe/events{/privacy}","received_events_url":"https://api.github.com/users/rice-bioe/received_events","type":"Organization","site_admin":false},"repo":{"id":38354829,"name":"fc","full_name":"rice-bioe/fc","owner":{"login":"rice-bioe","id":2345009,"avatar_url":"https://avatars.githubusercontent.com/u/2345009?v=3","gravatar_id":"","url":"https://api.github.com/users/rice-bioe","html_url":"https://github.com/rice-bioe","followers_url":"https://api.github.com/users/rice-bioe/followers","following_url":"https://api.github.com/users/rice-bioe/following{/other_user}","gists_url":"https://api.github.com/users/rice-bioe/gists{/gist_id}","starred_url":"https://api.github.com/users/rice-bioe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rice-bioe/subscriptions","organizations_url":"https://api.github.com/users/rice-bioe/orgs","repos_url":"https://api.github.com/users/rice-bioe/repos","events_url":"https://api.github.com/users/rice-bioe/events{/privacy}","received_events_url":"https://api.github.com/users/rice-bioe/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rice-bioe/fc","description":"Python Flow Cytometry Library","fork":false,"url":"https://api.github.com/repos/rice-bioe/fc","forks_url":"https://api.github.com/repos/rice-bioe/fc/forks","keys_url":"https://api.github.com/repos/rice-bioe/fc/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rice-bioe/fc/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rice-bioe/fc/teams","hooks_url":"https://api.github.com/repos/rice-bioe/fc/hooks","issue_events_url":"https://api.github.com/repos/rice-bioe/fc/issues/events{/number}","events_url":"https://api.github.com/repos/rice-bioe/fc/events","assignees_url":"https://api.github.com/repos/rice-bioe/fc/assignees{/user}","branches_url":"https://api.github.com/repos/rice-bioe/fc/branches{/branch}","tags_url":"https://api.github.com/repos/rice-bioe/fc/tags","blobs_url":"https://api.github.com/repos/rice-bioe/fc/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rice-bioe/fc/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rice-bioe/fc/git/refs{/sha}","trees_url":"https://api.github.com/repos/rice-bioe/fc/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rice-bioe/fc/statuses/{sha}","languages_url":"https://api.github.com/repos/rice-bioe/fc/languages","stargazers_url":"https://api.github.com/repos/rice-bioe/fc/stargazers","contributors_url":"https://api.github.com/repos/rice-bioe/fc/contributors","subscribers_url":"https://api.github.com/repos/rice-bioe/fc/subscribers","subscription_url":"https://api.github.com/repos/rice-bioe/fc/subscription","commits_url":"https://api.github.com/repos/rice-bioe/fc/commits{/sha}","git_commits_url":"https://api.github.com/repos/rice-bioe/fc/git/commits{/sha}","comments_url":"https://api.github.com/repos/rice-bioe/fc/comments{/number}","issue_comment_url":"https://api.github.com/repos/rice-bioe/fc/issues/comments{/number}","contents_url":"https://api.github.com/repos/rice-bioe/fc/contents/{+path}","compare_url":"https://api.github.com/repos/rice-bioe/fc/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rice-bioe/fc/merges","archive_url":"https://api.github.com/repos/rice-bioe/fc/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rice-bioe/fc/downloads","issues_url":"https://api.github.com/repos/rice-bioe/fc/issues{/number}","pulls_url":"https://api.github.com/repos/rice-bioe/fc/pulls{/number}","milestones_url":"https://api.github.com/repos/rice-bioe/fc/milestones{/number}","notifications_url":"https://api.github.com/repos/rice-bioe/fc/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rice-bioe/fc/labels{/name}","releases_url":"https://api.github.com/repos/rice-bioe/fc/releases{/id}","created_at":"2015-07-01T06:50:32Z","updated_at":"2015-12-02T20:24:37Z","pushed_at":"2015-12-07T17:57:48Z","git_url":"git://github.com/rice-bioe/fc.git","ssh_url":"git@github.com:rice-bioe/fc.git","clone_url":"https://github.com/rice-bioe/fc.git","svn_url":"https://github.com/rice-bioe/fc","homepage":null,"size":6340,"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":29,"forks":0,"open_issues":29,"watchers":0,"default_branch":"master"}},"base":{"label":"rice-bioe:develop","ref":"develop","sha":"911a7bd554ab7ee5fbc3640daa81fe5402928eb8","user":{"login":"rice-bioe","id":2345009,"avatar_url":"https://avatars.githubusercontent.com/u/2345009?v=3","gravatar_id":"","url":"https://api.github.com/users/rice-bioe","html_url":"https://github.com/rice-bioe","followers_url":"https://api.github.com/users/rice-bioe/followers","following_url":"https://api.github.com/users/rice-bioe/following{/other_user}","gists_url":"https://api.github.com/users/rice-bioe/gists{/gist_id}","starred_url":"https://api.github.com/users/rice-bioe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rice-bioe/subscriptions","organizations_url":"https://api.github.com/users/rice-bioe/orgs","repos_url":"https://api.github.com/users/rice-bioe/repos","events_url":"https://api.github.com/users/rice-bioe/events{/privacy}","received_events_url":"https://api.github.com/users/rice-bioe/received_events","type":"Organization","site_admin":false},"repo":{"id":38354829,"name":"fc","full_name":"rice-bioe/fc","owner":{"login":"rice-bioe","id":2345009,"avatar_url":"https://avatars.githubusercontent.com/u/2345009?v=3","gravatar_id":"","url":"https://api.github.com/users/rice-bioe","html_url":"https://github.com/rice-bioe","followers_url":"https://api.github.com/users/rice-bioe/followers","following_url":"https://api.github.com/users/rice-bioe/following{/other_user}","gists_url":"https://api.github.com/users/rice-bioe/gists{/gist_id}","starred_url":"https://api.github.com/users/rice-bioe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rice-bioe/subscriptions","organizations_url":"https://api.github.com/users/rice-bioe/orgs","repos_url":"https://api.github.com/users/rice-bioe/repos","events_url":"https://api.github.com/users/rice-bioe/events{/privacy}","received_events_url":"https://api.github.com/users/rice-bioe/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rice-bioe/fc","description":"Python Flow Cytometry Library","fork":false,"url":"https://api.github.com/repos/rice-bioe/fc","forks_url":"https://api.github.com/repos/rice-bioe/fc/forks","keys_url":"https://api.github.com/repos/rice-bioe/fc/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rice-bioe/fc/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rice-bioe/fc/teams","hooks_url":"https://api.github.com/repos/rice-bioe/fc/hooks","issue_events_url":"https://api.github.com/repos/rice-bioe/fc/issues/events{/number}","events_url":"https://api.github.com/repos/rice-bioe/fc/events","assignees_url":"https://api.github.com/repos/rice-bioe/fc/assignees{/user}","branches_url":"https://api.github.com/repos/rice-bioe/fc/branches{/branch}","tags_url":"https://api.github.com/repos/rice-bioe/fc/tags","blobs_url":"https://api.github.com/repos/rice-bioe/fc/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rice-bioe/fc/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rice-bioe/fc/git/refs{/sha}","trees_url":"https://api.github.com/repos/rice-bioe/fc/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rice-bioe/fc/statuses/{sha}","languages_url":"https://api.github.com/repos/rice-bioe/fc/languages","stargazers_url":"https://api.github.com/repos/rice-bioe/fc/stargazers","contributors_url":"https://api.github.com/repos/rice-bioe/fc/contributors","subscribers_url":"https://api.github.com/repos/rice-bioe/fc/subscribers","subscription_url":"https://api.github.com/repos/rice-bioe/fc/subscription","commits_url":"https://api.github.com/repos/rice-bioe/fc/commits{/sha}","git_commits_url":"https://api.github.com/repos/rice-bioe/fc/git/commits{/sha}","comments_url":"https://api.github.com/repos/rice-bioe/fc/comments{/number}","issue_comment_url":"https://api.github.com/repos/rice-bioe/fc/issues/comments{/number}","contents_url":"https://api.github.com/repos/rice-bioe/fc/contents/{+path}","compare_url":"https://api.github.com/repos/rice-bioe/fc/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rice-bioe/fc/merges","archive_url":"https://api.github.com/repos/rice-bioe/fc/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rice-bioe/fc/downloads","issues_url":"https://api.github.com/repos/rice-bioe/fc/issues{/number}","pulls_url":"https://api.github.com/repos/rice-bioe/fc/pulls{/number}","milestones_url":"https://api.github.com/repos/rice-bioe/fc/milestones{/number}","notifications_url":"https://api.github.com/repos/rice-bioe/fc/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rice-bioe/fc/labels{/name}","releases_url":"https://api.github.com/repos/rice-bioe/fc/releases{/id}","created_at":"2015-07-01T06:50:32Z","updated_at":"2015-12-02T20:24:37Z","pushed_at":"2015-12-07T17:57:48Z","git_url":"git://github.com/rice-bioe/fc.git","ssh_url":"git@github.com:rice-bioe/fc.git","clone_url":"https://github.com/rice-bioe/fc.git","svn_url":"https://github.com/rice-bioe/fc","homepage":null,"size":6340,"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":29,"forks":0,"open_issues":29,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rice-bioe/fc/pulls/165"},"html":{"href":"https://github.com/rice-bioe/fc/pull/165"},"issue":{"href":"https://api.github.com/repos/rice-bioe/fc/issues/165"},"comments":{"href":"https://api.github.com/repos/rice-bioe/fc/issues/165/comments"},"review_comments":{"href":"https://api.github.com/repos/rice-bioe/fc/pulls/165/comments"},"review_comment":{"href":"https://api.github.com/repos/rice-bioe/fc/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rice-bioe/fc/pulls/165/commits"},"statuses":{"href":"https://api.github.com/repos/rice-bioe/fc/statuses/bf2581e42c2227533df5e00f2f2f7ebfa9c8f04e"}}}}