Unable to load a segmentation encoded as .tag file

Operating system: Windows 10
Slicer version: 4.13.0
Expected behavior: Load pre-existing segmentation .tag file
Actual behavior: Unable to load

Hello 3Dslicer community,

I’m just starting with this amazing software. I would like to load pre-existing segmentation mask generated from a dicom CT-image using another software and saved as .tag files. I can succesfully load the dicom file, but when I load the .tag file (segmentation mask) nothing happens. That would save me a lot of time as I have hundreds of segmented mask file already saved and would like to manipulate them in 3Dslicer with the corresponding dicom image.

Best,

Max

I’m not aware of that format or of any existing tools in Slicer that will load those files. Usually it’s possible to reverse engineer a format like that. Your best bet is to look for any documentation about the software that generated these files and see if you can maybe find (or write) a converter to a more common format.

Thank you so much for your quick reply. I’m a newbie in dev (medical background) but I know the architecture of these .tag files:

The TAG file format is loosely based on the university of Waterloo IM format.

The image file is composed of two sections:

•The header

•the image binary data.

The Header

The header is entirely composed of lines of ASCII text. Each line is terminated by the characters and (0x0D and 0x0A). The header is terminated by a character (0x0C).

Everything on a line following a “*” will be considered as comments and can be disregarded by the program.

The header is composed of a series of keywords value pairs. The keyword and values are separated by “:”. Each pair of keyword and values are separated by one or more separation characters. The recognized separators are: " " (space), “,” (comma), “\t” (tab) or “\n” (new-line). You can use lowercase or uppercase indifferently in the keywords, the program converts all the keywords characters to uppercase before parsing the header.

The recognized keywords and their permitted values are:

x:

“X” resolution (in pixels).

y:

“Y” resolution (in pixels).

z:

Number of images in the file.

type:

Gives the size of each pixel, the values supported by the program are BYTE or SHORT (only BYTE is used for the “.tag” files).

org_x:

Position in “x”, “y” and “z” of the center of the top left pixel of the image.

org_y:

org_z:

dim_x:

Total dimension in “x” and “y” of the image (in millimeters).

dim_y:

inc_x:

Distance between 2 consecutive pixels in “x” and “y” of the image (in millimeters).

inc_y:

epais:

Slice thickness.

dir_h_x:

X, y and z components of the horizontal direction vector (in patient system).

dir_h_y:

dir_h_z:

dir_v_x:

X, y and z components of the vertical direction vector (in patient system).

dir_v_y:

dir_v_z:

uid:

Unique number used to make sure this tag is associated with the correct GLI image.

chksum:

Checksum of the original GLI image.

x:256 y:256 z:9 type:BYTE

org_x:-204.2221 org_y:-181.8909 org_z:-250.0000

inc_x:0.7105 inc_y:0.7105 epais:5.0000

dir_h_x:1.0000 dir_h_y:0.0000 dir_h_z:0.0000

dir_v_x:0.0000 dir_v_y:1.0000 dir_v_z:0.0000

uid:AFCCCAC6 chksum:09F1588D bin:256

  • number of echos: 0

^L

Sample TAG header

The Image Data

The image data is written in binary form. There are X x Y x Z pixels in the image data. The values for X, Y and Z come from the header. Each pixel takes 1 or 2 bytes according to the value associated with the “type” keyword (tag files use “Byte”, so one byte per pixel). The pixels are written using the algorithm:

      for each image k

                for each line j (starting at the top)

                          for each pixel i (starting at the left)

                                    write pixel [k][j][i] ;

Could that help ?

Best regards,

Max

You can read such images using RawImageGuess extension. You can get image dimensions, spacing, etc. from the information in the image header. RawImageGuess can generate a nhdr header file that you can use to load the .tag file.

You can easily create such nhdr file automatically, using a Python script, by parsing the .tag file header. Mapping from .tag to .nrrd:

  • x, y, z -> sizes
  • type -> type
  • org_* -> space origin
  • inc_* and dir_* -> space_directions (it is a 3x3 matrix, column norms equal inc* values, first column direction is dir_h, second column direction is dir_v, third column direction is cross(dir_h, dir_v))

To make eveyone’s life easier, I would recommend you to ask the developers of the software that generates these .tag files to generate standard .nrrd files instead.

Thank you so much, I’m indeed able to load the .tag file using the .nhdr header. I do not know how to code in Python to perform this process in batch , I will probably do it manually or a ask around.

I’m now trying to match the original dicom and the mask, but it seems 3D slicer considers them as separated volume. I tried loading the mask from the segmentation module using import labelmask/model nothing happens when I click on import (hence I’m not able to indicate the path of the .nhdr file)… any ideas…?

Best regards,

Max

RawImageGuess always sets a default image orientation, while axes of your input DICOM volume may be oriented differently. To make the segmentation line up with the original DICOM images, you probably need to compute the space_directions matrix as I described above.

Hello,

Thank you very much for your answers. I almost succeeded in alignement, I computed the space direction matrix only using the inc* value and the mask is almost aligned. However, it seems my problem is to correctly indicate the number of size of header (in bytes) : how could I know it? I tried with http://bytesizematters.com/ (lol), it indicates 223 without space but it’s still not correct.

image

So If I get it right, I have to be sure all my parameters are ok by manually checking on 3D slicer, and when everything is ok I can creare a python loop.

May I ask you an advice for the next step : how can I make 3D slicer understand that this file (openned with the .nhdr header) is actually a segmention and not a volume ? In the segmentation tools, nothing happens when I click on “import” (whether I select labelmaps or model).

Best regards,

Maxime

Edit : Here is the .tag file : [2.tag - Google Drive]

You can use the Volumes → Volume Information interface to turn it into a Labelmap volume, then you can import it to a Segmentation

2 Likes

Oh gosh thanks, that indeed works !! I feel I’m almost there :

image

I will try to solve the byte size issue (pretty sure the header size I put is not correct) and then test whether the radiomics extension works correctly on the mask…

If that works, you have just saved me weeks of labour.

Best regards,

Maxime

See some more options of how to conveniently load an image file directly as labelmap volume or segmentation: https://slicer.readthedocs.io/en/latest/user_guide/modules/volumes.html#load-image-file-as-labelmap-volume

Thank you for these tips, it seems I can load it as a labelmap volume directly, but not as a segmentation (since I load an .nhdr file and not a .nrrd)

I tried the radiomics analysis (even though mask is not perfectly aligned), but I have a blank sheet as a results… any ideas?

Maxime

Edit: it’s not a problem of mask/volume as I’m able to calculte segmentation statistics

I’ve added .nhdr as an acceptable extension for segmentation files (in addition to nrrd). It will be available in Slicer Preview Release from tomorrow.