{"action":"created","comment":{"url":"https://api.github.com/repos/obspy/obspy/pulls/comments/79043221","id":79043221,"diff_hunk":"@@ -0,0 +1,1379 @@\n+# -*- coding: utf-8 -*-\n+\"\"\"\n+Nordic file format support for ObsPy\n+\n+:copyright:\n+    The ObsPy Development Team (devs@obspy.org)\n+:license:\n+    GNU Lesser General Public License, Version 3\n+    (https://www.gnu.org/copyleft/lesser.html)\n+\n+.. note::\n+\n+    We have not implemented any handling of focal mechanism solutions between\n+    the two formats.\n+\n+.. note::\n+\n+    Pick time-residuals are handled in event.origins[0].arrivals, with\n+    the arrival.pick_id linking the arrival (which contain calculated\n+    information) with the pick.resource_id (where the pick contains only\n+    physical measured information).\n+\"\"\"\n+from __future__ import (absolute_import, division, print_function,\n+                        unicode_literals)\n+from future.builtins import *  # NOQA @UnusedWildImport\n+\n+import warnings\n+\n+import numpy as np\n+import os\n+\n+from obspy import UTCDateTime\n+from obspy.core.event import Event, Origin, Magnitude, Comment, Catalog\n+from obspy.core.event import EventDescription, CreationInfo\n+from obspy.core.event import Pick, WaveformStreamID, Arrival, Amplitude\n+\n+\n+def is_sfile(sfile):\n+    \"\"\"\n+    Basic test of whether the file is nordic format or not.\n+\n+    Not exhaustive, but checks some of the basics.\n+\n+    :type sfile: str\n+    :param sfile: Path to sfile\n+    :rtype: bool\n+    \"\"\"\n+    if not hasattr(sfile, \"readline\"):\n+        try:\n+            with open(sfile, 'r') as f:\n+                topline = f.readline()\n+                if not len(topline.rstrip()) == 80:\n+                    return False\n+                f.seek(0)\n+                for line in f:\n+                    if line[79] in [' ', '1']:\n+                        head_line = line\n+                        break\n+        except:\n+            return False\n+    else:\n+        topline = sfile.readline()\n+        if not len(topline.rstrip()) == 80:\n+            return False\n+        sfile.seek(0)\n+        for line in sfile:\n+            if line[79] in [' ', '1']:\n+                head_line = line\n+                break\n+    if 'head_line' in locals():\n+        try:\n+            sfile_seconds = int(head_line[16:18])\n+        except ValueError:\n+            return False\n+        if sfile_seconds == 60:\n+            sfile_seconds = 0\n+            add_seconds = 60\n+        else:\n+            add_seconds = 0\n+        try:\n+            UTCDateTime(int(head_line[1:5]), int(head_line[6:8]),\n+                        int(head_line[8:10]), int(head_line[11:13]),\n+                        int(head_line[13:15]), sfile_seconds,\n+                        int(head_line[19:20]) * 100000) + add_seconds\n+            return True\n+        except:\n+            return False\n+    else:\n+        return False\n+\n+\n+def _int_conv(string):\n+    \"\"\"\n+    Convenience tool to convert from string to integer.\n+    If empty string return a 999 rather than an error.\n+\n+    >>> _int_conv('12')\n+    12\n+    >>> _int_conv('')\n+    999\n+    \"\"\"\n+    try:\n+        intstring = int(string)\n+    except:\n+        intstring = 999\n+    return intstring\n+\n+\n+def _float_conv(string):\n+    \"\"\"\n+    Convenience tool to convert from string to float.\n+    If empty string return NaN rather than an error.\n+\n+    >>> _float_conv('12')\n+    12.0\n+    >>> _float_conv('')\n+    999.0\n+    >>> _float_conv('12.324')\n+    12.324\n+    \"\"\"\n+    try:\n+        floatstring = float(string)\n+    except:\n+        # cjh Changed this to deal with QuakeML validation issues with 'NaN'\n+        floatstring = float('999')\n+    return floatstring\n+\n+\n+def _str_conv(number, rounded=False):\n+    \"\"\"\n+    Convenience tool to convert a number, either float or int into a string.\n+    If the int is 999, or the float is NaN, returns empty string.\n+\n+    >>> _str_conv(12.3)\n+    '12.3'\n+    >>> _str_conv(12.34546, rounded=1)\n+    '12.3'\n+    \"\"\"\n+    string = str(number)\n+    if (isinstance(number, float) and np.isnan(number)) or number == 999:\n+        string = ' '\n+    elif not rounded and \\\n+            (isinstance(number, float) or isinstance(number, int)):\n+        if number < 100000:\n+            string = str(number)\n+        else:\n+            exponant = int('{0:.2E}'.format(number).split('E+')[-1]) - 1\n+            divisor = 10 ** exponant\n+            string = '{0:.1f}'.format(number / divisor) + 'e' + str(exponant)\n+    elif rounded == 2 and \\\n+            (isinstance(number, float) or isinstance(number, int)):\n+        string = '{0:.2f}'.format(number)\n+    elif rounded == 1 and \\\n+            (isinstance(number, float) or isinstance(number, int)):\n+        string = '{0:.1f}'.format(number)\n+    else:\n+        return str(number)\n+    return str(string)\n+\n+\n+def _evmagtonor(mag_type):\n+    \"\"\"\n+    Switch from obspy event magnitude types to seisan syntax.\n+\n+    >>> _evmagtonor('mB')\n+    'b'\n+    >>> _evmagtonor('M')\n+    'W'\n+    >>> _evmagtonor('bob')\n+    ''\n+    \"\"\"\n+    mag_type = str(mag_type)\n+    if mag_type in ['ML', 'MLv']:\n+        # MLv is local magnitude on vertical component\n+        mag = 'L'\n+    elif mag_type == 'mB':\n+        mag = 'b'\n+    elif mag_type == 'Ms':\n+        mag = 's'\n+    elif mag_type == 'MS':\n+        mag = 'S'\n+    elif mag_type in ['MW', 'Mw']:\n+        mag = 'W'\n+    elif mag_type == 'MbLg':\n+        mag = 'G'\n+    elif mag_type in ['Mc', 'MC']:\n+        mag = 'C'\n+    elif mag_type == 'M':\n+        mag = 'W'  # Convert generic magnitude to moment magnitude\n+        msg = ('Converting generic magnitude to being stored as moment mag')\n+        warnings.warn(msg)\n+    else:\n+        warnings.warn(mag_type + ' is not convertible')\n+        return str('')\n+    return str(mag)\n+\n+\n+def _nortoevmag(mag_type):\n+    \"\"\"\n+    Switch from nordic type magnitude notation to obspy event magnitudes.\n+\n+    >>> _nortoevmag('b')\n+    'mB'\n+    >>> _nortoevmag('bob')\n+    ''\n+    \"\"\"\n+    mag_type = str(mag_type)\n+    if mag_type == 'L':\n+        mag = 'ML'\n+    elif mag_type == 'b':\n+        mag = 'mB'\n+    elif mag_type == 's':\n+        mag = 'Ms'\n+    elif mag_type == 'S':\n+        mag = 'MS'\n+    elif mag_type == 'W':\n+        mag = 'MW'\n+    elif mag_type == 'G':\n+        mag = 'MbLg'\n+    elif mag_type == 'C':\n+        mag = 'Mc'\n+    else:\n+        warnings.warn(mag_type + ' is not convertible')\n+        return str('')\n+    return str(mag)\n+\n+\n+def readheader(sfile):\n+    \"\"\"\n+    Read header information from a seisan nordic format S-file.\n+    Returns an obspy.core.event.Catalog type: note this changed for version \\\n+    0.1.0 from the inbuilt class types.\n+\n+    :type sfile: str\n+    :param sfile: Path to the s-file\n+\n+    :returns: :class: obspy.core.event.Event\n+    \"\"\"\n+    with open(sfile, 'r') as f:\n+        header = _readheader(f=f)\n+    return header\n+\n+\n+def _readheader(f):\n+    \"\"\"Internal header reader.\n+    :type f: file\n+    :param f: File open in read-mode.\n+\n+    :returns: obspy.core.event.Event\"\"\"\n+    f.seek(0)\n+    # Base populate to allow for empty parts of file\n+    new_event = Event()\n+    topline = f.readline()\n+    if not len(topline.rstrip()) == 80:\n+        f.close()\n+        raise IOError('s-file has a corrupt header, not 80 char long')\n+    f.seek(0)\n+    for line in f:\n+        if line[79] in [' ', '1']:\n+            topline = line\n+            break\n+        if line[79] == '7':\n+            f.close()\n+            raise IOError('No header found, corrupt s-file?')\n+    try:\n+        sfile_seconds = int(topline[16:18])\n+        if sfile_seconds == 60:\n+            sfile_seconds = 0\n+            add_seconds = 60\n+        else:\n+            add_seconds = 0\n+        new_event.origins.append(Origin())\n+        new_event.origins[0].time = UTCDateTime(int(topline[1:5]),\n+                                                int(topline[6:8]),\n+                                                int(topline[8:10]),\n+                                                int(topline[11:13]),\n+                                                int(topline[13:15]),\n+                                                sfile_seconds,\n+                                                int(topline[19:20]) *\n+                                                100000)\\\n+            + add_seconds\n+    except:\n+        f.close()\n+        IOError(\"Couldn't read a date from sfile\")\n+    # new_event.loc_mod_ind=topline[20]\n+    new_event.event_descriptions.append(EventDescription())\n+    new_event.event_descriptions[0].text = topline[21:23]\n+    # new_event.ev_id=topline[22]\n+    if not _float_conv(topline[23:30]) == 999:\n+        new_event.origins[0].latitude = _float_conv(topline[23:30])\n+        new_event.origins[0].longitude = _float_conv(topline[31:38])\n+        new_event.origins[0].depth = _float_conv(topline[39:43]) * 1000\n+    else:\n+        # The origin 'requires' a lat & long\n+        new_event.origins[0].latitude = float('NaN')\n+        new_event.origins[0].longitude = float('NaN')\n+        new_event.origins[0].depth = float('NaN')\n+    # new_event.depth_ind = topline[44]\n+    # new_event.loc_ind = topline[45]\n+    new_event.creation_info = CreationInfo(agency_id=topline[45:48].\n+                                           strip())\n+    ksta = Comment(text='Number of stations=' +\n+                   topline[49:51].strip())\n+    new_event.origins[0].comments.append(ksta)\n+    # new_event.origins[0].nsta??? = _int_conv(topline[49:51])\n+    if not _float_conv(topline[51:55]) == 999:\n+        new_event.origins[0].time_errors['Time_Residual_RMS'] = \\\n+            _float_conv(topline[51:55])\n+    # Read in magnitudes if they are there.\n+    if len(topline[59].strip()) > 0:\n+        new_event.magnitudes.append(Magnitude())\n+        new_event.magnitudes[0].mag = _float_conv(topline[56:59])\n+        new_event.magnitudes[0].magnitude_type = topline[59]\n+        new_event.magnitudes[0].creation_info = \\\n+            CreationInfo(agency_id=topline[60:63].strip())\n+        new_event.magnitudes[0].origin_id = new_event.origins[0].\\\n+            resource_id\n+    if len(topline[67].strip()) > 0:\n+        new_event.magnitudes.append(Magnitude())\n+        new_event.magnitudes[1].mag = _float_conv(topline[64:67])\n+        new_event.magnitudes[1].magnitude_type = topline[67]\n+        new_event.magnitudes[1].creation_info = \\\n+            CreationInfo(agency_id=topline[68:71].strip())\n+        new_event.magnitudes[1].origin_id = new_event.origins[0].\\\n+            resource_id\n+    if len(topline[75].strip()) > 0:\n+        new_event.magnitudes.append(Magnitude())\n+        new_event.magnitudes[2].mag = _float_conv(topline[72:75])\n+        new_event.magnitudes[2].magnitude_type = topline[75]\n+        new_event.magnitudes[2].creation_info = \\\n+            CreationInfo(agency_id=topline[76:79].strip())\n+        new_event.magnitudes[2].origin_id = new_event.origins[0].\\\n+            resource_id\n+    # convert the nordic notation of magnitude to more general notation\n+    for _magnitude in new_event.magnitudes:\n+        _magnitude.magnitude_type = _nortoevmag(_magnitude.magnitude_type)\n+    # Set the useful things like preferred magnitude and preferred origin\n+    new_event.preferred_origin_id = str(new_event.origins[0].resource_id)\n+    if len(new_event.magnitudes) > 1:\n+        try:\n+            # Select moment first, then local, then\n+            mag_filter = ['MW', 'Mw', 'ML', 'Ml', 'MB', 'Mb',\n+                          'MS', 'Ms', 'Mc', 'MC']\n+            _magnitudes = [(m.magnitude_type, m.resource_id)\n+                           for m in new_event.magnitudes]\n+            preferred_magnitude = sorted(_magnitudes,\n+                                         key=lambda x: mag_filter.index(x[0]))\n+            new_event.preferred_magnitude_id = str(preferred_magnitude[0][1])\n+        except ValueError:\n+            # If there is a magnitude not specified in filter\n+            new_event.preferred_magnitude_id =\\\n+                str(new_event.magnitudes[0].resource_id)\n+    elif len(new_event.magnitudes) == 1:\n+        new_event.preferred_magnitude_id =\\\n+            str(new_event.magnitudes[0].resource_id)\n+    return new_event\n+\n+\n+def read_spectral_info(sfile):\n+    \"\"\"\n+    Read spectral info from an sfile.\n+\n+    :type sfile: str\n+    :param sfile: Sfile to read from.\n+\n+    :returns: dictionary of spectral information, units as in seisan manual, \\\n+        expect for logs which have been converted to floats.\n+    \"\"\"\n+    with open(sfile, 'r') as f:\n+        spec_inf = _read_spectral_info(f=f)\n+    return spec_inf\n+\n+\n+def _read_spectral_info(f):\n+    \"\"\"Internal spectral reader.\n+\n+    :type f: file\n+    :param f: File open in read mode.\n+\n+    :returns: dictionary of spectral information, units as in seisan manual, \\\n+        expect for logs which have been converted to floats.\n+    \"\"\"\n+    event = _readheader(f=f)\n+    f.seek(0)\n+    origin_date = UTCDateTime(event.origins[0].time.date)\n+    relevant_lines = []\n+    for line in f:\n+        if str(line[1:5]) == str('SPEC'):\n+            relevant_lines.append(line)\n+    spec_inf = []\n+    if len(relevant_lines) == 0:\n+        return spec_inf\n+    for line in relevant_lines:\n+        spec_str = str(line.rstrip().lstrip())\n+        if str(spec_str[5:12]) == str('AVERAGE'):\n+            info = {}\n+            info['station'] = str('AVERAGE')\n+            info['channel'] = str('')","path":"obspy/io/nordic/core.py","position":398,"original_position":398,"commit_id":"987e360d3683188ede1d07e38982498bbe689bb0","original_commit_id":"987e360d3683188ede1d07e38982498bbe689bb0","user":{"login":"krischer","id":800487,"avatar_url":"https://avatars.githubusercontent.com/u/800487?v=3","gravatar_id":"","url":"https://api.github.com/users/krischer","html_url":"https://github.com/krischer","followers_url":"https://api.github.com/users/krischer/followers","following_url":"https://api.github.com/users/krischer/following{/other_user}","gists_url":"https://api.github.com/users/krischer/gists{/gist_id}","starred_url":"https://api.github.com/users/krischer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krischer/subscriptions","organizations_url":"https://api.github.com/users/krischer/orgs","repos_url":"https://api.github.com/users/krischer/repos","events_url":"https://api.github.com/users/krischer/events{/privacy}","received_events_url":"https://api.github.com/users/krischer/received_events","type":"User","site_admin":false},"body":"already a string.","created_at":"2016-09-15T19:29:38Z","updated_at":"2016-09-15T19:29:38Z","html_url":"https://github.com/obspy/obspy/pull/1517#discussion_r79043221","pull_request_url":"https://api.github.com/repos/obspy/obspy/pulls/1517","_links":{"self":{"href":"https://api.github.com/repos/obspy/obspy/pulls/comments/79043221"},"html":{"href":"https://github.com/obspy/obspy/pull/1517#discussion_r79043221"},"pull_request":{"href":"https://api.github.com/repos/obspy/obspy/pulls/1517"}}},"pull_request":{"url":"https://api.github.com/repos/obspy/obspy/pulls/1517","id":83948378,"html_url":"https://github.com/obspy/obspy/pull/1517","diff_url":"https://github.com/obspy/obspy/pull/1517.diff","patch_url":"https://github.com/obspy/obspy/pull/1517.patch","issue_url":"https://api.github.com/repos/obspy/obspy/issues/1517","number":1517,"state":"open","locked":false,"title":"Nordic (s-file) integration.","user":{"login":"calum-chamberlain","id":10913395,"avatar_url":"https://avatars.githubusercontent.com/u/10913395?v=3","gravatar_id":"","url":"https://api.github.com/users/calum-chamberlain","html_url":"https://github.com/calum-chamberlain","followers_url":"https://api.github.com/users/calum-chamberlain/followers","following_url":"https://api.github.com/users/calum-chamberlain/following{/other_user}","gists_url":"https://api.github.com/users/calum-chamberlain/gists{/gist_id}","starred_url":"https://api.github.com/users/calum-chamberlain/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/calum-chamberlain/subscriptions","organizations_url":"https://api.github.com/users/calum-chamberlain/orgs","repos_url":"https://api.github.com/users/calum-chamberlain/repos","events_url":"https://api.github.com/users/calum-chamberlain/events{/privacy}","received_events_url":"https://api.github.com/users/calum-chamberlain/received_events","type":"User","site_admin":false},"body":"This pull request relates to the previous pull-request [1316](https://github.com/obspy/obspy/pull/1316).  I have moved across the [EQcorrscan](https://github.com/eqcorrscan/EQcorrscan) sfile_util submodule to here which has quite a bit (but not all) read/write support for nordic sfiles.\r\n\r\nWhat it does:\r\n- Read and write location (origin) information to obspy.core.event.Event\r\n- Read and write magnitude info (including relevant picks);\r\n- Read spectral info from nordic files, but this isn't stored in obspy structure at the moment, just in a dict\r\n- Read in pick information and uncertainties, possibly not ideal mapping for uncertainties, welcome suggestions\r\n\r\nWhat it doesn't do:\r\n- Read or write in focal mechanism information, I don't have a useful example at the moment, but it should be straight-forward to add, I just wanted to get this going\r\n- Read or write moment tensor info, again, no example to play with.\r\n- Read or write Hyp error assesments\r\n\r\nI have included my tests, which pass locally, shall see how they go on travis and appveyor (they were working for eqcorrscan before), and see how coverage goes.\r\n\r\nStill to do:\r\n- [x] Test that the plugin is found properly and that it plays nicely with read_events\r\n- [x] Add to CONTRIBUTING and CHANGELOG\r\n- [x]  Add test for plugin for read_events\r\n- [ ] aob","created_at":"2016-09-05T04:17:08Z","updated_at":"2016-09-15T19:47:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d8639804b2fb063bf5c107e0745a8cb7d589cea4","assignee":{"login":"calum-chamberlain","id":10913395,"avatar_url":"https://avatars.githubusercontent.com/u/10913395?v=3","gravatar_id":"","url":"https://api.github.com/users/calum-chamberlain","html_url":"https://github.com/calum-chamberlain","followers_url":"https://api.github.com/users/calum-chamberlain/followers","following_url":"https://api.github.com/users/calum-chamberlain/following{/other_user}","gists_url":"https://api.github.com/users/calum-chamberlain/gists{/gist_id}","starred_url":"https://api.github.com/users/calum-chamberlain/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/calum-chamberlain/subscriptions","organizations_url":"https://api.github.com/users/calum-chamberlain/orgs","repos_url":"https://api.github.com/users/calum-chamberlain/repos","events_url":"https://api.github.com/users/calum-chamberlain/events{/privacy}","received_events_url":"https://api.github.com/users/calum-chamberlain/received_events","type":"User","site_admin":false},"assignees":[{"login":"calum-chamberlain","id":10913395,"avatar_url":"https://avatars.githubusercontent.com/u/10913395?v=3","gravatar_id":"","url":"https://api.github.com/users/calum-chamberlain","html_url":"https://github.com/calum-chamberlain","followers_url":"https://api.github.com/users/calum-chamberlain/followers","following_url":"https://api.github.com/users/calum-chamberlain/following{/other_user}","gists_url":"https://api.github.com/users/calum-chamberlain/gists{/gist_id}","starred_url":"https://api.github.com/users/calum-chamberlain/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/calum-chamberlain/subscriptions","organizations_url":"https://api.github.com/users/calum-chamberlain/orgs","repos_url":"https://api.github.com/users/calum-chamberlain/repos","events_url":"https://api.github.com/users/calum-chamberlain/events{/privacy}","received_events_url":"https://api.github.com/users/calum-chamberlain/received_events","type":"User","site_admin":false}],"milestone":{"url":"https://api.github.com/repos/obspy/obspy/milestones/12","html_url":"https://github.com/obspy/obspy/milestones/1.1.0","labels_url":"https://api.github.com/repos/obspy/obspy/milestones/12/labels","id":1383698,"number":12,"title":"1.1.0","description":"","creator":{"login":"megies","id":1842780,"avatar_url":"https://avatars.githubusercontent.com/u/1842780?v=3","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":48,"closed_issues":29,"state":"open","created_at":"2015-10-29T15:40:55Z","updated_at":"2016-09-12T16:03:55Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/obspy/obspy/pulls/1517/commits","review_comments_url":"https://api.github.com/repos/obspy/obspy/pulls/1517/comments","review_comment_url":"https://api.github.com/repos/obspy/obspy/pulls/comments{/number}","comments_url":"https://api.github.com/repos/obspy/obspy/issues/1517/comments","statuses_url":"https://api.github.com/repos/obspy/obspy/statuses/987e360d3683188ede1d07e38982498bbe689bb0","head":{"label":"obspy:feature/nordic_integration","ref":"feature/nordic_integration","sha":"987e360d3683188ede1d07e38982498bbe689bb0","user":{"login":"obspy","id":1701221,"avatar_url":"https://avatars.githubusercontent.com/u/1701221?v=3","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=3","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}","deployments_url":"https://api.github.com/repos/obspy/obspy/deployments","created_at":"2012-09-08T19:17:46Z","updated_at":"2016-09-09T20:29:24Z","pushed_at":"2016-09-15T17:45:03Z","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":"https://www.obspy.org","size":97991,"stargazers_count":230,"watchers_count":230,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":172,"mirror_url":null,"open_issues_count":189,"forks":172,"open_issues":189,"watchers":230,"default_branch":"master"}},"base":{"label":"obspy:master","ref":"master","sha":"cac54d0fa40e20c788f3ae26c49136812cdeb4b4","user":{"login":"obspy","id":1701221,"avatar_url":"https://avatars.githubusercontent.com/u/1701221?v=3","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=3","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}","deployments_url":"https://api.github.com/repos/obspy/obspy/deployments","created_at":"2012-09-08T19:17:46Z","updated_at":"2016-09-09T20:29:24Z","pushed_at":"2016-09-15T17:45:03Z","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":"https://www.obspy.org","size":97991,"stargazers_count":230,"watchers_count":230,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":172,"mirror_url":null,"open_issues_count":189,"forks":172,"open_issues":189,"watchers":230,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/obspy/obspy/pulls/1517"},"html":{"href":"https://github.com/obspy/obspy/pull/1517"},"issue":{"href":"https://api.github.com/repos/obspy/obspy/issues/1517"},"comments":{"href":"https://api.github.com/repos/obspy/obspy/issues/1517/comments"},"review_comments":{"href":"https://api.github.com/repos/obspy/obspy/pulls/1517/comments"},"review_comment":{"href":"https://api.github.com/repos/obspy/obspy/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/obspy/obspy/pulls/1517/commits"},"statuses":{"href":"https://api.github.com/repos/obspy/obspy/statuses/987e360d3683188ede1d07e38982498bbe689bb0"}}}}
{"actor":{"display_login":"krischer"}}