Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:48:49

0001 #!/usr/bin/env python
0002 #
0003 # Copyright (c) 2019 Opticks Team. All Rights Reserved.
0004 #
0005 # This file is part of Opticks
0006 # (see https://bitbucket.org/simoncblyth/opticks).
0007 #
0008 # Licensed under the Apache License, Version 2.0 (the "License"); 
0009 # you may not use this file except in compliance with the License.  
0010 # You may obtain a copy of the License at
0011 #
0012 #   http://www.apache.org/licenses/LICENSE-2.0
0013 #
0014 # Unless required by applicable law or agreed to in writing, software 
0015 # distributed under the License is distributed on an "AS IS" BASIS, 
0016 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
0017 # See the License for the specific language governing permissions and 
0018 # limitations under the License.
0019 #
0020 
0021 """
0022 """
0023 
0024 import numpy as np
0025 import os, logging, re
0026 from collections import OrderedDict as odict 
0027 
0028 log = logging.getLogger(__name__) 
0029 
0030 class Num(object):
0031     """
0032     ::
0033 
0034         In [19]: np.power( 10, np.arange(10) )
0035         Out[19]: array([         1,         10,        100,       1000,      10000,     100000,    1000000,   10000000,  100000000, 1000000000])
0036 
0037         In [69]: map(Num.String, a )
0038         Out[69]: ['1', '10', '100', '1k', '10k', '100k', '1M', '10M', '100M', '1B']
0039 
0040     """
0041     Ptn0 = re.compile("^(?P<nz>[\d]+?)(?P<zz>[0]*)$")   # less greedy frount ints, before contiguous zeros
0042     Ptn = re.compile("^(?P<num>\d+)(?P<unit>[kM]*)$")
0043     Units = { "":1, "k":1000, "M":1000000 } 
0044     Pow10 = None    
0045 
0046     @classmethod
0047     def OrigShape(cls, a):
0048         return a.origshape() if hasattr(a, 'origshape') else "-"
0049 
0050     @classmethod
0051     def Init(cls):
0052         r = odict()
0053         r[            "0"] = (0,"")  
0054         r[            "1"] = (1,"")  
0055         r[           "10"] = (10,"")
0056         r[          "100"] = (100,"")
0057         r[        "1,000"] = (1,"k")
0058         r[       "10,000"] = (10,"k")
0059         r[      "100,000"] = (100,"k")
0060         r[    "1,000,000"] = (1,"M")
0061         r[   "10,000,000"] = (10,"M")
0062         r[  "100,000,000"] = (100,"M")
0063         r["1,000,000,000"] = (1,"B")
0064 
0065         d = odict()
0066         for k,v in r.items():
0067             d[int(k.replace(",",""))] = v
0068         pass
0069         return d 
0070 
0071     @classmethod
0072     def Int(cls, s):
0073         """
0074         :param s: string representation of integer eg "1","10","100","1k","10k","100k","1M",...
0075         :return i: the integer
0076         """
0077         if s.find(",") > -1:
0078             ret = tuple(map(cls.Int, s.split(",")))
0079         else: 
0080             m = cls.Ptn.match(s)
0081             if m is None:
0082                 return int(s)
0083             pass
0084             d = m.groupdict() 
0085             n = int(d["num"])      
0086             u = cls.Units[d["unit"]]      
0087             i = n*u  
0088             ret = i
0089         pass
0090         return ret         
0091      
0092 
0093     @classmethod
0094     def String(cls, i):
0095         """
0096         :param i: integer or tuple of integers
0097         :return s: summary string 
0098 
0099         Summarize large power of 10 numbers to make them easy to read without counting zeros 
0100         """ 
0101         if cls.Pow10 is None: cls.Pow10 = cls.Init()
0102 
0103         if type(i) in [ int, np.int64, np.int32 ]:
0104 
0105             m0 = cls.Ptn0.match(str(i))
0106             d0 = m0.groupdict() if m0 else None
0107             if d0: 
0108                 nz = int(d0["nz"])      # integers at front of contiguous zeros
0109                 zz = int("1"+d0["zz"])  # pull out contiguous zeros to the right 
0110                 n,u = cls.Pow10[zz] 
0111                 nnz = n*nz 
0112                 ret = "%d%s" % (nnz, u)
0113             else:
0114                 ret = str(i)
0115             pass
0116             return ret   
0117 
0118         elif type(i) is tuple:
0119             ret =  ",".join( map(lambda _:cls.String(_), list(i) ))
0120         elif type(i) is type(None):
0121             ret = "-" 
0122         else:
0123             assert 0, (i, type(i)) 
0124             ret = "-"
0125         pass    
0126         return ret 
0127 
0128 
0129 
0130 slice_ = lambda s:slice(*map(lambda _:Num.Int(_) if len(_) > 0 else None,s.split(":")))                     # string to slice
0131 _slice = lambda s:":".join(map(lambda _:Num.String(_) if not _ is None else "", (s.start,s.stop,s.step)))   # slice to string
0132 
0133 
0134 def test_roundtrip():
0135     for i in [(20000000, 4, 4), 200000000, 2, 20, 30,300,3000,30000,100000,1000000,10000000,101000]:
0136         s = Num.String(i)
0137         i2 = Num.Int(s)
0138         print(" i %20r Num.String %20r Num.Int %10r   " % ( i, s, i2 )) 
0139         assert i == i2, ( i, s, i2)
0140     pass
0141 
0142 
0143 
0144 
0145 if __name__ == '__main__':
0146     pass
0147     test_roundtrip()
0148 
0149