Click here to download this notebook.

How to use annex tables

When working with CLS tables you might want to save your own editings or processings done with these data.

This can be done using annex tables, a mechanism allowing to use a common read-only reference table while being able to write in a personal annex table.

Warning: Using the AnnexTableManager will change the environment variable GES_TABLE_DIR used to access CLS tables. If a table was already open (using NadirData or any TableMeasure object) this operation will fail. You need to restart your kernel !

The AnnexTableManager is in charge of managing your “annex” environment. It creates and update all the link to the reference tables and allows you to create your personal AnnexTable.

Parameters:

  • location: Location of your annex tables.

  • [optional]reference: Location of the reference tables.

Methods:

  • create_annex: Create a new annex table.

    • name: Name of the annex table.

    • reference: Name of the reference table.

    • fields: List of fields to include in the annex table.

  • remove_annex: Remove the provided annex table data and configuration files.

    • name: Name of the annex table.

  • store_data: Store the provided data into the annex table (Only fields declared at the annex ta creation are stored).

    • annex: Name of the annex table.

    • data: xarray dataset containing fields to store.

Create the annex table

In the following example, we create a new table named TABLE_C_J3_CUSTOM based on TABLE_C_J3_B_GDRD with 5 new fields.

Info: Might want to restart the kernel here

[2]:
os.makedirs(location, exist_ok=True)
[3]:
anx_manager = AnnexTableManager(location=location, reference=reference)
[4]:
# Define your fields
field_edt1 = Field(name="EDITING_1", description="Editing 1 based on ... (xx)")
field_edt2 = Field(name="EDITING_2", description="Editing 2 based on ... (xx)")
field_edt3 = Field(name="EDITING_3", description="Editing 3 based on ... (xx)")
field_custom1 = Field(
    name="FIELD_CUSTOM_1", description="Distance in cm ... (xx)", unit="cm"
)
field_custom2 = Field(
    name="FIELD_CUSTOM_2", description="Area in m^2 ... (xx)", unit="m**2"
)

new_fields = [field_edt1, field_edt2, field_edt3, field_custom1, field_custom2]

Warning: Only do this step once

[5]:
anx_manager.create_annex(
    name="TABLE_C_J3_CUSTOM", reference="TABLE_C_J3_B_GDRD", fields=new_fields
)

Use the annex table to computed new fields

[6]:
# Use your table

start = DateHandler.from_orf(orf="C_J3_GDRD", cycle_nb=122, pass_nb=1, pos="first")
end = DateHandler.from_orf(orf="C_J3_GDRD", cycle_nb=122, pass_nb=2, pos="last")

reader = CLSTableReader(
    name="TABLE_C_J3_CUSTOM",
    date_start=start,
    date_end=end,
    orf="C_J3_GDRD",
    time="time",
    longitude="LONGITUDE",
    latitude="LATITUDE",
)

ad_anx = NadirData(source=reader)
[7]:
# New fields are included
ad_anx.show_fields(containing="(xx)")
[7]:
Name Description Unit
EDITING_1Editing 1 based on ... (xx)unknown
EDITING_2Editing 2 based on ... (xx)unknown
EDITING_3Editing 3 based on ... (xx)unknown
FIELD_CUSTOM_1Distance in cm ... (xx)cm
FIELD_CUSTOM_2Area in m^2 ... (xx)m**2
[8]:
# Already existing ones too
ad_anx.show_fields(containing="wind")
[8]:
Name Description Unit
DYNAMICAL_ATMOSPHERIC_CORRECTION.MODEL.ERA_INTERIMMOG2D high resolution forced with ERA INTERIM pressure and wind fields plus inverse barometer. This correction is computed by am
DYNAMICAL_ATMOSPHERIC_CORRECTION.MODEL.MOG2D_HRMOG2D high resolution forced with ECMWF pressure and wind fields plus inverse barometer. This correction is computed by adding m
WIND_SPEED.ALTIWind Speed modulus computed from the radar echoes. Should not be used over land.m/s
WIND_SPEED.ALTI.RTK_MLE3Wind Speed modulus computed from the radar echoes. Should not be used over land.m/s
WIND_SPEED.ALTI.TRAN2015_2D_MLE4_BIASEDWind speed Tran2015m/s
WIND_SPEED.MODELWind speed from model, should not be used over land. This atmospheric correction is provided courtesy of ECMWF.m/s
WIND_SPEED.MODEL.ERA_INTERIMWind speed from ERA model. Should not be used over land. The main interest of using this model is to have a continuity in the cm/s
WIND_SPEED.MODEL.U_COMPU component of the model wind vector at the altimeter time-tag.m/s
WIND_SPEED.MODEL.V_COMPV component of the model wind vector at the altimeter time tagm/s
WIND_SPEED.RADRadiometer wind speedm/s

New fields might be created using NadirData diagnostics such as the Editing or manually:

[9]:
ad_anx.add_raw_data(name="Wind speed", field=Field(name="WIND_SPEED.ALTI"))

ad_anx.compute()
2025-05-14 11:00:27 INFO    Reading ['LONGITUDE', 'LATITUDE', 'WIND_SPEED.ALTI', 'time']
2025-05-14 11:00:28 INFO    Computing done.
[10]:
ds = ad_anx.data

ds[field_edt1.name] = xr.where(ds["WIND_SPEED.ALTI"] > 5, 1, 0)
ds[field_edt2.name] = xr.where(ds["WIND_SPEED.ALTI"] > 8, 1, 0)
ds[field_custom1.name] = ds["WIND_SPEED.ALTI"] * 36 + 4
[11]:
ds
[11]:
<xarray.Dataset> Size: 372kB
Dimensions:          (time: 6637)
Coordinates:
  * time             (time) datetime64[ns] 53kB 2019-06-01T05:30:29.807497 .....
Data variables:
    LONGITUDE        (time) float64 53kB 17.01 17.14 17.27 ... -11.53 -11.4
    LATITUDE         (time) float64 53kB -66.15 -66.15 -66.15 ... -66.15 -66.15
    WIND_SPEED.ALTI  (time) float64 53kB nan nan nan nan ... 9.85 10.19 7.84
    EDITING_1        (time) int64 53kB 0 0 0 0 0 0 0 0 0 0 ... 1 1 1 1 1 1 1 1 1
    EDITING_2        (time) int64 53kB 0 0 0 0 0 0 0 0 0 0 ... 1 1 1 1 1 1 1 1 0
    FIELD_CUSTOM_1   (time) float64 53kB nan nan nan nan ... 358.6 370.8 286.2

Store newly created data

[12]:
anx_manager.store_data(annex="TABLE_C_J3_CUSTOM", data=ds)

Make diagnostics using these new data

[13]:
# Creating a field based on newly added ones

field_custom1_edited = Field(
    name="Custom_Edited_Field",
    source=f"IIF({field_edt1.name} :== 1, {field_custom1.name}, DV)",
)

field_custom1_edited
[13]:
Name Description Unit
Custom_Edited_FieldIIF(EDITING_1 :== 1, FIELD_CUSTOM_1, DV)unknown
[14]:
ad_anx.add_raw_data(name="My editing 1", field=field_edt1)
ad_anx.add_raw_data(name="My custom field 1", field=field_custom1)

ad_anx.add_time_stat(
    name="Stat made based on my custom field",
    field=field_custom1_edited,
    freq="20min",
    stats=["mean", "median", "std"],
)
[15]:
ad_anx.compute()
2025-05-14 11:00:28 INFO    Reading ['FIELD_CUSTOM_1', 'EDITING_1', 'Custom_Edited_Field']
2025-05-14 11:00:28 INFO    Computing diagnostics ['Stat made based on my custom field']
2025-05-14 11:00:28 INFO    Computing done.
[16]:
cf_plot = CasysPlot(
    data=ad_anx, data_name="Stat made based on my custom field", stat="median"
)

cf_plot.show()
[16]:
../_images/howto_model_annex_tables_27_0.png
[17]:
# Cleaning everything
shutil.rmtree(path=location)