diff --git a/ChangeLog b/ChangeLog
index 7d1c5ab2ea063744967e811242bab9cc6c880070..60d0a39cd565c2e01a08634b16d6a5fcfd979c00 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,19 @@
-2024-11-??  Uwe Schulzweida
+2024-11-28  Uwe Schulzweida
 
         * using CGRIBEX library version 2.3.1
 	* Version 2.5.0 released
 
+2024-11-23  Uwe Schulzweida
+
+	* NetCDF: improved HealPIX support
+
+2024-11-04  Uwe Schulzweida
+
+	* reset chunktype if z and t are chunked
+
 2024-10-24  Uwe Schulzweida
 
+	* lock access to NCZARR in CDI_Threadsafe mode
 	* Renamed interface functions streamXXXRecord to streamXXXField
 
 2024-10-22  Uwe Schulzweida
diff --git a/NEWS b/NEWS
index 358f410f56ea015f82b75fc039c596b33b527c0c..d21b4942d545009488a8b484d6f3d109096da300 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,26 @@
 CDI NEWS
 --------
 
+Version 2.5.0 (28 Nov 2024):
+
+   Changes:
+     * NetCDF: improved HealPIX support
+     * reset chunktype if z and t are chunked
+     * lock access to NCZARR in CDI_Threadsafe mode
+
+Version 2.4.4 (19 Sep 2024):
+
+   Fixed bugs:
+     * absolute timeaxis failed with timeunits seconds [Bug #11916]
+
+Version 2.4.2 (21 Jun 2024):
+
+   Changes:
+     * NetCDF4: improved calculation of input chunk cache size
+     * NetCDF4: switched off output chunk cache
+   Fixed bugs:
+     * cdiInqContents: missing lock of non thread-safe netCDF4/HDF5 calls (bug fix)
+
 Version 2.4.1 (21 May 2024):
 
    Changes:
diff --git a/src/stream.c b/src/stream.c
index 8ebd6be67f58a15144661505f6d1f7bed42bda93..8da402e54315b32ad325dd10d22a20672be9b5e9 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -671,10 +671,17 @@ streamOpenID(const char *filename, char filemode, int filetype, int resH)
 #ifndef HAVE_NC4HDF5_THREADSAFE
   if (CDI_Threadsafe)
     {
-#ifndef HAVE_LIBPTHREAD
-      Error("CDI threadsafe failed, pthread support not compiled in!");
+#ifdef HAVE_LIBPTHREAD
+      if (filetype == CDI_FILETYPE_NC4 || filetype == CDI_FILETYPE_NC4C || filetype == CDI_FILETYPE_NCZARR)
+        streamptr->lockIO = true;
+#else
+      static bool lwarn = true;
+      if (lwarn)
+        {
+          lwarn = false;
+          Warning("CDI threadsafe failed, pthread support not compiled in!");
+        }
 #endif
-      if (filetype == CDI_FILETYPE_NC4 || filetype == CDI_FILETYPE_NC4C) streamptr->lockIO = true;
     }
 #endif
 
diff --git a/src/stream_cdf_i.c b/src/stream_cdf_i.c
index a58121a27b819e4e3933634768aaa35dd9a98fc3..9b7565a012bdd95b2b93a32f63d07e6db6648768 100644
--- a/src/stream_cdf_i.c
+++ b/src/stream_cdf_i.c
@@ -55,6 +55,7 @@ typedef struct
   int ncid;
   int varStatus;
   bool ignoreVar;
+  bool isHealPIX;
   bool isCubeSphere;
   bool isCharAxis;
   bool isXaxis;
@@ -544,8 +545,8 @@ cdf_time_dimid(int fileID, int ndims, ncdim_t *ncdims, int nvars, ncvar_t *ncvar
 
           if (dimid0 != CDI_UNDEFID && check_dimids[dimid0] == false)
             {
-              check_dimids[dimid0] = true;
               if (ncdims[dimid0].ncvarid != CDI_UNDEFID && ncdims[dimid0].ncvarid != varid) continue;
+              check_dimids[dimid0] = true;
 
               char sbuf[CDI_MAX_NAME];
               for (int iatt = 0; iatt < ncvar->nattsNC; ++iatt)
@@ -588,6 +589,7 @@ init_ncvars(int nvars, ncvar_t *ncvars, int ncid)
       ncvar->ncid = ncid;
       ncvar->varStatus = UndefVar;
       ncvar->ignoreVar = false;
+      ncvar->isHealPIX = false;
       ncvar->isCubeSphere = false;
       ncvar->isCharAxis = false;
       ncvar->isXaxis = false;
@@ -1486,6 +1488,14 @@ scan_vars_attr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int model
                 {
                   ncvar->gmapid = nc_gmap_id;
                   cdf_set_var(&ncvars[ncvar->gmapid], CoordVar);
+                  int nc_gmap_varid = ncvars[ncvar->gmapid].ncid;
+                  if (cdfCheckAttText(nc_gmap_varid, nc_gmap_id, "grid_mapping_name"))
+                    {
+                      char gridMappingName[CDI_MAX_NAME];
+                      cdfGetAttText(nc_gmap_varid, nc_gmap_id, "grid_mapping_name", CDI_MAX_NAME, gridMappingName);
+                      // if (str_is_equal(gridMappingName, "healpix")) ncvars[ncvar->gmapid].isHealPIX = true;
+                      if (str_is_equal(gridMappingName, "healpix")) ncvar->isHealPIX = true;
+                    }
                 }
               else
                 Warning("%s - %s", nc_strerror(status), attstring);
@@ -1702,6 +1712,31 @@ verify_vars_attr(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
     }
 }
 
+static void
+find_dimtypes(ncvar_t *ncvars, ncvar_t *ncvar, bool *plxdim, bool *plydim, bool *plzdim, int *plcdim)
+{
+  bool lxdim = false, lydim = false, lzdim = false /*, ltdim = false */;
+  int lcdim = 0;
+  int ndims = ncvar->ndims;
+  for (int i = 0; i < ndims; i++)
+    {
+      int dimtype = ncvar->dimtypes[i];
+      lxdim |= (dimtype == X_AXIS);
+      lydim |= (dimtype == Y_AXIS);
+      lzdim |= (dimtype == Z_AXIS);
+      if (ncvar->cvarids[i] != CDI_UNDEFID) lcdim++;
+      // ltdim |= (dimtype == T_AXIS);
+    }
+
+  if (!lxdim && ncvar->xvarid != CDI_UNDEFID && ncvars[ncvar->xvarid].ndims == 0) lxdim = true;
+  if (!lydim && ncvar->yvarid != CDI_UNDEFID && ncvars[ncvar->yvarid].ndims == 0) lydim = true;
+
+  *plxdim = lxdim;
+  *plydim = lydim;
+  *plzdim = lzdim;
+  *plcdim = lcdim;
+}
+
 static void
 cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
 {
@@ -1733,22 +1768,10 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
       if (ncvar->varStatus == DataVar)
         {
           bool lxdim = false, lydim = false, lzdim = false /* , ltdim = false */;
-          int lcdim = 0;
-          int ndims = ncvar->ndims;
-          for (int i = 0; i < ndims; i++)
-            {
-              int dimtype = ncvar->dimtypes[i];
-              lxdim |= (dimtype == X_AXIS);
-              lydim |= (dimtype == Y_AXIS);
-              lzdim |= (dimtype == Z_AXIS);
-              if (ncvar->cvarids[i] != CDI_UNDEFID) lcdim++;
-              // ltdim |= (dimtype == T_AXIS);
-            }
-
+          int lcdim;
+          find_dimtypes(ncvars, ncvar, &lxdim, &lydim, &lzdim, &lcdim);
           int allcdims = lcdim;
-
-          if (!lxdim && ncvar->xvarid != CDI_UNDEFID && ncvars[ncvar->xvarid].ndims == 0) lxdim = true;
-          if (!lydim && ncvar->yvarid != CDI_UNDEFID && ncvars[ncvar->yvarid].ndims == 0) lydim = true;
+          int ndims = ncvar->ndims;
 
           if (lxdim && (lydim || ncvar->gridtype == GRID_UNSTRUCTURED))
             for (int i = ndims - 1; i >= 0; i--)
@@ -1796,21 +1819,9 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
         {
           bool lxdim = false, lydim = false, lzdim = false /*, ltdim = false */;
           int lcdim = 0;
-          int ndims = ncvar->ndims;
-          for (int i = 0; i < ndims; i++)
-            {
-              int dimtype = ncvar->dimtypes[i];
-              lxdim |= (dimtype == X_AXIS);
-              lydim |= (dimtype == Y_AXIS);
-              lzdim |= (dimtype == Z_AXIS);
-              if (ncvar->cvarids[i] != CDI_UNDEFID) lcdim++;
-              // ltdim |= (dimtype == T_AXIS);
-            }
-
+          find_dimtypes(ncvars, ncvar, &lxdim, &lydim, &lzdim, &lcdim);
           int allcdims = lcdim;
-
-          if (!lxdim && ncvar->xvarid != CDI_UNDEFID && ncvars[ncvar->xvarid].ndims == 0) lxdim = true;
-          if (!lydim && ncvar->yvarid != CDI_UNDEFID && ncvars[ncvar->yvarid].ndims == 0) lydim = true;
+          int ndims = ncvar->ndims;
 
           //   if ( ndims > 1 )
           for (int i = ndims - 1; i >= 0; i--)
@@ -1829,7 +1840,7 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
                       dimtype = X_AXIS;
                       lxdim = true;
                     }
-                  else if (!lydim && ncvar->gridtype != GRID_UNSTRUCTURED)
+                  else if (!lydim && ncvar->gridtype != GRID_UNSTRUCTURED && ncvar->isHealPIX == false)
                     // else if ( !lydim && ! (ncvars[ncvar->xvarid].dimids[0] == ncvars[ncvar->yvarid].dimids[0] &&
                     //                        ncvars[ncvar->xvarid].ndims == 1 && ncvars[ncvar->yvarid].ndims == 1))
                     {
@@ -2075,19 +2086,21 @@ grid_set_chunktype(grid_t *grid, ncvar_t *ncvar)
   if (ncvar->isChunked)
     {
       int ndims = ncvar->ndims;
+      size_t chunkSizeAllDims = 1;
+      for (int i = 0; i < ndims; ++i) chunkSizeAllDims *= ncvar->chunks[i];
 
+      size_t dimN = ncvar->chunks[ndims - 1];
       if (grid->type == GRID_UNSTRUCTURED)
         {
-          size_t chunkSize = ncvar->chunks[ndims - 1];
+          size_t chunkSize = (chunkSizeAllDims == dimN) ? dimN : 0;
           ncvar->chunkType = (chunkSize == grid->size) ? CDI_CHUNK_GRID : CDI_CHUNK_AUTO;
           if (ncvar->chunkType == CDI_CHUNK_AUTO && chunkSize > 1) ncvar->chunkSize = (int) chunkSize;
         }
       else
         {
-          if (grid->x.size > 1 && grid->y.size > 1 && ndims > 1 && grid->x.size == ncvar->chunks[ndims - 1]
-              && grid->y.size == ncvar->chunks[ndims - 2])
+          if (grid->x.size > 1 && grid->y.size > 1 && ndims > 1 && grid->x.size == dimN && grid->y.size == ncvar->chunks[ndims - 2])
             ncvar->chunkType = CDI_CHUNK_GRID;
-          else if (grid->x.size > 1 && grid->x.size == ncvar->chunks[ndims - 1])
+          else if (grid->x.size > 1 && grid->x.size == dimN && chunkSizeAllDims == dimN)
             ncvar->chunkType = CDI_CHUNK_LINES;
           else
             ncvar->chunkType = CDI_CHUNK_AUTO;
@@ -4270,7 +4283,7 @@ cdfVerifyVars(int nvars, ncvar_t *ncvars
 }
 
 static CdiDateTime
-wrf_read_timestep(int fileID, int nctimevarid, int tsID)
+wrf_read_timestep(int fileID, int nctimevarid, size_t tsID)
 {
   enum
   {
@@ -4278,7 +4291,7 @@ wrf_read_timestep(int fileID, int nctimevarid, int tsID)
     dateTimeSepPos = 19,
     dateTimeStrSize = 128,
   };
-  size_t start[2] = { (size_t) tsID, 0 }, count[2] = { 1, dateTimeSepPos };
+  size_t start[2] = { tsID, 0 }, count[2] = { 1, dateTimeSepPos };
   char stvalue[dateTimeStrSize];
   stvalue[0] = 0;
   cdf_get_vara_text(fileID, nctimevarid, start, count, stvalue);
@@ -4324,7 +4337,7 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0)
       int fileID = streamptr->fileID;
       int nctimevarid = streamptr->basetime.ncvarid;
       int nctimeboundsid = streamptr->basetime.ncvarboundsid;
-      bool hasTimesteps = (nctimevarid != CDI_UNDEFID && streamptr->basetime.hasUnits);
+      bool hasTimesteps = (nctimevarid != CDI_UNDEFID /*&& streamptr->basetime.hasUnits*/);
 
       int *ncStepIndices = (int *) Malloc(numTimesteps * sizeof(int));
       for (size_t tsID = 0; tsID < numTimesteps; ++tsID) ncStepIndices[tsID] = (int) tsID;
@@ -4337,10 +4350,9 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0)
 
           if (streamptr->basetime.isWRF)
             {
-              for (size_t tsID = 0; tsID < numTimesteps; ++tsID)
-                vDateTimeList[tsID] = wrf_read_timestep(fileID, nctimevarid, (int) tsID);
+              for (size_t tsID = 0; tsID < numTimesteps; ++tsID) vDateTimeList[tsID] = wrf_read_timestep(fileID, nctimevarid, tsID);
             }
-          else
+          else if (streamptr->basetime.hasUnits)
             {
               double *timevarBuffer = (double *) Malloc(numTimesteps * sizeof(double));
               cdf_get_var_double(fileID, nctimevarid, timevarBuffer);
@@ -4348,6 +4360,10 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0)
                 vDateTimeList[tsID] = cdi_decode_timeval(get_timevalue(fileID, nctimevarid, tsID, timevarBuffer), taxis0);
               if (timevarBuffer) Free(timevarBuffer);
             }
+          else
+            {
+              hasTimesteps = false;
+            }
         }
 
       // process query information if available
@@ -4383,6 +4399,7 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0)
         }
 
       if (ncStepIndices) Free(ncStepIndices);
+      if (vDateTimeList) Free(vDateTimeList);
 
       if (hasTimesteps)
         {
@@ -4421,8 +4438,6 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0)
                 }
             }
         }
-
-      if (vDateTimeList) Free(vDateTimeList);
     }
 }
 
@@ -4503,7 +4518,7 @@ find_coordinates_vars(int ndims, ncdim_t *ncdims, int nvars, ncvar_t *ncvars)
 
 // set time dependent data vars
 static void
-find_varying_data_vars(int timedimid, int nvars, ncvar_t *ncvars)
+find_varying_data_vars1d(int timedimid, int nvars, ncvar_t *ncvars)
 {
   for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
     {
@@ -4637,9 +4652,9 @@ cdfInqContents(stream_t *streamptr)
 
   if (CDI_Convert_Cubesphere) check_cube_sphere(vlistID, nvars, ncvars, ncdims);
 
-  if (CDI_Debug) cdf_print_vars(ncvars, nvars, "find_varying_data_vars");
+  if (CDI_Debug) cdf_print_vars(ncvars, nvars, "find_varying_data_vars1d");
 
-  find_varying_data_vars(timedimid, nvars, ncvars);
+  find_varying_data_vars1d(timedimid, nvars, ncvars);
 
   // find time vars
   bool timeHasUnits = false;