From 903745e354a19b2fb8529908ce2a0dfeab84725f Mon Sep 17 00:00:00 2001 From: William Moore Date: Tue, 10 May 2022 09:50:37 +0100 Subject: [PATCH 1/3] Add new script Compare_Ome_Xml.py --- omero/export_scripts/Compare_Ome_Xml.py | 140 ++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 omero/export_scripts/Compare_Ome_Xml.py diff --git a/omero/export_scripts/Compare_Ome_Xml.py b/omero/export_scripts/Compare_Ome_Xml.py new file mode 100644 index 000000000..2cdd7c9e2 --- /dev/null +++ b/omero/export_scripts/Compare_Ome_Xml.py @@ -0,0 +1,140 @@ + +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# ----------------------------------------------------------------------------- +# Copyright (C) 2022 University of Dundee. All rights reserved. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +# This script exports the OME.xml from all Images in a Dataset. +# The OME.xml from Images with the same Name is compared and +# any differences are shown in the printed log. + +from xml.etree import ElementTree as ET + +import omero.scripts as scripts +from omero.gateway import BlitzGateway +from omero.rtypes import rlong, rstring, robject, unwrap + + +def get_image_ome_xml(conn, image_id): + + exporter = conn.createExporter() + exporter.addImage(image_id) + size = exporter.generateXml() + xml = exporter.read(0, size) + exporter.close() + return xml + + +def compare_xml(xml1, xml2): + tree1 = ET.ElementTree(ET.fromstring(xml1)) + tree2 = ET.ElementTree(ET.fromstring(xml2)) + + mismatch = False + for child1, child2 in zip(tree1.iter(), tree2.iter()): + # Ignore IDs which will be unique + child1.attrib.pop("ID", None) + child2.attrib.pop("ID", None) + + print("Checking element", child1) + + if child1.attrib != child2.attrib: + mismatch = True + print("-------- ** difference... ** --------------") + print("CHILD1", child1.attrib) + print("CHILD2", child2.attrib) + print("...----------------------") + + return mismatch + + +def process_data(conn, script_params): + """Main entry point. Get images, process them and return result.""" + + dtype = script_params['Data_Type'] + ids = script_params['IDs'] + + comparison_count = 0 + mismatch_count = 0 + + if dtype == "Dataset": + + for dataset in conn.getObjects("Dataset", ids): + xml_by_image_name = {} + for image in dataset.listChildren(): + xml = get_image_ome_xml(conn, image.id) + name = image.name + print("Image...", image.id, image.name) + if name in xml_by_image_name: + print("\n\nChecking images named", name) + prev_img = xml_by_image_name[name]["image"] + print("Compare image ----------", image.id) + print(xml) + print("with image -----------", prev_img.id) + xml2 = xml_by_image_name[name]["xml"] + print(xml2) + # assert xml == xml2 + comparison_count += 1 + + print("xml1 from image", image.id) + print("xml2 from image", prev_img.id) + mismatch = compare_xml(xml, xml2) + if mismatch: + mismatch_count += 1 + else: + xml_by_image_name[name] = {"xml": xml, "image": image} + + return mismatch_count, comparison_count + + +def run_script(): + data_types = [rstring(s) for s in + ['Dataset']] + + client = scripts.client( + 'Compare_Ome_Xml.py', + """Compares OME.xml for Images with the same Names in each Dataset""", + + scripts.String( + "Data_Type", optional=False, grouping="1", + description="The data you want to work with.", values=data_types, + default="Dataset"), + + scripts.List( + "IDs", optional=False, grouping="2", + description="List of Dataset IDs or Image IDs").ofType(rlong(0)), + ) + + try: + conn = BlitzGateway(client_obj=client) + + script_params = client.getInputs(unwrap=True) + print("script_params:") + print(script_params) + + # call the main script + mismatch_count, comparison_count = process_data(conn, script_params) + message = f"Compared OME.xml for {comparison_count} images, found {mismatch_count} diffs" + + client.setOutput("Message", rstring(message)) + + finally: + client.closeSession() + + +if __name__ == "__main__": + run_script() From ae278f15f0e1114e60e8165cf85d28af55b63836 Mon Sep 17 00:00:00 2001 From: William Moore Date: Tue, 10 May 2022 10:02:46 +0100 Subject: [PATCH 2/3] flake8 fixes --- omero/export_scripts/Compare_Ome_Xml.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/omero/export_scripts/Compare_Ome_Xml.py b/omero/export_scripts/Compare_Ome_Xml.py index 2cdd7c9e2..8ae12df95 100644 --- a/omero/export_scripts/Compare_Ome_Xml.py +++ b/omero/export_scripts/Compare_Ome_Xml.py @@ -1,5 +1,4 @@ - -#!/usr/bin/env python +# !/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- @@ -17,17 +16,16 @@ # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# # This script exports the OME.xml from all Images in a Dataset. # The OME.xml from Images with the same Name is compared and # any differences are shown in the printed log. -from xml.etree import ElementTree as ET +from xml.etree import ElementTree import omero.scripts as scripts from omero.gateway import BlitzGateway -from omero.rtypes import rlong, rstring, robject, unwrap +from omero.rtypes import rlong, rstring def get_image_ome_xml(conn, image_id): @@ -41,8 +39,8 @@ def get_image_ome_xml(conn, image_id): def compare_xml(xml1, xml2): - tree1 = ET.ElementTree(ET.fromstring(xml1)) - tree2 = ET.ElementTree(ET.fromstring(xml2)) + tree1 = ElementTree.ElementTree(ElementTree.fromstring(xml1)) + tree2 = ElementTree.ElementTree(ElementTree.fromstring(xml2)) mismatch = False for child1, child2 in zip(tree1.iter(), tree2.iter()): @@ -128,7 +126,8 @@ def run_script(): # call the main script mismatch_count, comparison_count = process_data(conn, script_params) - message = f"Compared OME.xml for {comparison_count} images, found {mismatch_count} diffs" + message = (f"Compared OME.xml for {comparison_count} images," + + f" found {mismatch_count} diffs") client.setOutput("Message", rstring(message)) From 9213cfecb7f71363b1717513002f7b3b86ae5438 Mon Sep 17 00:00:00 2001 From: William Moore Date: Thu, 12 May 2022 10:52:43 +0100 Subject: [PATCH 3/3] Compare Planes by matching Z,C,T first --- omero/export_scripts/Compare_Ome_Xml.py | 60 ++++++++++++++++++++----- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/omero/export_scripts/Compare_Ome_Xml.py b/omero/export_scripts/Compare_Ome_Xml.py index 8ae12df95..9a36018f8 100644 --- a/omero/export_scripts/Compare_Ome_Xml.py +++ b/omero/export_scripts/Compare_Ome_Xml.py @@ -27,6 +27,7 @@ from omero.gateway import BlitzGateway from omero.rtypes import rlong, rstring +elements_by_id = {} def get_image_ome_xml(conn, image_id): @@ -44,22 +45,57 @@ def compare_xml(xml1, xml2): mismatch = False for child1, child2 in zip(tree1.iter(), tree2.iter()): - # Ignore IDs which will be unique - child1.attrib.pop("ID", None) - child2.attrib.pop("ID", None) - - print("Checking element", child1) - - if child1.attrib != child2.attrib: + if nodes_mismatch(child1, child2): mismatch = True - print("-------- ** difference... ** --------------") - print("CHILD1", child1.attrib) - print("CHILD2", child2.attrib) - print("...----------------------") return mismatch +def nodes_mismatch(node1, node2): + # Ignore IDs which will be unique + node1.attrib.pop("ID", None) + node2.attrib.pop("ID", None) + + print("Checking element", node1) + if node1.tag != node2.tag: + print("Node names mismatch:", node1.tag, node2.tag) + return False + + print("TAGS", node1.tag, node2.tag) + # if node comes in List, compare identical nodes + if node1.tag.endswith("Plane"): + for node in [node1, node2]: + theZ = node.attrib.get("TheZ") + theC = node.attrib.get("TheC") + theT = node.attrib.get("TheT") + plane_id = f"Plane:{theZ}:{theC}:{theT}" + print("plane_id", plane_id) + if plane_id in elements_by_id: + nodeA = elements_by_id[plane_id] + nodeB = node + print("Comparing planes", plane_id) + if nodeA.attrib != nodeB.attrib: + print("-------- ** difference... ** --------------") + print("nodeA", nodeA.attrib) + print("nodeB", nodeB.attrib) + print("...----------------------") + return True + else: + elements_by_id[plane_id] = node + return False + + # Directly compare nodes + if node1.attrib != node2.attrib: + print("-------- ** difference... ** --------------") + print("node1", node1.attrib) + print("node2", node2.attrib) + print("...----------------------") + return True + return False + + + + def process_data(conn, script_params): """Main entry point. Get images, process them and return result.""" @@ -74,6 +110,8 @@ def process_data(conn, script_params): for dataset in conn.getObjects("Dataset", ids): xml_by_image_name = {} for image in dataset.listChildren(): + # reset elements registry + elements_by_id = {} xml = get_image_ome_xml(conn, image.id) name = image.name print("Image...", image.id, image.name)