spike.v1.Param — spike 0.99.23 documentation

# Source code for spike.v1.Param

    #!/usr/bin/env python
    # encoding: utf-8

    """
    This class extend the standard dictionnary behaviour.
    It is used to read and store all the parameters used by the NPK program.

    - it adds the possibility to load from files and dump/store to files the content of the dictionnary
      the file will be of the form :
      key=value, with one entry per line

    - when extracted from the dictionnnary, values are interpreted in several manner
        o 1K is replaced by 1024 and all multiples (4k; 24k; etc...)
        o 1M is replaced by 1024*1024 and all multiples (4M; 24M; etc...)
        o all arithmetic is evaluated : math.pi/2, 0.1*get_si1_2d(), etc...

    """

    from __future__ import print_function

    __author__ = "Marc A. Delsuc <delsuc@igbmc.fr>"
    __date__ = "Oct 2009"

    # UserDict is used for 2.1 compatibility required by jython

    import collections
    import os
    try:
        from UserDict import UserDict
    except ImportError:
        from collections import UserDict

    #---------------------------------------------------------------------------
    def parse(line):
        import re
        """Parse one property entry and prepare it to be entered in the  dictionnary
        """
        l = re.split(r'(?<!\\)=', line,1)   #matches = but not \=
    #    dkey = re.sub(r'\\=', '=',l[0]).lower()
        dkey = re.sub(r'\\=', '=',l[0])
        val = re.sub(r'\\=', '=',l[1])      # replaces \= by =

    #    l = line.strip().split("=",2)
    #    dkey=l[0].lower()
    #    val = l[1]

    #    fval=NPKevaluate(val)
    #    print dkey,fval
        return (dkey,val)

    #---------------------------------------------------------------------------
    def NPKevaluate(val):
        """
        - val is interpreted in several manner
            o 1K is replaced by 1024 and all multiples (4k; 24k; etc...)
            o 1M is replaced by 1024*1024 and all multiples (4M; 24M; etc...)
            o all arithmetic is evaluated : math.pi/2, 0.1*get_si1_2d(), etc...
        """
        import math
        # from NPK import *   # will be used by eval()
        found=0
        try:    # try eval()
            fval=eval(val)
            if  isinstance(fval, collections.abc.Callable) :  # we want to avoid functions !
                pass
    #            print " callable"
            else:
    #            print " worked"
                found=1
        except:
    #        print " failed"
            pass
        if (not found):
            try:    # try to type value
                if ( val.endswith("k")):
                    fval = 1024*int(val[0:len(val)-1])
                    found=1
                elif ( val.endswith("M")):
                    fval = 1024*1024*int(val[0:len(val)-1])
                    found=1
                else:
                    fval = float(val)
                    found=1
            except:
                pass
        if (not found):
            try:    # try to type value
                if ( val.lower() == "false" ):
                    fval = 0
                    found=1
                elif ( val.lower() == "true" ):
                    fval = 1
                    found=1
            except:
                fval = val
                found=1
        if (not found):
            fval=val
     #   print val, fval
        return fval

    #---------------------------------------------------------------------------
    class NPKParam(UserDict):
        "NPKParam class handles the parameter set used by NPK"
        #---------------------------------------------------------------------------
        def __init__(self,dict_=()):
            import copy
            if dict_ == ():
                ldict = {}
            else:
                ldict = copy.copy(dict_)
            self.data=ldict
        #---------------------------------------------------------------------------
        def __str__(self):
            return 'parameters :\n'+repr(self)

        #---------------------------------------------------------------------------
        def __getitem__(self,key):
            """overloading of the dictionnary [] method
            evaluates the content
            """
            i=NPKevaluate(self.data[key])
            return i

        #---------------------------------------------------------------------------
        def raw(self,key):
            """
            acces to the raw data present in the dictionnary, necessary in certain cases
            """
            return self.data[key]

        #---------------------------------------------------------------------------
        def dump(self,fname):
            """
            dump the content of the Parameter dictionnary as a property list file
            entries are not evaluated

            one entry per line with the following syntax :
            entry=value

            """
            try:
                fout = open(fname, 'w')
            except:
                print("Error while opening file :", sys.exc_info()[0])
                raise

            fout.write("#Property list file, dumped :"+time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime())+"\n")

            for i in self.keys():
                lk = re.sub('=', r'\\=', i)      # replaces = by \=
                lv = re.sub('=', r'\\=', str(self.data[i]))      # replaces = by \=

                fout.write(lk+"="+lv+"\n")
            fout.close()

        #---------------------------------------------------------------------------
        def store(self,fname):
            """
            write the content of the Parameter dictionnary as a property list file
            equivalent to dump, BUT entries are evaluated

            one entry per line with the following syntax :
            entry=value

            """
            try:
                fout = open(fname, 'w')
            except:
                print("Error while opening file :", sys.exc_info()[0])
                raise

            fout.write("#Property list file, output :"+time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime())+"\n")

            for i in self.keys():
                lk = re.sub('=', r'\\=', i)      # replaces = by \=
                lv = re.sub('=', r'\\=', self[i])      # replaces = by \=

                fout.write(lk+"="+lv+"\n")
            fout.close()

        #---------------------------------------------------------------------------
        def load(self,fname):
            """
            load a property list file as a dictionary

            one entry per line with the following syntax :
            entry=value

            keys are set to lowercase
            """
            try:
                fin = open(fname)
                f = fin.read()
                ls = f.split("\n")
                for v in ls:
                    if ( v == "" or v[0] == "#"):   # skip comments and empty lines
                        pass
                    else:
                        (dkey,fval) = parse(v.strip())
                        try:            # check key existence
                            val=self.data[dkey]
                        except:
                            pass
                        # else:
                        #     if val != fval:
                        #         print "WARNING, key -",dkey,"- defined twice in",fname
                        #         print "         previous value :",val," new value",fval
                        self.data[dkey]=fval
                fin.close
            except:
                print("File "+fname+" not found.")
                print("Creating empty parameter list\n")

        #---------------------------------------------------------------------------
        def build_default(self,default_list):
            """ build the default parameter dictionary

            used in standard actions,
            returns a dictionary built from the default parmaters (see do_default.py and Param/*)
            and the additional parameters defined in the optionnal p_in_arg overwrite the default values

            """
    #        from NPK import NPK_PATH
    #        base = os.path.join(NPK_PATH,"Param")
            from . import Generic
            base = os.path.join( os.path.dirname(Generic.__file__),"Param")
            for l in default_list:
                self.load( os.path.join(base,l) +".gtb" )
    #            for i in pp.keys():
    #                self[i]=pp[i]
        #---------------------------------------------------------------------------
        def change_key(self,patternOut, patternIn):
            """
            goes though the given dictionnay (which remains unchanged)
            and changes in keys the pattern "patternIn" to "patternOut"
            and returns the modified dictionnary

            typically used in 3D processing :

            p_in.change_key('f1', 'f2').change_key('f2', 'f3')

                substitutes F2 (of the 3D) by F1 (of the 2D plane)
                substitutes F3 (of the 3D) by F2 (of the 2D plane)

            """
            import re
            verbose = 0
            if verbose: print("change_key\n", patternIn,patternOut, self)
            p = NPKParam()
            if (len(self)>0):
                for i in self.keys():
                    j=re.sub(patternIn,patternOut,i)
                    try:
                        p[j]=self.raw(i)        # we want raw() values
                    except:
                        p[j]=self[i]
            if verbose:
                print(p)
                raise Exception("stop due to verbose mode")
            return p

    # if launched with
    # NPK -e Param.py

    if (__name__ == "__main__"):
      import math
      p=NPKParam()
      p["a"]="pa"
      p["b"]="1k"
      p["c"]="math.pi"
      p["d"]="2*3*4"
      for i in p.keys():
          print(i,":",p[i],type(p[i]))