ialdev-io 0.1.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.
- iad/io/__init__.py +17 -0
- iad/io/basic_formats.py +98 -0
- iad/io/bit_streams.py +98 -0
- iad/io/ciif.py +852 -0
- iad/io/format.py +678 -0
- iad/io/imread.py +296 -0
- iad/io/imwrite.py +55 -0
- iad/io/inu/__init__.py +0 -0
- iad/io/inu/env._py +55 -0
- iad/io/inu/utils/__init__.py +0 -0
- iad/io/inu/utils/imread.py +296 -0
- iad/io/pfm.py +79 -0
- iad/io/ply.py +260 -0
- iad/io/special.py +93 -0
- iad/io/tb.py +43 -0
- iad/io/tiff_tags.py +322 -0
- iad/io/video.py +189 -0
- iad/io/zfp.py +33 -0
- ialdev_io-0.1.0.dist-info/METADATA +24 -0
- ialdev_io-0.1.0.dist-info/RECORD +21 -0
- ialdev_io-0.1.0.dist-info/WHEEL +4 -0
iad/io/ciif.py
ADDED
|
@@ -0,0 +1,852 @@
|
|
|
1
|
+
""" Operate with ciif and tif file formats."""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import re
|
|
5
|
+
import warnings
|
|
6
|
+
from ast import literal_eval
|
|
7
|
+
from functools import reduce
|
|
8
|
+
from os import path, makedirs
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import skimage.io as io
|
|
12
|
+
|
|
13
|
+
from iad.core.short import unless
|
|
14
|
+
from iad.core.logs import logger
|
|
15
|
+
from iad.core.events import TimePoints
|
|
16
|
+
|
|
17
|
+
SCHEME_DEF_LOC = r'\\bkp01\tmp\Algo\test_point\test_points_scheme.xlsx'
|
|
18
|
+
|
|
19
|
+
_TM = TimePoints(True)
|
|
20
|
+
_log = logger('io')
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def load_scheme(info_file=SCHEME_DEF_LOC, sheet_name=None) -> dict:
|
|
24
|
+
""" Load test points info excel file to the dictionary DB
|
|
25
|
+
|
|
26
|
+
:return dict: keys - test points file names (no extension)
|
|
27
|
+
values: dict with keys: ('signals', 'io', 'groups')
|
|
28
|
+
"""
|
|
29
|
+
import pandas as pd
|
|
30
|
+
|
|
31
|
+
def parse_struct(structure):
|
|
32
|
+
struc = structure.strip().split('.')
|
|
33
|
+
comp = struc[0] if struc else None # dpe, ppr, …
|
|
34
|
+
block = struc[1] if struc and (len(struc) > 1) else None # agg, unite, opt
|
|
35
|
+
view = struc[2] if struc and (len(struc) > 2) and (struc[2] in ['left', 'right']) else None # # left|right
|
|
36
|
+
tp_name = '.'.join([w for w in struc if w not in [comp, block, view]])
|
|
37
|
+
return comp, block, view, tp_name
|
|
38
|
+
|
|
39
|
+
def parse_bits(str_format, total_length):
|
|
40
|
+
bits = [int(s) for s in re.split('[^\d]+', str_format.strip())]
|
|
41
|
+
bits_in_group = sum(bits)
|
|
42
|
+
|
|
43
|
+
unless(total_length % bits_in_group == 0,
|
|
44
|
+
'%d signals in ciif file %s can not be grouped by %d' % (total_length, i, bits_in_group))
|
|
45
|
+
bit_groups_num = total_length//bits_in_group
|
|
46
|
+
return bits * bit_groups_num
|
|
47
|
+
|
|
48
|
+
def index_groups(names, num, sep='_'):
|
|
49
|
+
""" Given names in a group generate for multiple groups """
|
|
50
|
+
if num == 1:
|
|
51
|
+
return names
|
|
52
|
+
return reduce(list.__add__, ([f + sep + str(gid) for f in names] for gid in range(num)))
|
|
53
|
+
|
|
54
|
+
_log.debug('reading from: %s' % path.abspath(info_file))
|
|
55
|
+
dfs = pd.read_excel(info_file, sheet_name=sheet_name, converters={'format': str})
|
|
56
|
+
columns = ['structure', 'comments', 'name', 'alias', 'signals', 'length', 'format'] # the columns we will need
|
|
57
|
+
|
|
58
|
+
df = pd.concat(dv[columns].dropna(axis='index', how='any', subset=['structure', 'name', 'signals', 'length', 'format'])
|
|
59
|
+
for dv in dfs.values()
|
|
60
|
+
if all(c in dv.columns for c in columns)) # type: pd.DataFrame
|
|
61
|
+
|
|
62
|
+
df.set_index('name', inplace=True)
|
|
63
|
+
# file_name: name
|
|
64
|
+
df.rename_axis('file_name', inplace=True)
|
|
65
|
+
|
|
66
|
+
df = df.reindex(columns=columns + ['groups', 'component', 'block', 'view', 'tp_name'])
|
|
67
|
+
df['groups'] = np.zeros((len(df), 1)) # number of groups may be useful
|
|
68
|
+
|
|
69
|
+
for i, r in df.iterrows():
|
|
70
|
+
try:
|
|
71
|
+
bits = parse_bits(r.format, int(r.length))
|
|
72
|
+
|
|
73
|
+
signals = re.split('[^\w]+', r.signals.strip())
|
|
74
|
+
sig_in_group = len(signals)
|
|
75
|
+
unless(len(bits) % sig_in_group == 0,
|
|
76
|
+
'%s signals in ciif file %s can not be grouped by %s' % (r.signals.strip(), i, r.format.strip()))
|
|
77
|
+
sig_groups_num = len(bits)//sig_in_group
|
|
78
|
+
unless(all(bits[k*sig_in_group:(k+1)*sig_in_group] == bits[0:sig_in_group] for k in range(sig_groups_num)),
|
|
79
|
+
'format in ciif file %s is not a repeating pattern of size %d' % (i, sig_in_group))
|
|
80
|
+
signals = index_groups(signals, sig_groups_num)
|
|
81
|
+
|
|
82
|
+
comp, block, view, tp_name = parse_struct(r.structure) if r.structure else None, None, None, None
|
|
83
|
+
df.loc[i, ['signals', 'format', 'groups', 'component', 'block', 'view', 'tp_name']] = \
|
|
84
|
+
signals, bits, sig_groups_num, comp, block, view, tp_name
|
|
85
|
+
except Exception as e:
|
|
86
|
+
raise Exception('TP %s descr problem in file %s: %s' % (i, info_file, e))
|
|
87
|
+
|
|
88
|
+
return df.to_dict('index')
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def load_signals(ciif_file, tp_scheme=SCHEME_DEF_LOC, out_df=False, show=False):
|
|
92
|
+
"""Load content of ciif files to dictionary according to the tp scheme.
|
|
93
|
+
High level wrapper on load_ciif.
|
|
94
|
+
|
|
95
|
+
:param ciif_file: test points - the source of the signals
|
|
96
|
+
:param tp_scheme: as excel file or as dictionary
|
|
97
|
+
:param out_df: if True - return data as pandas DataFrame
|
|
98
|
+
:param show: show additional processing information
|
|
99
|
+
:return: dict of {field_name: image_ndarray} or additional DataFrame if requested
|
|
100
|
+
"""
|
|
101
|
+
tps_db = load_scheme(info_file=tp_scheme) if isinstance(tp_scheme, str) else tp_scheme
|
|
102
|
+
|
|
103
|
+
m = re.match('(?P<name>\w+)_(0|1)_00.ciif', path.basename(ciif_file)).groupdict()
|
|
104
|
+
|
|
105
|
+
# name = '_'.join(file_name(ciif_file).split('_')[:-2])
|
|
106
|
+
return load_ciif(ciif_file, data_fields=tps_db[m['name']]['signals'], out='df' if out_df else dict,
|
|
107
|
+
show=(['summary'] if show else []))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def images_to_ciif(file_path: str, images,
|
|
111
|
+
bits_num=None,
|
|
112
|
+
start_bits=None,
|
|
113
|
+
stream_names=None,
|
|
114
|
+
lane_shape=None,
|
|
115
|
+
stream_sign=None,
|
|
116
|
+
bits_write=None,
|
|
117
|
+
new_hdr=True):
|
|
118
|
+
"""Save array of same-sized images to ciif file io.
|
|
119
|
+
|
|
120
|
+
:Hdr io:
|
|
121
|
+
|
|
122
|
+
//Frame_width=(200, 0)
|
|
123
|
+
//Frame_height=(26, 0)
|
|
124
|
+
//Stream_name=(y10)
|
|
125
|
+
//Stream_bit_num=(10)
|
|
126
|
+
//Stream_sign=(unsigned)
|
|
127
|
+
|
|
128
|
+
:Example:
|
|
129
|
+
|
|
130
|
+
images_to_ciif('resulting.ciif', img) # simplest form - use first max_bit(img) bits
|
|
131
|
+
images_to_ciif('resulting.ciif', [img1, img2], [2, 13]) # usual form - 2 and 13 bits data
|
|
132
|
+
images_to_ciif('resulting.ciif', [img, img], [6, 8], [0, 6]) # extract fields from same img
|
|
133
|
+
|
|
134
|
+
:param file_path: Distention file path
|
|
135
|
+
:param images: iterable of images of numpy.ndarray type (or a single image)
|
|
136
|
+
:param bits_num: numbers of meaningful bits in the data elements (default: estimate from data)
|
|
137
|
+
:param start_bits: list of (0-based) starting bits used in each image data element (default = 0)
|
|
138
|
+
:param stream_names: names for the data elements (by default will be set: 'f0', 'f1' ...)
|
|
139
|
+
:param lane_shape: shape of lane (default: 0,0)
|
|
140
|
+
:param stream_sign: types of the data elements (by default will be set: 'unsigned')
|
|
141
|
+
:param bits_write: numbers of stream bits in output ciif (default: from bits_num)
|
|
142
|
+
:param new_hdr: flag for header io; True by default)
|
|
143
|
+
:param pix_format: used if new_hdr==False; USER_DEFINED by default)
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
def data_bits(d):
|
|
147
|
+
return np.ceil(np.log(1 + min(1, d.max() + 1)) / np.log(2))
|
|
148
|
+
|
|
149
|
+
# normalize the inputs io
|
|
150
|
+
if isinstance(images, np.ndarray):
|
|
151
|
+
images = [images]
|
|
152
|
+
|
|
153
|
+
if isinstance(stream_names, str):
|
|
154
|
+
stream_names = [stream_names]
|
|
155
|
+
|
|
156
|
+
if not len(images):
|
|
157
|
+
warnings.warn('No images provided - exiting!')
|
|
158
|
+
return
|
|
159
|
+
|
|
160
|
+
if start_bits is None:
|
|
161
|
+
start_bits = [0] * len(images)
|
|
162
|
+
if not type(start_bits) in (tuple, list):
|
|
163
|
+
start_bits = [start_bits] * len(images)
|
|
164
|
+
if isinstance(start_bits[0], str):
|
|
165
|
+
start_bits = [int(bits) for bits in start_bits]
|
|
166
|
+
|
|
167
|
+
if stream_names is None:
|
|
168
|
+
if isinstance(images[0], dict):
|
|
169
|
+
stream_names = images.keys()
|
|
170
|
+
else:
|
|
171
|
+
stream_names = ['f%d' % i for i in range(len(images))]
|
|
172
|
+
|
|
173
|
+
if bits_num is None:
|
|
174
|
+
bits_num = [data_bits(im) for im in images]
|
|
175
|
+
if not type(bits_num) in (tuple, list):
|
|
176
|
+
bits_num = [bits_num] * len(images)
|
|
177
|
+
if isinstance(bits_num[0], str):
|
|
178
|
+
bits_num = [int(bits) for bits in bits_num]
|
|
179
|
+
|
|
180
|
+
if bits_write is None:
|
|
181
|
+
bits_write = bits_num
|
|
182
|
+
if not type(bits_write) in (tuple, list):
|
|
183
|
+
bits_write = [bits_write] * len(images)
|
|
184
|
+
if isinstance(bits_write[0], str):
|
|
185
|
+
bits_write = [int(bits) for bits in bits_write]
|
|
186
|
+
|
|
187
|
+
if stream_sign is None:
|
|
188
|
+
stream_sign = ['unsigned' for im in images]
|
|
189
|
+
elif not type(stream_sign) in (tuple, list):
|
|
190
|
+
stream_sign = [stream_sign] * len(images)
|
|
191
|
+
|
|
192
|
+
if lane_shape is None:
|
|
193
|
+
lane_shape = [0, 0]
|
|
194
|
+
|
|
195
|
+
# validate inputs
|
|
196
|
+
unless(len(images) == len(start_bits) == len(bits_num) == len(stream_sign) == len(bits_write),
|
|
197
|
+
'mismatched arrays of images and bits') # It shouldt work
|
|
198
|
+
for im, start, bits, bits_w, signed in zip(images, start_bits, bits_num, bits_write, stream_sign):
|
|
199
|
+
unless(im.dtype.kind in 'bBui', 'Only integer data types are supported')
|
|
200
|
+
if signed != 'unsigned': # Consider: add support
|
|
201
|
+
unless(bits <= 32, 'Negative data supported only up to 32 bits')
|
|
202
|
+
unless(start >= 0 and bits != 0 and bits_w != 0 and bits <= bits_w,
|
|
203
|
+
'invalid start_bits, bits_num, bits_write: %s, %s, %s' % (start, bits, bits_w))
|
|
204
|
+
|
|
205
|
+
images = [im.astype('uint32') if sgn == 'signed' else im for sgn, im in zip(stream_sign, images)]
|
|
206
|
+
|
|
207
|
+
unless(all(len(im.shape) == 2 for im in images), 'images must be greyscaled')
|
|
208
|
+
height, width = next(iter(images)).shape
|
|
209
|
+
unless(all(im.shape == (height, width) for im in images), 'images must be of same size')
|
|
210
|
+
|
|
211
|
+
# define formatting
|
|
212
|
+
if new_hdr:
|
|
213
|
+
ciif_header = ("Frame_width=({width}, {lane_shape_w})\n"
|
|
214
|
+
"Frame_height=({height}, {lane_shape_h})\n"
|
|
215
|
+
"Stream_name=({stream_names})\n"
|
|
216
|
+
"Stream_bit_num=({bits_o})\n"
|
|
217
|
+
"Stream_sign=({signed})"
|
|
218
|
+
).format(width=width, lane_shape_w=lane_shape[0],
|
|
219
|
+
height=height, lane_shape_h=lane_shape[1],
|
|
220
|
+
stream_names=', '.join([name for name in stream_names]),
|
|
221
|
+
bits_o=', '.join(['%u' % b_num for b_num in bits_write]),
|
|
222
|
+
signed=', '.join([sign for sign in stream_sign]))
|
|
223
|
+
else:
|
|
224
|
+
ciif_header = ("Frame_width={width}\n"
|
|
225
|
+
"Frame_height={height}\n"
|
|
226
|
+
"Number_disparities=1\n"
|
|
227
|
+
"Number_frames=1\n"
|
|
228
|
+
"Pixel_format=({bits_o})\n" # USER_SPECIFIC
|
|
229
|
+
"Line_direction=LeftToRight\n"
|
|
230
|
+
"Data_format=Hex"
|
|
231
|
+
).format(width=width, height=height,
|
|
232
|
+
bits_o=', '.join(['%u' % b_num for b_num in bits_write]),)
|
|
233
|
+
|
|
234
|
+
# line_format = "( 0,%4u,%4u) " + "_".join("%%0%ux" % np.ceil(bits / 4) for bits in bits_num)
|
|
235
|
+
if len(bits_write) > 1:
|
|
236
|
+
line_format = "( 0,%4u,%4u) " + "_".join(
|
|
237
|
+
"%%0%lux" % np.ceil(abs(bits) / 4) for bits in bits_write) # abs(bits) for signed numbers support
|
|
238
|
+
else:
|
|
239
|
+
line_format = "( 0,%4u,%4u) " + "%%0%lux" % np.ceil(abs(bits_write[0]) / 4)
|
|
240
|
+
|
|
241
|
+
# prepare data for printing out
|
|
242
|
+
masked_images = (((im.flatten() >> start) & int(2 ** abs(bits) - 1)) for # abs(bits) for signed numbers support
|
|
243
|
+
im, start, bits in zip(images, start_bits, bits_num))
|
|
244
|
+
|
|
245
|
+
data = np.stack((*np.where(np.ones((height, width))), *masked_images))
|
|
246
|
+
data = data.astype('uint64') if np.sum(bits_write) > 32 else data.astype('uint32')
|
|
247
|
+
np.savetxt(file_path, data.T, fmt=line_format, header=ciif_header, comments='//')
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _ciif_hdr_info(ciif_path) -> dict:
|
|
251
|
+
""" Extract header info as dict; count number of header lines
|
|
252
|
+
|
|
253
|
+
:param ciif_path: file_path to ciif file
|
|
254
|
+
:return: hdr_attr_dict
|
|
255
|
+
"""
|
|
256
|
+
import pandas as pd
|
|
257
|
+
|
|
258
|
+
def extract_stream_name(header_dict):
|
|
259
|
+
""" Extract stream names from from ciif hdr dict
|
|
260
|
+
|
|
261
|
+
:param header_dict: dict read from ciif hdr dict
|
|
262
|
+
|
|
263
|
+
:return: stream_names list
|
|
264
|
+
"""
|
|
265
|
+
|
|
266
|
+
names_str = header_dict.get('Stream_name', None)
|
|
267
|
+
if names_str and isinstance(names_str, str): # new hdr io
|
|
268
|
+
names = re.split(',', names_str.strip('()'))
|
|
269
|
+
return [field.strip() for field in names]
|
|
270
|
+
return None
|
|
271
|
+
|
|
272
|
+
def extract_shape(header_dict):
|
|
273
|
+
""" Extract Frame_height and Frame_width from ciif hdr dict
|
|
274
|
+
|
|
275
|
+
:param header_dict: dict read from ciif hdr
|
|
276
|
+
:return: (Frame_height, Frame_width) values tuple
|
|
277
|
+
"""
|
|
278
|
+
|
|
279
|
+
dim_fields = ['Frame_height', 'Frame_width']
|
|
280
|
+
the_shape = None
|
|
281
|
+
if set(dim_fields).issubset(header_dict):
|
|
282
|
+
h = literal_eval(header_dict['Frame_height'])
|
|
283
|
+
w = literal_eval(header_dict['Frame_width'])
|
|
284
|
+
|
|
285
|
+
if isinstance(h, tuple): # new hdr io
|
|
286
|
+
the_shape = (h[0], w[0])
|
|
287
|
+
else: # old hdr io
|
|
288
|
+
the_shape = (h, w)
|
|
289
|
+
return the_shape
|
|
290
|
+
|
|
291
|
+
def extract_stream_bit_num(header_dict):
|
|
292
|
+
""" Extract Stream_bit_num from ciif hdr dict
|
|
293
|
+
|
|
294
|
+
:param header_dict: dict read from ciif hdr
|
|
295
|
+
:return: Stream_bit_num values list
|
|
296
|
+
"""
|
|
297
|
+
if 'Stream_bit_num' not in header_dict:
|
|
298
|
+
return None
|
|
299
|
+
|
|
300
|
+
str_bits = re.split(',', header_dict.get('Stream_bit_num').strip('()'))
|
|
301
|
+
return [int(str_bits_num) for str_bits_num in str_bits]
|
|
302
|
+
|
|
303
|
+
def extract_stream_sign(header_dict):
|
|
304
|
+
""" Extract Stream_sign from ciif hdr dict
|
|
305
|
+
|
|
306
|
+
:param header_dict: dict read from ciif hdr
|
|
307
|
+
:return: Stream_sign str list
|
|
308
|
+
"""
|
|
309
|
+
if 'Stream_sign' not in header_dict:
|
|
310
|
+
return None
|
|
311
|
+
signed = re.split(',', header_dict.get('Stream_sign').strip('()'))
|
|
312
|
+
return [s.strip(' ') for s in signed]
|
|
313
|
+
|
|
314
|
+
def extract_dtypes(header_dict):
|
|
315
|
+
""" Extract Stream_sign from ciif hdr dict
|
|
316
|
+
|
|
317
|
+
:param header_dict: dict read from ciif hdr
|
|
318
|
+
:return: Stream_sign str list
|
|
319
|
+
"""
|
|
320
|
+
|
|
321
|
+
def hdr_str_to_dtype(str_signed, str_bits_num):
|
|
322
|
+
num_of_bits = int(str_bits_num)
|
|
323
|
+
num_of_bits = 2 ** math.ceil(math.log2(num_of_bits))
|
|
324
|
+
num_of_bits = max(num_of_bits, 8)
|
|
325
|
+
if str_signed.strip() == 'unsigned':
|
|
326
|
+
signed_int = 'uint'
|
|
327
|
+
else:
|
|
328
|
+
signed_int = 'int'
|
|
329
|
+
return eval('np.{}{}'.format(signed_int, num_of_bits))
|
|
330
|
+
|
|
331
|
+
stream_signed = extract_stream_sign(header_dict)
|
|
332
|
+
bits_num = extract_stream_bit_num(header_dict)
|
|
333
|
+
dtypes = None
|
|
334
|
+
if stream_signed and bits_num:
|
|
335
|
+
dtypes = []
|
|
336
|
+
for sign, bits in zip(stream_signed, bits_num):
|
|
337
|
+
dtype = hdr_str_to_dtype(sign, bits)
|
|
338
|
+
dtypes.append(dtype)
|
|
339
|
+
return dtypes
|
|
340
|
+
|
|
341
|
+
try:
|
|
342
|
+
header = pd.read_table(ciif_path, sep='=|//', engine='python', nrows=50,
|
|
343
|
+
usecols=range(1, 3), names=['', ' ', 'val'], index_col=0).dropna()
|
|
344
|
+
except BaseException as e:
|
|
345
|
+
# print('missing header in "%s"' % ciif_path)
|
|
346
|
+
return {}
|
|
347
|
+
else:
|
|
348
|
+
hdr_dict = header['val'].to_dict()
|
|
349
|
+
shape_info = extract_shape(hdr_dict)
|
|
350
|
+
|
|
351
|
+
return {'Frame_height': shape_info[0], 'Frame_width': shape_info[1],
|
|
352
|
+
'Stream_name': extract_stream_name(hdr_dict),
|
|
353
|
+
'Stream_bit_num': extract_stream_bit_num(hdr_dict),
|
|
354
|
+
'Stream_sign': extract_stream_sign(hdr_dict),
|
|
355
|
+
'dtypes': extract_dtypes(hdr_dict),
|
|
356
|
+
'hdr_rows': header.shape[0]}
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def _ciif_data_info(ciif_path) -> dict:
|
|
360
|
+
""" Extract header info as dict; count number of header lines
|
|
361
|
+
|
|
362
|
+
:param ciif_path: file_path to ciif file
|
|
363
|
+
:return: attr_dict extracted from data
|
|
364
|
+
"""
|
|
365
|
+
|
|
366
|
+
import pandas as pd
|
|
367
|
+
|
|
368
|
+
def default_field_names(df_readdata):
|
|
369
|
+
num_found_fields = df_readdata.shape[1] - len(('frame', 'row', 'col'))
|
|
370
|
+
return ['f%d' % i for i in range(num_found_fields)]
|
|
371
|
+
|
|
372
|
+
hdr_info = _ciif_hdr_info(ciif_path)
|
|
373
|
+
hdr_rows = hdr_info.get('hdr_rows', 0) if hdr_info else 0
|
|
374
|
+
|
|
375
|
+
df = pd.read_table(ciif_path, sep=r',\s*|\(\s*|\)\s*|_', engine='python', header=None,
|
|
376
|
+
skiprows=hdr_rows, usecols=range(1, 10000), index_col=False)
|
|
377
|
+
data_fields = default_field_names(df)
|
|
378
|
+
|
|
379
|
+
position_fields = ('frame', 'row', 'col')
|
|
380
|
+
df.columns = position_fields + tuple(data_fields)
|
|
381
|
+
data_shape = tuple(np.array(df[['row', 'col']].apply(np.max)) + 1)
|
|
382
|
+
|
|
383
|
+
return {'Stream_name': default_field_names(df),
|
|
384
|
+
'Frame_height': data_shape[0],
|
|
385
|
+
'Frame_width': data_shape[1],
|
|
386
|
+
'hdr_rows': hdr_rows}
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def extract_metadata(file_name) -> dict:
|
|
390
|
+
""" Extract CIIF file info from ciif_hdr or from ciif_data.
|
|
391
|
+
|
|
392
|
+
:param file_name: name of the ciif file.
|
|
393
|
+
:return: dict with ciif info.
|
|
394
|
+
"""
|
|
395
|
+
|
|
396
|
+
all_keys = ['Frame_width', 'Frame_height', 'Stream_name', 'Stream_bit_num', 'Stream_sign', 'dtypes', 'hdr_rows']
|
|
397
|
+
|
|
398
|
+
res_dict = _ciif_hdr_info(file_name)
|
|
399
|
+
default_keys = [k for k in all_keys if res_dict.get(k, None) is None]
|
|
400
|
+
|
|
401
|
+
if len(default_keys) > 0:
|
|
402
|
+
res_dict.update({'default': True})
|
|
403
|
+
data_dict = _ciif_data_info(file_name)
|
|
404
|
+
for key in default_keys:
|
|
405
|
+
res_dict.update({key: data_dict.get(key, None)})
|
|
406
|
+
return res_dict
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def load_ciif(file_name, data_fields=None, out=dict, partial=False, show=None):
|
|
410
|
+
""" Load CIIF file with multiple fields and extract them into dictionary of corresponding images
|
|
411
|
+
|
|
412
|
+
:param file_name: name of the ciif file
|
|
413
|
+
:param data_fields: list of names of the fields - defaults=['f0', 'f1', ...]
|
|
414
|
+
:param out: output io [dict] | tuple | list | df (DataFrame) | 'content';
|
|
415
|
+
IF out=’content’, ignore other flags and return instead of the data:
|
|
416
|
+
- if new header io: list of stream names
|
|
417
|
+
- if old header io: number of streams.
|
|
418
|
+
:param partial: if True, falls on not complete data
|
|
419
|
+
:param show: list of strings to control verbosity: ['summary', ]
|
|
420
|
+
:return: dict of {field_name: image_ndarray}
|
|
421
|
+
"""
|
|
422
|
+
|
|
423
|
+
import pandas as pd
|
|
424
|
+
|
|
425
|
+
def device_data_fields(param_field_names, default_field_names):
|
|
426
|
+
"""
|
|
427
|
+
Device data field names, using stream names read from new hdr, field names from call parameters, default field names.
|
|
428
|
+
|
|
429
|
+
:param param_field_names: field names from call parameter;
|
|
430
|
+
:param default_field_names:
|
|
431
|
+
|
|
432
|
+
:return: Data field names to be used in result df or dict.
|
|
433
|
+
"""
|
|
434
|
+
field_names = param_field_names or []
|
|
435
|
+
if not all(re.fullmatch('\w+', field) for field in field_names):
|
|
436
|
+
raise ValueError('An invalid data field in: %s' % field_names)
|
|
437
|
+
|
|
438
|
+
if param_field_names and (len(param_field_names) != 0) and (len(default_field_names) != len(param_field_names)):
|
|
439
|
+
print('Found %d fields instead of %d. Using defaults.' % (len(default_field_names), len(param_field_names)))
|
|
440
|
+
return default_field_names
|
|
441
|
+
|
|
442
|
+
return field_names or default_field_names
|
|
443
|
+
|
|
444
|
+
if not out:
|
|
445
|
+
out = dict
|
|
446
|
+
|
|
447
|
+
_TM.point(file_name)
|
|
448
|
+
meta_dict = extract_metadata(file_name)
|
|
449
|
+
|
|
450
|
+
# -------------- Format output ---------------
|
|
451
|
+
field_names = meta_dict.get('Stream_name', None)
|
|
452
|
+
if out == 'content':
|
|
453
|
+
return len(field_names) if meta_dict.get('default', False) else field_names
|
|
454
|
+
|
|
455
|
+
if out in {pd.DataFrame, 'df'}:
|
|
456
|
+
out = pd.DataFrame
|
|
457
|
+
elif out not in {dict, tuple, list}:
|
|
458
|
+
raise ValueError('Unsupported output io: ', out)
|
|
459
|
+
|
|
460
|
+
# -------------- data_fields ---------------
|
|
461
|
+
if meta_dict.get('default', False):
|
|
462
|
+
data_fields = device_data_fields(param_field_names=data_fields, default_field_names=field_names)
|
|
463
|
+
else:
|
|
464
|
+
data_fields = field_names
|
|
465
|
+
|
|
466
|
+
# -------------- read data ---------------
|
|
467
|
+
df = pd.read_table(file_name, sep=r',\s*|\(\s*|\)\s*|_', engine='python', header=None,
|
|
468
|
+
skiprows=meta_dict.get('hdr_rows', 0), usecols=range(1, 10000), index_col=False)
|
|
469
|
+
position_fields = ('frame', 'row', 'col')
|
|
470
|
+
df.columns = position_fields + tuple(data_fields)
|
|
471
|
+
|
|
472
|
+
# -------------- data_shape: check consistency with header ---------------
|
|
473
|
+
data_shape = tuple(np.array(df[['row', 'col']].apply(np.max)) + 1)
|
|
474
|
+
hdr_shape = (meta_dict.get('Frame_height', None), meta_dict.get('Frame_width', None))
|
|
475
|
+
if not data_shape == hdr_shape:
|
|
476
|
+
msg = 'Mismatch ({})!=({}) in {}'.format(data_shape, hdr_shape, file_name)
|
|
477
|
+
if partial:
|
|
478
|
+
warnings.warn(msg)
|
|
479
|
+
else:
|
|
480
|
+
raise ValueError(msg)
|
|
481
|
+
# update actual number of rows:
|
|
482
|
+
data_shape = int(df.shape[0] / data_shape[1]), data_shape[1]
|
|
483
|
+
df = df[: (data_shape[0] * data_shape[1])]
|
|
484
|
+
|
|
485
|
+
# -------------- dtypes ---------------
|
|
486
|
+
dtypes = meta_dict.get('dtypes', [])
|
|
487
|
+
stream_signed = meta_dict.get('Stream_sign', None)
|
|
488
|
+
bits_num = meta_dict.get('Stream_bit_num', None)
|
|
489
|
+
|
|
490
|
+
def hdr_str_to_dtype(str_signed, num_of_bits):
|
|
491
|
+
num_of_bits = 2 ** math.ceil(math.log2(num_of_bits))
|
|
492
|
+
num_of_bits = max(num_of_bits, 8)
|
|
493
|
+
if str_signed.strip() == 'unsigned':
|
|
494
|
+
signed_int = 'uint'
|
|
495
|
+
else:
|
|
496
|
+
signed_int = 'int'
|
|
497
|
+
return eval('np.{}{}'.format(signed_int, num_of_bits))
|
|
498
|
+
|
|
499
|
+
if stream_signed and bits_num:
|
|
500
|
+
for sign, bits in zip(stream_signed, bits_num):
|
|
501
|
+
dtype = hdr_str_to_dtype(sign, bits)
|
|
502
|
+
dtypes.append(dtype)
|
|
503
|
+
|
|
504
|
+
# _TM.point('convert hex')
|
|
505
|
+
# convert data to numeric
|
|
506
|
+
def str_to_dtype(str):
|
|
507
|
+
num_of_bits = len(str) * 4
|
|
508
|
+
num_of_bits = 2 ** math.ceil(math.log2(num_of_bits))
|
|
509
|
+
num_of_bits = max(num_of_bits, 8)
|
|
510
|
+
return eval('np.uint{}'.format(num_of_bits))
|
|
511
|
+
|
|
512
|
+
for field in data_fields:
|
|
513
|
+
if df[field].dtype is np.dtype('int64'):
|
|
514
|
+
df.loc[:, field] = df[field].apply(str)
|
|
515
|
+
|
|
516
|
+
if meta_dict.get('default', False): # is_old_format
|
|
517
|
+
dtype = str_to_dtype(df[field].iloc[0])
|
|
518
|
+
dtypes.append(dtype)
|
|
519
|
+
|
|
520
|
+
df.loc[:, field] = df[field].apply(int, args=(16,))
|
|
521
|
+
|
|
522
|
+
# -------------- show summary ---------------
|
|
523
|
+
_TM.point(measure_from=file_name)
|
|
524
|
+
if show and 'summary' in show:
|
|
525
|
+
print(df[[*data_fields]].describe())
|
|
526
|
+
|
|
527
|
+
# -------------- out ---------------
|
|
528
|
+
# special request to return only data frame
|
|
529
|
+
if out in {'df', pd.DataFrame}:
|
|
530
|
+
return df[[*data_fields]]
|
|
531
|
+
|
|
532
|
+
images = {field: df[field].values.reshape(data_shape)[df.row, df.col].reshape(data_shape).astype(image_type)
|
|
533
|
+
for field, image_type in zip(data_fields, dtypes)}
|
|
534
|
+
return images if out is dict else out(images[field] for field in data_fields)
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
def save_tiffs(images, path_prefix, compress=0):
|
|
538
|
+
""" Save dictionary of images into multiple tiff files as type 'uint16'
|
|
539
|
+
using given path_prefix as prefix and keys as suffix
|
|
540
|
+
|
|
541
|
+
:param images: dictionary of 1:3 images, of view {field:image}, where image is ndarray
|
|
542
|
+
:param path_prefix: output_folder [and output files basename without suffix and extension]
|
|
543
|
+
:param compress: not used for now
|
|
544
|
+
:usage: process_ciif_to_tiffs(images,args.prefix)
|
|
545
|
+
"""
|
|
546
|
+
with warnings.catch_warnings():
|
|
547
|
+
warnings.simplefilter("ignore")
|
|
548
|
+
for field in images:
|
|
549
|
+
io.imsave('%s_%s.tif' % (path_prefix, field), images[field].astype('uint16'),
|
|
550
|
+
compress=compress)
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def parse_command_line():
|
|
554
|
+
import argparse
|
|
555
|
+
|
|
556
|
+
parser = argparse.ArgumentParser(prog='ciif')
|
|
557
|
+
|
|
558
|
+
x_group = parser.add_mutually_exclusive_group(required=True)
|
|
559
|
+
x_group.add_argument('-ciif', action='store_true',
|
|
560
|
+
help='Input CIIF mode. Mutually exclusive with --img')
|
|
561
|
+
x_group.add_argument('-img', '--image', action='store_true',
|
|
562
|
+
help='Input images mode - provide image files accordingly')
|
|
563
|
+
|
|
564
|
+
# parser = parser.add_argument_group('calling conventions')
|
|
565
|
+
parser.add_argument('input_files', nargs='+', type=str,
|
|
566
|
+
help='single *.ciif file in -ciif mode; '
|
|
567
|
+
'1+ *.ciif files in -ciif -c mode;'
|
|
568
|
+
'1+ image files in -img mode')
|
|
569
|
+
parser.add_argument('-o', '--output_folder', type=str, nargs='?', default=[],
|
|
570
|
+
help='Default: the same as input files folder')
|
|
571
|
+
parser.add_argument('-p', '--prefix', type=str,
|
|
572
|
+
help='Prefix for output file names. '
|
|
573
|
+
'-ciif mode: --signals are used as suffix.'
|
|
574
|
+
' Default: use prefix extracted from the input name.'
|
|
575
|
+
'-ciif -c mode: full name of the output file.'
|
|
576
|
+
'-img mode: name of the output file.'
|
|
577
|
+
' May contain folder name if -o not defined.'
|
|
578
|
+
' default: _ joined names of the input files.')
|
|
579
|
+
|
|
580
|
+
# input param in -ciif -c mode: concat option
|
|
581
|
+
parser.add_argument('-c', '--concat', type=int, nargs='+',
|
|
582
|
+
help='(-ciif -c mode only) Number of streams to use from each input ciif file')
|
|
583
|
+
parser.add_argument('-w', '--width', type=int,
|
|
584
|
+
help='(-ciif -c mode only) Width of concatenated result stream')
|
|
585
|
+
|
|
586
|
+
# input params in -img mode and -ciif -c mode
|
|
587
|
+
parser.add_argument('-f', '--first_bit', type=int, nargs='+',
|
|
588
|
+
help='(-img mode; -ciif -c mode) Starting bit (zero based) for each input signal')
|
|
589
|
+
parser.add_argument('-b', '--bits_read', type=int, nargs='+',
|
|
590
|
+
help='(-img mode; -ciif -c mode) Number of bits to read from each tiff file')
|
|
591
|
+
|
|
592
|
+
# input params in -img mode
|
|
593
|
+
parser.add_argument('-g', '--grey', action='store_true',
|
|
594
|
+
help='(-img mode only) If set color inputs will be excepted and converted to grey')
|
|
595
|
+
|
|
596
|
+
# output params in -img mode
|
|
597
|
+
parser.add_argument('-ho', '--header_old', action='store_true',
|
|
598
|
+
help='(-img mode only) Ciif header format to be written: new header by default')
|
|
599
|
+
parser.add_argument('-bw', '--bits_write', type=int, nargs='+',
|
|
600
|
+
help='(-img mode only) Number of bits in each signal')
|
|
601
|
+
parser.add_argument('-ft', '--formats', type=str, nargs='+',
|
|
602
|
+
help='(-img mode only) Format "signed"/"unsigned" for each signal')
|
|
603
|
+
|
|
604
|
+
f_group = parser.add_mutually_exclusive_group()
|
|
605
|
+
f_group.add_argument('-s', '--signals', nargs='+',
|
|
606
|
+
help='(-img mode; -ciif -c mode) list names of all the signals in the ciif or in repeating group'
|
|
607
|
+
'Default values: "s1", "s2", ...')
|
|
608
|
+
f_group.add_argument('-db', '--formats_db',
|
|
609
|
+
help='Excel file describing io of test points')
|
|
610
|
+
|
|
611
|
+
specific_verb_terms = ['time', 'summary', 'db']
|
|
612
|
+
general_verb_terms = ['0', 'none', 'all']
|
|
613
|
+
parser.add_argument('-v', '--verbose', type=str, nargs='+', default=[],
|
|
614
|
+
choices=specific_verb_terms + general_verb_terms,
|
|
615
|
+
help='Add information type to hear about')
|
|
616
|
+
|
|
617
|
+
class Args:
|
|
618
|
+
def __init__(self): # just to please PyCharm ;-)
|
|
619
|
+
self.ciif = None
|
|
620
|
+
self.image = None
|
|
621
|
+
self.input_files = None
|
|
622
|
+
self.input_folder = None
|
|
623
|
+
self.output_folder = None
|
|
624
|
+
self.prefix = None
|
|
625
|
+
self.ciif_file = None
|
|
626
|
+
self.grey = None
|
|
627
|
+
self.first_bit = None
|
|
628
|
+
self.bits_read = None
|
|
629
|
+
self.header_old = None
|
|
630
|
+
self.bits_write = None
|
|
631
|
+
self.formats_db = None
|
|
632
|
+
self.concat = None
|
|
633
|
+
self.width = None
|
|
634
|
+
self.signals = []
|
|
635
|
+
self.formats = []
|
|
636
|
+
self.verbose = []
|
|
637
|
+
|
|
638
|
+
def devise_out_folder(self):
|
|
639
|
+
if not self.output_folder:
|
|
640
|
+
input_folder = path.dirname(self.input_files[0])
|
|
641
|
+
if path.commonpath(self.input_files) != input_folder:
|
|
642
|
+
warnings.warn('Using first input file folder for output: %s' % input_folder)
|
|
643
|
+
self.output_folder = input_folder
|
|
644
|
+
# Prepare output dir
|
|
645
|
+
if not path.exists(self.output_folder):
|
|
646
|
+
makedirs(self.output_folder)
|
|
647
|
+
return self.output_folder
|
|
648
|
+
|
|
649
|
+
def devise_out_ciif_path(self):
|
|
650
|
+
if self.prefix: # output folder may be part of the prefix argument:
|
|
651
|
+
if path.split(self.prefix)[0]:
|
|
652
|
+
unless(not self.output_folder, 'output folder provided also with prefix')
|
|
653
|
+
self.output_folder = path.dirname(self.prefix)
|
|
654
|
+
self.ciif_file = path.basename(self.prefix)
|
|
655
|
+
else:
|
|
656
|
+
self.ciif_file = self.prefix
|
|
657
|
+
else: # if output ciif image name not provided combine it from inputs names
|
|
658
|
+
# eliminate common prefix from file names to leave only meaningful signal tag
|
|
659
|
+
file_names = [path.split(inp)[1] for inp in self.input_files] # throw paths away
|
|
660
|
+
if len(file_names) > 1:
|
|
661
|
+
prefix = path.commonprefix(file_names)
|
|
662
|
+
signals = [path.splitext(name[len(prefix):])[0] for name in file_names]
|
|
663
|
+
self.ciif_file = prefix + '_' + '_'.join(signals) + '.ciif'
|
|
664
|
+
else:
|
|
665
|
+
self.ciif_file = path.splitext(file_names[0])[0] + '.ciif'
|
|
666
|
+
|
|
667
|
+
self.devise_out_folder()
|
|
668
|
+
self.ciif_file = path.join(self.output_folder, self.ciif_file)
|
|
669
|
+
|
|
670
|
+
arguments = Args()
|
|
671
|
+
parser.parse_args(namespace=arguments)
|
|
672
|
+
|
|
673
|
+
if 'all' in arguments.verbose:
|
|
674
|
+
arguments.verbose += specific_verb_terms
|
|
675
|
+
|
|
676
|
+
return arguments
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
def _concat_im_fields(images, signals, first_bits, bits_reads):
|
|
680
|
+
"""Concat fields of images
|
|
681
|
+
|
|
682
|
+
:param images: dict of {signal : im} pairs
|
|
683
|
+
:param signals: list of signals from dict.keys() to be used for result
|
|
684
|
+
:param first_bits: list of first_bits per signal from signals to be used for result
|
|
685
|
+
:param bits_reads list of bits_reads per signal from signals to be used for result
|
|
686
|
+
:return: uint64 3ith MSB from signals[0] and LSB from signals[-1]
|
|
687
|
+
"""
|
|
688
|
+
if type(images) is dict:
|
|
689
|
+
init_base = [np.zeros_like(im) for _, im in images.items()][0]
|
|
690
|
+
elif type(images) is list:
|
|
691
|
+
init_base = np.zeros_like(images[0])
|
|
692
|
+
else:
|
|
693
|
+
init_base = np.zeros_like(images)
|
|
694
|
+
|
|
695
|
+
res = init_base.flatten().astype('uint64')
|
|
696
|
+
shift = 0
|
|
697
|
+
for signal, first_bit, bits in zip(signals, first_bits, bits_reads):
|
|
698
|
+
im = ((images[signal].flatten() >> first_bit) & int(2 ** abs(bits) - 1))
|
|
699
|
+
# old: signals_list[0] will be LSB in output: res += im << shift; shift += bits
|
|
700
|
+
|
|
701
|
+
# new: signals_list[0] will be MSB in output
|
|
702
|
+
shift += bits
|
|
703
|
+
res = (res << bits) + im
|
|
704
|
+
return res.reshape(init_base.shape)
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
def concat_ciifs_to_ciif(args):
|
|
708
|
+
"""Treat ciif(s) -> ciif concat mode of the command line processing.
|
|
709
|
+
|
|
710
|
+
:param args: command line arguments
|
|
711
|
+
:return:
|
|
712
|
+
"""
|
|
713
|
+
ciif_num = len(args.concat)
|
|
714
|
+
if len(args.input_files) != ciif_num:
|
|
715
|
+
warnings.warn('-c arg needs the same num of vals as input files num')
|
|
716
|
+
return
|
|
717
|
+
|
|
718
|
+
im_dicts_list = [load_ciif(f) for f in args.input_files]
|
|
719
|
+
|
|
720
|
+
start_pos = 0
|
|
721
|
+
res = []
|
|
722
|
+
bits_reads = []
|
|
723
|
+
for im_dict, f_num in zip(im_dicts_list, args.concat):
|
|
724
|
+
num = int(f_num)
|
|
725
|
+
res.append(_concat_im_fields(images=im_dict,
|
|
726
|
+
signals=args.signals[start_pos:start_pos + num],
|
|
727
|
+
first_bits=args.first_bit[start_pos:start_pos + num],
|
|
728
|
+
bits_reads=args.bits_read[start_pos:start_pos + num]))
|
|
729
|
+
read = sum(args.bits_read[start_pos:start_pos + num])
|
|
730
|
+
bits_reads.append(read)
|
|
731
|
+
start_pos += num
|
|
732
|
+
|
|
733
|
+
res = _concat_im_fields(images=res, signals=range(ciif_num),
|
|
734
|
+
first_bits=[0] * ciif_num, bits_reads=bits_reads)
|
|
735
|
+
images_to_ciif(args.prefix, res, bits_num=sum(bits_reads), bits_write=args.width, new_hdr=False)
|
|
736
|
+
pass
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
def process_ciif_to_tiff(args):
|
|
740
|
+
"""Treat ciif -> tiff mode of the command line processing
|
|
741
|
+
|
|
742
|
+
:param args: command line arguments
|
|
743
|
+
:return:
|
|
744
|
+
"""
|
|
745
|
+
unless(len(args.input_files) == 1, 'ciif source requires single input file name')
|
|
746
|
+
args.ciif_file = args.input_files[0]
|
|
747
|
+
args.devise_out_folder()
|
|
748
|
+
|
|
749
|
+
def file_name_part(filename):
|
|
750
|
+
return path.splitext(path.basename(filename))[0]
|
|
751
|
+
|
|
752
|
+
if not args.prefix: # extract prefix from the ciif file: /ddd/aa_bb_ok.ext -> aa
|
|
753
|
+
args.prefix = file_name_part(args.ciif_file).split('_')[0]
|
|
754
|
+
args.prefix = path.join(args.output_folder, args.prefix)
|
|
755
|
+
|
|
756
|
+
# _TM.point('load DB')
|
|
757
|
+
if args.formats_db: # if excel Test Points Data Base is provided get signals from there
|
|
758
|
+
tp_db = load_scheme(args.formats_db)
|
|
759
|
+
if 'db' in args.verbose:
|
|
760
|
+
print('Test Points formats found in the DB:')
|
|
761
|
+
[print('\t' + tp) for tp in tp_db]
|
|
762
|
+
|
|
763
|
+
try:
|
|
764
|
+
args.signals = tp_db[file_name_part(args.ciif_file)]['signals']
|
|
765
|
+
except KeyError:
|
|
766
|
+
warnings.warn('No io info from file "%s" - using defaults' % args.format[0])
|
|
767
|
+
else:
|
|
768
|
+
print('Successfully extracted Test Points data io.')
|
|
769
|
+
|
|
770
|
+
# _TM.point('load ciif complete', measure_from='load DB')
|
|
771
|
+
images = load_ciif(args.ciif_file, args.signals, show=args.verbose)
|
|
772
|
+
|
|
773
|
+
# _TM.point('save tiffs', measure_from='load ciif complete')
|
|
774
|
+
save_tiffs(images, args.prefix)
|
|
775
|
+
# _TM.point(measure_from='save tiffs')
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
def rgb2gray(img):
|
|
779
|
+
from skimage.color import rgb2gray
|
|
780
|
+
return (rgb2gray(img) * 0xFF).astype('uint8')
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
def process_tiff_to_ciif(args):
|
|
784
|
+
"""Treat tiff -> ciif mode of the command line processing
|
|
785
|
+
|
|
786
|
+
:param args: command line arguments
|
|
787
|
+
:return:
|
|
788
|
+
"""
|
|
789
|
+
args.devise_out_ciif_path()
|
|
790
|
+
images = [io.imread(file) for file in args.input_files]
|
|
791
|
+
|
|
792
|
+
if args.grey:
|
|
793
|
+
images = [im[:, :, 1] if im.ndim == 3 and im.shape[2] in [3, 4] else im for im in images]
|
|
794
|
+
# images = [rgb2gray(im) for im in images]
|
|
795
|
+
|
|
796
|
+
if not args.bits_write:
|
|
797
|
+
args.bits_write = args.bits_read
|
|
798
|
+
|
|
799
|
+
images_to_ciif(args.ciif_file,
|
|
800
|
+
images=images,
|
|
801
|
+
bits_num=args.bits_read,
|
|
802
|
+
start_bits=args.first_bit,
|
|
803
|
+
stream_names=args.signals,
|
|
804
|
+
new_hdr = (not args.header_old),
|
|
805
|
+
bits_write=args.bits_write)
|
|
806
|
+
|
|
807
|
+
# OLDER VERSION?
|
|
808
|
+
# def cif_to_tif(file):
|
|
809
|
+
# """
|
|
810
|
+
# Convert images in a single ciif file into multiple separate tif files
|
|
811
|
+
# named `{original}_{internal_item_name}.tif`
|
|
812
|
+
#
|
|
813
|
+
# :param file: The source
|
|
814
|
+
# :return: number of files created
|
|
815
|
+
# """
|
|
816
|
+
# import warnings
|
|
817
|
+
# from skimage.io import imsave
|
|
818
|
+
# mport ciff as cif
|
|
819
|
+
# ext = '.ciif'
|
|
820
|
+
#
|
|
821
|
+
# try:
|
|
822
|
+
# file = Path(file)
|
|
823
|
+
# if not file.is_file():
|
|
824
|
+
# raise FileExistsError(file)
|
|
825
|
+
# if not file.suffix.lower() is ext:
|
|
826
|
+
# raise TypeError(f'{file} not {ext} file')
|
|
827
|
+
#
|
|
828
|
+
# ciif_data = cif.load_ciif(file)
|
|
829
|
+
# for key, image in ciif_data.items():
|
|
830
|
+
# with warnings.catch_warnings():
|
|
831
|
+
# warnings.simplefilter('ignore')
|
|
832
|
+
# img_name = f'{file[:-len(ext)]}_{key}.tif'
|
|
833
|
+
# imsave(img_name, image)
|
|
834
|
+
# print(f'Created: {img_name}')
|
|
835
|
+
# except Exception as e:
|
|
836
|
+
# print('Failed to parse:', file)
|
|
837
|
+
# print(e)
|
|
838
|
+
# return 0
|
|
839
|
+
# return len(ciif_data)
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
if __name__ == '__main__':
|
|
843
|
+
cmd_args = parse_command_line()
|
|
844
|
+
_TM.enable = 'time' in cmd_args.verbose
|
|
845
|
+
|
|
846
|
+
if cmd_args.ciif:
|
|
847
|
+
if cmd_args.width:
|
|
848
|
+
concat_ciifs_to_ciif(cmd_args)
|
|
849
|
+
else:
|
|
850
|
+
process_ciif_to_tiff(cmd_args)
|
|
851
|
+
elif cmd_args.image:
|
|
852
|
+
process_tiff_to_ciif(cmd_args)
|