The AuxiliaryData class includes many useful functions that make it easy to read and edit metadata. Editing metadata in Focus requires manual work, whereas this tutorial demonstrates how to automate metadata editing using Python. You can also integrate these functions into larger batch workflows to edit metadata for multiple images at once.
This tutorial outlines how to read and write metadata to a PIX file. Specifically, it looks at various functions with the Python API’s AuxiliaryData class and how they can be used to work with metadata from a PIX file.
Data: The data used in this tutorial is the Demo data available on our Downloads webpage
NOTE: The metadata for band 1 of the l7_fuse.pix file was edited to include the 'Extra_Field' tag in Focus (see Figure 2):
The AuxiliaryData class in the CATALYST Professional Python API allows us to access file and channel metadata from within Python. This tutorial outlines how to read and write metadata, including instructions on copying metadata from one file to another. Before you start the Python script, open the files l7_fuse.pix and l7_ms_atcor.pix in Focus. To view the file’s metadata, right-click on the folder in the file tab and then click Properties. To view channel metadata, expand the channel list in the Files tab, right-click the channel, and click Properties. Take note of the various metadata fields at both the file and channel levels.
For the purpose of this tutorial, we will be editing the file metadata, channel 1 metadata and channel 1 description in our Python script.




The Python API's datasource class is used to get the auxiliary data from the file. The script below uses the l7_fuse.pix and the l7_ms_atcor.pix files
from pci.api import datasource as ds
l7_ms_atcor_file = r"C:\PCI Geomatics\CATALYST Professional\demo\l7_ms_atcor.pix"
l7_fuse_file = r"C:\PCI Geomatics\CATALYST Professional\demo\l7_fuse.pix"
To access the datasets' metadata, they have to be open. This can be done using the 'with' and the 'eAM_WRITE' and 'eAM_READ' clauses:
# opening the dataset
with ds.open_dataset(l7_fuse_file , ds.eAM_WRITE) as fuse, ds.open_dataset(7_ms_atcor_file, ds.eAM_READ) as ms_atcor:
# Reading metadata from files
aux_ms_atcor = ms_atcor.aux_data
aux_fuse = fuse.aux_data
You want to open the datasets in a with clause to ensure that they will be automatically closed when the clause is exited. Use ds.open_dataset to open each of the files. You will need to specify two inputs: the image and the access mode . Uneditable image files can only be opened for reading. Although the l7_ms_atcor.pix file is modifiable, we will just be copying metadata from this file to the l7_fuse.pix file. You will notice that the l7_fuse.pix file is opened as WRITE, which means we will be able to read and write to this file.
Now that the images are open, you can read the metadata from each file. The auxiliary data and metadata about a file and the raster channels can be extracted using l7_ms_atcor.aux_data and l7_fuse.aux_data. The auxiliary data for the two datasets will be saved to their respective variables.
We can now extract metadata information from the metadata map. There is metadata for the entire file and each channel within this map. In the code below, we extract the file-level metadata, create a new metadata field, copy metadata and search for a specific metadata value.
# **Working with File Level metadata**
file_level_metadata = aux_ms_atcor.file_metadata # A
print(file_level_metadata)
# Get a value from the file metadata
unit = aux_ms_atcor.get_file_metadata_value('Units') # B
print("Units: " + unit)
# Copy metadata value from one file to another
new_atmosphere_cond = aux_ms_atcor.get_file_metadata_value('Atmosphere_Condition') # C
aux_fuse.set_file_metadata_value("Atmosphere_Condition", new_atmosphere_cond)
print(aux_fuse.file_metadata)
There are a number of print statements in the code above. These were added to help illustrate the output of each procedure. On line A, the file-level metadata is extracted from the pix file’s auxiliary data. The metadata will be stored in a metadata map , which can be indexed like a dictionary. The metadata for the l7_ms_atcor file looks like {'Adjacency_effect': '0', 'Atmosphere_Condition': 'us', 'Atmosphere_Type': 'Variable', ...}. In this case, Adjacency_effect, Units, Terrain_Reflectance_Iteration, and so on, are the metadata key names as shown in Figure 4. The metadata map also includes the corresponding values for each key.
You can extract a value for a specific key, as shown on line B, get_file_metadata_value requires one value: the name of the metadata key. The variable unit now contains the value of the Units key (Reflectance).
In the aux_fuse, there is no information related to the atmosphere condition of the image. We will copy this information from aux_ms_atcor and add it to a new metadata value in aux_fuse. On line C, the value of the metadata field Atmosphere_Condition from the aux_ms_atcor is saved to the variable new_atmosphere_cond. On the next line, we use set_file_metadata_value to save the value new_date to a newly created metadata field Atmosphere_Condition. When you print aux_fuse.file_metadata , you will notice that the new field has been added.
In addition to the file-level metadata, aux_fuse also includes the metadata for each channel. In this next section of code, we extract the channel count and work with channel 1 to set a new description and delete a metadata value.
# **Working with Channel Level metadata**
# Get the number of channels
channel_count = aux_fuse.chan_count # D
print "Channel count: " + str(channel_count) # E
# Set a new channel description
chan_desc = aux_fuse.get_chan_description(1) # F
print "Old channel description was: " + chan_desc
aux_fuse.set_chan_description("B1: Blue (0.45-0.52)",1) # G
# Delete metadata value
aux_fuse.remove_chan_metadata_value('Extra_Field', 1) # H
# set the modified auxiliary data to the dataset
fuse.aux_data = aux_fuse # I
On line D, the channel count is extracted using chan_count. It is then printed on line E.
The channel description for channel 1 in aux_fuse is extracted on line F. We will then change the channel 1 description on line G with set_chan_description. Remember that you must specify the channel number when using the channel-specific functions.
On line H, the field Extra_Field is removed using remove_chan_metadata_value. This is the final edit that we will make to the metadata.
Throughout the script so far, we have been editing a copy of the metadata map, aux_fuse. In order to save these changes to the actual pix file, we need to set the modified auxiliary data (aux_fuse) back to the dataset (l7_fuse). This is completed on line I. You can check the Python API documentation for more information on the AuxiliaryData class.
Once you run this script, you can reopen the file in Focus and view the metadata again. You will notice the changes that we made, as outlined in the following three figures.


