Changeset 139


Ignore:
Timestamp:
08/06/2009 04:11:51 PM (13 years ago)
Author:
marcus
Message:
  • trace handling
  • simple trace plots (matplotlib)
  • more tests
Location:
SHX/trunk/src
Files:
3 added
16 edited

Legend:

Unmodified
Added
Removed
  • SHX/trunk/src

    • Property svn:ignore set to
      *.pyc
  • SHX/trunk/src/SeismicHandler

    • Property svn:ignore set to
      *.pyc
  • SHX/trunk/src/SeismicHandler/config

    • Property svn:ignore set to
      *.pyc
  • SHX/trunk/src/SeismicHandler/core

    • Property svn:ignore set to
      *.pyc
  • SHX/trunk/src/SeismicHandler/core/commands

    • Property svn:ignore set to
      *.pyc
  • SHX/trunk/src/SeismicHandler/core/commands/run.py

    r137 r139  
    55# This file is part of Seismic Handler eXtended (SHX) 
    66# Full details can be found at project website http://www.seismic-handler.org/ 
    7 #  
     7# 
    88# SHX is free software; you can redistribute it and/or modify 
    99# it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by 
     
    2828class Run(Command): 
    2929    """run command directly on shlib instance 
    30      
     30 
    3131       - easy access to "old" SH functions: 
    3232           -> e.g. Run("copy 1") = copy trace number one 
     
    4646    def run(self): 
    4747        """run command 
    48          
     48 
    4949           since shlib call function reads only streams, use StringIO to build one""" 
    5050        shlib().call(StringIO(self.cmdstr)) 
  • SHX/trunk/src/SeismicHandler/core/error.py

    r131 r139  
    6363        return """Command "%s" was removed!""" % self.cmd 
    6464 
     65class InfoEntryNotFoundError(Error): 
     66    def __init__(self, name): 
     67        Error.__init__(self) 
     68        self.name = name 
     69 
     70    def __str__(self): 
     71        return """info entry "%s" not found!""" % self.name 
     72 
     73class InfoEntryReadOnlyError(Error): 
     74    def __init__(self, name): 
     75        Error.__init__(self) 
     76        self.name = name 
     77 
     78    def __str__(self): 
     79        return """info entry "%s" not writable!""" % self.name 
     80 
     81class VarsInternalReadOnlyError(Error): 
     82    def __init__(self): 
     83        Error.__init__(self) 
     84 
     85    def __str__(self): 
     86        return """internal variables are unchangeable!""" 
  • SHX/trunk/src/SeismicHandler/core/log.py

    r137 r139  
    2525import os 
    2626 
    27 class Logging(object): 
     27class Logging(logging.Logger): 
    2828    logging = None 
    2929 
     
    3838    def __init__(self): 
    3939        """configure logging once""" 
     40         
     41        logging.Logger.__init__(self, "shx") 
    4042 
    4143        if not self.logging: 
     
    5658            for lvl in newlvl: 
    5759                logging.addLevelName(lvl, newlvl[lvl]) 
    58                 setattr(logging, lvl.lower(), lambda *args: logging.log(newlvl[lvl], *args)) 
     60#                setattr(self, lvl.lower(), lambda *args: self.log(newlvl[lvl], *args)) 
    5961 
    6062            try: 
     
    6567                                    filemode='w') 
    6668            except IOError: 
    67                 logging.warning("Cannot log to disc, path %s not writable! Logging everything to console." % dir) 
     69                self.warning("Cannot log to disc, path %s not writable! Logging everything to console." % dir) 
    6870 
    6971                logging.basicConfig(level=logging.DEBUG, 
     
    8890            self.logging = logging 
    8991 
     92    def debug2(self, args, kwargs): 
     93        if self.manager.disable >= logging.DEBUG+1: 
     94            return  
     95     
    9096Logging() 
    9197 
  • SHX/trunk/src/SeismicHandler/core/modules

    • Property svn:ignore set to
      *.pyc
  • SHX/trunk/src/SeismicHandler/core/modules/Events.py

    r137 r139  
    109109    """ 
    110110 
     111    # standard events 
    111112    TRACEUPDATE = "traceupdate" 
    112113    REDRAW = "redraw" 
    113114    COMMANDRUN = "cmdrun" 
     115    INFOIDXUPDATE = "infoindexupdate" 
    114116 
    115117    events = {} 
  • SHX/trunk/src/SeismicHandler/core/modules/Trace.py

    r137 r139  
    2828from SeismicHandler.core.log import logging 
    2929from SeismicHandler.core.modules.Events import EventManager, Event 
    30 from SeismicHandler.core.shheaders import MEMBLC 
     30from SeismicHandler.core.shheaders import MEMBLC, EMPTYVALUES 
     31from SeismicHandler.core.error import InfoEntryNotFoundError, InfoEntryReadOnlyError 
    3132 
    3233from uuid import uuid4 as uuid 
     34import ctypes as C 
     35import numpy as np 
     36 
     37# trace info entry flags 
     38NOCOPY = 0x0800 
     39RDONLY = 0x0400 
    3340 
    3441class Trace(object): 
     
    3946 
    4047    def __init__(self, **kwargs): 
    41 #        print kwargs["memblc"] 
    42         self.logger = logging.getLogger("modules.trace") 
    43          
    4448        # holds info entries 
    4549        self._info = {} 
    4650 
     51        self.logger = logging.getLogger("modules.trace") 
     52 
    4753        # unique id 
    4854        self.id = uuid().hex 
    4955 
    50     def __getattr__(self, attr): 
     56        # update info from memblc / address info supplied 
     57        if kwargs.has_key("memblc"): 
     58            self.address = kwargs.get("address") 
     59            self.update(memblc=kwargs.get("memblc")) 
     60 
     61    def __len__(self): 
     62        return self.delta * self.length  
     63     
     64    def __getattr__(self, name): 
    5165        """allow access to trace metadata by querying as attribute 
    5266 
    5367        """ 
    5468 
    55         # check for really existing attributes 
    56         if attr in self.__dict__: 
    57             return self.__dict__[attr] 
     69        # check for really existing class attribute 
     70        if name in self.__dict__: 
     71            return self.__dict__[name] 
     72 
     73        # try to return info entry 
     74        try: 
     75            return self.__dict__["_info"][name.upper()] 
     76        except KeyError: 
     77            raise InfoEntryNotFoundError(name) 
     78 
     79        return None 
     80 
     81    def __setattr__(self, name, value): 
     82        try: 
     83            if not name.upper() in self.__dict__["_info"]: 
     84                self.__dict__[name] = value 
     85            else: 
     86                # check for readonly attributes 
     87                idxmap = shlib().idx 
     88 
     89                if idxmap[name.upper()][1] & RDONLY: 
     90                    raise InfoEntryReadOnlyError(name.upper()) 
     91 
     92                self.__dict__["_info"][name] = value 
     93                shlib().setInfoEntry(self.address, name, value) 
     94 
     95        except KeyError: 
     96            self.__dict__[name] = value 
    5897 
    5998    def plot(self): 
    6099        self.logger.info("plot") 
    61100 
     101        from SeismicHandler.core.modules.Graphics import pylab 
     102 
     103        # get data into array 
     104        pylab.title(self.station) 
     105        pylab.plot(np.arange(0, self.delta * self.length, self.delta), self.fetchData(), "k") 
     106        pylab.grid() 
     107        pylab.show() 
     108        pylab.close(1) 
     109 
     110        del pylab 
     111 
     112    def fetchData(self): 
     113        return (C.c_float * self.length).from_address(self.data) 
     114 
    62115    def delete(self): 
    63116        self.logger.info("delete") 
    64117 
     118    def listInfo(self): 
     119        print "info entries for trace id %s, address %u" % (self.id, self.address) 
     120        for i in sorted(self._info.keys()): 
     121            print i, self._info[i] 
     122 
    65123    def update(self, **kwargs): 
    66         self.logger.info("update") 
     124        if not kwargs.has_key("memblc"): 
     125            return False 
     126 
     127        self.logger.info("updating from memory block, trace id %s" % self.id) 
     128 
     129        mb = kwargs.get("memblc") 
     130 
     131        idxmap = shlib().idx 
     132 
     133        info = {} 
     134        # read all info entries 
     135        for e in idxmap: 
     136            dattype = idxmap[e][0] 
     137            abbr = dattype[0] 
     138            idx =  idxmap[e][2] 
     139 
     140            if dattype == "flag": 
     141                value = mb.fm & (1 << idx) 
     142            elif dattype == "xtra": 
     143                # XXX todo read special! 
     144                # in fact this is only some formatted output of standard entries 
     145                continue 
     146            elif dattype == "char": 
     147                value = chr(mb.cm[idx]) 
     148            else: 
     149                value = getattr(mb, "%cm" % abbr)[idx] 
     150 
     151            try: 
     152                value = value.value 
     153            except AttributeError: 
     154                # leave value as it is 
     155                pass 
     156 
     157            # check for empty values 
     158            if dattype == "real": 
     159                if value - EMPTYVALUES[dattype] <= EMPTYVALUES["real_epsilon"]: 
     160                    value = None 
     161            elif dattype == "flag": 
     162                # flags should remain 0 aka "False" 
     163                pass 
     164            else: 
     165                if value == EMPTYVALUES[dattype]: 
     166                    value = None 
     167 
     168            info[e] = value 
     169 
     170        self._info = info 
     171#        self.listInfo() 
    67172 
    68173class Traces(object): 
     
    73178 
    74179    # helds addresses and corresponding trace instances 
    75     traces = {} 
     180    traces = [] 
     181    tracedata = {} 
    76182 
    77183    def __init__(self): 
     
    80186        self.logger = logging.getLogger("modules.traces") 
    81187        self.update() 
     188 
     189    def __getitem__(self, number): 
     190        return self.tracedata[self.traces[number]] 
    82191 
    83192    def update(self, event=None): 
     
    92201            # but still referenced here? 
    93202            if len(self.traces): 
     203                self.traces = [] 
    94204                # delete all 
    95                 for t in self.traces: 
    96                     self.traces[t].delete() 
    97                 self.trace = [] 
     205                for t in self.tracedata: 
     206                    self.tracedata[t].delete() 
    98207 
    99208            return 
    100209 
    101210        addresses = [] 
    102         old_addresses = self.traces.keys() 
    103          
     211        old_addresses = self.traces 
     212 
    104213        p = root.pm[0] 
    105          
     214 
    106215        while p: 
    107216            addresses.append(p) 
    108              
     217 
    109218            mb = MEMBLC.from_address(p) 
    110              
     219 
    111220            if p in self.traces: 
    112                 self.traces[p].update(memblc=mb) 
    113             else: 
    114                 self.traces[p] = Trace(memblc=mb) 
    115              
     221                self.tracedata[p].update(memblc=mb, event=event) 
     222            else: 
     223                self.tracedata[p] = Trace(memblc=mb, event=event, address=p) 
     224                self.traces.append(p) 
     225 
    116226            p = mb.pm[0] 
    117          
     227 
    118228        new = list(set(addresses) - set(old_addresses)) 
    119229        gone = list(set(old_addresses) - set(addresses)) 
    120          
     230 
    121231        for addr in gone: 
    122             self.traces[addr].delete() 
     232            # clean up 
     233            self.tracedata[addr].delete() 
     234            # delete reference 
     235            del self.tracedata[addr] 
     236            del self.traces[self.traces.index(addr)] 
    123237 
    124238        self.logger.debug("new traces: %s" % new) 
    125239        self.logger.debug("gone traces: %s" % gone) 
    126             
     240 
     241    def __len__(self): 
     242        return len(self.traces) 
     243 
    127244if __name__ == "__main__": 
    128245    t = Traces() 
    129246    from SeismicHandler.core.commands import Run 
     247    from SeismicHandler.core.modules.Graphics import pylab 
    130248 
    131249    EventManager.block(Event(EventManager.REDRAW)) 
     250    # create 2 hours of synthetic data (100 Hz) 
     251    # position set by counter 
    132252    for i in range(2): 
    133         Run("cresharp") 
     253        Run("CREATE SHARP 0.05 100 1. %u .1 .5" % (10+i*6)) 
     254#        Run("create sharp 0.1 7200 1 %u 0.005 .05" % 5**(i+1)) 
     255 
     256    Run("sum all") 
     257 
    134258    EventManager.unblock(Event(EventManager.REDRAW)) 
    135     Run("del 1") 
     259 
     260    fig = pylab.figure() 
     261    pylab.subplots_adjust(hspace=0.00001,wspace=20) 
     262 
     263    for i, trc in enumerate(t.traces): 
     264        x = t[i] 
     265 
     266        x.station = "TST%u" % i 
     267        x.zoom = 5.5 
     268        x.comment = "Tell me what you think of me #%u" % i 
     269        x.chan1 = "B" 
     270        x.chan2 = "H" 
     271        x.comp = "N" 
     272 
     273        EventManager.trigger(Event(EventManager.REDRAW)) 
     274 
     275#        x.listInfo() 
     276 
     277        ax = pylab.subplot(len(t),1,i+1) 
     278 
     279        # don't show axis ticks except for last one 
     280        if i < len(t)-1: 
     281            ax.xaxis.set_major_locator(pylab.NullLocator()) 
     282 
     283        pylab.plot(np.arange(0, x.delta * x.length, x.delta), x.fetchData(), "k") 
     284#        x.plot() 
     285 
     286    pylab.show() 
  • SHX/trunk/src/SeismicHandler/core/shheaders.py

    r131 r139  
    2929LINELENGTH = 199 
    3030CAPCNV = 0x4 
     31 
     32# from shdataba.c and qfileio.c (real) 
     33EMPTYVALUES = { 
     34         "long": 0x7fffffffL, 
     35         "int": 0x7fff, 
     36         "byte": 0x7f, 
     37         "char": '\x00', 
     38         "string": '', 
     39         "time": 0L, 
     40         "pointer": None, 
     41         "flag": 0, 
     42         "real": 5.37531e-38, 
     43         "real_epsilon": 1e-40, 
     44} 
     45 
     46# from infoidx.h 
     47LISTLENGTH = { 
     48              "long": 30, 
     49              "int": 30, 
     50              "byte": 20, 
     51              "real": 60, 
     52              "string": 20, 
     53              "char": 40, 
     54              "time": 15, 
     55              "pointer": 8                           
     56} 
    3157 
    3258class PARAM(C.Structure): 
     
    100126 
    101127    _fields_ = [ 
    102         ("lm", C.c_long * 30), 
    103         ("im", C.c_int * 30), 
    104         ("bm", C.c_byte * 20), 
    105         ("rm", C.c_float * 60), 
    106         ("tm", TIME * 15), 
    107         ("sm", (C.c_char * 132) * 20), 
    108         ("cm", C.c_char * 40), 
    109         ("pm", C.c_void_p * 8), 
     128        ("lm", C.c_long * LISTLENGTH["long"]), 
     129        ("im", C.c_int * LISTLENGTH["int"]), 
     130        ("bm", C.c_byte * LISTLENGTH["byte"]), 
     131        ("rm", C.c_float * LISTLENGTH["real"]), 
     132        ("tm", TIME * LISTLENGTH["time"]), 
     133        ("sm", (C.c_char * 132) * LISTLENGTH["string"]), 
     134#        ("cm", C.c_char * LISTLENGTH["char"]), 
     135        # unfortunately ctypes treats an array of chars as string 
     136        # so null bytes will cut following array values 
     137        ("cm", C.c_byte * LISTLENGTH["char"]), 
     138        ("pm", C.c_void_p * LISTLENGTH["pointer"]), 
    110139        ("fm", C.c_int), 
    111140    ] 
  • SHX/trunk/src/SeismicHandler/core/shlib.py

    r137 r139  
    3636from SeismicHandler.core.error import MultipleLibError, CommandStreamError, GotoTargetNotFoundError 
    3737from SeismicHandler.config.options import environment 
    38 from SeismicHandler.core.shheaders import LINELENGTH, NOERROR, PARAM, CAPCNV 
     38from SeismicHandler.core.shheaders import LINELENGTH, NOERROR, PARAM, CAPCNV, EMPTYVALUES 
    3939from SeismicHandler.core.modules.Events import EventManager, Event 
    4040 
     
    6464        if not "sh" in self.__dict__: 
    6565            # load shared lib (once per identifier) 
     66 
    6667            try: 
    6768                self.sh = C.CDLL(os.path.join(environment["root"], "libshc.so")) 
     
    9596        self._startup() 
    9697 
     98        idxu = Event(EventManager.INFOIDXUPDATE) 
     99        EventManager.subscribe(idxu, self._readIdxStructure) 
     100        EventManager.trigger(idxu) 
     101 
     102    def _readIdxStructure(self, *args, **kwargs): 
     103        idxlist = { 
     104                   "long": C.c_long, 
     105                   "int": C.c_int, 
     106                   "byte": C.c_byte, 
     107                   "real": C.c_float, 
     108                   "string": C.c_char_p, 
     109                   "char": C.c_char, 
     110                   "time": lambda x: x, 
     111                   "pointer": C.pointer, 
     112                   "flag": lambda x: x, 
     113                   "xtra": lambda x: x 
     114                   } 
     115 
     116        slib = self._instances[self._active].sh 
     117 
     118        idxstructure = {} 
     119 
     120        for idx in idxlist: 
     121            idx_1 = idx[0] 
     122 
     123            i = C.c_int.in_dll(slib, "icnt_%c_dbv" % idx_1) 
     124 
     125            nam = ((C.c_char*11)*i.value).in_dll(slib, "inam_%c_dbv" % idx_1) 
     126            ent = (C.c_uint*i.value).in_dll(slib, "ient_%c_dbv" % idx_1) 
     127 
     128            for e in range(i.value): 
     129                # structure maps name to type, ientry value, index and function 
     130                idxstructure[nam[e].value.replace("-", "_")] = (idx, ent[e], ent[e] & 0x03ff, idxlist[idx]) 
     131 
     132        self.idx = idxstructure 
     133 
     134    def setInfoEntry(self, trc, name, value): 
     135        """transfer info entry "name" to shlib instance for trace at address trc 
     136 
     137        """ 
     138 
     139        map = { 
     140               "long": "db_setl", 
     141               "int": "db_seti", 
     142               "byte": "db_setb", 
     143               "string": "db_sets", 
     144               "char": "db_setc", 
     145               "real": "db_setr", 
     146               "flag": "db_setf", # XXX  
     147               "pointer": "db_setp", # XXX not needed (still unchangeable) 
     148               "time": "db_sett", # XXX 
     149               } 
     150 
     151        dattype, ientry, _, vmap = self.idx[name.upper()] 
     152 
     153        fct = getattr(self.sh, map[dattype]) 
     154 
     155        status = C.c_int() 
     156 
     157        if value == None: 
     158            value = EMPTYVALUES[dattype] 
     159        else: 
     160            value = vmap(value) 
     161 
     162        fct(trc, ientry, value, C.byref(status)) 
     163 
     164        if status.value: 
     165            logger.error("could not set info entry '%s'" % name) 
     166        else: 
     167            logger.debug("set info entry '%s' to '%s' for trace %u" % (name, str(value), trc)) 
     168 
    97169    def _startup(self): 
    98170        """set some start up parameters""" 
     
    100172        self.call(StringIO("wdw/dc=s/ic=s/main")) 
    101173        self.call(StringIO("wdw/ic=s")) 
     174 
     175        # new info entries 
     176        self.call(StringIO("entry define sign      i  6 11")) 
     177        self.call(StringIO("entry define eventno   i  7 12")) 
     178        self.call(StringIO("entry define mark      i  8 14")) 
     179        self.call(StringIO("entry define calib     r  1 26")) 
     180        self.call(StringIO("entry define distance  r  2 11")) 
     181        self.call(StringIO("entry define azimuth   r  4 12")) 
     182        self.call(StringIO("entry define slowness  r  3 18")) 
     183        self.call(StringIO("entry define inci      r 12 13")) 
     184        self.call(StringIO("entry define depth     r 13 14")) 
     185        self.call(StringIO("entry define magnitude r 14 15")) 
     186        self.call(StringIO("entry define lat       r 15 16")) 
     187        self.call(StringIO("entry define lon       r 16 17")) 
     188        self.call(StringIO("entry define signoise  r 17 22")) 
     189        self.call(StringIO("entry define pwdw      r 18 23")) 
     190        self.call(StringIO("entry define dcvreg    r 19 24")) 
     191        self.call(StringIO("entry define dcvinci   r 20 25")) 
     192        self.call(StringIO("entry define filter    s 10 11")) 
     193        self.call(StringIO("entry define quality   s 11 12")) 
     194        self.call(StringIO("entry define p-onset   t  1 22")) 
     195        self.call(StringIO("entry define s-onset   t  2 23")) 
     196        self.call(StringIO("entry define origin    t  3 24")) 
    102197 
    103198    def call(self, stream): 
     
    161256            iscmdproc = C.c_int() 
    162257            rdlevel = C.c_int() 
    163              
     258 
    164259            # check for prompt (not set if running non-interactively 
    165260            try: 
     
    167262            except AttributeError: 
    168263                ptstr = "" 
    169                  
     264 
    170265            prompt = C.create_string_buffer(ptstr, LINELENGTH) 
    171266 
     
    203298            else: 
    204299                pass 
    205  
    206300 
    207301        return 
     
    340434        if comp[check](var2): 
    341435            self.Goto(cmd.p[5].value) 
     436 
     437if __name__ == "__main__": 
     438    s = shlib() 
  • SHX/trunk/src/SeismicHandler/tests

    • Property svn:ignore set to
      *.pyc
  • SHX/trunk/src/SeismicHandler/tests/test_events.py

    r131 r139  
    11# -*- coding: utf-8 -*- 
    22 
    3 from SeismicHandler.core.modules.Events import EventManager 
     3from SeismicHandler.core.modules.Events import Event, EventManager 
    44import unittest 
    5  
    65 
    76class eventsTestCase(unittest.TestCase): 
    87    def setUp(self): 
    98        self.ret = [] 
    10         EventManager.subscribe(["test", "test2"], self.returnValue) 
     9         
     10        self.test = Event("test") 
     11        self.test2 = Event("test2") 
     12         
     13        EventManager.subscribe([self.test, self.test2], self.returnValue) 
    1114 
    1215    def returnValue(self, *c): 
    1316        """ helper function for event trigger """ 
    14         self.ret.append(c) 
     17        self.ret.append(c[1]) 
    1518 
    1619    def testSubscribe(self): 
    17         self.assertTrue("test" in EventManager.events) 
    18         self.assertTrue("test2" in EventManager.events) 
     20        self.assertTrue(self.test in EventManager.events) 
     21        self.assertTrue(self.test2 in EventManager.events) 
    1922 
    2023    def testTrigger(self): 
    21         EventManager.trigger("test", "one") 
    22         EventManager.trigger("test2", "two") 
     24        EventManager.trigger(self.test, "one") 
     25        EventManager.trigger(self.test2, "two") 
    2326 
    24         self.assertEqual(self.ret, [("one",), ("two",)]) 
     27        self.assertEqual(self.ret, ["one", "two"]) 
    2528 
    2629    def testUnsubscribe(self): 
    27         EventManager.unsubscribe(self.returnValue, "test") 
    28         self.assertFalse(self.returnValue in EventManager.events["test"]) 
     30        EventManager.unsubscribe(self.returnValue, self.test) 
     31        self.assertFalse(self.returnValue in EventManager.events[self.test]) 
    2932 
    30         EventManager.trigger("test", "one2") 
    31         EventManager.trigger("test2", "two2") 
     33        EventManager.trigger(self.test, "one2") 
     34        EventManager.trigger(self.test2, "two2") 
    3235 
    33         self.assertEqual(self.ret, [("two2",)]) 
     36        self.assertEqual(self.ret, ["two2",]) 
    3437 
    3538    def tearDown(self): 
  • SHX/trunk/src/SeismicHandler/tests/test_shlib.py

    r131 r139  
    33from SeismicHandler.core.shlib import shlib 
    44from SeismicHandler.config.options import config 
     5from SeismicHandler.core.commands import Run 
    56 
    67import unittest 
     
    1213 
    1314    def tearDown(self): 
    14         pass 
     15        Run("del all") 
    1516 
    1617    def testAccess(self): 
     
    2021    def testRunCommand(self): 
    2122        """ check run command """ 
    22         from SeismicHandler.core.commands import Run 
    2323 
    2424        Run("cresharp") 
Note: See TracChangeset for help on using the changeset viewer.