comparison pyramid_upgrade.py @ 1:f183d9de4622 draft

planemo upload for repository https://github.com/ohsu-comp-bio/ashlar commit 95998c84e130c9f3d2183591957464df7d90dd53
author goeckslab
date Wed, 24 Aug 2022 19:19:40 +0000
parents b3054f3d42b2
children
comparison
equal deleted inserted replaced
0:b3054f3d42b2 1:f183d9de4622
1 import sys
2 import os
3 import argparse 1 import argparse
4 import struct 2 import dataclasses
5 import re
6 import fractions 3 import fractions
7 import io 4 import io
5 import os
6 import re
7 import reprlib
8 import struct
9 import sys
8 import xml.etree.ElementTree 10 import xml.etree.ElementTree
9 import collections 11 from typing import Any, List
10 import reprlib
11 import dataclasses
12 from typing import List, Any
13 12
14 13
15 datatype_formats = { 14 datatype_formats = {
16 1: "B", # BYTE 15 1: "B", # BYTE
17 2: "s", # ASCII 16 2: "s", # ASCII
18 3: "H", # SHORT 17 3: "H", # SHORT
19 4: "I", # LONG 18 4: "I", # LONG
20 5: "I", # RATIONAL (pairs) 19 5: "I", # RATIONAL (pairs)
21 6: "b", # SBYTE 20 6: "b", # SBYTE
22 7: "B", # UNDEFINED 21 7: "B", # UNDEFINED
23 8: "h", # SSHORT 22 8: "h", # SSHORT
24 9: "i", # SLONG 23 9: "i", # SLONG
25 10: "i", # SRATIONAL (pairs) 24 10: "i", # SRATIONAL (pairs)
26 11: "f", # FLOAT 25 11: "f", # FLOAT
27 12: "d", # DOUBLE 26 12: "d", # DOUBLE
28 13: "I", # IFD 27 13: "I", # IFD
29 16: "Q", # LONG8 28 16: "Q", # LONG8
30 17: "q", # SLONG8 29 17: "q", # SLONG8
31 18: "Q", # IFD8 30 18: "Q", # IFD8
32 } 31 }
33 rational_datatypes = {5, 10} 32 rational_datatypes = {5, 10}
34 33
35 34
36 class TiffSurgeon: 35 class TiffSurgeon:
251 + f"count={self.count!r}, data={self.data!r}, " 250 + f"count={self.count!r}, data={self.data!r}, "
252 + f"value={self.vrepr(self.value)}" 251 + f"value={self.vrepr(self.value)}"
253 + ")" 252 + ")"
254 ) 253 )
255 254
255
256 @dataclasses.dataclass(frozen=True) 256 @dataclasses.dataclass(frozen=True)
257 class TagSet: 257 class TagSet:
258 """Container for Tag objects as stored in a TIFF IFD. 258 """Container for Tag objects as stored in a TIFF IFD.
259 259
260 Tag objects are maintained in a list that's always sorted in ascending order 260 Tag objects are maintained in a list that's always sorted in ascending order
291 def __delitem__(self, code): 291 def __delitem__(self, code):
292 try: 292 try:
293 i = self.codes.index(code) 293 i = self.codes.index(code)
294 except ValueError: 294 except ValueError:
295 raise KeyError(code) from None 295 raise KeyError(code) from None
296 self.tags[:] = self.tags[:i] + self.tags[i+1:] 296 self.tags[:] = self.tags[:i] + self.tags[i + 1:]
297 297
298 def __contains__(self, code): 298 def __contains__(self, code):
299 return code in self.codes 299 return code in self.codes
300 300
301 def __len__(self): 301 def __len__(self):
326 elif tag.code < t.code: 326 elif tag.code < t.code:
327 break 327 break
328 else: 328 else:
329 i = len(self.tags) 329 i = len(self.tags)
330 n = len(self.tags) 330 n = len(self.tags)
331 self.tags[i:n+1] = [tag] + self.tags[i:n] 331 self.tags[i:n + 1] = [tag] + self.tags[i:n]
332 332
333 333
334 @dataclasses.dataclass(frozen=True) 334 @dataclasses.dataclass(frozen=True)
335 class Ifd: 335 class Ifd:
336 tags: TagSet 336 tags: TagSet
370 370
371 371
372 def parse_args(): 372 def parse_args():
373 parser = argparse.ArgumentParser( 373 parser = argparse.ArgumentParser(
374 description="Convert an OME-TIFF legacy pyramid to the BioFormats 6" 374 description="Convert an OME-TIFF legacy pyramid to the BioFormats 6"
375 " OME-TIFF pyramid format in-place.", 375 " OME-TIFF pyramid format in-place.",
376 ) 376 )
377 parser.add_argument("image", help="OME-TIFF file to convert") 377 parser.add_argument("image", help="OME-TIFF file to convert")
378 parser.add_argument( 378 parser.add_argument(
379 "-n", 379 "-n",
380 dest="channel_names", 380 dest="channel_names",
381 nargs="+", 381 nargs="+",
382 default=[], 382 default=[],
383 metavar="NAME", 383 metavar="NAME",
384 help="Channel names to be inserted into OME metadata. Number of names" 384 help="Channel names to be inserted into OME metadata. Number of names"
385 " must match number of channels in image. Be sure to put quotes" 385 " must match number of channels in image. Be sure to put quotes"
386 " around names containing spaces or other special shell characters." 386 " around names containing spaces or other special shell characters."
387 ) 387 )
388 args = parser.parse_args() 388 args = parser.parse_args()
389 return args 389 return args
390 390
391 391
449 sys.exit(1) 449 sys.exit(1)
450 if any(dims != (size_x, size_y) for dims in page_dims[:size_c]): 450 if any(dims != (size_x, size_y) for dims in page_dims[:size_c]):
451 print(f"TIFF does not begin with SizeC={size_c} full-size pages.") 451 print(f"TIFF does not begin with SizeC={size_c} full-size pages.")
452 sys.exit(1) 452 sys.exit(1)
453 for level in range(1, num_levels): 453 for level in range(1, num_levels):
454 level_dims = page_dims[level * size_c : (level + 1) * size_c] 454 level_dims = page_dims[level * size_c: (level + 1) * size_c]
455 if len(set(level_dims)) != 1: 455 if len(set(level_dims)) != 1:
456 print( 456 print(
457 f"Pyramid level {level + 1} out of {num_levels} has inconsistent" 457 f"Pyramid level {level + 1} out of {num_levels} has inconsistent"
458 f" sizes:\n{level_dims}" 458 f" sizes:\n{level_dims}"
459 ) 459 )
511 new_omexml = xml_file.getvalue() 511 new_omexml = xml_file.getvalue()
512 512
513 print("Writing new TIFF headers...") 513 print("Writing new TIFF headers...")
514 stale_ranges = [ifd.offset_range for ifd in tiff.ifds] 514 stale_ranges = [ifd.offset_range for ifd in tiff.ifds]
515 main_ifds = tiff.ifds[:size_c] 515 main_ifds = tiff.ifds[:size_c]
516 channel_sub_ifds = [tiff.ifds[c + size_c : : size_c] for c in range(size_c)] 516 channel_sub_ifds = [tiff.ifds[c + size_c::size_c] for c in range(size_c)]
517 for i, (main_ifd, sub_ifds) in enumerate(zip(main_ifds, channel_sub_ifds)): 517 for i, (main_ifd, sub_ifds) in enumerate(zip(main_ifds, channel_sub_ifds)):
518 for ifd in sub_ifds: 518 for ifd in sub_ifds:
519 if 305 in ifd.tags: 519 if 305 in ifd.tags:
520 stale_ranges.append(ifd.tags[305].offset_range) 520 stale_ranges.append(ifd.tags[305].offset_range)
521 del ifd.tags[305] 521 del ifd.tags[305]