diff --git a/pyswiftsim/dev.py b/pyswiftsim/dev.py
new file mode 100644
index 0000000000000000000000000000000000000000..6646ecf4235022217387f0775c6fdf17ad3dd730
--- /dev/null
+++ b/pyswiftsim/dev.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+
+symbol_table = {
+    " int ": "i",
+    " double ": "d",
+    " char ": "c",
+}
+
+def _generateFormatString(filename):
+    """
+    Open a file containing a single struct and generate a format string
+    from it. (for dev, no guarantee of working).
+    """
+
+    struct_format = ""
+    struct_attribute = []
+    
+    with open(filename, "r") as f:
+        line = ""
+        # skip until reaching struct
+        while ("struct" not in line):
+            line = f.readline()
+
+        count = 0
+        in_struct = False
+
+        while (not in_struct or count != 0):
+            # count { and }
+            count += line.count("{")
+            if (count > 0):
+                in_struct = True
+            count -= line.count("}")
+            line = f.readline()
+
+            for k in symbol_table.keys():
+                if k not in line:
+                    continue
+
+                i = line.index(k) + len(k)
+
+                if (line[i] == "*"):
+                    struct_format += "p"
+                    i += 1
+                else:
+                    struct_format += symbol_table[k]
+
+                j = line.index(";")
+                struct_attribute.append(line[i:j])
+                
+
+    return struct_format, struct_attribute
+
+            
+if __name__ == "__main__":
+
+    filename = "chemistry_data.h"
+    struct_format, struct_attribute = _generateFormatString(filename)
+
+    attr = "[\n"
+    for i in struct_attribute:
+        attr += "\t'%s',\n" % i
+    attr += "]"
+        
+    txt = """
+    _format = "{form}"
+    _name = {attr}
+    """.format(attr=attr,
+               form=struct_format)
+    print(txt)
diff --git a/pyswiftsim/structure.py b/pyswiftsim/structure.py
index 6197a2241d1dfa038cbc64d5836fe261b1618dc5..f42e65e8a1ef0014a6183d68ddb9393a05867121 100644
--- a/pyswiftsim/structure.py
+++ b/pyswiftsim/structure.py
@@ -148,17 +148,15 @@ class SwiftStruct(struct.Struct):
         return out_nber, out_form
 
 
-    def __str__(self):
-        tab = ""
-        parent = self.parent
-        while parent is not None:
-            tab += "\t"
-            parent = parent.parent
-             
+    def __str__(self, tab=""):
         txt = tab + "%s:\n" % type(self)
         for name in self.struct_name:
             d = getattr(self, name)
-            txt += tab + "\t%s: %s\n" % (name, d)
+            txt += tab + "\t%s: " % name
+            if isinstance(d, SwiftStruct):
+                txt += d.__str__(tab+"\t")
+            else:
+                txt += "%s\n" % d
         return txt
 
     def __getattr__(self, name):
@@ -181,7 +179,11 @@ class SwiftStruct(struct.Struct):
                     for j in range(d["size"]):
                         data_tmp = data[i][size*j:(j+1)*size]
                         tmp.append(cl(data_tmp, parent=self))
-                    return tmp
+
+                    if d["size"] == 1:
+                        return tmp[0]
+                    else:
+                        return tmp
                 # other case => array
                 else:
                     return data[i]
@@ -248,10 +250,10 @@ class ArrayStruct(SwiftStruct):
 
         return data
 
-    def __str__(self):
+    def __str__(self, tab=""):
         data = self.unpack(self.data)
         data = self._clean(data)
-        return str(data)
+        return tab + str(data) + "\n"
         
         
     def getArray(self):
@@ -414,6 +416,71 @@ class PhysConst(SwiftStruct):
         super().__init__(self.struct_format, data, parent)
 
 
+class GrackleUnits(SwiftStruct):
+    _format = "idddddd"
+    _name = [
+        "comoving_coordinates",
+        "density_units",
+        "length_units",
+        "time_units",
+        "velocity_units",
+        "a_units",
+        "a_value"
+    ]
+
+    def __init__(self, data, parent=None):
+        super().__init__(self.struct_format, data, parent)
+    
+class GrackleChemistryData(SwiftStruct):
+    _format = "iiiiiPidiidiiiiiiidddiiddiddiiddddddiiiiii"
+    _name = [
+        'use_grackle',
+        'with_radiative_cooling',
+        'primordial_chemistry',
+        'metal_cooling',
+        'UVbackground',
+        'grackle_data_file',
+        'cmb_temperature_floor',
+        'Gamma',
+        'h2_on_dust',
+        'photoelectric_heating',
+        'photoelectric_heating_rate',
+        'use_volumetric_heating_rate',
+        'use_specific_heating_rate',
+        'three_body_rate',
+        'cie_cooling',
+        'h2_optical_depth_approximation',
+        'ih2co',
+        'ipiht',
+        'HydrogenFractionByMass',
+        'DeuteriumToHydrogenRatio',
+        'SolarMetalFractionByMass',
+        'NumberOfTemperatureBins',
+        'CaseBRecombination',
+        'TemperatureStart',
+        'TemperatureEnd',
+        'NumberOfDustTemperatureBins',
+        'DustTemperatureStart',
+        'DustTemperatureEnd',
+        'Compton_xray_heating',
+        'LWbackground_sawtooth_suppression',
+        'LWbackground_intensity',
+        'UVbackground_redshift_on',
+        'UVbackground_redshift_off',
+        'UVbackground_redshift_fullon',
+        'UVbackground_redshift_drop',
+        'cloudy_electron_fraction_factor',
+        'use_radiative_transfer',
+        'radiative_transfer_coupled_rate_solver',
+        'radiative_transfer_intermediate_step',
+        'radiative_transfer_hydrogen_only',
+        'self_shielding_method',
+        'H2_self_shielding',
+    ]
+
+    def __init__(self, data, parent=None):
+        super().__init__(self.struct_format, data, parent)
+
 class CoolingFunctionData(SwiftStruct):
     cooling_type = wrapper.configGetCooling()
     if cooling_type == "const_lambda":
@@ -426,16 +493,39 @@ class CoolingFunctionData(SwiftStruct):
             "cooling_tstep_mult"
         ]
     elif cooling_type == "grackle":
-        _format = "200cidd"
+        _format = "200cidd{units}s{chemistry}s".format(
+            units=struct.calcsize(GrackleUnits._format),
+            chemistry=struct.calcsize(GrackleChemistryData._format)
+        )
         _name = [
-            "GrackleCloudyTable",
-            "UVbackground",
-            "GrackleRedshift",
-            "GrackleHSShieldingDensityThreshold"
+            "cloudy_table",
+            "uv_background",
+            "redshift",
+            "density_self_shielding",
+            "units",
+            "chemistry"
         ]
+
+        @property
+        def struct_substruct(self):
+            chemistry = {
+                "class": GrackleChemistryData,
+                "size": 1
+            }
+
+            units = {
+                "class": GrackleUnits,
+                "size": 1
+            }
+            return {
+                "units": units,
+                "chemistry": chemistry
+            }
+
     else:
         raise ValueError(
             "Cooling Type %s not implemented" % cooling_type)
 
+
     def __init__(self, data, parent=None):
         super().__init__(self.struct_format, data, parent)
diff --git a/src/cooling_wrapper.c b/src/cooling_wrapper.c
index 49d6592c4cb9d4f63a61633e21f8dbedbc7379e8..59fd431e911caf87677e2ea826e6d3f30ec3f235 100644
--- a/src/cooling_wrapper.c
+++ b/src/cooling_wrapper.c
@@ -99,6 +99,10 @@ PyArrayObject* pycooling_rate(PyObject* self, PyObject* args) {
 
   struct part p;
 
+#ifdef COOLING_GRACKLE
+  grackle_data = &cooling->chemistry;
+#endif
+
   /* return object */
   PyArrayObject *rate = PyArray_NewLikeArray(energy, NPY_ANYORDER, NULL, 1);