petal-qc 0.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.

Potentially problematic release.


This version of petal-qc might be problematic. Click here for more details.

Files changed (51) hide show
  1. petal_qc/BTreport/CheckBTtests.py +321 -0
  2. petal_qc/BTreport/__init__.py +0 -0
  3. petal_qc/BTreport/bustapeReport.py +144 -0
  4. petal_qc/__init__.py +14 -0
  5. petal_qc/metrology/Cluster.py +90 -0
  6. petal_qc/metrology/DataFile.py +47 -0
  7. petal_qc/metrology/PetalMetrology.py +327 -0
  8. petal_qc/metrology/__init__.py +0 -0
  9. petal_qc/metrology/all2csv.py +57 -0
  10. petal_qc/metrology/analyze_locking_points.py +597 -0
  11. petal_qc/metrology/cold_noise.py +106 -0
  12. petal_qc/metrology/comparisonTable.py +59 -0
  13. petal_qc/metrology/convert_mitutoyo.py +175 -0
  14. petal_qc/metrology/convert_smartscope.py +145 -0
  15. petal_qc/metrology/coreMetrology.py +402 -0
  16. petal_qc/metrology/data2csv.py +63 -0
  17. petal_qc/metrology/do_Metrology.py +117 -0
  18. petal_qc/metrology/flatness4nigel.py +157 -0
  19. petal_qc/metrology/gtkutils.py +120 -0
  20. petal_qc/metrology/petal_flatness.py +353 -0
  21. petal_qc/metrology/show_data_file.py +118 -0
  22. petal_qc/metrology/testSummary.py +37 -0
  23. petal_qc/metrology/test_paralelism.py +71 -0
  24. petal_qc/thermal/CSVImage.py +69 -0
  25. petal_qc/thermal/DebugPlot.py +76 -0
  26. petal_qc/thermal/IRBFile.py +768 -0
  27. petal_qc/thermal/IRCore.py +110 -0
  28. petal_qc/thermal/IRDataGetter.py +359 -0
  29. petal_qc/thermal/IRPetal.py +1338 -0
  30. petal_qc/thermal/IRPetalParam.py +71 -0
  31. petal_qc/thermal/PetalColorMaps.py +62 -0
  32. petal_qc/thermal/Petal_IR_Analysis.py +142 -0
  33. petal_qc/thermal/PipeFit.py +598 -0
  34. petal_qc/thermal/__init__.py +0 -0
  35. petal_qc/thermal/analyze_IRCore.py +417 -0
  36. petal_qc/thermal/contours.py +378 -0
  37. petal_qc/thermal/create_IRCore.py +185 -0
  38. petal_qc/thermal/pipe_read.py +182 -0
  39. petal_qc/thermal/show_IR_petal.py +420 -0
  40. petal_qc/utils/Geometry.py +756 -0
  41. petal_qc/utils/Progress.py +182 -0
  42. petal_qc/utils/__init__.py +0 -0
  43. petal_qc/utils/all_files.py +35 -0
  44. petal_qc/utils/docx_utils.py +186 -0
  45. petal_qc/utils/fit_utils.py +188 -0
  46. petal_qc/utils/utils.py +180 -0
  47. petal_qc-0.0.0.dist-info/METADATA +29 -0
  48. petal_qc-0.0.0.dist-info/RECORD +51 -0
  49. petal_qc-0.0.0.dist-info/WHEEL +5 -0
  50. petal_qc-0.0.0.dist-info/entry_points.txt +3 -0
  51. petal_qc-0.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,768 @@
1
+ #!/usr/bin/env python3
2
+ """A python port of https://github.com/jonathanschilling/irb.
3
+
4
+ This is in turn inspired by https://github.com/tomsoftware/Irbis-File-Format.
5
+
6
+ Do not expect 'optimized' python code. The java one was not neither...
7
+ """
8
+ import bz2
9
+ import copy
10
+ import datetime
11
+ import os
12
+ import pickle
13
+ import struct
14
+ import sys
15
+ from collections.abc import Iterable
16
+ from pathlib import Path
17
+
18
+ import matplotlib.pyplot as plt
19
+ import numpy as np
20
+
21
+ OLE_TIME_ZERO = datetime.datetime(1899, 12, 30, 0, 0, 0)
22
+
23
+
24
+ def ole2datetime(oledt):
25
+ """Convert OLE_TIME to python datetime."""
26
+ return OLE_TIME_ZERO + datetime.timedelta(days=float(oledt))
27
+
28
+
29
+ def is_iterable(obj):
30
+ """Tell if an object is iterable. Strings are not considered iterables."""
31
+ if isinstance(obj, Iterable):
32
+ if isinstance(obj, str) or isinstance(obj, bytes):
33
+ return False
34
+ else:
35
+ return True
36
+ else:
37
+ return False
38
+
39
+
40
+ class BinaryFile(object):
41
+ """Encapsulates a binary file."""
42
+
43
+ def __init__(self, ifile):
44
+ """Initialize from a file-like object."""
45
+ self.ifile = ifile
46
+
47
+ # Figure out the file size.
48
+ old_pos = self.ifile.tell()
49
+ self.ifile.seek(0, os.SEEK_END)
50
+ self.end = self.ifile.tell()
51
+ self.ifile.seek(old_pos)
52
+
53
+ def get_from_file(self, fmt, offset=-1):
54
+ """Get data from a binary file.
55
+
56
+ Args:
57
+ ----
58
+ fmt: The format (see struct)
59
+ offset (int, optional): THe offset in the file.
60
+ Defaults to -1, which ignores the offset.
61
+
62
+ Return:
63
+ ------
64
+ array: The output data
65
+
66
+ """
67
+ if offset > 0:
68
+ self.ifile.seek(offset)
69
+
70
+ sz = struct.calcsize(fmt)
71
+ dt = self.ifile.read(sz)
72
+ return struct.unpack(fmt, dt)
73
+
74
+ def read(self, n):
75
+ """Read bytes from file."""
76
+ return self.ifile.read(n)
77
+
78
+ def seek(self, pos=0, whence=os.SEEK_SET):
79
+ """Delegate teh seek functionality."""
80
+ return self.ifile.seek(pos, whence)
81
+
82
+ def tell(self):
83
+ """Delegate the tell funcionality."""
84
+ return self.ifile.tell()
85
+
86
+ def __getValue(self, n, offset, fmt1, fmt2):
87
+ """Get values from file."""
88
+ if n == 1:
89
+ return self.get_from_file(fmt1, offset)[0]
90
+ else:
91
+ return self.get_from_file(fmt2.format(n), offset)
92
+
93
+ def getInt(self, n=1, offset=-1):
94
+ """Get an int."""
95
+ return self.__getValue(n, offset, "<i", "<{}i")
96
+
97
+ def getShort(self, n=1, offset=-1):
98
+ """Get a short."""
99
+ return self.__getValue(n, offset, "<h", "<{}h")
100
+
101
+ def getFloat(self, n=1, offset=-1):
102
+ """Get a float."""
103
+ return self.__getValue(n, offset, "<f", "<{}f")
104
+
105
+ def getDouble(self, n=1, offset=-1):
106
+ """Get a float."""
107
+ return self.__getValue(n, offset, "<d", "<{}d")
108
+
109
+ def getUChar(self, n=1, offset=-1):
110
+ """Get an unsigned char."""
111
+ return self.__getValue(n, offset, "<B", "<{}B")
112
+
113
+ def getString(self, n, offset=-1):
114
+ """Get a string array."""
115
+ out = self.get_from_file("<{}c".format(n), offset)
116
+ ifirst = out.index(b'\x00')
117
+ return b"".join(out[:ifirst])
118
+
119
+
120
+ class HeaderBlock(object):
121
+ """A header block in the IRB file."""
122
+
123
+ UNKNOWN, EMPTY, IMAGE, PREVIEW, TEXT_INFO, HEADER, AUDIO = (
124
+ -1, 0, 1, 2, 3, 4, 7)
125
+
126
+ header_name = {
127
+ UNKNOWN: "Unknown",
128
+ EMPTY: "Empty",
129
+ IMAGE: "Image",
130
+ PREVIEW: "Preview",
131
+ TEXT_INFO: "Text Info",
132
+ HEADER: "Header",
133
+ AUDIO: "Audio"
134
+ }
135
+
136
+ def __init__(self, ifile):
137
+ """Initialize the object.
138
+
139
+ Args:
140
+ ----
141
+ ifile: The input file
142
+
143
+ """
144
+ self.ifile = ifile
145
+ self.where = ifile.tell()
146
+ self.type = ifile.getInt()
147
+ self.word2 = ifile.getInt()
148
+ self.frameIndex = ifile.getInt()
149
+ self.offset = ifile.getInt()
150
+ self.size = ifile.getInt()
151
+
152
+ # head has fixed size of 0x6C0
153
+ # but check against headerSize...
154
+ headerSize = 0x6C0
155
+ if (headerSize > self.size):
156
+ headerSize = self.size
157
+
158
+ # headerOffset = 0
159
+
160
+ self.imageOffset = headerSize
161
+ self.imageSize = self.size - self.imageOffset
162
+
163
+ self.word6 = ifile.getInt()
164
+ self.word7 = ifile.getInt()
165
+ self.word8 = ifile.getInt()
166
+ self.end = ifile.tell()
167
+
168
+ def get_name(self):
169
+ """Return the header type as string."""
170
+ return HeaderBlock.header_name[self.type]
171
+
172
+
173
+ class IRBImage(object):
174
+ """An image in the IRBis file."""
175
+
176
+ FLAGS_OFFSET = 1084
177
+ CELSIUS_OFFSET = 273.15
178
+
179
+ def __init__(self, block):
180
+ """Initialize.
181
+
182
+ Args:
183
+ ----
184
+ ifile: The input file
185
+ block: The block with the information.
186
+
187
+ """
188
+ self.block = block
189
+ ifile = block.ifile
190
+ old_position = ifile.tell()
191
+
192
+ # GEt to the correct position in buffer
193
+ ifile.seek(block.offset)
194
+ self.bytesPerPixel = ifile.getShort()
195
+ self.compressed = ifile.getShort()
196
+ self.width = ifile.getShort()
197
+ self.height = ifile.getShort()
198
+
199
+ zero = ifile.getInt()
200
+ zero = ifile.getShort()
201
+
202
+ widthM1 = ifile.getShort()
203
+ if self.width-1 != widthM1:
204
+ print("width-1 check failed")
205
+
206
+ zero = ifile.getShort()
207
+ heightM1 = ifile.getShort()
208
+ if self.height - 1 != heightM1:
209
+ print("height-1 check failed")
210
+
211
+ zero = ifile.getShort() # -32768 VarioCAM
212
+ zero = ifile.getShort()
213
+
214
+ # Get other parameters
215
+ self.emissivity = ifile.getFloat()
216
+ self.distance = ifile.getFloat()
217
+ self.envTemp = ifile.getFloat()
218
+
219
+ zero = ifile.getShort()
220
+ zero = ifile.getShort() # -32768 VarioCAM
221
+
222
+ self.pathTemp = ifile.getFloat()
223
+
224
+ zero = ifile.getShort() # 0x65 for variocam
225
+ zero = ifile.getShort() # 16256 for VarioCAM
226
+
227
+ self.centerWavelength = ifile.getFloat()
228
+
229
+ zero = ifile.getShort()
230
+ zero = ifile.getShort()
231
+ zero = ifile.getShort()
232
+ zero = ifile.getShort()
233
+
234
+ if self.width > 10000 or self.height > 10000:
235
+ print("Image size out of range ({}x{})".format(
236
+ self.width, self.height))
237
+ return
238
+
239
+ flagsPosition = block.offset + IRBImage.FLAGS_OFFSET
240
+ self.readImageFlags(flagsPosition)
241
+
242
+ # TODO: is this HeaderBlock.headerSize ?
243
+ self.data_offset = 0x6C0
244
+ self.palette_offset = 60
245
+ self.offset = block.offset
246
+ self._image = None
247
+ # self.readImageData(ifile)
248
+
249
+ ifile.seek(old_position)
250
+
251
+ def __getstate__(self):
252
+ """Select memeber that will not be pickled."""
253
+ state = self.__dict__.copy()
254
+ del state['block']
255
+ return state
256
+
257
+ def __setstate__(self, state):
258
+ """Restore block."""
259
+ self.__dict__.update(state)
260
+ self.block = None
261
+
262
+ def readImageFlags(self, position):
263
+ """Read Image Flags."""
264
+ ifile = self.block.ifile
265
+ old_position = ifile.tell()
266
+
267
+ self.calibRangeMin = ifile.getFloat(offset=position+92)
268
+ self.calibRangeMax = ifile.getFloat(offset=position+96)
269
+ self.device = ifile.getString(12, position+142)
270
+ self.deviceSN = ifile.getString(16, position+450)
271
+ self.optics = ifile.getString(32, position+202)
272
+ self.opticsResolution = ifile.getString(32, position+234)
273
+ self.opticsText = ifile.getString(48, position+554)
274
+
275
+ self.shortRangeStartErr = ifile.getFloat(offset=position+532)
276
+ self.shotRangeSize = ifile.getFloat(offset=position+536)
277
+
278
+ self.timeStampRaw = ifile.getDouble(offset=position+540)
279
+ self.timestampMillisecond = ifile.getInt(offset=position+548)
280
+ self.timestamp = ole2datetime(self.timeStampRaw)
281
+
282
+ ifile.seek(old_position)
283
+
284
+ def readImageData(self):
285
+ """Get Image data."""
286
+ ifile = self.block.ifile
287
+ offset = self.offset
288
+ data_offset = self.data_offset
289
+ palette_offset = self.palette_offset
290
+ dataSize = self.width * self.height
291
+ self._image = np.zeros(dataSize)
292
+ matrixDataPos = 0
293
+ v1_pos = data_offset
294
+ v2_pos = v1_pos + dataSize
295
+ v1 = 0
296
+ v2 = 0
297
+ v2_count = 0
298
+
299
+ # Read Palette
300
+ self.readPalette(ifile, offset + palette_offset)
301
+
302
+ # Read the data
303
+ v1_data = ifile.getUChar(n=dataSize, offset=offset+data_offset)
304
+
305
+ if self.compressed:
306
+ # Compression
307
+ # Read Data
308
+ n2 = self.block.size-data_offset-dataSize
309
+ v2_data = ifile.getUChar(n=n2)
310
+ v2_pos = 0
311
+
312
+ for i in range(dataSize):
313
+ if v2_count < 1:
314
+ v2_count = v2_data[v2_pos]
315
+ v2 = v2_data[v2_pos+1]
316
+ P1 = self.palette[v2+1]
317
+ P2 = self.palette[v2]
318
+ v2_pos += 2
319
+
320
+ v2_count -= 1
321
+
322
+ v1 = v1_data[i]
323
+ f = v1/256.0
324
+
325
+ # linear interpolation betweeen eighboring palette entries
326
+ v = P1*f + P2*(1.0-f)
327
+ if v < 0.0:
328
+ v = 0.0
329
+
330
+ self._image[matrixDataPos] = v
331
+ matrixDataPos += 1
332
+
333
+ else:
334
+ # No compression
335
+ for i in range(dataSize):
336
+ v1 = v2_data[v1_pos]
337
+ v2 = v2_data[v1_pos+1]
338
+ P1 = self.palette[v2+1]
339
+ P2 = self.palette[v2]
340
+ v1_pos += 2
341
+
342
+ f = v1/256.0
343
+
344
+ # linear interpolation betweeen eighboring palette entries
345
+ v = P1*f + P2*(1.0-f)
346
+ if v < 0.0:
347
+ v = 0.0
348
+
349
+ self._image[matrixDataPos] = v
350
+ matrixDataPos += 1
351
+
352
+ self._image -= IRBImage.CELSIUS_OFFSET
353
+ self._image = self.image.reshape(self.height, self.width)
354
+ self._image = np.flipud(self._image)
355
+
356
+ def readPalette(self, ifile, offset):
357
+ """Read palette from input buffer."""
358
+ old_position = ifile.tell()
359
+ ifile.seek(offset)
360
+ self.palette = np.array(ifile.getFloat(n=256))
361
+ ifile.seek(old_position)
362
+
363
+ def __getImage(self):
364
+ """Get image."""
365
+ if self._image is None:
366
+ self.readImageData()
367
+
368
+ return self._image
369
+
370
+ def __setImage(self, val):
371
+ """Set the image."""
372
+ self._image = val
373
+
374
+ def __delImage(self):
375
+ """Delete the imafe"""
376
+ del self._image
377
+
378
+ # Get image
379
+ image = property(lambda self: self.__getImage(),
380
+ lambda self, val: self.__setImage(val),
381
+ lambda self: self.__delImage())
382
+
383
+
384
+ class IRBFile(object):
385
+ """An IRB file.
386
+
387
+ Read a file or list of files and store the different blocks and immages.
388
+
389
+ Examples
390
+ --------
391
+ An IRB file is opened like this:
392
+
393
+ irbf = IRBFile.open_file( file )
394
+
395
+ This wull get just the header information, but not yet the full heavy
396
+ load of values per pixel. These will only be loaded when access is
397
+ requested.
398
+
399
+ One can iterate over the images or frames using
400
+ irbf.images()
401
+
402
+ That will return an iterator. An example of use:
403
+
404
+ for i, img in enumerate(irbf.images()):
405
+ values_i = img.image ...
406
+
407
+ One can access a given image by its index:
408
+ img = irbf.getImage(i)
409
+
410
+ The total nubmer of images of frams available is given by
411
+ irbf.n_images()
412
+
413
+ """
414
+
415
+ def __init__(self, fname, concatenate=False):
416
+ """Initialize.
417
+
418
+ Args:
419
+ ----
420
+ fname: Path of input file or list of files.
421
+
422
+ """
423
+ self.concatenate = concatenate
424
+ self.imgList = []
425
+ self.blocks = []
426
+ self.ifiles = []
427
+ self.file_images = []
428
+ self.current_file = 0
429
+
430
+ if not is_iterable(fname):
431
+ fname = [fname]
432
+
433
+ for fnam in fname:
434
+ fb = open(fnam, 'rb')
435
+ ifile = BinaryFile(fb)
436
+ if not concatenate:
437
+ self.imgList = []
438
+
439
+ self.parseHeader(ifile)
440
+ self.ifiles.append(ifile)
441
+ self.file_images.append(self.imgList)
442
+
443
+ self.set_file(self.current_file)
444
+
445
+ def __getstate__(self):
446
+ """Select memeber that will not be pickled."""
447
+ state = self.__dict__.copy()
448
+ del state['blocks']
449
+ del state['ifiles']
450
+ return state
451
+
452
+ def __setstate__(self, state):
453
+ """Restore block."""
454
+ self.__dict__.update(state)
455
+ self.blocks = []
456
+ self.ifiles = []
457
+
458
+ # number of files
459
+ nfiles = property(lambda self: len(self.ifiles))
460
+
461
+ # number of images
462
+ nimages = property(lambda self: len(self.imgList))
463
+
464
+ def parseHeader(self, ifile):
465
+ """Read the header."""
466
+ magic = ifile.read(5)
467
+ # if magic[1:-1] != "IRB":
468
+ # print("Not an IRB file")
469
+
470
+ # GEt the file type
471
+ self.fileType = ifile.read(8)
472
+ if b"IRBIS" in self.fileType:
473
+ self.is_sequence = True
474
+ else:
475
+ self.is_sequence = False
476
+
477
+ # GEt Second filetype (ignored)
478
+ tmp = ifile.read(8)
479
+
480
+ flag1 = ifile.getInt()
481
+ blockOffset = ifile.getInt()
482
+ blockCount = ifile.getInt()
483
+
484
+ # Get the blocks
485
+ ifile.seek(blockOffset)
486
+ for iblk in range(blockCount):
487
+ block = HeaderBlock(ifile)
488
+ if block.type != HeaderBlock.EMPTY:
489
+ self.blocks.append(block)
490
+
491
+ for block in self.blocks:
492
+ if block.type == HeaderBlock.IMAGE:
493
+ image = IRBImage(block)
494
+ self.imgList.append(image)
495
+
496
+ if self.is_sequence:
497
+ offset = -1
498
+ for block in self.blocks:
499
+ if block.type == HeaderBlock.HEADER:
500
+ offset = block.offset
501
+
502
+ ifile.seek(offset)
503
+ while True:
504
+ space_left = ifile.end - ifile.tell()
505
+ if space_left < 32:
506
+ break
507
+
508
+ block = HeaderBlock(ifile)
509
+ if block.type == HeaderBlock.IMAGE:
510
+ if block.offset + block.imageSize > ifile.end:
511
+ break
512
+
513
+ image = IRBImage(block)
514
+ self.imgList.append(image)
515
+
516
+ elif block.type == HeaderBlock.HEADER:
517
+ offset = block.offset
518
+ ifile.seek(offset)
519
+
520
+ elif block.type == HeaderBlock.TEXT_INFO:
521
+ pass
522
+
523
+ def set_concatenate(self, val):
524
+ """Set the 'concatenate' mode.
525
+
526
+ If trye Files are read one after the other, if False, fileas are read in parallel.
527
+ """
528
+ if self.concatenate == val:
529
+ return
530
+
531
+ self.concatenate = val
532
+ self.imgList = []
533
+ for i in range(self.nfiles):
534
+ for im in self.file_images[i]:
535
+ self.imgList.append(im)
536
+
537
+ def set_file(self, i):
538
+ """Selects i-th file.
539
+
540
+ This will select the images from that file.
541
+
542
+ Args:
543
+ i: the index of the file.
544
+ """
545
+ if i < 0 or i > self.nfiles:
546
+ raise IndexError
547
+
548
+ self.current_file = i
549
+ self.imgList = self.file_images[i]
550
+
551
+ def getImage(self, i):
552
+ """Get i-th image in current file.
553
+
554
+ Use set_file to change to another IRBfile.
555
+ """
556
+ if i > self.nimages:
557
+ return None
558
+
559
+ if self.imgList[i].image is None:
560
+ self.imgList[i].readImageData()
561
+
562
+ return self.imgList[i]
563
+
564
+ def images(self, first=0, nframes=-1):
565
+ """Generator to loop on images in current file."""
566
+ nyield = 0
567
+ if self.concatenate:
568
+ for i, im in enumerate(self.imgList):
569
+ if i < first:
570
+ continue
571
+
572
+ if nframes > 0 and nyield >= nframes:
573
+ break
574
+
575
+ nyield += 1
576
+ yield [im]
577
+ else:
578
+ for i, im in enumerate(zip(*self.file_images)):
579
+ if i < first:
580
+ continue
581
+
582
+ if nframes > 0 and nyield >= nframes:
583
+ break
584
+
585
+ nyield += 1
586
+ yield im
587
+
588
+ def append_average(self, nframes=-1, debug=False):
589
+ """Append the average of all images to the list of images.
590
+
591
+ Args:
592
+ ----
593
+ debug (bool, optional): True for debugging. Defaults to False.
594
+
595
+ Raises
596
+ ------
597
+ RuntimeError: Will raise a RunTimeError if IRBfile is empty.
598
+
599
+ """
600
+ # Get all images
601
+ out = []
602
+ for ifile in range(self.nfiles):
603
+ self.set_file(ifile)
604
+ list_values = []
605
+ if nframes < 0:
606
+ nframes = self.nimages
607
+
608
+ img = None
609
+ for i in range(self.nimages):
610
+ img = self.getImage(i)
611
+ if debug:
612
+ print('Image: ', i, ) # ' - Size: ',img.height,' x ', img.width)
613
+
614
+ values_i = img.image
615
+ list_values.append(values_i)
616
+ if i >= nframes:
617
+ break
618
+
619
+ if len(list_values) == 0:
620
+ continue
621
+
622
+ # and compute the average
623
+ values_average = np.mean(list_values, axis=0)
624
+
625
+ # Append the average to the list
626
+ # Copy data from last image for average_image, some info will be replaced
627
+ avg_img = copy.copy(img)
628
+ self.imgList.append(avg_img)
629
+
630
+ # Replace values of last img with values for average_image
631
+ # avg_img.block.end = 0 # Unsure what this is...
632
+ # avg_img.block.frameIndex += 1 # Correct
633
+ # avg_img.block.ifile.end = 0 # ifile is a bit weird to understand, but the only obviious difference is end
634
+ # avg_img.block.imageSize = 0 # Unsure what this is...
635
+ # avg_img.block.offset = 0 # Unsure what this is...
636
+ # avg_img.block.size = 0 # Unsure what this is...
637
+ # avg_img.block.where = 0 # Unsure what this is...
638
+ # avg_img.offset = 0 # Unsure what this is... 98: 8769050, 99: 88362978
639
+ # avg_img.palette = np.zeros(256,) # Unsure what this is...
640
+ # avg_img.timeStampRaw = img.timeStampRaw # currently the timestamp of the last image/frame
641
+ # avg_img.timestamp = img.timestamp # currently the timestamp of the last image/frame
642
+ # avg_img.timestampMillisecond = img.timestampMillisecond # currently the timestamp of the last image/frame
643
+ avg_img.image = values_average # Here go the new values
644
+ self.has_average = True
645
+
646
+ # Hope I found them all!
647
+ print('Average calculated!')
648
+
649
+ if debug:
650
+ x = 0
651
+ y = 0
652
+ xy_average = np.mean([frame[x, y]for frame in list_values])
653
+
654
+ print('Average on pixel ', x, ' , ', y, ' is ', xy_average)
655
+ print('The pixel ', x, ' , ', y, ' is in values_average is ', values_average[x, y])
656
+
657
+ out.append(avg_img)
658
+
659
+ if len(out) != self.nfiles:
660
+ raise RuntimeError("No images found to compute the average")
661
+
662
+ return out
663
+
664
+ def save(self, fname):
665
+ """Save teh list of images in pickle format."""
666
+ # Be sure that all images are loaded.
667
+ for i in range(self.nimages):
668
+ if self.imgList[i].image is None:
669
+ self.imgList[i].readImageData()
670
+
671
+ with bz2.BZ2File(fname, 'w') as ofile:
672
+ pickle.dump(self, ofile)
673
+
674
+ @staticmethod
675
+ def load(fname):
676
+ """Load an IRBFile objecr."""
677
+ out = None
678
+ with bz2.BZ2File(fname, 'rb') as ifile:
679
+ out = pickle.load(ifile)
680
+
681
+ return out
682
+
683
+
684
+ def open_file(fname):
685
+ """Opens a file an returns a IRBFile instance.
686
+
687
+ Args:
688
+ ----
689
+ fname: Path of input file or list of files.
690
+
691
+ """
692
+ irb = None
693
+ if is_iterable(fname):
694
+ # we assume it is a list of IRB files...
695
+ try:
696
+ irbf = IRBFile(fname)
697
+
698
+ except FileNotFoundError as eee:
699
+ print(eee)
700
+
701
+ else:
702
+ # it is a single file path. Check that it exists.
703
+ ifile = Path(fname).expanduser().resolve()
704
+ if not ifile.exists():
705
+ print("Input file does not exist.")
706
+ return None
707
+
708
+ suffix = ifile.suffix.lower()
709
+ if suffix == ".irb":
710
+ irbf = IRBFile(fname)
711
+
712
+ else:
713
+ try:
714
+ irbf = IRBFile.load(fname)
715
+ except Exception as eee:
716
+ print(eee)
717
+ irbf = None
718
+
719
+ return irbf
720
+
721
+
722
+ if __name__ == "__main__":
723
+ """Example of use of IRBFile.
724
+
725
+ Shows all the images in a file.
726
+
727
+ """
728
+ from argparse import ArgumentParser
729
+ parser = ArgumentParser()
730
+ parser.add_argument('files', nargs='*', help="Input files")
731
+ parser.add_argument("--save", action="store_true",
732
+ default=False,
733
+ help="save all figures")
734
+ options = parser.parse_args()
735
+ if len(options.files) == 0:
736
+ print("I need an input file")
737
+ sys.exit()
738
+
739
+ IRfile = IRBFile(options.files)
740
+ nimgs = IRfile.nimages
741
+ print("Number of images: {}".format(nimgs))
742
+
743
+ fig = None
744
+ nimg = 0
745
+ ratio = -1
746
+ for img in IRfile.images():
747
+ tmin = np.min(img.image)
748
+ print("Tmin {:1f} - {}x{}".format(tmin, img.width, img.height))
749
+ if ratio < 0:
750
+ ratio = float(img.width)/float(img.height)
751
+
752
+ plt.clf()
753
+ plt.gca().clear()
754
+ pcm = plt.imshow(img.image, origin='lower', cmap="jet")
755
+ plt.gca().set_title("Min T. {:.1f} - {}".format(tmin, img.timestamp))
756
+ plt.colorbar(pcm, ax=plt.gca())
757
+ plt.draw()
758
+ if options.save:
759
+ if fig is None:
760
+ fig = plt.gcf()
761
+ fig.set_size_inches(6*ratio, 6)
762
+
763
+ fig.savefig('fig_{}.png'.format(nimg), dpi=300)
764
+ nimg += 1
765
+
766
+ plt.pause(0.00001)
767
+
768
+ plt.show()