source: SHX/trunk/SeismicHandler/commands/meta.py @ 1130

Revision 1130, 8.2 KB checked in by klaus, 4 years ago (diff)

bugfix in metadata update; bugfix in menue entries using fdsn reading

Line 
1# -*- coding: utf-8 -*-
2
3#    This file is part of Seismic Handler eXtended (SHX). For terms of use and
4#    license information please see license.txt and visit
5#    http://www.seismic-handler.org/portal/wiki/Shx/LicenseTerms
6
7from SeismicHandler.basics.command import BaseCommand
8from SeismicHandler.core import Traces
9from SeismicHandler.modules.traces import Traces as BaseTraces, \
10    traces_from_list, get_meta_status, META_STATUS_LOCATION, \
11    META_STATUS_COMPLETE, META_STATUS_EMPTY
12from SeismicHandler.modules.stations import ChannelMeta, Stations, \
13    triggerDatabaseReload
14from SeismicHandler.config import Settings
15from SeismicHandler.basics import timeit
16from SeismicHandler.basics.error import ShxError
17from obspy.fdsn.client import Client
18
19provides = {"meta": "meta"}
20class meta(BaseCommand):
21    """
22    URI:http://www.seismic-handler.org/portal/wiki/ShDisplay
23    """
24    numberOfParameters = [2]
25    parameterQueries = [
26        {
27            "text": "trace list",
28            "type": "str",
29            "question": False,
30        },
31        {
32            "text": "subcmd",
33            "type": "str",
34            "question": False,
35        },
36    ]
37    known_qualifiers = [
38        "ADDR",
39        "DEL_INCOMPLETE",
40    ]
41   
42    legal_subcmds = "list,complete,complete_location,complete_response".split(",")
43
44    def __init__(self, *args, **kwargs):
45        # unroll args & kwargs
46        BaseCommand.__init__(self, *args, **kwargs)
47
48    #@timeit
49    def run(self):
50        "Metadata management."
51
52        traces = traces_from_list(self.parameters[0])
53        subcmd = self.parameters[1].lower()
54        if subcmd not in self.legal_subcmds:
55            raise ShxError( "illegal subcmd '%s'. legal are: '%s'" % (subcmd,
56                ','.join(self.legal_subcmds)), status=1111 )
57
58        fdsnadr = Settings.config.fdsnws['default_meta_source'][0]
59        if self.qualifiers["ADDR"]:
60            fdsnadr = self.qualifiers["ADDR"]
61       
62        self.stations = Stations()
63
64        if subcmd == 'list':
65            print "idx net sta     cha   location       gain   response-ok"
66            for trc in traces:
67                itext, metastatus = self.infostring( trc )
68                print itext
69                trc.stats.sh.METASTATUS = metastatus
70        elif subcmd in ('complete','complete_location','complete_response'):
71            self.completeMetadata( fdsnadr, traces, subcmd )
72        else:
73            raise ShxError( "illegal subcmd. this cannot happen", status=1111 )
74       
75        # delete traces with incomplete metadata
76        if self.qualifiers["DEL_INCOMPLETE"]:
77            for trc in self.listIncompleteTraces(traces,subcmd):
78                trc.shx._parent.remove(trc)
79            BaseTraces().updateCounter()
80
81
82    def infostring( self, trc ):
83        "Returns info string about trace."
84        sname = "%s.%s.%s.%s" % (trc.stats.network, trc.stats.station,
85            trc.stats.location, trc.stats.channel)
86        metatime = trc.stats.starttime \
87            + (trc.stats.endtime-trc.stats.starttime)/2
88        metastatus = META_STATUS_EMPTY
89        try:
90            r = self.stations[(sname, metatime)]
91        except:
92            r = None
93        try:
94            slat = float( r.latitude )
95            slon = float( r.longitude )
96            locstring = "(%6.2f,%6.2f)" % (slat,slon)
97            metastatus = META_STATUS_LOCATION
98        except:
99            locstring = "(------,------)"
100        try:
101            gain = float( r.gain )
102            gainstr = "%6.3f" % gain
103        except:
104            gain = None
105            gainstr = "------"
106        if gain and gain == 1.:
107            gainstr = " [1]? "
108        if r and r.poles and r.poles != '[]':
109            respstr = "resp_given"
110            metastatus = META_STATUS_COMPLETE
111        else:
112            respstr = "---"
113        infostr = "%3d %2s %5s %2s %3s %s %s  %s" % (trc.index(True),
114            trc.stats.network,trc.stats.station,trc.stats.location,
115            trc.stats.channel,locstring,gainstr,respstr)
116        return (infostr,metastatus)
117   
118    def completeMetadata( self, fdsnadr, traces, subcmd ):
119        "Completes metadata of selected traces using FDSN WS."
120        incomplete = []
121        startend = {}
122        oldgains = []
123        for trc in traces:
124            metastatus, oldgain = get_meta_status( trc, addgain=True )
125            oldgains.append( oldgain )
126            if metastatus == META_STATUS_COMPLETE:
127                continue
128            if metastatus == META_STATUS_LOCATION \
129                and subcmd == 'complete_location':
130                continue
131            incomplete.append((
132                trc.stats.network,
133                trc.stats.station,
134                trc.stats.location,
135                trc.stats.channel,
136                trc.stats.starttime,
137                trc.stats.endtime
138            ))
139            startend["%s.%s.%s.%s" % (trc.stats.network,trc.stats.station,
140                trc.stats.location,trc.stats.channel)] = (
141                trc.stats.starttime,trc.stats.endtime,oldgain)
142        if incomplete == []:
143            return
144        if subcmd == 'complete_location':
145            level = 'channel'
146        else:
147            level = 'response'
148        # request station data using bulk request
149        #print "dbg: bulk station request", incomplete
150        client = Client(fdsnadr)
151        inv = client.get_stations_bulk( incomplete, level=level )
152        #p = incomplete[0]
153        #inv = client.get_stations( network=p[0], station=p[1],
154        #    location=p[2], channel=p[3], starttime=p[4], endtime=p[5],
155        #    level=level )
156        for chan in inv.get_contents()['channels']:
157            if not chan in startend.keys():
158                print "got unrequested info for '%s', ignored" % chan
159                continue
160            stime, etime, oldgain = startend[chan]
161            cm = inv.get_coordinates( chan )
162            try:
163                n, s, l, c = chan.split('.')
164            except:
165                print "illegal channel format i '%s'" % chan
166            if subcmd == 'complete_location':
167                meta = ChannelMeta(
168                    network=n, station=s, location=l,
169                    stream=c[:2], component=c[-1],
170                    start=stime, end=etime,
171                    latitude=cm['latitude'],
172                    longitude=cm['longitude'],
173                    depth=cm.get('local_depth',0.),
174                    elevation=cm.get('elevation',0.),
175                    poles=str([]), zeros=str([]),  # this is dangerous, but
176                    gain=1.                        # ChannelMeta wants sth.
177                )
178            else:
179                metatime = stime + (etime-stime)/2
180                r = inv.get_response( chan, metatime )
181                paz = r.get_paz()
182                meta = ChannelMeta(
183                    network=n, station=s, location=l,
184                    stream=c[:2], component=c[-1],
185                    start=stime, end=etime,
186                    latitude=cm['latitude'],
187                    longitude=cm['longitude'],
188                    depth=cm.get('local_depth',0.),
189                    elevation=cm.get('elevation',0.),
190                    gain=1.e9/r.instrument_sensitivity.value,
191                    poles=str(paz.poles),
192                    zeros=str(paz.zeros),
193                )
194            self.stations.add(meta, replace=True, local=True)
195        # reread DB due to bug in Db interface
196        triggerDatabaseReload()
197        #self.stations.read( clear=True )
198        for itrc, trc in enumerate(traces):
199            # check for correctly applied gain
200            oldgain = oldgains[itrc]
201            metstat, newgain = get_meta_status( trc, addgain=True )
202            if (oldgain == None or oldgain == 1.) and newgain != 1.:
203                # multiply new gain onto trace data
204                trc.data *= newgain
205            trc.set_info( 'METASTATUS', metstat )
206   
207    def listIncompleteTraces( self, traces, subcmd ):
208        "Returns list of traces with incomplete metadata."
209        incomplete = []
210        for trc in traces:
211            metastatus = get_meta_status( trc )
212            if metastatus == META_STATUS_COMPLETE:
213                continue
214            if metastatus == META_STATUS_LOCATION \
215                and subcmd == 'complete_location':
216                continue
217            incomplete.append( trc )
218        return incomplete
Note: See TracBrowser for help on using the repository browser.