Mercurial > repos > perssond > ashlar
comparison rename_channels.py @ 4:0b8423c7ee3e draft default tip
planemo upload for repository https://github.com/ohsu-comp-bio/ashlar commit d1f9d43d20432cc958e340271ba63c85a17ff338
| author | goeckslab |
|---|---|
| date | Wed, 26 Feb 2025 18:09:34 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 3:ef68bc2a4dbc | 4:0b8423c7ee3e |
|---|---|
| 1 # ------------------------------------------------------------------------------------ | |
| 2 # Stripped down and modified from: | |
| 3 # https://github.com/ohsu-comp-bio/ashlar/blob/master/pyramid_upgrade.py | |
| 4 # ------------------------------------------------------------------------------------ | |
| 5 | |
| 6 import argparse | |
| 7 import csv | |
| 8 import xml.etree.ElementTree | |
| 9 | |
| 10 from tifffile import tiffcomment | |
| 11 | |
| 12 | |
| 13 def fix_attrib_namespace(elt): | |
| 14 """Prefix un-namespaced XML attributes with the tag's namespace.""" | |
| 15 # This fixes ElementTree's inability to round-trip XML with a default | |
| 16 # namespace ("cannot use non-qualified names with default_namespace option" | |
| 17 # error). 7-year-old BPO issue here: https://bugs.python.org/issue17088 | |
| 18 # Code inspired by https://gist.github.com/provegard/1381912 . | |
| 19 if elt.tag[0] == "{": | |
| 20 uri, _ = elt.tag[1:].rsplit("}", 1) | |
| 21 new_attrib = {} | |
| 22 for name, value in elt.attrib.items(): | |
| 23 if name[0] != "{": | |
| 24 # For un-namespaced attributes, copy namespace from element. | |
| 25 name = f"{{{uri}}}{name}" | |
| 26 new_attrib[name] = value | |
| 27 elt.attrib = new_attrib | |
| 28 for child in elt: | |
| 29 fix_attrib_namespace(child) | |
| 30 | |
| 31 | |
| 32 def main(image_fh, marker_file): | |
| 33 """ | |
| 34 Parameters | |
| 35 --------- | |
| 36 image_fh : str | |
| 37 File path to the OME Tiff image. | |
| 38 marker_file : str | |
| 39 File path to CSV containing marker name information. | |
| 40 """ | |
| 41 | |
| 42 # parse marker file, create list of new marker names | |
| 43 new_channel_names = [] | |
| 44 with open(marker_file, newline='') as csvfile: | |
| 45 reader = csv.DictReader(csvfile) | |
| 46 for row in reader: | |
| 47 new_channel_names.append(row['marker_name']) | |
| 48 | |
| 49 # read OME-XML metadata and parse down to channels | |
| 50 xml_ns = {"ome": "http://www.openmicroscopy.org/Schemas/OME/2016-06"} | |
| 51 root = xml.etree.ElementTree.fromstring(tiffcomment(image_fh)) | |
| 52 image = root.find("ome:Image", xml_ns) | |
| 53 pixels = image.find("ome:Pixels", xml_ns) | |
| 54 channels = pixels.findall("ome:Channel", xml_ns) | |
| 55 | |
| 56 # name channels | |
| 57 for channel, name in zip(channels, new_channel_names): | |
| 58 channel.attrib["Name"] = name | |
| 59 | |
| 60 # encode new xml and set image metadata | |
| 61 fix_attrib_namespace(root) | |
| 62 new_ome_xml = xml.etree.ElementTree.tostring( | |
| 63 root, | |
| 64 encoding='utf-8', | |
| 65 xml_declaration=True, | |
| 66 default_namespace=xml_ns["ome"]) | |
| 67 | |
| 68 tiffcomment(image_fh, comment=new_ome_xml) | |
| 69 | |
| 70 print("Updated OME-TIFF metadata:") | |
| 71 print(tiffcomment(image_fh)) | |
| 72 | |
| 73 | |
| 74 if __name__ == '__main__': | |
| 75 aparser = argparse.ArgumentParser() | |
| 76 aparser.add_argument("-i", "--image", dest="image", required=True) | |
| 77 aparser.add_argument("-m", "--markers", dest="markers", required=True) | |
| 78 | |
| 79 args = aparser.parse_args() | |
| 80 | |
| 81 main(args.image, args.markers) |
