Expand help text and add SVG for harmonize two collections tool

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
nekrut
2026-03-02 01:34:17 +00:00
co-authored by Claude Opus 4.6
parent e63e2c9135
commit cc07f516ca
2 changed files with 120 additions and 18 deletions
@@ -218,31 +218,58 @@ Harmonizes two collections so they contain the same element identifiers in the s
Description
===========
This tool takes two collections and produces two output collections that share exactly the same set of identifiers in the same order. Any identifiers that are present in only one of the two input collections are removed from both outputs. The order of the first input collection is preserved.
This tool takes two collections and produces two output collections that share exactly the same set of identifiers in the same order. It performs two operations:
=======
Example
=======
1. **Intersection** — any identifier that appears in only one of the two input collections is removed from both outputs.
2. **Reordering** — the output elements follow the order of the **first** input collection.
If the inputs are::
This is useful when two collections were produced by independent analyses and you need to pair them element-wise for a downstream tool. Without harmonization, mismatched identifiers or different ordering would cause errors.
Collection 1: [Horse123]
[Donkey543]
[Mule176]
The two input collections do not need to have the same collection type. For example, you can harmonize a ``list`` with a ``list:paired`` — each output preserves the type of its corresponding input.
Collection 2: [Horse]
[Mule176]
[Donkey543]
========
Examples
========
The tool will output::
**Keep only shared identifiers**
Collection 1: [Donkey543]
[Mule176]
Given two collections with partially overlapping identifiers::
Collection 2: [Donkey543]
[Mule176]
Collection 1 (reference order):
Note that ``Horse123`` and ``Horse`` are removed because they do not match between collections.
sampleA → Dataset 1
sampleB → Dataset 2
sampleC → Dataset 3
Collection 2 (different order, extra element):
sampleD → Dataset 4
sampleC → Dataset 5
sampleA → Dataset 6
Output 1 (from Collection 1, matching order preserved)::
sampleA → Dataset 1
sampleC → Dataset 3
Output 2 (from Collection 2, reordered to match Collection 1)::
sampleA → Dataset 6
sampleC → Dataset 5
``sampleB`` and ``sampleD`` are removed because they are not present in both collections.
-------
**No matching identifiers**
If the two collections share no identifiers at all, both outputs will be empty collections.
-------
.. image:: ${static_path}/images/tools/collection_ops/harmonize.svg
:alt: Harmonize two collections to match identifiers and order
:width: 620
-------
@@ -250,5 +277,5 @@ Note that ``Horse123`` and ``Horse`` are removed because they do not match betwe
@QUOTA_USAGE_NOTE@
]]></help>
]]></help>
</tool>
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 680 310" width="680" height="310">
<defs>
<filter id="shadow" x="-4%" y="-4%" width="110%" height="110%">
<feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur"/>
<feComponentTransfer in="blur">
<feFuncA type="linear" slope="0.3"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#555"/>
</marker>
</defs>
<!-- Left: Input Collection 1 (reference order) -->
<rect x="10" y="10" width="200" height="135" rx="8" ry="8" fill="#d9ead3" stroke="#888" stroke-width="1" filter="url(#shadow)"/>
<text x="110" y="28" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="bold" fill="#333">Collection 1</text>
<rect x="22" y="36" width="176" height="26" rx="4" ry="4" fill="#fff" stroke="#aaa" stroke-width="0.7"/>
<text x="110" y="54" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#333">sampleA</text>
<rect x="22" y="68" width="176" height="26" rx="4" ry="4" fill="#f0f0f0" stroke="#999" stroke-width="1" stroke-dasharray="4,2"/>
<text x="110" y="86" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#999">sampleB</text>
<text x="192" y="86" text-anchor="end" font-family="sans-serif" font-size="8" fill="#999">only here</text>
<rect x="22" y="100" width="176" height="26" rx="4" ry="4" fill="#fff" stroke="#aaa" stroke-width="0.7"/>
<text x="110" y="118" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#333">sampleC</text>
<!-- Left: Input Collection 2 (different order) -->
<rect x="10" y="165" width="200" height="135" rx="8" ry="8" fill="#d9ead3" stroke="#888" stroke-width="1" filter="url(#shadow)"/>
<text x="110" y="183" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="bold" fill="#333">Collection 2</text>
<rect x="22" y="191" width="176" height="26" rx="4" ry="4" fill="#f0f0f0" stroke="#999" stroke-width="1" stroke-dasharray="4,2"/>
<text x="110" y="209" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#999">sampleD</text>
<text x="192" y="209" text-anchor="end" font-family="sans-serif" font-size="8" fill="#999">only here</text>
<rect x="22" y="223" width="176" height="26" rx="4" ry="4" fill="#fff" stroke="#aaa" stroke-width="0.7"/>
<text x="110" y="241" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#333">sampleC</text>
<rect x="22" y="255" width="176" height="26" rx="4" ry="4" fill="#fff" stroke="#aaa" stroke-width="0.7"/>
<text x="110" y="273" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#333">sampleA</text>
<!-- Arrow -->
<line x1="225" y1="155" x2="440" y2="155" stroke="#555" stroke-width="2" marker-end="url(#arrowhead)"/>
<text x="333" y="145" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="bold" fill="#555">Harmonize</text>
<text x="333" y="173" text-anchor="middle" font-family="sans-serif" font-size="10" fill="#888">keep shared, match order</text>
<!-- Right: Output Collection 1 -->
<rect x="460" y="10" width="200" height="105" rx="8" ry="8" fill="#d9ead3" stroke="#888" stroke-width="1" filter="url(#shadow)"/>
<text x="560" y="28" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="bold" fill="#333">Output 1</text>
<rect x="472" y="36" width="176" height="26" rx="4" ry="4" fill="#fff" stroke="#aaa" stroke-width="0.7"/>
<text x="560" y="54" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#333">sampleA</text>
<rect x="472" y="68" width="176" height="26" rx="4" ry="4" fill="#fff" stroke="#aaa" stroke-width="0.7"/>
<text x="560" y="86" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#333">sampleC</text>
<!-- Right: Output Collection 2 -->
<rect x="460" y="165" width="200" height="105" rx="8" ry="8" fill="#d9ead3" stroke="#888" stroke-width="1" filter="url(#shadow)"/>
<text x="560" y="183" text-anchor="middle" font-family="sans-serif" font-size="12" font-weight="bold" fill="#333">Output 2</text>
<rect x="472" y="191" width="176" height="26" rx="4" ry="4" fill="#fff" stroke="#aaa" stroke-width="0.7"/>
<text x="560" y="209" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#333">sampleA</text>
<rect x="472" y="223" width="176" height="26" rx="4" ry="4" fill="#fff" stroke="#aaa" stroke-width="0.7"/>
<text x="560" y="241" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#333">sampleC</text>
<!-- Annotations -->
<text x="560" y="290" text-anchor="middle" font-family="sans-serif" font-size="10" font-style="italic" fill="#666">same identifiers, same order</text>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB