Who this is for: anyone who has a folder full of ImageXpress TIFF files that OMERO refuses to import as a plate, and who has never run a Python script before. No programming knowledge is assumed. Every command you need to type is written out in full.
If you already know your way around conda and the command line, you only need this:
conda create -n omero-htd -c conda-forge python=3.11 tifffile -y
conda activate omero-htd
python make_imagexpress_htd.py "D:\Screens\MyPlate_Plate_101" --inspect-channels
python make_imagexpress_htd.py "D:\Screens\MyPlate_Plate_101"
Everyone else, read on.
When MetaXpress exports a plate, it writes a small text file ending in
.HTD next to the images. That file is a table of contents: it says how many
rows and columns the plate has, which wells were imaged, how many sites per
well, and how many wavelengths.
OMERO needs that file. Without it, OMERO looks at your folder and sees a few thousand unrelated pictures. With it, OMERO sees one plate, with wells laid out in a grid, channels merged together, and sites grouped per well.
Your images were never exported, so the .HTD was never written. But all the
information it contains is still recoverable — it is sitting in the filenames
and in the headers of the TIFF files themselves. This script reads both and
writes the missing .HTD for you.
The script never modifies or moves your images. It only reads them, and writes one new small text file.
The script expects the MetaXpress naming convention. A typical plate folder:
MyPlate_Plate_101\
TimePoint_1\
MyPlate_A01_s1_w1.TIF
MyPlate_A01_s1_w2.TIF
MyPlate_A01_s2_w1.TIF
...
Reading one filename, MyPlate_A01_s2_w1.TIF:
| Piece | Meaning |
|---|---|
MyPlate |
the plate prefix — every file in the plate shares it |
A01 |
the well (row A, column 1) |
s2 |
site 2 — the second field of view in that well |
w1 |
wavelength 1 — the first channel, e.g. DAPI |
The _s and _w parts are optional; single-site or single-channel plates
just leave them out. A flat folder with no TimePoint_1 subfolder is fine too.
Some systems add a long jumble of letters and numbers after the wavelength
(..._w1 9F3A1B2C-4D5E-....TIF) — that is handled.
If your filenames look nothing like this, stop here. This approach cannot
work, because OMERO reconstructs the filenames from the convention. Ask for the
.companion.ome approach instead.
Skip this section if you already have Miniforge or Anaconda installed.
Download Miniforge from https://conda-forge.org/download/ and run the installer. Accept all the defaults. When it asks whether to add conda to your PATH, you can leave that unchecked — the next section explains why it doesn't matter.
This is the step that trips up almost everyone, so read it carefully.
You do not use the normal Windows Command Prompt, and you do not double-click the script. You use a special terminal that the conda installer created for you.
Press the Start button and type Miniforge Prompt (or Anaconda Prompt if you installed Anaconda). Click it. A black window opens with a line that ends in something like:
(base) C:\Users\Rudmer>
That (base) in brackets at the start of the line is important. It tells you
which Python environment is currently switched on. Keep an eye on it — it is
going to change in the next step, and if it doesn't change, something went
wrong.
If you open the ordinary Command Prompt instead, you will get
'conda' is not recognized as an internal or external command. That error does not mean conda failed to install. It means you are in the wrong window. Close it and open the Miniforge Prompt.
An "environment" is a private, self-contained Python installation. Making one per project means installing something for this script can never break a different project. It costs nothing to make.
Type this into the Miniforge Prompt and press Enter:
conda create -n omero-htd -c conda-forge python=3.11 tifffile -y
It will churn for a minute or two and print a lot of text. omero-htd is just
a name; you could call it anything.
tifffile is the one extra package the script uses. It is what lets the script
peek inside your TIFF files to find the channel names. The script still runs
without it — you just get channels called w1, w2 instead of DAPI, FITC.
Creating an environment does not switch it on. You have to activate it, and you have to do it again every time you open a new Miniforge Prompt window.
conda activate omero-htd
Now look at the start of your line. It should have changed from (base) to:
(omero-htd) C:\Users\Rudmer>
If it still says (base), the activation did not work and nothing after this
will run correctly. This is by far the most common problem people hit.
Why does this matter so much? If you skip activation, you are still using the
(base)environment, which does not havetifffileinstalled. You'll either get aModuleNotFoundError, or — more confusingly — the script will run but quietly fall back to naming your channelsw1,w2,w3and you won't know why.
You need two paths: where the script is, and where your plate folder is.
The easy way: put make_imagexpress_htd.py in a folder you can find, say
D:\Scripts. In the Miniforge Prompt, go there:
D:
cd \Scripts
(On Windows, switching to another drive letter needs its own command — cd D:\Scripts
alone will not move you there from C:. Type D: first, then cd.)
Getting your plate folder path: open Windows Explorer, navigate to the plate folder, click once in the address bar at the top — the path becomes selectable text — and copy it with Ctrl+C. Paste into the terminal with a right-click (Ctrl+V often does not work in these windows).
Always wrap the path in double quotes. If your path contains a space and you don't quote it, the script will see two half-paths and fail:
python make_imagexpress_htd.py "D:\Screens\Plate 12_Plate_101"
Run this first. It only reads; it writes nothing at all.
python make_imagexpress_htd.py "D:\Screens\MyPlate_Plate_101" --inspect-channels
You'll see something like:
Plate folder : D:\Screens\MyPlate_Plate_101
Prefix : MyPlate
TIFFs matched: 4608
Plate format : 384-well (16 x 24)
Wells with data: 384 (A01 .. P24)
Sites : 4 (declared as 1 x 4)
Wavelengths : 2 -> DAPI, Alexa 488
Timepoints : 1
Z steps : 1
Expected files per well: 8
Channel names read from TIFF headers:
w1: 'DAPI' [3/3 agree, MetaSeries _IllumSetting_]
w2: 'Alexa 488' [3/3 agree, MetaSeries _IllumSetting_]
To use these names: --wave-names "DAPI,Alexa 488"
Read every line and sanity-check it against what you know you acquired. The script is inferring all of this; if it inferred something wrong, this is where you catch it, not after a four-hour import.
- Is the plate format right? A 384-well plate where you only used the first two
rows will be correctly detected as 384-well only if some well beyond row H
or column 12 was imaged. Otherwise it guesses 96. Fix with
--plate-type 384. - Is the site count right?
- Are the channel names right?
The script opens three files per channel, taken from wells spread across the plate, and compares what they say. If they disagree you'll see:
w3: 'Texas Red' DISAGREEMENT across files -> 'Texas Red'x2, 'Cy5'x1
Note the quotes in the suggested --wave-names "DAPI,Alexa 488". If any channel
name contains a space, the whole list must be quoted or the terminal will treat
it as two separate arguments.
A disagreement means the illumination setting was not the same everywhere on the plate,
which is worth understanding before you go further. The script picks the
majority and carries on, but you should set the name yourself once you know
what happened. Use --channel-samples 8 to open more files and get a clearer
picture.
python make_imagexpress_htd.py "D:\Screens\MyPlate_Plate_101" --dry-run
This prints the exact .HTD it would write, without writing it. You don't
need to understand the contents — it is enough to see that WellsSelection
rows have TRUE where you expect wells, and that the WaveName lines have the
right channel names.
python make_imagexpress_htd.py "D:\Screens\MyPlate_Plate_101"
Ends with:
Wrote D:\Screens\MyPlate_Plate_101\MyPlate.HTD
Now run: omero import "D:\Screens\MyPlate_Plate_101\MyPlate.HTD"
That's the whole job. One new file, roughly 2 KB.
Do not move that file. OMERO works out where your images are from the
.HTDfile's own name and location:MyPlate.HTDtells it to look for files startingMyPlate_, in the same folder. Move it or rename it and OMERO will find zero images.
If you run the script twice you'll get ERROR: ... already exists. That is
deliberate. Add --force if you really do want to overwrite.
Using OMERO.insight (the desktop application): open the importer, browse to
the plate folder, and select the .HTD file — not the folder, and not the
TIFFs. Choose a screen or dataset as the target and import.
Using the command line, if you have the OMERO client tools installed:
omero login
omero import "D:\Screens\MyPlate_Plate_101\MyPlate.HTD"
Either way, check afterwards that it arrived as a Plate with a well grid,
not as a pile of individual images. If you got a pile of images, the .HTD was
not picked up — see the troubleshooting table.
| Option | What it does |
|---|---|
--inspect-channels |
Report channel names and exit. Writes nothing. |
--dry-run |
Print the .HTD without saving it. |
--force |
Overwrite an existing .HTD. |
--plate-type 384 |
Force the plate format instead of guessing. |
--wave-names "DAPI,FITC" |
Set channel names yourself. Order matters: first name is w1. |
--channel-samples 8 |
Open more files per channel when checking names. |
--sites-grid 3x3 |
Declare sites as a 3×3 grid rather than a single row. |
--help |
Show all options. |
| What you see | What it means | What to do |
|---|---|---|
'conda' is not recognized |
Wrong terminal window. | Close it, open the Miniforge Prompt. |
Prompt still says (base) |
Environment not activated. | Run conda activate omero-htd again. |
'python' is not recognized |
Same cause — environment not activated. | As above. |
can't open file 'make_imagexpress_htd.py' |
You are not in the folder holding the script. | cd to it, or type its full path in quotes. |
ERROR: not a directory |
Path typo, or unquoted path with a space. | Re-copy from the Explorer address bar, keep the quotes. |
ERROR: no MetaXpress-style TIFFs found |
Filenames don't match the convention. | Read the listed examples it prints. If they genuinely differ, this approach won't work. |
Channels named w1, w2 instead of real names |
tifffile missing, or your TIFFs carry no channel metadata. |
Check activation. Otherwise pass --wave-names yourself. |
WARNING: ... do not have N files |
Some wells have fewer images than expected. | Often fine — an aborted or partial acquisition. OMERO shows blanks for the gaps. |
WARNING: more than one filename prefix |
Two plates' worth of files in one folder. | Separate them into their own folders and run once per folder. |
| Imports as loose images, not a plate | OMERO ignored the .HTD. |
Check the .HTD sits beside the TIFFs (or beside TimePoint_1) and its name matches the file prefix exactly. |
DISAGREEMENT across files |
Channel name differs between wells. | Investigate, then set it explicitly with --wave-names. |
If you prefer Spyder to the terminal: launch it from within the activated
environment (conda activate omero-htd, then spyder) so it uses the right
Python — launching Spyder from the Start menu will typically give you base
instead, and tifffile will be missing.
Open the script, then set the arguments in Run → Configuration per file → Command line options, entering just the arguments and not the script name:
"D:\Screens\MyPlate_Plate_101" --inspect-channels
Then press F5. Output appears in the console pane.
- conda — the tool that installs Python packages and manages environments.
- environment — a private Python installation for one project.
- activate — switching an environment on for the current terminal window. Must be repeated in every new window.
- package / module — an add-on library.
tifffileis one. - prompt — the
(omero-htd) C:\Users\...>line where you type commands. - argument / option — extra words after the script name that change its
behaviour, e.g.
--dry-run. - HTD — the plate header file this script reconstructs.
- well — one compartment of the plate, e.g.
A01. - site / field — one field of view within a well. Four sites means the microscope imaged four positions in that well.
- wavelength / channel — one fluorescence channel, e.g. DAPI.