{"action":"created","comment":{"url":"https://api.github.com/repos/xgcm/xmitgcm/pulls/comments/208329398","pull_request_review_id":144106161,"id":208329398,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwODMyOTM5OA==","diff_hunk":"@@ -549,3 +549,236 @@ def _llc_data_shape(llc_id, nz=None):\n     # should we accomodate multiple records?\n     # no, not in this function\n     return data_shape\n+\n+\n+def read_all_variables(variable_list, metadata, use_mmap=True):\n+    ''' return a dictionary of dask arrays\n+    variable_list : list\n+                    list of MITgcm variables, from fldList in .meta\n+    metadata      : dict\n+                    internal metadata for binary file\n+    use_mmap      : bool, optional\n+                    Whether to read the data using a numpy.memmap\n+    '''\n+    out = []\n+    for variable in variable_list:\n+        out.append(read_generic_data(variable, metadata, use_mmap=use_mmap))\n+\n+    return out\n+\n+\n+def read_generic_data(variable, metadata, use_mmap=True):\n+    ''' return dask array for variable using the given metadata\n+    variable : string\n+               name of the variable to read\n+    metadata : dict\n+               internal metadata for binary file\n+    use_mmap : bool, optional\n+               Whether to read the data using a numpy.memmap\n+    '''\n+\n+    if (metadata['nx'] == 1) and (metadata['ny'] == 1) and \\\n+       (len(metadata['vars']) == 1):\n+            # vertical coordinate\n+        data_raw = read_raw_data(metadata['filename'], metadata['dtype'],\n+                                 (metadata['nz'],), use_mmap=use_mmap,\n+                                 offset=0, order='C', partial_read=False)\n+\n+        shape = (metadata['nt'], metadata['nz'], 1,\n+                 metadata['nx'], metadata['nx'])\n+        data_raw = np.reshape(data_raw, shape)\n+        chunks = (metadata['nt'], 1, 1,\n+                  metadata['nx'], metadata['nx'])\n+        data = dsa.from_array(data_raw, chunks=chunks)\n+\n+    else:\n+        if metadata['has_faces']:\n+            def load_chunk(face, lev, rec):\n+                return _read_xy_chunk(variable, metadata, rec=rec, lev=lev,\n+                                      face=face, use_mmap=use_mmap)[None,\n+                                                                    None, None]\n+\n+            chunks = (1, 1, 1, metadata['nx'], metadata['nx'])\n+            shape = (metadata['nt'], metadata['nz'],\n+                     len(metadata['face_facets']),\n+                     metadata['nx'], metadata['nx'])\n+            name = 'llc-' + tokenize(metadata['filename'])\n+\n+            dsk = {(name, rec, lev, face, 0, 0): (load_chunk, face,\n+                                                  lev, rec)\n+                   for face in range(len(metadata['face_facets']))\n+                   for lev in range(metadata['nz'])\n+                   for rec in range(metadata['nt'])}\n+\n+            data = dsa.Array(dsk, name, chunks,\n+                             dtype=metadata['dtype'], shape=shape)\n+        else:\n+            def load_chunk(lev, rec):\n+                return _read_xy_chunk(variable, metadata, rec=rec, lev=lev,\n+                                      face=0, use_mmap=use_mmap)[None, None]\n+\n+            chunks = (1, 1, metadata['ny'], metadata['nx'])\n+            shape = (metadata['nt'], metadata['nz'],\n+                     metadata['ny'], metadata['nx'])\n+            name = 'reg-' + tokenize(metadata['filename'])\n+\n+            dsk = {(name, rec, lev, 0, 0): (load_chunk, lev, rec)\n+                   for lev in range(metadata['nz'])\n+                   for rec in range(metadata['nt'])}\n+\n+            data = dsa.Array(dsk, name, chunks,\n+                             dtype=metadata['dtype'], shape=shape)\n+\n+    return data\n+\n+\n+def _read_xy_chunk(variable, metadata, rec=0, lev=0, face=0, use_mmap=False):\n+    ''' read a 2d chunk along (x,y)\n+    variable : string\n+               name of the variable to read\n+    metadata : dict\n+               metadata for binary file\n+    rec      : integer, optional\n+               time record to read (default=0)\n+    lev      : integer, optional\n+               vertical level to read (default=0)\n+    face     : integer, optional\n+               face to read for llc configurations (default=0)\n+    use_mmap : bool, optional\n+               Whether to read the data using a numpy.memmap\n+    '''\n+\n+    # size of the data element\n+    nbytes = metadata['dtype'].itemsize\n+    # byte order\n+    metadata['dtype'] = metadata['dtype'].newbyteorder(metadata['endian'])\n+    # find index of variable\n+    idx_var = metadata['vars'].index(variable)\n+\n+    # 1. compute offset_variable, init to zero\n+    offset_vars = 0\n+    # loop on variables before the one to read\n+    for jvar in np.arange(idx_var):\n+        # inspect its dimensions\n+        dims = metadata['dims_vars'][jvar]\n+        # compute the byte size of this variable\n+        nbytes_thisvar = 1*nbytes\n+        for dim in dims:\n+            nbytes_thisvar = nbytes_thisvar*metadata[dim]\n+        # update offset from previous variables\n+        offset_vars = offset_vars+nbytes_thisvar\n+\n+    # 2. get dimensions of desired variable\n+    dims = metadata['dims_vars'][idx_var]\n+    # set values to 1 by default\n+    nx = 1\n+    ny = 1\n+    nz = 1\n+    nt = 1\n+    # update with true values\n+    if 'nx' in dims:\n+        nx = metadata['nx']\n+    if 'ny' in dims:\n+        ny = metadata['ny']\n+    if 'nz' in dims:\n+        nz = metadata['nz']\n+    if 'nt' in dims:\n+        nt = metadata['nt']\n+\n+    # 3. compute offset from previous records of current variable\n+    if (rec > nt-1):\n+        raise ValueError(\"time record %g greater than number of records %g\" %\n+                         (rec, nt))\n+    else:\n+        offset_timerecords = rec * nz * ny * nx * nbytes\n+\n+    # 4. compute offset from previous vertical levels of current variable\n+    if (lev > nz-1):\n+        raise ValueError(\"level %g is greater than number of levels %g\" %\n+                         (lev, nz))\n+    else:\n+        offset_verticallevels = lev * ny * nx * nbytes\n+\n+    # 5. compute the offset of the previous variables, records and levels\n+    offset = offset_vars + offset_timerecords + offset_verticallevels\n+\n+    # 6. compute offset due to faces\n+    if metadata['has_faces']:\n+        # determin which facet the face belong to\n+        facet_origin = metadata['face_facets'][face]\n+        # compute the offset from previous facets\n+        ny_facets = np.array(metadata['ny_facets'])\n+        nyglo_facets = np.concatenate(([0], ny_facets.cumsum()[:-1]), axis=0)\n+        offset_facets = nyglo_facets[facet_origin] * metadata['nx'] * nbytes\n+        # update offset\n+        offset = offset + offset_facets\n+        # shape if shape of the facet\n+        shape = (metadata['ny_facets'][facet_origin], nx,)\n+    else:\n+        # no need to update offset and shape is simply:\n+        shape = (ny, nx,)\n+\n+    # check if we do a partial read of the file\n+    if (nt > 1) or (nz > 1) or (len(metadata['vars']) > 1) or \\\n+       metadata['has_faces']:\n+        partial_read = True\n+    else:\n+        partial_read = False\n+\n+    # define the order (row/column major)\n+    if metadata['has_faces']:\n+        # in llc, we can have either C or F\n+        order = metadata['facet_orders'][facet_origin]\n+    else:\n+        # in conventional grids, it's in C\n+        order = 'C'\n+\n+    # 7. Do the actual read\n+    data_raw = read_raw_data(metadata['filename'], metadata['dtype'],\n+                             shape, use_mmap=use_mmap, offset=offset,\n+                             order=order, partial_read=partial_read)\n+\n+    ddata_interior = dsa.from_array(data_raw, chunks=data_raw.shape)\n+\n+    # 8. Pad data, if needed\n+    if 'pad_before_y' in metadata:\n+        if metadata['has_faces']:\n+            nypad_before = metadata['pad_before_y'][facet_origin]\n+        else:\n+            nypad_before = metadata['pad_before_y']\n+\n+        pad_before = dsa.from_array(\n+            np.zeros((nypad_before, nx)), chunks=(nypad_before, nx))\n+        ddata_padded_before = dsa.concatenate(\n+            (pad_before, ddata_interior), axis=0)","path":"xmitgcm/utils.py","position":205,"original_position":205,"commit_id":"a93b9e8e6a3045c5c8a75dd644904206aec1ea6d","original_commit_id":"a93b9e8e6a3045c5c8a75dd644904206aec1ea6d","user":{"login":"rabernat","id":1197350,"node_id":"MDQ6VXNlcjExOTczNTA=","avatar_url":"https://avatars1.githubusercontent.com/u/1197350?v=4","gravatar_id":"","url":"https://api.github.com/users/rabernat","html_url":"https://github.com/rabernat","followers_url":"https://api.github.com/users/rabernat/followers","following_url":"https://api.github.com/users/rabernat/following{/other_user}","gists_url":"https://api.github.com/users/rabernat/gists{/gist_id}","starred_url":"https://api.github.com/users/rabernat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rabernat/subscriptions","organizations_url":"https://api.github.com/users/rabernat/orgs","repos_url":"https://api.github.com/users/rabernat/repos","events_url":"https://api.github.com/users/rabernat/events{/privacy}","received_events_url":"https://api.github.com/users/rabernat/received_events","type":"User","site_admin":false},"body":"These calls to zeros / concatenate should be refactored to use some sort of duck-operations, selecting either dask or numpy functions depending on the user's desired format. See\r\nhttps://github.com/xgcm/xgcm/blob/master/xgcm/duck_array_ops.py","created_at":"2018-08-07T18:03:01Z","updated_at":"2018-08-07T18:06:45Z","html_url":"https://github.com/xgcm/xmitgcm/pull/87#discussion_r208329398","pull_request_url":"https://api.github.com/repos/xgcm/xmitgcm/pulls/87","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/xgcm/xmitgcm/pulls/comments/208329398"},"html":{"href":"https://github.com/xgcm/xmitgcm/pull/87#discussion_r208329398"},"pull_request":{"href":"https://api.github.com/repos/xgcm/xmitgcm/pulls/87"}}},"pull_request":{"url":"https://api.github.com/repos/xgcm/xmitgcm/pulls/87","id":205465298,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA1NDY1Mjk4","html_url":"https://github.com/xgcm/xmitgcm/pull/87","diff_url":"https://github.com/xgcm/xmitgcm/pull/87.diff","patch_url":"https://github.com/xgcm/xmitgcm/pull/87.patch","issue_url":"https://api.github.com/repos/xgcm/xmitgcm/issues/87","number":87,"state":"open","locked":false,"title":"WIP refactoring of low level functions","user":{"login":"raphaeldussin","id":14662821,"node_id":"MDQ6VXNlcjE0NjYyODIx","avatar_url":"https://avatars1.githubusercontent.com/u/14662821?v=4","gravatar_id":"","url":"https://api.github.com/users/raphaeldussin","html_url":"https://github.com/raphaeldussin","followers_url":"https://api.github.com/users/raphaeldussin/followers","following_url":"https://api.github.com/users/raphaeldussin/following{/other_user}","gists_url":"https://api.github.com/users/raphaeldussin/gists{/gist_id}","starred_url":"https://api.github.com/users/raphaeldussin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raphaeldussin/subscriptions","organizations_url":"https://api.github.com/users/raphaeldussin/orgs","repos_url":"https://api.github.com/users/raphaeldussin/repos","events_url":"https://api.github.com/users/raphaeldussin/events{/privacy}","received_events_url":"https://api.github.com/users/raphaeldussin/received_events","type":"User","site_admin":false},"body":"rewritting low level functions so they can handle cropped llc data and restart files\r\n(mixed 3d/2d variables in files). All variables are outputted as dask arrays regardless\r\nof geometry. Call order as follows : \r\n\r\nread_mds\r\n  -> read_all_variables\r\n     -> read_generic_data\r\n       -> _read_xy_chunk\r\n          -> read_raw_data\r\n\r\nsome changes are necessary in upper level functions read_mds and _MDSstore\r\nand will be in next PR once this is merged.\r\n\r\nWIP : need some tests. What do we want to test ? type = dask.array,...","created_at":"2018-08-01T15:30:54Z","updated_at":"2018-08-07T18:06:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"387bc2f372bc34806754cbf3f8c53521172abacb","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/xgcm/xmitgcm/pulls/87/commits","review_comments_url":"https://api.github.com/repos/xgcm/xmitgcm/pulls/87/comments","review_comment_url":"https://api.github.com/repos/xgcm/xmitgcm/pulls/comments{/number}","comments_url":"https://api.github.com/repos/xgcm/xmitgcm/issues/87/comments","statuses_url":"https://api.github.com/repos/xgcm/xmitgcm/statuses/a93b9e8e6a3045c5c8a75dd644904206aec1ea6d","head":{"label":"raphaeldussin:low_level","ref":"low_level","sha":"a93b9e8e6a3045c5c8a75dd644904206aec1ea6d","user":{"login":"raphaeldussin","id":14662821,"node_id":"MDQ6VXNlcjE0NjYyODIx","avatar_url":"https://avatars1.githubusercontent.com/u/14662821?v=4","gravatar_id":"","url":"https://api.github.com/users/raphaeldussin","html_url":"https://github.com/raphaeldussin","followers_url":"https://api.github.com/users/raphaeldussin/followers","following_url":"https://api.github.com/users/raphaeldussin/following{/other_user}","gists_url":"https://api.github.com/users/raphaeldussin/gists{/gist_id}","starred_url":"https://api.github.com/users/raphaeldussin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raphaeldussin/subscriptions","organizations_url":"https://api.github.com/users/raphaeldussin/orgs","repos_url":"https://api.github.com/users/raphaeldussin/repos","events_url":"https://api.github.com/users/raphaeldussin/events{/privacy}","received_events_url":"https://api.github.com/users/raphaeldussin/received_events","type":"User","site_admin":false},"repo":{"id":138317630,"node_id":"MDEwOlJlcG9zaXRvcnkxMzgzMTc2MzA=","name":"xmitgcm","full_name":"raphaeldussin/xmitgcm","owner":{"login":"raphaeldussin","id":14662821,"node_id":"MDQ6VXNlcjE0NjYyODIx","avatar_url":"https://avatars1.githubusercontent.com/u/14662821?v=4","gravatar_id":"","url":"https://api.github.com/users/raphaeldussin","html_url":"https://github.com/raphaeldussin","followers_url":"https://api.github.com/users/raphaeldussin/followers","following_url":"https://api.github.com/users/raphaeldussin/following{/other_user}","gists_url":"https://api.github.com/users/raphaeldussin/gists{/gist_id}","starred_url":"https://api.github.com/users/raphaeldussin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raphaeldussin/subscriptions","organizations_url":"https://api.github.com/users/raphaeldussin/orgs","repos_url":"https://api.github.com/users/raphaeldussin/repos","events_url":"https://api.github.com/users/raphaeldussin/events{/privacy}","received_events_url":"https://api.github.com/users/raphaeldussin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/raphaeldussin/xmitgcm","description":"Read MITgcm mds binary files into xarray","fork":true,"url":"https://api.github.com/repos/raphaeldussin/xmitgcm","forks_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/forks","keys_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/keys{/key_id}","collaborators_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/teams","hooks_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/hooks","issue_events_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/issues/events{/number}","events_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/events","assignees_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/assignees{/user}","branches_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/branches{/branch}","tags_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/tags","blobs_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/git/refs{/sha}","trees_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/git/trees{/sha}","statuses_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/statuses/{sha}","languages_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/languages","stargazers_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/stargazers","contributors_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/contributors","subscribers_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/subscribers","subscription_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/subscription","commits_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/commits{/sha}","git_commits_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/git/commits{/sha}","comments_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/comments{/number}","issue_comment_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/issues/comments{/number}","contents_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/contents/{+path}","compare_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/compare/{base}...{head}","merges_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/merges","archive_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/downloads","issues_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/issues{/number}","pulls_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/pulls{/number}","milestones_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/milestones{/number}","notifications_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/labels{/name}","releases_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/releases{/id}","deployments_url":"https://api.github.com/repos/raphaeldussin/xmitgcm/deployments","created_at":"2018-06-22T15:17:13Z","updated_at":"2018-08-01T16:01:11Z","pushed_at":"2018-08-07T17:31:50Z","git_url":"git://github.com/raphaeldussin/xmitgcm.git","ssh_url":"git@github.com:raphaeldussin/xmitgcm.git","clone_url":"https://github.com/raphaeldussin/xmitgcm.git","svn_url":"https://github.com/raphaeldussin/xmitgcm","homepage":"http://xmitgcm.readthedocs.io","size":117022,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"xgcm:master","ref":"master","sha":"1e3ad2c86399da0884c18032ab9b3dd400bf3976","user":{"login":"xgcm","id":14025832,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MDI1ODMy","avatar_url":"https://avatars2.githubusercontent.com/u/14025832?v=4","gravatar_id":"","url":"https://api.github.com/users/xgcm","html_url":"https://github.com/xgcm","followers_url":"https://api.github.com/users/xgcm/followers","following_url":"https://api.github.com/users/xgcm/following{/other_user}","gists_url":"https://api.github.com/users/xgcm/gists{/gist_id}","starred_url":"https://api.github.com/users/xgcm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xgcm/subscriptions","organizations_url":"https://api.github.com/users/xgcm/orgs","repos_url":"https://api.github.com/users/xgcm/repos","events_url":"https://api.github.com/users/xgcm/events{/privacy}","received_events_url":"https://api.github.com/users/xgcm/received_events","type":"Organization","site_admin":false},"repo":{"id":70649781,"node_id":"MDEwOlJlcG9zaXRvcnk3MDY0OTc4MQ==","name":"xmitgcm","full_name":"xgcm/xmitgcm","owner":{"login":"xgcm","id":14025832,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0MDI1ODMy","avatar_url":"https://avatars2.githubusercontent.com/u/14025832?v=4","gravatar_id":"","url":"https://api.github.com/users/xgcm","html_url":"https://github.com/xgcm","followers_url":"https://api.github.com/users/xgcm/followers","following_url":"https://api.github.com/users/xgcm/following{/other_user}","gists_url":"https://api.github.com/users/xgcm/gists{/gist_id}","starred_url":"https://api.github.com/users/xgcm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xgcm/subscriptions","organizations_url":"https://api.github.com/users/xgcm/orgs","repos_url":"https://api.github.com/users/xgcm/repos","events_url":"https://api.github.com/users/xgcm/events{/privacy}","received_events_url":"https://api.github.com/users/xgcm/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/xgcm/xmitgcm","description":"Read MITgcm mds binary files into xarray","fork":false,"url":"https://api.github.com/repos/xgcm/xmitgcm","forks_url":"https://api.github.com/repos/xgcm/xmitgcm/forks","keys_url":"https://api.github.com/repos/xgcm/xmitgcm/keys{/key_id}","collaborators_url":"https://api.github.com/repos/xgcm/xmitgcm/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/xgcm/xmitgcm/teams","hooks_url":"https://api.github.com/repos/xgcm/xmitgcm/hooks","issue_events_url":"https://api.github.com/repos/xgcm/xmitgcm/issues/events{/number}","events_url":"https://api.github.com/repos/xgcm/xmitgcm/events","assignees_url":"https://api.github.com/repos/xgcm/xmitgcm/assignees{/user}","branches_url":"https://api.github.com/repos/xgcm/xmitgcm/branches{/branch}","tags_url":"https://api.github.com/repos/xgcm/xmitgcm/tags","blobs_url":"https://api.github.com/repos/xgcm/xmitgcm/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/xgcm/xmitgcm/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/xgcm/xmitgcm/git/refs{/sha}","trees_url":"https://api.github.com/repos/xgcm/xmitgcm/git/trees{/sha}","statuses_url":"https://api.github.com/repos/xgcm/xmitgcm/statuses/{sha}","languages_url":"https://api.github.com/repos/xgcm/xmitgcm/languages","stargazers_url":"https://api.github.com/repos/xgcm/xmitgcm/stargazers","contributors_url":"https://api.github.com/repos/xgcm/xmitgcm/contributors","subscribers_url":"https://api.github.com/repos/xgcm/xmitgcm/subscribers","subscription_url":"https://api.github.com/repos/xgcm/xmitgcm/subscription","commits_url":"https://api.github.com/repos/xgcm/xmitgcm/commits{/sha}","git_commits_url":"https://api.github.com/repos/xgcm/xmitgcm/git/commits{/sha}","comments_url":"https://api.github.com/repos/xgcm/xmitgcm/comments{/number}","issue_comment_url":"https://api.github.com/repos/xgcm/xmitgcm/issues/comments{/number}","contents_url":"https://api.github.com/repos/xgcm/xmitgcm/contents/{+path}","compare_url":"https://api.github.com/repos/xgcm/xmitgcm/compare/{base}...{head}","merges_url":"https://api.github.com/repos/xgcm/xmitgcm/merges","archive_url":"https://api.github.com/repos/xgcm/xmitgcm/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/xgcm/xmitgcm/downloads","issues_url":"https://api.github.com/repos/xgcm/xmitgcm/issues{/number}","pulls_url":"https://api.github.com/repos/xgcm/xmitgcm/pulls{/number}","milestones_url":"https://api.github.com/repos/xgcm/xmitgcm/milestones{/number}","notifications_url":"https://api.github.com/repos/xgcm/xmitgcm/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/xgcm/xmitgcm/labels{/name}","releases_url":"https://api.github.com/repos/xgcm/xmitgcm/releases{/id}","deployments_url":"https://api.github.com/repos/xgcm/xmitgcm/deployments","created_at":"2016-10-12T01:22:04Z","updated_at":"2018-08-07T17:36:09Z","pushed_at":"2018-08-07T17:36:07Z","git_url":"git://github.com/xgcm/xmitgcm.git","ssh_url":"git@github.com:xgcm/xmitgcm.git","clone_url":"https://github.com/xgcm/xmitgcm.git","svn_url":"https://github.com/xgcm/xmitgcm","homepage":"http://xmitgcm.readthedocs.io","size":116991,"stargazers_count":16,"watchers_count":16,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":23,"mirror_url":null,"archived":false,"open_issues_count":19,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":23,"open_issues":19,"watchers":16,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/xgcm/xmitgcm/pulls/87"},"html":{"href":"https://github.com/xgcm/xmitgcm/pull/87"},"issue":{"href":"https://api.github.com/repos/xgcm/xmitgcm/issues/87"},"comments":{"href":"https://api.github.com/repos/xgcm/xmitgcm/issues/87/comments"},"review_comments":{"href":"https://api.github.com/repos/xgcm/xmitgcm/pulls/87/comments"},"review_comment":{"href":"https://api.github.com/repos/xgcm/xmitgcm/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/xgcm/xmitgcm/pulls/87/commits"},"statuses":{"href":"https://api.github.com/repos/xgcm/xmitgcm/statuses/a93b9e8e6a3045c5c8a75dd644904206aec1ea6d"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"rabernat"}}