GitHub PullRequestReviewCommentEvent at 2014-10-01 21:59:46
Repository: obspy
Actor: QuLogic
Payload: {"action":"created","comment":{"url":"https://api.github.com/repos/obspy/obspy/pulls/comments/18311169","id":18311169,"diff_hunk":"@@ -0,0 +1,393 @@\n+# -*- coding: utf-8 -*-\n+\"\"\"\n+EVT (Kinemetrics) format support for ObsPy.\n+\n+:copyright:\n+    Royal Observatory of Belgium, 2013\n+:license:\n+    GNU Lesser General Public License, Version 3\n+    (http://www.gnu.org/copyleft/lesser.html)\n+\"\"\"\n+from __future__ import (absolute_import, division, print_function,\n+                        unicode_literals)\n+from future.builtins import *  # NOQA\n+\n+from struct import unpack\n+import numpy as np\n+\n+from obspy import Trace, Stream\n+from obspy.kinemetrics.evt_base import EVTBadHeaderError, EVTEOFError, \\\n+    EVTBadDataError, EVT_Virtual\n+\n+\n+WARNING_HEADER = \"Only tested with files from ROB networks :\" + \\\n+    \" - New ETna and old Etna\" + \\\n+    \" - ByteOrder : MSB first (Motorola) \" + \\\n+    \" - File Header of 2040 bytes (12 Channels)\" + \\\n+    \" - ..........\" + \\\n+    \"Other situation may not work (not yet implemented).\"\n+\n+FRAME_STRUCT = b\"BBHHLHHBBHB13s\"\n+\n+# 0 - 0x7c (0-34)\n+HEADER_STRUCT1 = b\"3sB2H3B3x6Hh2Hh22x3B5x2H4hH2x2h6L16x\"\n+# 0x7c - 0x22c (35-106)\n+HEADER_STRUCT2 = b\"lLlL2l12x\"*12\n+# 0x22c-0x2c8(->139)\n+HEADER_STRUCT3 = b\"3L4H2L4x2H5s33sh2f4h4B2LB17s2B2B6xh22x\"\n+# 0x2c8 - 0x658 (140 - 464) (27*12)\n+HEADER_STRUCT4 = b\"5sbH5h3H4BHBx8f2B10x\"*12\n+# 0x658 - 0x688\n+HEADER_STRUCT5 = b\"3B5x6H2hb2Bxh3Hl8x\"\n+# 0x688 - 0x6c4 (3*15)\n+HEADER_STRUCT6 = b\"cBh\"*15\n+# 0x6c4 - 0x7f8\n+HEADER_STRUCT7 = b\"64s16s16s16s16s16s24s24s24s24s3B3b5h4xH46s\"\n+\n+\n+class EVT(object):\n+    \"\"\"\n+    Class to read EVT (Kinemetrics) formatted files.\n+    \"\"\"\n+    def __init__(self):\n+        self.ETag = EVT_TAG()\n+        self.EHeader = EVT_HEADER()\n+        self.EFrame = EVT_FRAME()\n+        self.EData = EVT_DATA()\n+        self.samplingrate = 0\n+\n+    def calibration(self):\n+        \"\"\"\n+        Apply calibrations on data matrix\n+        \"\"\"\n+        for i in range(self.EHeader.nchannels):\n+            # grange = 8.0/(2 ** self.EHeader.chan_range[i])\n+            calibV = 8388608.0 / self.EHeader.chan_fullscale[i]\n+            calibMKS = (calibV * self.EHeader.chan_sensitivity[i]) / (9.81)\n+            self.data[i] /= calibMKS\n+\n+    def readFile(self, filename_or_object, Raw=False):\n+        \"\"\"\n+        Reads an EVT file to the internal data structure.\n+\n+        :type filename_or_object: string or file-like object.\n+        :param filename_or_object: EVT file to be read.\n+        :type raw : boolean\n+        :param raw : True if Raw data (no corrections, int32)\n+                     False if data in m/s2 (default)\n+        :rtype: obspy.core.stream.Stream\n+        :return: Obspy Stream with data\n+        \"\"\"\n+        # Support reading from filenames of file-like objects.\n+        if hasattr(filename_or_object, \"seek\") and \\\n+                hasattr(filename_or_object, \"tell\") and \\\n+                hasattr(filename_or_object, \"read\"):\n+            is_fileobject = True\n+            file_pointer = filename_or_object\n+        else:\n+            is_fileobject = False\n+            file_pointer = open(filename_or_object, \"rb\")\n+\n+        self.ETag.read(file_pointer)\n+        endian = self.ETag.endian\n+        self.EHeader.unsetdico()\n+        self.EHeader.read(file_pointer, self.ETag.length, endian)\n+\n+        self.data = np.ndarray([self.EHeader.nchannels, 0])\n+\n+        while True:\n+            try:\n+                self.ETag.read(file_pointer)\n+                retparam = self.EFrame.read(file_pointer,\n+                                            self.ETag.length, endian)\n+                if (self.samplingrate == 0):\n+                    self.samplingrate = retparam[0]\n+                elif (self.samplingrate != retparam[0]):\n+                    raise EVTBadHeaderError(\"Sampling rate not constant\")\n+                datal = self.EData.read(file_pointer,\n+                                        self.ETag.datalength, endian, retparam)\n+                npdata = np.array(datal)\n+                self.data = np.hstack((self.data, npdata))  # append data\n+            except EVTEOFError:\n+                break\n+        if (self.EFrame.count() != self.EHeader.duration):\n+            raise EVTBadDataError(\"Bad number of blocks\")\n+\n+        if not Raw:\n+            self.calibration()\n+        if is_fileobject is False:\n+            file_pointer.close()\n+\n+        traces = []\n+        for i in range(self.EHeader.nchannels):\n+            t = Trace(data=self.data[i])\n+            t.stats.channel = str(i)\n+            t.stats.station = self.EHeader.stnid.replace(b\"\\x00\", b\"\").decode()\n+            t.stats.sampling_rate = float(self.samplingrate)\n+            t.stats.starttime = self.EHeader.startime\n+            t.stats.kinemetrics_evt = self.EHeader.makeobspydico(i)\n+            traces.append(t)\n+\n+        return Stream(traces=traces)\n+\n+\n+class EVT_DATA(object):\n+    def read(self, fp, length, endian, param):\n+        \"\"\"\n+        read data from fp\n+\n+        :param fp: file pointer\n+        :param length: length to be readed\n+        :param endian: endian type in datafile\n+        :type param: list\n+        :param param: sampling rate,sample size, block time, channels\n+        :rtype: list of list\n+        :return: list of data\n+        \"\"\"\n+        buff = fp.read(length)\n+        samplrate = param[0]\n+        numbyte = param[1]\n+        numchan = param[3].count(1)\n+        num = (samplrate / 10) * numbyte * numchan\n+        data = [[] for _ in range(numchan)]\n+        if (length != num):\n+            raise EVTBadDataError(\"Bad data length\")\n+        for j in range(samplrate // 10):\n+            for k in range(numchan):\n+                i = (j * numchan) + k\n+                if numbyte == 2:\n+                    val = unpack(b\">i\", buff[i * 2:(i * 2) + 2] + b'\\0\\0')[0] \\\n+                        >> 8\n+                elif numbyte == 3:\n+                    val = unpack(b\">i\", buff[i * 3:(i * 3) + 3] + b'\\0')[0] \\\n+                        >> 8\n+                elif numbyte == 4:\n+                    val = unpack(b\">i\", buff[i * 4:(i * 4) + 4])[0]\n+                else:\n+                    raise EVTBadDataError(\"Bad data format\")\n+                data[k].append(val)\n+        return data\n+\n+\n+class EVT_HEADER(EVT_Virtual):\n+    HEADER = {'instrument': [1, ['_instrument', '']],\n+              'a2dbits': [4, \"\"],\n+              'samplebytes': [5, \"\"],\n+              'installedchan': [7, \"\"],\n+              'maxchannels': [8, \"\"],\n+              'batteryvoltage': [13, \"\"],\n+              'temperature': [16, \"\"],\n+              'gpsstatus': [18, ['_gpsstatus', '']],\n+              'gpslastlock': [33, ['_time', -1]],\n+              'startime': [107, ['_time', 112]],\n+              'triggertime': [108, ['_time', 113]],\n+              'duration': [109, \"\"],\n+              'nscans': [115, \"\"],\n+              'serialnumber': [116, \"\"],\n+              'nchannels': [117, \"\"],\n+              'stnid': [118, ['_strnull', '']],\n+              'comment': [119, ['_strnull', '']],\n+              'elevation': [120, \"\"],\n+              'latitude': [121, \"\"],\n+              'longitude': [122, \"\"],\n+              'chan_id': [140, ['_arraynull', [12, 27, 140]]],\n+              'chan_north': [143, ['_arraynull', [12, 27, 143]]],\n+              'chan_east': [144, ['_arraynull', [12, 27, 144]]],\n+              'chan_up': [145, ['_arraynull', [12, 27, 145]]],\n+              'chan_azimuth': [147, ['_arraynull', [12, 27, 147]]],\n+              'chan_gain': [150, ['_array', [12, 27, 150]]],\n+              'chan_fullscale': [157, ['_array', [12, 27, 157]]],\n+              'chan_sensitivity': [158, ['_array', [12, 27, 158]]],\n+              'chan_damping': [159, ['_array', [12, 27, 159]]],\n+              'chan_natfreq': [160, ['_array', [12, 27, 160]]],\n+              'chan_calcoil': [164, ['_array', [12, 27, 164]]],\n+              'chan_range': [165, ['_array', [12, 27, 165]]],\n+              'chan_sensogain': [166, ['_array', [12, 27, 166]]]}\n+\n+    def __init__(self):\n+        EVT_Virtual.__init__(self)\n+\n+    def read(self, fp, length, endian):\n+        \"\"\"\n+        read the Header of Evt file\n+        \"\"\"\n+        buff = fp.read(length)\n+        self.endian = endian.encode()\n+        if (length == 2040):  # File Header 12 channel\n+            self.analyse_header12(buff)\n+        elif (length == 2736):  # File Header 18 channel\n+            raise NotImplementedError(\"16 Channel not implemented\")\n+        else:\n+            raise EVTBadHeaderError(\"Bad Header length \" + length)\n+\n+    def analyse_header12(self, head_buff):\n+        val = unpack(self.endian+HEADER_STRUCT1, head_buff[0:0x7c])\n+        self.setdico(list(val), 0)\n+        val = unpack(self.endian+HEADER_STRUCT2, head_buff[0x7c:0x22c])\n+        self.setdico(list(val), 35)\n+        val = unpack(self.endian+HEADER_STRUCT3, head_buff[0x22c:0x2c8])\n+        self.setdico(list(val), 107)\n+        val = unpack(self.endian+HEADER_STRUCT4, head_buff[0x2c8:0x658])\n+        self.setdico(list(val), 140)\n+        # XXX: Those three do not do anything...\n+        # val = unpack(self.endian+HEADER_STRUCT5, head_buff[0x658:0x688])\n+        # val = unpack(self.endian+HEADER_STRUCT6, head_buff[0x688:0x6c4])\n+        # val = unpack(self.endian+HEADER_STRUCT7, head_buff[0x6c4:0x7f8])\n+\n+    def makeobspydico(self, numchan):\n+        \"\"\"\n+        Make an ObsPy dictionary from header dictionary for 1 channel\n+\n+        :param numchan: channel to be converted\n+        :rtype: dictionary\n+        \"\"\"\n+        dico = {}\n+        for key in self.HEADER:\n+            value = self.HEADER[key][2]\n+            if isinstance(value, list):\n+                dico[key] = value[numchan]\n+            else:\n+                dico[key] = value\n+        return dico\n+\n+    def _gpsstatus(self, value, a, b, c):\n+        \"\"\"\n+        Transform bitarray for gpsstatus in human readable string\n+\n+        :param value: gps status\n+        :rtype: string\n+        \"\"\"\n+        dico = {1: 'Checking', 2: 'Present', 4: 'Error', 8: 'Failed',\n+                16: 'Not Locked', 32: 'ON'}\n+        retval = \"\"\n+        for key in sorted(dico):\n+            if value & key:\n+                retval += dico[key] + \" \"\n+        return retval\n+\n+\n+class EVT_FRAME(EVT_Virtual):\n+    HEADER = {'frametype': [0, ''],\n+              'instrumentcode': [1, ['_instrument', '']],\n+              'recorderid': [2, ''],\n+              'framesize': [3, ''],\n+              'blocktime': [4, ['_time', 9]],\n+              'channelbitmap': [5, ''],\n+              'streampar': [6, ''],\n+              'framestatus': [7, ''],\n+              'framestatus2': [8, ''],\n+              'msec': [9, ''],\n+              'channelbitmap1': [10, ''],\n+              'timecode': [11, '']}\n+\n+    endian = 0\n+\n+    def __init__(self):\n+        EVT_Virtual.__init__(self)\n+        self.numframe = 0\n+\n+    def count(self):\n+        \"\"\"\n+        return the number of frames readed","path":"obspy/kinemetrics/evt.py","position":291,"original_position":291,"commit_id":"7765f622ae088ff6f5bb73a0ad79da4aa0754ecb","original_commit_id":"7765f622ae088ff6f5bb73a0ad79da4aa0754ecb","user":{"login":"QuLogic","id":302469,"avatar_url":"https://avatars.githubusercontent.com/u/302469?v=2","gravatar_id":"","url":"https://api.github.com/users/QuLogic","html_url":"https://github.com/QuLogic","followers_url":"https://api.github.com/users/QuLogic/followers","following_url":"https://api.github.com/users/QuLogic/following{/other_user}","gists_url":"https://api.github.com/users/QuLogic/gists{/gist_id}","starred_url":"https://api.github.com/users/QuLogic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/QuLogic/subscriptions","organizations_url":"https://api.github.com/users/QuLogic/orgs","repos_url":"https://api.github.com/users/QuLogic/repos","events_url":"https://api.github.com/users/QuLogic/events{/privacy}","received_events_url":"https://api.github.com/users/QuLogic/received_events","type":"User","site_admin":false},"body":"s/readed/read/","created_at":"2014-10-01T21:59:46Z","updated_at":"2014-10-01T21:59:46Z","html_url":"https://github.com/obspy/obspy/pull/781#discussion_r18311169","pull_request_url":"https://api.github.com/repos/obspy/obspy/pulls/781","_links":{"self":{"href":"https://api.github.com/repos/obspy/obspy/pulls/comments/18311169"},"html":{"href":"https://github.com/obspy/obspy/pull/781#discussion_r18311169"},"pull_request":{"href":"https://api.github.com/repos/obspy/obspy/pulls/781"}}},"pull_request":{"url":"https://api.github.com/repos/obspy/obspy/pulls/781","id":15225303,"html_url":"https://github.com/obspy/obspy/pull/781","diff_url":"https://github.com/obspy/obspy/pull/781.diff","patch_url":"https://github.com/obspy/obspy/pull/781.patch","issue_url":"https://api.github.com/repos/obspy/obspy/issues/781","number":781,"state":"open","locked":false,"title":"Kinemetrics EVT data format support.","user":{"login":"ThomasLecocq","id":916937,"avatar_url":"https://avatars.githubusercontent.com/u/916937?v=2","gravatar_id":"","url":"https://api.github.com/users/ThomasLecocq","html_url":"https://github.com/ThomasLecocq","followers_url":"https://api.github.com/users/ThomasLecocq/followers","following_url":"https://api.github.com/users/ThomasLecocq/following{/other_user}","gists_url":"https://api.github.com/users/ThomasLecocq/gists{/gist_id}","starred_url":"https://api.github.com/users/ThomasLecocq/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ThomasLecocq/subscriptions","organizations_url":"https://api.github.com/users/ThomasLecocq/orgs","repos_url":"https://api.github.com/users/ThomasLecocq/repos","events_url":"https://api.github.com/users/ThomasLecocq/events{/privacy}","received_events_url":"https://api.github.com/users/ThomasLecocq/received_events","type":"User","site_admin":false},"body":"Added support for the format + tests + reference PDF.","created_at":"2014-04-28T08:17:23Z","updated_at":"2014-10-01T21:59:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"be2c7e75dd8e5726b22f04fda898e08b6c16420a","assignee":null,"milestone":{"url":"https://api.github.com/repos/obspy/obspy/milestones/5","labels_url":"https://api.github.com/repos/obspy/obspy/milestones/5/labels","id":449804,"number":5,"title":"0.10.0","description":"","creator":{"login":"megies","id":1842780,"avatar_url":"https://avatars.githubusercontent.com/u/1842780?v=2","gravatar_id":"","url":"https://api.github.com/users/megies","html_url":"https://github.com/megies","followers_url":"https://api.github.com/users/megies/followers","following_url":"https://api.github.com/users/megies/following{/other_user}","gists_url":"https://api.github.com/users/megies/gists{/gist_id}","starred_url":"https://api.github.com/users/megies/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/megies/subscriptions","organizations_url":"https://api.github.com/users/megies/orgs","repos_url":"https://api.github.com/users/megies/repos","events_url":"https://api.github.com/users/megies/events{/privacy}","received_events_url":"https://api.github.com/users/megies/received_events","type":"User","site_admin":false},"open_issues":27,"closed_issues":74,"state":"open","created_at":"2013-10-08T14:41:54Z","updated_at":"2014-10-01T11:20:49Z","due_on":null},"commits_url":"https://api.github.com/repos/obspy/obspy/pulls/781/commits","review_comments_url":"https://api.github.com/repos/obspy/obspy/pulls/781/comments","review_comment_url":"https://api.github.com/repos/obspy/obspy/pulls/comments/{number}","comments_url":"https://api.github.com/repos/obspy/obspy/issues/781/comments","statuses_url":"https://api.github.com/repos/obspy/obspy/statuses/7765f622ae088ff6f5bb73a0ad79da4aa0754ecb","head":{"label":"ThomasLecocq:feature_evt","ref":"feature_evt","sha":"7765f622ae088ff6f5bb73a0ad79da4aa0754ecb","user":{"login":"ThomasLecocq","id":916937,"avatar_url":"https://avatars.githubusercontent.com/u/916937?v=2","gravatar_id":"","url":"https://api.github.com/users/ThomasLecocq","html_url":"https://github.com/ThomasLecocq","followers_url":"https://api.github.com/users/ThomasLecocq/followers","following_url":"https://api.github.com/users/ThomasLecocq/following{/other_user}","gists_url":"https://api.github.com/users/ThomasLecocq/gists{/gist_id}","starred_url":"https://api.github.com/users/ThomasLecocq/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ThomasLecocq/subscriptions","organizations_url":"https://api.github.com/users/ThomasLecocq/orgs","repos_url":"https://api.github.com/users/ThomasLecocq/repos","events_url":"https://api.github.com/users/ThomasLecocq/events{/privacy}","received_events_url":"https://api.github.com/users/ThomasLecocq/received_events","type":"User","site_admin":false},"repo":{"id":16171009,"name":"obspy","full_name":"ThomasLecocq/obspy","owner":{"login":"ThomasLecocq","id":916937,"avatar_url":"https://avatars.githubusercontent.com/u/916937?v=2","gravatar_id":"","url":"https://api.github.com/users/ThomasLecocq","html_url":"https://github.com/ThomasLecocq","followers_url":"https://api.github.com/users/ThomasLecocq/followers","following_url":"https://api.github.com/users/ThomasLecocq/following{/other_user}","gists_url":"https://api.github.com/users/ThomasLecocq/gists{/gist_id}","starred_url":"https://api.github.com/users/ThomasLecocq/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ThomasLecocq/subscriptions","organizations_url":"https://api.github.com/users/ThomasLecocq/orgs","repos_url":"https://api.github.com/users/ThomasLecocq/repos","events_url":"https://api.github.com/users/ThomasLecocq/events{/privacy}","received_events_url":"https://api.github.com/users/ThomasLecocq/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ThomasLecocq/obspy","description":"ObsPy: A Python Toolbox for seismology/seismological observatories.","fork":true,"url":"https://api.github.com/repos/ThomasLecocq/obspy","forks_url":"https://api.github.com/repos/ThomasLecocq/obspy/forks","keys_url":"https://api.github.com/repos/ThomasLecocq/obspy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ThomasLecocq/obspy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ThomasLecocq/obspy/teams","hooks_url":"https://api.github.com/repos/ThomasLecocq/obspy/hooks","issue_events_url":"https://api.github.com/repos/ThomasLecocq/obspy/issues/events{/number}","events_url":"https://api.github.com/repos/ThomasLecocq/obspy/events","assignees_url":"https://api.github.com/repos/ThomasLecocq/obspy/assignees{/user}","branches_url":"https://api.github.com/repos/ThomasLecocq/obspy/branches{/branch}","tags_url":"https://api.github.com/repos/ThomasLecocq/obspy/tags","blobs_url":"https://api.github.com/repos/ThomasLecocq/obspy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ThomasLecocq/obspy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ThomasLecocq/obspy/git/refs{/sha}","trees_url":"https://api.github.com/repos/ThomasLecocq/obspy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ThomasLecocq/obspy/statuses/{sha}","languages_url":"https://api.github.com/repos/ThomasLecocq/obspy/languages","stargazers_url":"https://api.github.com/repos/ThomasLecocq/obspy/stargazers","contributors_url":"https://api.github.com/repos/ThomasLecocq/obspy/contributors","subscribers_url":"https://api.github.com/repos/ThomasLecocq/obspy/subscribers","subscription_url":"https://api.github.com/repos/ThomasLecocq/obspy/subscription","commits_url":"https://api.github.com/repos/ThomasLecocq/obspy/commits{/sha}","git_commits_url":"https://api.github.com/repos/ThomasLecocq/obspy/git/commits{/sha}","comments_url":"https://api.github.com/repos/ThomasLecocq/obspy/comments{/number}","issue_comment_url":"https://api.github.com/repos/ThomasLecocq/obspy/issues/comments/{number}","contents_url":"https://api.github.com/repos/ThomasLecocq/obspy/contents/{+path}","compare_url":"https://api.github.com/repos/ThomasLecocq/obspy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ThomasLecocq/obspy/merges","archive_url":"https://api.github.com/repos/ThomasLecocq/obspy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ThomasLecocq/obspy/downloads","issues_url":"https://api.github.com/repos/ThomasLecocq/obspy/issues{/number}","pulls_url":"https://api.github.com/repos/ThomasLecocq/obspy/pulls{/number}","milestones_url":"https://api.github.com/repos/ThomasLecocq/obspy/milestones{/number}","notifications_url":"https://api.github.com/repos/ThomasLecocq/obspy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ThomasLecocq/obspy/labels{/name}","releases_url":"https://api.github.com/repos/ThomasLecocq/obspy/releases{/id}","created_at":"2014-01-23T11:51:02Z","updated_at":"2014-05-09T09:42:52Z","pushed_at":"2014-08-04T11:59:09Z","git_url":"git://github.com/ThomasLecocq/obspy.git","ssh_url":"git@github.com:ThomasLecocq/obspy.git","clone_url":"https://github.com/ThomasLecocq/obspy.git","svn_url":"https://github.com/ThomasLecocq/obspy","homepage":"http://www.obspy.org","size":47258,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"obspy:master","ref":"master","sha":"df3a8f1688febabea6be2f2c51f5ca8d684a21e0","user":{"login":"obspy","id":1701221,"avatar_url":"https://avatars.githubusercontent.com/u/1701221?v=2","gravatar_id":"","url":"https://api.github.com/users/obspy","html_url":"https://github.com/obspy","followers_url":"https://api.github.com/users/obspy/followers","following_url":"https://api.github.com/users/obspy/following{/other_user}","gists_url":"https://api.github.com/users/obspy/gists{/gist_id}","starred_url":"https://api.github.com/users/obspy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/obspy/subscriptions","organizations_url":"https://api.github.com/users/obspy/orgs","repos_url":"https://api.github.com/users/obspy/repos","events_url":"https://api.github.com/users/obspy/events{/privacy}","received_events_url":"https://api.github.com/users/obspy/received_events","type":"Organization","site_admin":false},"repo":{"id":5731348,"name":"obspy","full_name":"obspy/obspy","owner":{"login":"obspy","id":1701221,"avatar_url":"https://avatars.githubusercontent.com/u/1701221?v=2","gravatar_id":"","url":"https://api.github.com/users/obspy","html_url":"https://github.com/obspy","followers_url":"https://api.github.com/users/obspy/followers","following_url":"https://api.github.com/users/obspy/following{/other_user}","gists_url":"https://api.github.com/users/obspy/gists{/gist_id}","starred_url":"https://api.github.com/users/obspy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/obspy/subscriptions","organizations_url":"https://api.github.com/users/obspy/orgs","repos_url":"https://api.github.com/users/obspy/repos","events_url":"https://api.github.com/users/obspy/events{/privacy}","received_events_url":"https://api.github.com/users/obspy/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/obspy/obspy","description":"ObsPy: A Python Toolbox for seismology/seismological observatories.","fork":false,"url":"https://api.github.com/repos/obspy/obspy","forks_url":"https://api.github.com/repos/obspy/obspy/forks","keys_url":"https://api.github.com/repos/obspy/obspy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/obspy/obspy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/obspy/obspy/teams","hooks_url":"https://api.github.com/repos/obspy/obspy/hooks","issue_events_url":"https://api.github.com/repos/obspy/obspy/issues/events{/number}","events_url":"https://api.github.com/repos/obspy/obspy/events","assignees_url":"https://api.github.com/repos/obspy/obspy/assignees{/user}","branches_url":"https://api.github.com/repos/obspy/obspy/branches{/branch}","tags_url":"https://api.github.com/repos/obspy/obspy/tags","blobs_url":"https://api.github.com/repos/obspy/obspy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/obspy/obspy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/obspy/obspy/git/refs{/sha}","trees_url":"https://api.github.com/repos/obspy/obspy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/obspy/obspy/statuses/{sha}","languages_url":"https://api.github.com/repos/obspy/obspy/languages","stargazers_url":"https://api.github.com/repos/obspy/obspy/stargazers","contributors_url":"https://api.github.com/repos/obspy/obspy/contributors","subscribers_url":"https://api.github.com/repos/obspy/obspy/subscribers","subscription_url":"https://api.github.com/repos/obspy/obspy/subscription","commits_url":"https://api.github.com/repos/obspy/obspy/commits{/sha}","git_commits_url":"https://api.github.com/repos/obspy/obspy/git/commits{/sha}","comments_url":"https://api.github.com/repos/obspy/obspy/comments{/number}","issue_comment_url":"https://api.github.com/repos/obspy/obspy/issues/comments/{number}","contents_url":"https://api.github.com/repos/obspy/obspy/contents/{+path}","compare_url":"https://api.github.com/repos/obspy/obspy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/obspy/obspy/merges","archive_url":"https://api.github.com/repos/obspy/obspy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/obspy/obspy/downloads","issues_url":"https://api.github.com/repos/obspy/obspy/issues{/number}","pulls_url":"https://api.github.com/repos/obspy/obspy/pulls{/number}","milestones_url":"https://api.github.com/repos/obspy/obspy/milestones{/number}","notifications_url":"https://api.github.com/repos/obspy/obspy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/obspy/obspy/labels{/name}","releases_url":"https://api.github.com/repos/obspy/obspy/releases{/id}","created_at":"2012-09-08T19:17:46Z","updated_at":"2014-09-22T20:23:52Z","pushed_at":"2014-10-01T11:43:51Z","git_url":"git://github.com/obspy/obspy.git","ssh_url":"git@github.com:obspy/obspy.git","clone_url":"https://github.com/obspy/obspy.git","svn_url":"https://github.com/obspy/obspy","homepage":"http://www.obspy.org","size":70918,"stargazers_count":87,"watchers_count":87,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":71,"mirror_url":null,"open_issues_count":53,"forks":71,"open_issues":53,"watchers":87,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/obspy/obspy/pulls/781"},"html":{"href":"https://github.com/obspy/obspy/pull/781"},"issue":{"href":"https://api.github.com/repos/obspy/obspy/issues/781"},"comments":{"href":"https://api.github.com/repos/obspy/obspy/issues/781/comments"},"review_comments":{"href":"https://api.github.com/repos/obspy/obspy/pulls/781/comments"},"review_comment":{"href":"https://api.github.com/repos/obspy/obspy/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/obspy/obspy/pulls/781/commits"},"statuses":{"href":"https://api.github.com/repos/obspy/obspy/statuses/7765f622ae088ff6f5bb73a0ad79da4aa0754ecb"}}}}