meshRW 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
meshRW/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = '1.0.0'
meshRW/configMESH.py ADDED
@@ -0,0 +1,22 @@
1
+ """
2
+ This file contains the default
3
+ declaration of the keywords
4
+ used to declare/manipulate a mesh in Python
5
+ ----
6
+ Luc Laurent - luc.laurent@lecnam.net -- 2021
7
+ """
8
+
9
+ DFLT_MESH = 'connectivity'
10
+ DFLT_TYPE_ELEM = 'type'
11
+ DFLT_PHYS_GRP = 'physgrp'
12
+ DFLT_FIELD_DATA = 'data'
13
+ DFLT_FIELD_TYPE = 'type'
14
+ DFLT_FIELD_TYPE_NODAL = 'nodal'
15
+ DFLT_FIELD_TYPE_ELEMENT = 'elemental'
16
+ DFLT_FIELD_TYPE_NODAL_SCALAR = 'nodal_scalar'
17
+ DFLT_FIELD_TYPE_ELEMENT_SCALAR = 'elemental_scalar'
18
+ DFLT_FIELD_DIM = 'dim'
19
+ DFLT_FIELD_NAME = 'name'
20
+ DFLT_FIELD_STEPS = 'steps'
21
+ DFLT_FIELD_NBSTEPS = 'nbsteps'
22
+ DFLT_FIELD_NUMENTITIES = 'numentities'
meshRW/dbmsh.py ADDED
@@ -0,0 +1,172 @@
1
+ """ "
2
+ This file includes the definition
3
+ and tools to manipulate MSH format
4
+ Documentation available here:
5
+ https://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format
6
+ ----
7
+ Luc Laurent - luc.laurent@lecnam.net -- 2021
8
+
9
+ """
10
+
11
+ from loguru import logger as Logger
12
+
13
+
14
+ def loadElementDict():
15
+ """
16
+ dictionary from element (string) to msh element number
17
+ """
18
+ elementDict = {
19
+ # 2-nodes line
20
+ 'LIN2': {'code': 1, 'nodes': 2, 'dim': 1},
21
+ # 3-nodes second order line
22
+ 'LIN3': {'code': 8, 'nodes': 3, 'dim': 1},
23
+ # 4-nodes third order line
24
+ 'LIN4': None,
25
+ # 3-nodes triangle
26
+ 'TRI3': {'code': 2, 'nodes': 3, 'dim': 2},
27
+ # 6-nodes second order triangle (3 vertices, 3 on edges)
28
+ 'TRI6': {'code': 9, 'nodes': 6, 'dim': 2},
29
+ # 9-nodes cubic order triangle (3 vertices, 3 on edges and 3 inside)
30
+ 'TRI9': None,
31
+ # 10-nodes higher order triangle (3 vertices, 6 on edges and 1 inside)
32
+ 'TRI10': None,
33
+ # 12-nodes higher order triangle (3 vertices and 9 on edges)
34
+ 'TRI12': None,
35
+ # 15-nodes higher order triangle (3 vertices, 9 on edges and 3 inside)
36
+ 'TRI15': None,
37
+ # 4-nodes quadrangle
38
+ 'QUA4': {'code': 3, 'nodes': 4, 'dim': 2},
39
+ # 8-nodes second order quadrangle (4 vertices and 4 on edges)
40
+ 'QUA8': {'code': 16, 'nodes': 8, 'dim': 2},
41
+ # 9-nodes higher order quadrangle (4 vertices, 4 on edges and 1 inside)
42
+ 'QUA9': {'code': 10, 'nodes': 9, 'dim': 2},
43
+ # 4-nodes tetrahedron
44
+ 'TET4': {'code': 4, 'nodes': 4, 'dim': 3},
45
+ # 10-nodes second order tetrahedron (4 vertices and 6 on edges)
46
+ 'TET10': {'code': 11, 'nodes': 10, 'dim': 3},
47
+ # 8-nodes hexahedron
48
+ 'HEX8': {'code': 5, 'nodes': 8, 'dim': 3},
49
+ # 20-nodes second order hexahedron (8 vertices and 12 on edges)
50
+ 'HEX20': {'code': 17, 'nodes': 20, 'dim': 3},
51
+ # 27-nodes higher order hexahedron
52
+ # (8 vertices, 12 on edges, 6 on faces and 1 inside)
53
+ 'HEX27': {'code': 12, 'nodes': 27, 'dim': 3},
54
+ # 6-nodes prism
55
+ 'PRI6': {'code': 6, 'nodes': 6, 'dim': 3},
56
+ # 15-nodes second order prism (6 vertices and 9 on edges)
57
+ 'PRI15': {'code': 18, 'nodes': 15, 'dim': 3},
58
+ # 18-nodes higher order prism (6 vertices, 9 on edges and 3 on faces)
59
+ 'PRI18': {'code': 13, 'nodes': 18, 'dim': 3},
60
+ # 5-node pyramid
61
+ 'PYR5': {'code': 7, 'nodes': 5, 'dim': 3},
62
+ # 13-nodes second order pyramid (5 edges and 8 on edges)
63
+ 'PYR13': {'code': 19, 'nodes': 13, 'dim': 3},
64
+ # 14-nodes higher order pyramid (5 edges, 8 on edges and 1 inside)
65
+ 'PYR14': {'code': 14, 'nodes': 14, 'dim': 3},
66
+ # 1-node point
67
+ 'NOD1': {'code': 15, 'nodes': 1, 'dim': 0},
68
+ }
69
+ return elementDict
70
+
71
+
72
+ def getMSHElemType(txtEltype):
73
+ """
74
+ Get the element type defined as in gmsh (refer to gmsh documentation for numbering) from text declaration
75
+ syntax:
76
+ getMshElemType(txtEltype)
77
+
78
+ input:
79
+ txtEltype: element declared using string (if number is used the function will return it)
80
+ output:
81
+ element type defined as gmsh number
82
+ """
83
+ elementDict = loadElementDict()
84
+
85
+ # depending on the type of txtEltype
86
+ # - if int: return txtEltype
87
+ # - else get the number from the dictionary
88
+ if isinstance(txtEltype, int):
89
+ elementNum = txtEltype
90
+ else:
91
+ elementNum = elementDict[txtEltype.upper()].get('code', None)
92
+ # show error if the type is not available
93
+ if not elementNum:
94
+ Logger.error(f'Element type {txtEltype} not implemented')
95
+ return elementNum
96
+
97
+
98
+ def getElemTypeFromMSH(elementNum):
99
+ """
100
+ Get the element type from id (integer) defined in gmsh (refer to gmsh documentation for numbering)
101
+ syntax:
102
+ getElemTypeFromMSH(elementNum)
103
+
104
+ input:
105
+ elementNum: integer used in gmsh to declare element
106
+ output:
107
+ global name of the element
108
+ """
109
+ # load the dictionary
110
+ elementDict = loadElementDict()
111
+ globalName = None
112
+ # get the name of the element using the integer iD along the dictionary
113
+ for k, v in elementDict.items():
114
+ if v:
115
+ if v.get('code', None) == elementNum:
116
+ globalName = k
117
+ break
118
+ # if the name of the element if not available show error
119
+ if globalName is None:
120
+ Logger.error(f'Element type not found with id {elementNum}')
121
+ return globalName
122
+
123
+
124
+ def getNumberNodes(txtElemtype):
125
+ """
126
+ Get the number of nodes for a specific element type type (declare as string)
127
+ syntax:
128
+ getNumberNodes(txtElemtype)
129
+
130
+ input:
131
+ txtElemtype: element declared using string (if number is used the function wil return it)
132
+ output:
133
+ number of nodes for txtEltype
134
+ """
135
+ # load the dictionary
136
+ elementDict = loadElementDict()
137
+ nbNodes = 0
138
+ # check if the type of element exists
139
+ if txtElemtype in elementDict.keys():
140
+ # get the number of nodes for the type of element
141
+ if elementDict[txtElemtype]:
142
+ nbNodes = elementDict[txtElemtype].get('nodes', None)
143
+ else:
144
+ # show error message if the type of element does not exist
145
+ Logger.error(f'Element type {txtElemtype} not defined')
146
+ return nbNodes
147
+
148
+
149
+ def getNumberNodesFromNum(elementNum):
150
+ """
151
+ Get the number of nodfs for a specific element type type (declare as string)
152
+ syntax:
153
+ getNumberNodesFromNum(elementNum)
154
+
155
+ input:
156
+ elementNum: integer used in gmsh to declare element
157
+ output:
158
+ number of nodes for txtEltype
159
+ """
160
+ return getNumberNodes(getElemTypeFromMSH(elementNum))
161
+
162
+
163
+ # DEFAULT VALUES
164
+ ALLOWED_EXTENSIONS = ['.msh', '.msh.bz2', '.msh.gz']
165
+
166
+ # Keywords MSH
167
+ DFLT_FILE_OPEN_CLOSE = {'open': '$MeshFormat', 'close': '$EndMeshFormat'}
168
+ DFLT_FILE_VERSION = '2.2 0 8'
169
+ DFLT_NODES_OPEN_CLOSE = {'open': '$Nodes', 'close': '$EndNodes'}
170
+ DFLT_ELEMS_OPEN_CLOSE = {'open': '$Elements', 'close': '$EndElements'}
171
+ DFLT_FIELDS_NODES_OPEN_CLOSE = {'open': '$NodeData', 'close': '$EndNodeData'}
172
+ DFLT_FIELDS_ELEMS_OPEN_CLOSE = {'open': '$ElementData', 'close': '$EndElementData'}
meshRW/dbvtk.py ADDED
@@ -0,0 +1,261 @@
1
+ """ "
2
+ This file includes the definition and tools to manipulate MSH format
3
+ Documentation available here: https://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format
4
+ ----
5
+ Luc Laurent - luc.laurent@lecnam.net -- 2021
6
+
7
+ """
8
+
9
+ import vtk
10
+ from loguru import logger as Logger
11
+
12
+
13
+ def loadElementDict():
14
+ """
15
+ dictionary from element (string) to VTK number
16
+ """
17
+ elementDict = {
18
+ # 2-nodes line
19
+ 'LIN2': {'code': 3, 'nodes': 2, 'dim': 1, 'vtkobj': vtk.vtkLine()},
20
+ # 3-nodes second order line
21
+ 'LIN3': {'code': 21, 'nodes': 3, 'dim': 1, 'vtkobj': vtk.vtkQuadraticEdge()},
22
+ # 4-nodes third order line
23
+ 'LIN4': None,
24
+ # 3-nodes triangle
25
+ 'TRI3': {'code': 5, 'nodes': 3, 'dim': 2, 'vtkobj': vtk.vtkTriangle()},
26
+ # 6-nodes second order triangle (3 vertices, 3 on edges)
27
+ 'TRI6': {'code': 22, 'nodes': 6, 'dim': 2, 'vtkobj': vtk.vtkQuadraticTriangle()},
28
+ # 9-nodes cubic order triangle (3 vertices, 3 on edges and 3 inside)
29
+ 'TRI9': None,
30
+ # 10-nodes higher order triangle (3 vertices, 6 on edges and 1 inside)
31
+ 'TRI10': None,
32
+ # 12-nodes higher order triangle (3 vertices and 9 on edges)
33
+ 'TRI12': None,
34
+ # 15-nodes higher order triangle (3 vertices, 9 on edges and 3 inside)
35
+ 'TRI15': None,
36
+ # 4-nodes quadrangle
37
+ 'QUA4': {'code': 9, 'nodes': 4, 'dim': 2, 'vtkobj': vtk.vtkQuad()},
38
+ # 8-nodes second order quadrangle (4 vertices and 4 on edges)
39
+ 'QUA8': {'code': 23, 'nodes': 8, 'dim': 2, 'vtkobj': vtk.vtkQuadraticQuad()},
40
+ # 9-nodes higher order quadrangle (4 vertices, 4 on edges and 1 inside)
41
+ 'QUA9': None,
42
+ # 4-nodes tetrahedron
43
+ 'TET4': {'code': 10, 'nodes': 4, 'dim': 3, 'vtkobj': vtk.vtkTetra()},
44
+ # 10-nodes second order tetrahedron (4 vertices and 6 on edges)
45
+ 'TET10': {'code': 24, 'nodes': 10, 'dim': 3, 'vtkobj': vtk.vtkQuadraticTetra()},
46
+ # 8-nodes hexahedron
47
+ 'HEX8': {'code': 12, 'nodes': 8, 'dim': 3, 'vtkobj': vtk.vtkHexahedron()},
48
+ # 20-nodes second order hexahedron (8 vertices and 12 on edges)
49
+ 'HEX20': {'code': 25, 'nodes': 20, 'dim': 3, 'vtkobj': vtk.vtkQuadraticHexahedron()},
50
+ # 27-nodes higher order hexahedron (8 vertices,
51
+ # 12 on edges, 6 on faces and 1 inside)
52
+ 'HEX27': None,
53
+ # 6-nodes prism
54
+ 'PRI6': {'code': 13, 'nodes': 6, 'dim': 3, 'vtkobj': vtk.vtkWedge()},
55
+ # 15-nodes second order prism (6 vertices and 9 on edges)
56
+ 'PRI15': None,
57
+ # 18-nodes higher order prism (6 vertices, 9 on edges and 3 on faces)
58
+ 'PRI18': None,
59
+ # 5-node pyramid
60
+ 'PYR5': {'code': 14, 'nodes': 5, 'dim': 3, 'vtkobj': vtk.vtkPyramid()},
61
+ # 13-nodes second order pyramid (5 edges and 8 on edges)
62
+ 'PYR13': None,
63
+ # 14-nodes higher order pyramid (5 edges, 8 on edges and 1 inside)
64
+ 'PYR14': None,
65
+ # 1-node point
66
+ 'NOD1': {'code': 1, 'nodes': 1, 'dim': 0, 'vtkobj': vtk.vtkVertex()},
67
+ #
68
+ # many nodes
69
+ 'NODN': {'code': 2, 'nodes': -1, 'dim': 0, 'vtkobj': vtk.vtkPolyVertex()},
70
+ # many lines (poly-lines)
71
+ 'LINEN': {'code': 4, 'nodes': -1, 'dim': 1, 'vtkobj': vtk.vtkPolyLine()},
72
+ # many stripped triangles
73
+ 'TRIN': {'code': 6, 'nodes': -1, 'dim': 2, 'vtkobj': vtk.vtkTriangleStrip()},
74
+ # polygons
75
+ 'POLY': {'code': 7, 'nodes': -1, 'dim': 2, 'vtkobj': vtk.vtkPolygon()},
76
+ # pixel
77
+ 'PIXEL': {'code': 8, 'nodes': -1, 'dim': 2, 'vtkobj': vtk.vtkPixel()},
78
+ # voxel
79
+ 'VOXEL': {'code': 11, 'nodes': -1, 'dim': 3, 'vtkobj': vtk.vtkVoxel()},
80
+ }
81
+ return elementDict
82
+
83
+
84
+ def getVTKtoElem():
85
+ """
86
+ dictionary from VTK element to name of element (string)
87
+ """
88
+ VTKtoElem = {
89
+ 'VTK_VERTEX': 'NOD1',
90
+ 'VTK_LINE': 'LIN2',
91
+ 'VTK_TRIANGLE': 'TRI3',
92
+ 'VTK_QUAD': 'QUAD4',
93
+ 'VTK_TETRA': 'TET4',
94
+ 'VTK_HEXAHEDRON': 'HEX8',
95
+ 'VTK_WEDGE': 'PRI6',
96
+ 'VTK_PYRAMID': 'PYR5',
97
+ 'VTK_QUADRATIC_EDGE': 'LIN3',
98
+ 'VTK_QUADRATIC_TRIANGLE': 'TRI6',
99
+ 'VTK_QUADRATIC_QUAD': 'QUA8',
100
+ 'VTK_QUADRATIC_TETRA': 'TET10',
101
+ 'VTK_QUADRATIC_HEXAHEDRON': 'HEX20',
102
+ #
103
+ 'VTK_POLY_VERTEX': 'NODN',
104
+ 'VTK_POLY_LINE': 'LINEN',
105
+ 'VTK_TRIANGLE_STRIP': 'TRIN',
106
+ 'VTK_POLYGON': 'POLY',
107
+ 'VTK_PIXEL': 'PIXEL',
108
+ 'VTK_VOXEL': 'VOXEL',
109
+ }
110
+ return VTKtoElem
111
+
112
+
113
+ def getVTKObj(txtEltype):
114
+ """
115
+ Get the vtk class from libvtk from text declaration
116
+ syntax:
117
+ getVTKEObjType(txtEltype)
118
+
119
+ input:
120
+ txtEltype: element declared using VTK string (if number is used the function wil return it)
121
+ output:
122
+ vtk class for the requested element
123
+ number of nodes on element
124
+ """
125
+
126
+ VTKtoElem = getVTKtoElem()
127
+ elementDict = loadElementDict()
128
+
129
+ # depending on the type of txtEltype
130
+ numPerElement = -1
131
+ if txtEltype.upper() in VTKtoElem.keys():
132
+ txtEltype = VTKtoElem[txtEltype]
133
+ vtkobj = elementDict[txtEltype.upper()].get('vtkobj', None)
134
+ numPerElement = getNumberNodes(txtEltype.upper())
135
+ if not vtkobj:
136
+ Logger.error(f'Element type {txtEltype} not implemented')
137
+ return vtkobj, numPerElement
138
+
139
+
140
+ def getVTKElemType(txtEltype):
141
+ """
142
+ Get the element type defined as in vtk (refer to VTK documentation for numbering) from text declaration
143
+ syntax:
144
+ getVTKElemType(txtEltype)
145
+
146
+ input:
147
+ txtEltype: element declared using VTK string (if number is used the function wil return it)
148
+ output:
149
+ element type defined as VTK number
150
+ """
151
+
152
+ VTKtoElem = getVTKtoElem()
153
+ elementDict = loadElementDict()
154
+
155
+ # depending on the type of txtEltype
156
+ numPerElement = -1
157
+ if isinstance(txtEltype, int):
158
+ elementNum = txtEltype
159
+ else:
160
+ if txtEltype.upper() in VTKtoElem.keys():
161
+ txtEltype = VTKtoElem[txtEltype]
162
+ elementNum = elementDict[txtEltype.upper()].get('code', None)
163
+ numPerElement = getNumberNodes(txtEltype.upper())
164
+ if not elementNum:
165
+ Logger.error(f'Element type {txtEltype} not implemented')
166
+ return elementNum, numPerElement
167
+
168
+
169
+ def getElemTypeFromVTK(elementNum):
170
+ """
171
+ Get the element type from id (integer) defined in gmsh (refer to gmsh documentation for numbering)
172
+ syntax:
173
+ getElemTypeFromVTK(elementNum)
174
+
175
+ input:
176
+ elementNum: integer used in gmsh to declare element
177
+ output:
178
+ global name of the element
179
+ """
180
+ # load the dictionary
181
+ elementDict = loadElementDict()
182
+ globalName = None
183
+ # get the name of the element using the integer iD along the dictionary
184
+ for k, v in elementDict.items():
185
+ if v:
186
+ if v.get('code', None) == elementNum:
187
+ globalName = k
188
+ break
189
+ # if the name of the element if not available show error
190
+ if globalName is None:
191
+ Logger.error(f'Element type not found with id {elementNum}')
192
+ return globalName
193
+
194
+
195
+ def getNumberNodes(txtElemtype):
196
+ """
197
+ Get the number of nodes for a specific element type type (declare as string)
198
+ syntax:
199
+ getNumberNodes(txtElemtype)
200
+
201
+ input:
202
+ txtElemtype: element declared using string (if number is used the function wil return it)
203
+ output:
204
+ number of nodes for txtEltype
205
+ """
206
+
207
+ elementDict = loadElementDict()
208
+ # check if the type of element exists
209
+ if txtElemtype in elementDict.keys():
210
+ # get the number of nodes for the type of element
211
+ if elementDict[txtElemtype]:
212
+ nbNodes = elementDict[txtElemtype].get('nodes', None)
213
+ else:
214
+ # show error message if the type of element does not exist
215
+ Logger.error(f'Element type {txtElemtype} not defined')
216
+ return nbNodes
217
+
218
+
219
+ def getNumberNodesFromNum(elementNum):
220
+ """
221
+ Get the number of nodfs for a specific element type type (declare as string)
222
+ syntax:
223
+ getNumberNodesFromNum(elementNum)
224
+
225
+ input:
226
+ elementNum: integer used in gmsh to declare element
227
+ output:
228
+ number of nodes for txtEltype
229
+ """
230
+
231
+ return getNumberNodes(getElemTypeFromVTK(elementNum))
232
+
233
+
234
+ # DEFAULT VALUES
235
+ ALLOWED_EXTENSIONS = [
236
+ '.vtk',
237
+ '.vtk.bz2',
238
+ '.vtk.gz',
239
+ '.vtu',
240
+ '.vtu.bz2',
241
+ '.vtu.gz',
242
+ ]
243
+
244
+
245
+ # Keywords MSH
246
+ DFLT_HEADER_VERSION = '# vtk DataFile Version 2.0'
247
+ DFLT_TYPE_ASCII = 'ASCII'
248
+ DFLT_FILE_VERSION = '2.2 0 8'
249
+ DFLT_TYPE_MESH = 'DATASET UNSTRUCTURED_GRID'
250
+ DFLT_NODES = 'POINTS'
251
+ DFLT_NODES_DATA = 'POINT_DATA'
252
+ DFLT_DOUBLE = 'double'
253
+ DFLT_FLOAT = 'float'
254
+ DFLT_INT = 'int'
255
+ DFLT_ELEMS = 'CELLS'
256
+ DFLT_ELEMS_TYPE = 'CELL_TYPES'
257
+ DFLT_ELEMS_DATA = 'CELL_DATA'
258
+ DFLT_FIELD = 'FIELD'
259
+ DFLT_SCALARS = 'SCALARS'
260
+ DFLT_TABLE = 'LOOKUP_TABLE'
261
+ DFLT_TABLE_DEFAULT = 'default'
meshRW/fileio.py ADDED
@@ -0,0 +1,141 @@
1
+ """
2
+ This file includes the definition and tools to manipulate files
3
+ ----
4
+ Luc Laurent - luc.laurent@lecnam.net -- 2021
5
+ """
6
+
7
+ import time
8
+ from pathlib import Path
9
+
10
+ from loguru import logger as Logger
11
+
12
+ from . import various
13
+
14
+
15
+ class fileHandler:
16
+ def __init__(self, filename=None, append=None, right='w', gz=False, bz2=False, safeMode=False):
17
+ """
18
+ create the class
19
+ arguments:
20
+ - filename: name of the file to open
21
+ - append: append to existing file (override 'right')
22
+ - right: specific right when open the file ('r','a','w'...)
23
+ - gz: on the fly compress file with gunzip
24
+ - bz2: on the fly compress file with bunzip2
25
+ - safeMode: avoid overwritten
26
+ """
27
+ self.filename = None
28
+ self.dirname = None
29
+ self.fhandle = None
30
+ self.right = right
31
+ self.append = None
32
+ self.compress = None
33
+ self.startTime = 0
34
+ #
35
+ self.fixRight(append=append, right=right)
36
+
37
+ # check arguments
38
+ checkOk = True
39
+ if not filename:
40
+ checkOk = False
41
+ Logger.error('Filename argument missing')
42
+ if not right and not append:
43
+ checkOk = False
44
+ Logger.error('Right(s) not provided')
45
+ # load the filename
46
+ self.getFilename(Path(filename), gz, bz2)
47
+ # open the file
48
+ self.open(safeMode)
49
+
50
+ def getFilename(self, filename, gz=None, bz2=None):
51
+ """
52
+ Load the right filename
53
+ """
54
+ self.compress = None
55
+ # check extension for compression
56
+ if filename.suffix == '.gz':
57
+ self.compress = 'gz'
58
+ elif filename.suffix == '.bz2':
59
+ self.compress = 'bz2'
60
+ elif gz:
61
+ filename.with_suffix(filename.suffix + '.gz')
62
+ self.compress = 'gz'
63
+ elif bz2:
64
+ filename.with_suffix(filename.suffix + '.bz2')
65
+ self.compress = 'bz2'
66
+ # extract information about filename
67
+ self.basename = filename.name
68
+ self.dirname = filename.absolute().parent
69
+ self.filename = filename
70
+
71
+ def open(self, safeMode=False):
72
+ """
73
+ Open the file w/- or W/o safe mode (avoid overwrite existing file
74
+ """
75
+ # adapt the rights (in case of the file does not exist)
76
+ if self.append and self.filename.exists():
77
+ Logger.warning(f'{self.basename} does not exist! Unable to append')
78
+ self.fixRight(append=False)
79
+ if not safeMode and self.filename.exists() and not self.append and 'w' in self.right:
80
+ Logger.warning(f'{self.basename} already exists! It will be overwritten')
81
+ if safeMode and self.filename.exists() and not self.append and 'w' in self.right:
82
+ Logger.warning(f'{self.basename} already exists! Not overwrite it')
83
+ else:
84
+ #
85
+ Logger.debug(f'Open {self.basename} in {self.dirname} with right {self.right}')
86
+ # open file
87
+ if self.compress == 'gz':
88
+ Logger.debug('Use GZ lib')
89
+ import gzip
90
+
91
+ self.fhandle = gzip.open(self.filename, self.right)
92
+ elif self.compress == 'bz2':
93
+ Logger.debug('Use BZ2 lib')
94
+ import bz2
95
+
96
+ self.fhandle = bz2.open(self.filename, self.right)
97
+ else:
98
+ self.fhandle = open(self.filename, self.right)
99
+ # store timestamp at opening
100
+ self.startTime = time.perf_counter()
101
+ return self.fhandle
102
+
103
+ def close(self):
104
+ """
105
+ Close openned file
106
+ """
107
+ if self.fhandle:
108
+ self.fhandle.close()
109
+ self.fhandle = None
110
+ Logger.info(
111
+ f'Close file {self.basename} with elapsed time {time.perf_counter()-self.startTime:g}s - size {various.convert_size(self.filename.stat().st_size)}'
112
+ )
113
+
114
+ def getHandler(self):
115
+ """
116
+ get the file handler
117
+ """
118
+ return self.fhandle
119
+
120
+ def write(self, txt):
121
+ """
122
+ write in the file using handle
123
+ """
124
+ return self.fhandle.write(txt)
125
+
126
+ def fixRight(self, append=None, right=None):
127
+ """
128
+ Fix issue on right to write file
129
+ """
130
+ if append is not None:
131
+ self.append = append
132
+ if append:
133
+ self.right = 'a'
134
+ else:
135
+ self.right = 'w'
136
+ else:
137
+ self.right = right
138
+ if right[0] == 'w':
139
+ self.append = False
140
+ elif right[0] == 'a':
141
+ self.append = True