Data readers ============ A data reader scans a directory tree for available data and loads individual fields on demand. All readers inherit from ``MAbstractDataReader``, which provides ``setDataRoot()`` and the pure virtual ``scanDataRoot()``. NWP readers additionally inherit from ``MWeatherPredictionReader``, which adds the standard availability interface (``availableLevelTypes()``, ``availableVariables()``, ``availableInitTimes()``, ``availableValidTimes()``, ``availableEnsembleMembers()``) and the pure virtual ``readGrid(levelType, variableName, initTime, validTime, ensembleMember)``. CF/NetCDF reader ----------------- ``MClimateForecastReader`` reads NetCDF files following the CF (Climate and Forecast) conventions. ``scanDataRoot()`` walks the configured file tree, opens each NetCDF file, and registers all variables together with their level types, init and valid times, and ensemble members. ``readGrid()`` then loads a single field on user request by indexing into the variable along the appropriate time and ensemble dimensions. GRIB reader ------------ ``MGribReader`` reads GRIB files using the ecCodes library. GRIB files do not have an internal index, so scanning every message in a large dataset on startup would be slow. The reader therefore builds a binary *index file* alongside each GRIB file the first time it is opened. Index files use the extension ``.met3d_grib_index_vN``, where N is the current format version (currently 6). Each index stores the per-message metadata that is needed to answer availability queries, including variable name, level type, init and valid time, ensemble member, and the byte offset of the message within the GRIB file. On subsequent startups the reader loads the index instead of re-scanning the file, and ``readGrid()`` uses the stored byte offset to seek directly to the relevant message. The version suffix in the extension ensures that an index written by an older version of Met.3D is not silently reused after the format changes. If the version does not match, the index is regenerated automatically. Trajectory reader ------------------ ``MTrajectoryReader`` reads precomputed trajectory data from NetCDF files. The availability queries follow a different structure than NWP readers: data is organised by forecast init time, trajectory start time (used as valid time), and ensemble member. For the required NetCDF file format, variable names, dimension layout, and required attributes, see the user manual section :ref:`trajectory_data`. Radar reader ------------- ``MRadarReader`` is the abstract base class for radar data readers. It mirrors the role that ``MWeatherPredictionReader`` plays for NWP data, declaring the pure virtual ``readGrid()`` that subclasses must implement. ``MDwdHdf5RadarReader`` reads DWD radar data in HDF5 files following the EUMETNET OPERA radar information model. Data is organised by variable (e.g. DBZH, VRADH), sweep elevation angle, and scan time. The polar grid geometry is described by azimuth and range parameters together with antenna position (lat, lon, height) and beam widths. Raw integer values are converted to physical quantities using the affine formula ``quantity = offset + gain * raw_value``; separate missing values mark areas that were never radiated (nodata) and areas below the measurement threshold (undetect). A second file class, ``NcDwdRadarFile``, handles DWD radar data distributed in a NetCDF variant of the same format.