| Home | Trees | Indices | Help |
|---|
|
|
1 # -*- coding: UTF-8 -*- 2 # 3 # Copyright (C) 2008-2010 Yung-Yu Chen <yyc@solvcon.net>. 4 # 5 # This program is free software; you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License as published by 7 # the Free Software Foundation; either version 2 of the License, or 8 # (at your option) any later version. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public License along 16 # with this program; if not, write to the Free Software Foundation, Inc., 17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 19 """ 20 Core I/O facilities for SOLVCON intrinsic constructs. 21 """ 22 23 from ..gendata import SingleAssignDict, AttributeDict26 """ 27 Registry for a certain class of formats. 28 """3430 name = ftype.__name__ 31 rev = ftype.FORMAT_REV 32 self[name] = self[rev] = ftype 33 return ftype36 """ 37 Sum the length of all META_ entries of bases and derived classes; only 38 collect from 1 level of parents. 39 """5641 mldict = dict() 42 # collect length from base classes. later overrides former. 43 # NOTE: only 1 level of parents is considered. 44 for base in bases: 45 for key in base.__dict__: 46 if key.startswith('META_'): 47 mldict[key] = len(getattr(base, key)) 48 # collect length from derived class, and override bases. 49 for key in namespace: 50 if key.startswith('META_'): 51 mldict[key] = len(namespace[key]) 52 # sum them all. 53 namespace['meta_length'] = sum([mldict[k] for k in mldict]) 54 # recreate and return the class. 55 return super(FormatMeta, cls).__new__(cls, name, bases, namespace)58 """ 59 Abstract class for SOLVCON intrinsic I/O format Each of the concrete 60 derived classes represents a version of format. Public interface method is 61 read_meta(). read_meta() method uses _parse_meta() private method to 62 report the meta-data of the format, which is defined in META_* class 63 attributes (as tuples). The default _parse_meta() and _save_meta() use 64 SPEC_OF_META to determine the order and converter the each field of the 65 META section. 66 67 The supported intrisic formats must consist of two parts: (i) text part and 68 (ii) binary part. Compression is OK for the binary part. The text part 69 starts at the beginneg of the file and ends after BINARY_MARKER, which the 70 binary part starts after BINARY_MARKER and ends with the file. 71 72 @cvar READ_BLOCK: length per reading from file. 73 @ctype READ_BLOCK: int 74 @cvar FILE_HEADER: header of the format; must be overridden. 75 @ctype FILE_HEADER: str 76 @cvar BINARY_MARKER: a string to mark the starting of binary data. 77 @ctype BINARY_MARKER: str 78 @cvar FORMAT_REV: revision of format; must be overridden. 79 @ctype FORMAT_REV: str 80 @cvar SPEC_OF_META: the order and converter of each meta-data section 81 occured in the text part; must be overridden. 82 @ctype SPEC_OF_META: tuple of (str, callable) 83 84 @cvar meta_length: length of all META_ entries; calculated by FormatMeta. 85 @ctype meta_length: int 86 """ 87 88 __metaclass__ = FormatMeta 89 90 READ_BLOCK = 1024 91 FILE_HEADER = None 92 BINARY_MARKER = '-*- start of binary data -*-' 93 FORMAT_REV = None 94 SPEC_OF_META = None 95240 249 fioregy = FormatIORegistry() # registry singleton.97 """ 98 Read meta-data from stream. 99 100 @param stream: file object or file name to be read. 101 @type stream: file or str 102 @return: meta-data, raw text lines of meta-data, and the length of 103 meta-data in bytes. 104 @rtype: solvcon.gendata.AttributeDict 105 """ 106 return self._parse_meta(self._get_textpart(stream)[0])107 108 ############################################################################ 109 # Facilities for writing. 110 ############################################################################ 111 @staticmethod113 """ 114 @param compressor: how to compress data arrays. 115 @type compressor: str 116 @param arr: the array to be written. 117 @type arr: numpy.ndarray 118 @param stream: output stream. 119 @type stream: file 120 @return: nothing. 121 """ 122 import bz2, zlib, struct 123 if compressor == 'bz2': 124 data = bz2.compress(arr.data, 9) 125 stream.write(struct.pack('q', len(data))) 126 elif compressor == 'gz': 127 data = zlib.compress(arr.data, 9) 128 stream.write(struct.pack('q', len(data))) 129 else: 130 data = arr.data 131 stream.write(data)132 ############################################################################ 133 # Facilities for reading. 134 ############################################################################ 135 @classmethod137 """ 138 Retrieve the text part from the stream. 139 140 @param stream: input stream. 141 @type stream: file 142 @return: text lines and length of text part (including separator). 143 @rtype: tuple 144 """ 145 buf = '' 146 while cls.BINARY_MARKER not in buf: 147 buf += stream.read(cls.READ_BLOCK) 148 buf = buf.split(cls.BINARY_MARKER)[0] 149 lines = buf.split('\n')[:-1] 150 textlen = len(buf) + len(cls.BINARY_MARKER) + 1 151 # assert text format. 152 assert lines[0].strip()[:3] == '-*-' 153 assert lines[0].strip()[-3:] == '-*-' 154 # assert text end location. 155 stream.seek(0) 156 assert stream.read(textlen)[-1] == '\n' 157 stream.seek(0) 158 return lines, textlen159 @classmethod161 """ 162 Parse meta information from the file. 163 164 @param lines: text part of the file. 165 @type lines: list 166 @return: meta information dictionary. 167 @rtype: solvcon.gendata.AttributeDict 168 """ 169 import numpy as np 170 from ..gendata import AttributeDict 171 meta = AttributeDict() 172 end = 1 173 for mname, mfunc in cls.SPEC_OF_META: 174 # skip everything after the first section with None converter. 175 if mfunc == None: break 176 # process. 177 msec = getattr(cls, 'META_'+mname) 178 begin = end 179 end = begin + len(msec) 180 for line in lines[begin:end]: 181 key, val = [to.strip() for to in line.split('=')] 182 try: 183 meta[key] = mfunc(val) 184 except ValueError: 185 meta[key] = None 186 return meta187 @staticmethod189 """ 190 Read data from the input stream and convert it to ndarray with given 191 shape and dtype. 192 193 @param compressor: how to compress data arrays. 194 @type compressor: str 195 @param shape: ndarray shape. 196 @type shape: tuple 197 @param dtype: ndarray dtype. 198 @type dtype: numpy.dtype or str 199 @param stream: input stream. 200 @type stream: file 201 @keyword seek_only: do not really read, only seek; default False. 202 @type seek_only: bool 203 @return: resulted array. 204 @rtype: numpy.ndarray 205 """ 206 import bz2 207 import zlib 208 import numpy as np 209 length = shape[0] 210 for dim in shape[1:]: 211 length *= dim 212 if isinstance(dtype, basestring): 213 dtype = getattr(np, dtype) 214 dobj = dtype() 215 if compressor == 'bz2': 216 buflen = np.frombuffer(stream.read(8), dtype=np.int64)[0] 217 if seek_only: 218 stream.seek(stream.tell() + buflen) 219 else: 220 buf = stream.read(buflen) 221 buf = bz2.decompress(buf) 222 elif compressor == 'gz': 223 buflen = np.frombuffer(stream.read(8), dtype=np.int64)[0] 224 if seek_only: 225 stream.seek(stream.tell() + buflen) 226 else: 227 buf = stream.read(buflen) 228 buf = zlib.decompress(buf) 229 else: 230 buflen = length * dobj.itemsize 231 if seek_only: 232 stream.seek(stream.tell() + buflen) 233 else: 234 buf = stream.read(buflen) 235 if seek_only: 236 arr = None 237 else: 238 arr = np.frombuffer(buf, dtype=dtype).reshape(shape).copy() 239 return arr251 """ 252 Metaclass for FormatIO. 253 """280255 # recreate the class. 256 newcls = super(FormatIOMeta, cls).__new__( 257 cls, name, bases, namespace) 258 # register. 259 fioregy.register(newcls) 260 return newcls281 ################################################################################ 282 # Utility 283 ################################################################################ 284 -def strbool(val):285 """ 286 Create bool object from string. None is returned if input is not 287 derterminable. 288 289 @param val: the string to check. 290 @type val: str 291 @return: True/False/None. 292 @rtype: bool 293 """ 294 try: 295 return bool(int(val)) 296 except: 297 val = val.lower() 298 if val == 'true' or val == 'on': 299 return True 300 elif val == 'false' or val == 'off': 301 return False 302 else: 303 return None304
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Thu Aug 11 23:04:51 2011 | http://epydoc.sourceforge.net |