Skip to content

fix(med): extend field writer to support all MED 4.x numeric types#7

Open
fznoussi wants to merge 1 commit into
mainfrom
feat/med-writer-extended-data-types
Open

fix(med): extend field writer to support all MED 4.x numeric types#7
fznoussi wants to merge 1 commit into
mainfrom
feat/med-writer-extended-data-types

Conversation

@fznoussi
Copy link
Copy Markdown
Collaborator

fix(med): extend field writer to support all MED 4.x numeric types

MED format version 4.x supports multiple numeric types for result
fields (NOEUD, ELNO, ELGA). The field writer was hardcoding a local
mapping inside _write_data() that only covered four types and was
duplicating a mapping that already existed at module level, causing
inconsistency and preventing the use of lighter types such as
FLOAT32 or INT32 for memory optimization.

Context: MED numeric type constants

The MED 4.x specification defines the following numeric type constants
stored in the TYP attribute of each field group in the HDF5 file:

MED_FLOAT32 = 4 single precision float
MED_FLOAT64 = 6 double precision float (was the only type used)
MED_INT32 = 24 32-bit signed integer
MED_INT64 = 26 64-bit signed integer

The TYP attribute written in the HDF5 field group must match exactly
the numpy dtype of the data array being written, otherwise Code_Aster
and other MED readers will misinterpret the binary layout of the field.

Fix : Consolidate numpy_to_med_type at module level

A global mapping covering all five MED numeric types was defined at
module level and was already used elsewhere in the writer. Inside
_write_data() a redundant local mapping with only four entries was
shadowing the global one:

local mapping inside _write_data() - REMOVED

numpy_to_med_type = {
np.dtype("float64"): 6,
np.dtype("float32"): 4,
np.dtype("int32"): 24,
np.dtype("int64"): 26,
}

The local mapping is removed. _write_data() now uses the global
numpy_to_med_type directly, which includes MED_INT and stays in sync
with any future additions:

module level - single source of truth

MED_FLOAT32 = 4
MED_FLOAT64 = 6
MED_INT32 = 24
MED_INT64 = 26

numpy_to_med_type = {
np.dtype("float32"): MED_FLOAT32,
np.dtype("float64"): MED_FLOAT64,
np.dtype("int32"): MED_INT32,
np.dtype("int64"): MED_INT64,
np.dtype("int"): MED_INT,
}

─────────────────────────────────────────────────────────────────────
Fix B - Add tracker parameter to _write_data signature
─────────────────────────────────────────────────────────────────────
A tracker parameter was added to _write_data() to support future
field tracking (e.g. MED 4.1 field bitmask writer). It is not used
in the current implementation and defaults to None, preserving full
backward compatibility with all existing call sites.

Tests added :

Three test functions were added to cover the mapping and the round-trip:

test_med_type_mapping (parametrized over float32, float64, int32, int64)
Verifies that numpy_to_med_type returns the correct MED constant
for each supported dtype.

test_med_type_mapping_unknown_dtype
Verifies that an unsupported dtype (e.g. complex128) raises a
KeyError, making failures explicit rather than silent.

test_med_type_preserved_after_write_read (parametrized, uses tmp_path)
Writes a mesh with point_data cast to each supported dtype, reads
back the HDF5 file with h5py and asserts that the TYP attribute of
each field group matches the expected MED constant. This ensures
that the TYP written in the HDF5 binary layout is consistent with
the actual numpy dtype of the data.

MED format version 4.x supports multiple numeric types for result
fields (NOEUD, ELNO, ELGA). The field writer was hardcoding a local
mapping inside _write_data() that only covered four types and was
duplicating a mapping that already existed at module level, causing
inconsistency and preventing the use of lighter types such as
FLOAT32 or INT32 for memory optimization.

─────────────────────────────────────────────────────────────────────
Context: MED numeric type constants
─────────────────────────────────────────────────────────────────────
The MED 4.x specification defines the following numeric type constants
stored in the TYP attribute of each field group in the HDF5 file:

  MED_FLOAT32 =  4   single precision float
  MED_FLOAT64 =  6   double precision float  (was the only type used)
  MED_INT32   = 24   32-bit signed integer
  MED_INT64   = 26   64-bit signed integer
  MED_INT     = 28   platform-dependent integer

The TYP attribute written in the HDF5 field group must match exactly
the numpy dtype of the data array being written, otherwise Code_Aster
and other MED readers will misinterpret the binary layout of the field.

─────────────────────────────────────────────────────────────────────
Fix A - Consolidate numpy_to_med_type at module level
─────────────────────────────────────────────────────────────────────
A global mapping covering all five MED numeric types was defined at
module level and was already used elsewhere in the writer. Inside
_write_data() a redundant local mapping with only four entries was
shadowing the global one:

  # local mapping inside _write_data() - REMOVED
  numpy_to_med_type = {
      np.dtype(float64): 6,
      np.dtype(float32): 4,
      np.dtype(int32):   24,
      np.dtype(int64):   26,
      # MED_INT (28) was missing
  }

The local mapping is removed. _write_data() now uses the global
numpy_to_med_type directly, which includes MED_INT and stays in sync
with any future additions:

  # module level - single source of truth
  MED_FLOAT32 =  4
  MED_FLOAT64 =  6
  MED_INT32   = 24
  MED_INT64   = 26
  MED_INT     = 28

  numpy_to_med_type = {
      np.dtype(float32): MED_FLOAT32,
      np.dtype(float64): MED_FLOAT64,
      np.dtype(int32):   MED_INT32,
      np.dtype(int64):   MED_INT64,
      np.dtype(int):     MED_INT,
  }

─────────────────────────────────────────────────────────────────────
Fix B - Add tracker parameter to _write_data signature
─────────────────────────────────────────────────────────────────────
A tracker parameter was added to _write_data() to support future
field tracking (e.g. MED 4.1 field bitmask writer). It is not used
in the current implementation and defaults to None, preserving full
backward compatibility with all existing call sites.

─────────────────────────────────────────────────────────────────────
Tests added
─────────────────────────────────────────────────────────────────────
Three test functions were added to cover the mapping and the round-trip:

test_med_type_mapping (parametrized over float32, float64, int32, int64)
  Verifies that numpy_to_med_type returns the correct MED constant
  for each supported dtype.

test_med_type_mapping_unknown_dtype
  Verifies that an unsupported dtype (e.g. complex128) raises a
  KeyError, making failures explicit rather than silent.

test_med_type_preserved_after_write_read (parametrized, uses tmp_path)
  Writes a mesh with point_data cast to each supported dtype, reads
  back the HDF5 file with h5py and asserts that the TYP attribute of
  each field group matches the expected MED constant. This ensures
  that the TYP written in the HDF5 binary layout is consistent with
  the actual numpy dtype of the data.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant