diff --git a/configure.ac b/configure.ac
index 960b098a6f5917caf428c84684415ee17a44f81a..6558696ba25ed72f1789f5149b0ae022427c4610 100644
--- a/configure.ac
+++ b/configure.ac
@@ -38,47 +38,6 @@ AX_CHECK_ENABLE_DEBUG
 AC_PROG_CC
 AM_PROG_CC_C_O
 
-
-# Master subgrid options
-# If you add a restriction (e.g. no cooling, chemistry or hydro)
-# you will need to check for overwrite after reading the additional options.
-# As an example for this, see the call to AC_ARG_WITH for cooling.
-AC_ARG_WITH([subgrid],
-	[AS_HELP_STRING([--with-subgrid=<subgrid>],
-		[Master switch for subgrid methods. Inexperienced user should start from here @<:@none, GEAR, EAGLE default: none@:>@]
-	)],
-	[with_subgrid="$withval"],
-	[with_subgrid=none]
-)
-
-# Default values
-with_subgrid_cooling=none
-with_subgrid_chemistry=none
-with_subgrid_hydro=none
-
-case "$with_subgrid" in
-   yes)
-      AC_MSG_ERROR([Invalid option. A subgrid model must be chosen.])
-   ;;
-   none)
-   ;;
-   GEAR)
-	with_subgrid_cooling=grackle
-	with_subgrid_chemistry=GEAR
-	with_subgrid_hydro=gadget2
-   ;;
-   EAGLE)
-	with_subgrid_cooling=EAGLE
-	with_subgrid_chemistry=EAGLE
-	with_subgrid_hydro=gadget2
-   ;;
-   *)
-      AC_MSG_ERROR([Unknown subgrid choice: $with_subgrid])
-   ;;
-esac
-
-
-
 # If debug is selected then we also define SWIFT_DEVELOP_MODE to control
 # any developer code options.
 if test "x$ax_enable_debug" != "xno"; then
@@ -594,42 +553,6 @@ AH_VERBATIM([__STDC_FORMAT_MACROS],
 #define __STDC_FORMAT_MACROS 1
 #endif])
 
-# Check for grackle.
-have_grackle="no"
-AC_ARG_WITH([grackle],
-    [AS_HELP_STRING([--with-grackle=PATH],
-       [root directory where grackle is installed @<:@yes/no@:>@]
-    )],
-    [with_grackle="$withval"],
-    [with_grackle="no"]
-)
-if test "x$with_grackle" != "xno"; then
-   AC_PROG_FC
-   AC_FC_LIBRARY_LDFLAGS
-   if test "x$with_grackle" != "xyes" -a "x$with_grackle" != "x"; then
-      GRACKLE_LIBS="-L$with_grackle/lib -lgrackle"
-      GRACKLE_INCS="-I$with_grackle/include"
-   else
-      GRACKLE_LIBS="-lgrackle"
-      GRACKLE_INCS=""
-   fi
-
-   have_grackle="yes"
-
-   AC_CHECK_LIB(
-      [grackle],
-      [initialize_chemistry_data],
-      [AC_DEFINE([HAVE_GRACKLE],1,[The GRACKLE library appears to be present.])
-        AC_DEFINE([CONFIG_BFLOAT_8],1,[Use doubles in grackle])
-      ],
-      [AC_MSG_ERROR(Cannot find grackle library!)],
-      [$GRACKLE_LIBS $GRACKLE_INCS $FCLIBS]
-   )
-fi
-AC_SUBST([GRACKLE_LIBS])
-AC_SUBST([GRACKLE_INCS])
-AM_CONDITIONAL([HAVEGRACKLE],[test -n "$GRACKLE_LIBS"])
-
 # Check for FFTW. We test for this in the standard directories by default,
 # and only disable if using --with-fftw=no or --without-fftw. When a value
 # is given GSL must be found.
@@ -989,6 +912,46 @@ fi
 
 # Various package configuration options.
 
+# Master subgrid options
+# If you add a restriction (e.g. no cooling, chemistry or hydro)
+# you will need to check for overwrite after reading the additional options.
+# As an example for this, see the call to AC_ARG_WITH for cooling.
+AC_ARG_WITH([subgrid],
+	[AS_HELP_STRING([--with-subgrid=<subgrid>],
+		[Master switch for subgrid methods. Inexperienced user should start from here @<:@none, GEAR, EAGLE default: none@:>@]
+	)],
+	[with_subgrid="$withval"],
+	[with_subgrid=none]
+)
+
+# Default values
+with_subgrid_cooling=none
+with_subgrid_chemistry=none
+with_subgrid_hydro=none
+
+case "$with_subgrid" in
+   yes)
+      AC_MSG_ERROR([Invalid option. A subgrid model must be chosen.])
+   ;;
+   none)
+   ;;
+   GEAR)
+	with_subgrid_cooling=grackle
+	with_subgrid_chemistry=GEAR
+	with_subgrid_hydro=gadget2
+   ;;
+   EAGLE)
+	with_subgrid_cooling=EAGLE
+	with_subgrid_chemistry=EAGLE
+	with_subgrid_hydro=gadget2
+   ;;
+   *)
+      AC_MSG_ERROR([Unknown subgrid choice: $with_subgrid])
+   ;;
+esac
+
+
+
 # Hydro scheme.
 AC_ARG_WITH([hydro],
    [AS_HELP_STRING([--with-hydro=<scheme>],
@@ -1193,6 +1156,42 @@ case "$with_riemann" in
    ;;
 esac
 
+# Check for grackle.
+have_grackle="no"
+AC_ARG_WITH([grackle],
+    [AS_HELP_STRING([--with-grackle=PATH],
+       [root directory where grackle is installed @<:@yes/no@:>@]
+    )],
+    [with_grackle="$withval"],
+    [with_grackle="no"]
+)
+if test "x$with_grackle" != "xno"; then
+   AC_PROG_FC
+   AC_FC_LIBRARY_LDFLAGS
+   if test "x$with_grackle" != "xyes" -a "x$with_grackle" != "x"; then
+      GRACKLE_LIBS="-L$with_grackle/lib -lgrackle"
+      GRACKLE_INCS="-I$with_grackle/include"
+   else
+      GRACKLE_LIBS="-lgrackle"
+      GRACKLE_INCS=""
+   fi
+
+   have_grackle="yes"
+
+   AC_CHECK_LIB(
+      [grackle],
+      [initialize_chemistry_data],
+      [AC_DEFINE([HAVE_GRACKLE],1,[The GRACKLE library appears to be present.])
+        AC_DEFINE([CONFIG_BFLOAT_8],1,[Use doubles in grackle])
+      ],
+      [AC_MSG_ERROR(Cannot find grackle library!)],
+      [$GRACKLE_LIBS $GRACKLE_INCS $FCLIBS]
+   )
+fi
+AC_SUBST([GRACKLE_LIBS])
+AC_SUBST([GRACKLE_INCS])
+AM_CONDITIONAL([HAVEGRACKLE],[test -n "$GRACKLE_LIBS"])
+
 #  Cooling function
 AC_ARG_WITH([cooling],
    [AS_HELP_STRING([--with-cooling=<function>],
diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in
index 2b177a8a0d6abff8b2d7e83cb23b2950e3da2efe..cba52250ccc37f50ed130c70d8a5039d8c786474 100644
--- a/doc/Doxyfile.in
+++ b/doc/Doxyfile.in
@@ -1991,6 +1991,7 @@ INCLUDE_FILE_PATTERNS  =
 
 PREDEFINED             = "__attribute__(x)= "
 PREDEFINED             += HAVE_HDF5
+PREDEFINED             += HAVE_FFTW
 PREDEFINED             += WITH_MPI
 PREDEFINED             += WITH_VECTORIZATION
 PREDEFINED             += __GNUC__
diff --git a/doc/RTD/source/GettingStarted/parameter_file.rst b/doc/RTD/source/GettingStarted/parameter_file.rst
index 32a4f1220d0dc1c65074cc14b53d2c4edd666a67..cecf2fa085b23946b8bcbebd324372b01f4940c2 100644
--- a/doc/RTD/source/GettingStarted/parameter_file.rst
+++ b/doc/RTD/source/GettingStarted/parameter_file.rst
@@ -1,6 +1,8 @@
 .. Parameter File
    Loic Hausammann, 1 june 2018
 
+.. _Parameter_File_label:
+
 Parameter File
 ==============
 
diff --git a/doc/RTD/source/InitialConditions/index.rst b/doc/RTD/source/InitialConditions/index.rst
index e9684ac4ffde5886f7a110de2cd7fb0fbb572a5e..eba438c722fbf4ffd78984aa55d6bfa5efcd71ad 100644
--- a/doc/RTD/source/InitialConditions/index.rst
+++ b/doc/RTD/source/InitialConditions/index.rst
@@ -4,45 +4,63 @@
 Initial Conditions
 ==================
 
-To run anything more than examples from our suite, you will need to be able to 
-produce your own initial conditions for SWIFT. We use the same initial conditions
-as the popular GADGET-2 code, which uses the HDF5 file format.
+To run anything more than examples from our suite, you will need to be able to
+produce your own initial conditions for SWIFT. We use the same initial
+conditions format as the popular `GADGET-2
+<https://wwwmpa.mpa-garching.mpg.de/~volker/gadget/>`_ code, which uses HDF5 for
+its type 3 format. Note that we do not support the GADGET-2 types 1 and 2
+formats.
+
+The original GADGET-2 file format only contains 2 types of particles: gas
+particles and 5 sorts of collisionless particles that allow users to run with 5
+separate particle masses and softenings. In SWIFT, we expand on this by using
+two of these types for stars and black holes.
+
+GADGET-2 can have initial conditions split over many files. This allow multiple
+ones to be read in parallel and is the only way the code can handle more than
+2^31 particles. This limitation is not in place in SWIFT. A single file can
+contain any number of particles (well... up to 2^64...) and the file is read in
+parallel by HDF5 when running on more than one compute node.
 
 As the original documentation for the GADGET-2 initial conditions format is
-quite sparse, we lay out here all of the necessary components. If you are generating
-your initial conditions from python, we recommend you use the h5py package. We
-provide a writing wrapper for this for our initial conditions in
+quite sparse, we lay out here all of the necessary components. If you are
+generating your initial conditions from python, we recommend you use the h5py
+package. We provide a writing wrapper for this for our initial conditions in
 ``examples/KeplerianRing/write_gadget.py``.
 
-You can find out more about the HDF5 format on their webpages, here:
-https://support.hdfgroup.org/HDF5/doc/H5.intro.html
+You can find out more about the HDF5 format on their `webpages
+<https://support.hdfgroup.org/HDF5/doc/H5.intro.html>`_.
 
 
 Structure of the File
 ---------------------
 
-There are several groups that contain 'auxilliary' information, such as ``Header``.
-Particle data is placed in groups that signify particle type.
-
-+---------------------+------------------------+
-| Group Name          | Physical Particle Type |
-+=====================+========================+
-| ``PartType0``       | Gas                    |
-+---------------------+------------------------+
-| ``PartType1``       | Dark Matter            |
-+---------------------+------------------------+
-| ``PartType2``       | Ignored                |
-+---------------------+------------------------+
-| ``PartType3``       | Ignored                |
-+---------------------+------------------------+
-| ``PartType4``       | Stars                  |
-+---------------------+------------------------+
-| ``PartType5``       | Black Holes            |
-+---------------------+------------------------+
-
-Currently, not all of these particle types are included in SWIFT. Note that the
-only particles that have hydrodynamical forces calculated between them are those
-in ``PartType0``.
+There are several groups that contain 'auxilliary' information, such as
+``Header``.  Particle data is placed in separate groups depending of the type of
+the particles. Some types are currently ignored by SWIFT but are kept in the
+file format for compatibility reasons.
+
++---------------------+------------------------+----------------------------+
+| HDF5 Group Name     | Physical Particle Type | In code ``enum part_type`` |
++=====================+========================+============================+
+| ``/PartType0/``     | Gas                    | ``swift_type_gas``         |
++---------------------+------------------------+----------------------------+
+| ``/PartType1/``     | Dark Matter            | ``swift_type_dark_matter`` |
++---------------------+------------------------+----------------------------+
+| ``/PartType2/``     | Ignored                |                            |
++---------------------+------------------------+----------------------------+
+| ``/PartType3/``     | Ignored                |                            |
++---------------------+------------------------+----------------------------+
+| ``/PartType4/``     | Stars                  | ``swift_type_star``        |
++---------------------+------------------------+----------------------------+
+| ``/PartType5/``     | Black Holes            | ``swift_type_black_hole``  |
++---------------------+------------------------+----------------------------+
+
+The last column in the table gives the ``enum`` value from ``part_type.h``
+corresponding to a given entry in the files.
+
+Note that the only particles that have hydrodynamical forces calculated between
+them are those in ``PartType0``.
 
 
 Necessary Components
@@ -55,27 +73,34 @@ script.
 Header
 ~~~~~~
 
-In ``Header``, the following attributes are required:
-
-+ ``BoxSize``, a floating point number or N-dimensional (usually 3) array
-  that describes the size of the box.
+In the ``/Header/`` group, the following attributes are required:
+
++ ``Dimension``, an integer indicating the dimensionality of the ICs (1,2 or 3).
+  Note that this parameter is an addition to the GADGET-2 format and will be
+  ignored by GADGET. SWIFT will use this value to verify that the dimensionality
+  of the code matches the ICs. If this parameter is not provided, it defaults
+  to 3.
++ ``BoxSize``, a floating point number or N-dimensional (usually 3) array that
+  describes the size of the box. If only one number is provided (as per the
+  GADGET-2 standard) then the box is assumed have the same size along all the
+  axis. In cosmological runs, this is the comoving box-size expressed in the
+  units specified in the ``/Units`` group (see below). Note that, unlike GADGET,
+  we express all quantities in "h-free" units. So that, for instance, we express
+  the box side-length in ``Mpc`` and not ``Mpc/h``. 
++ ``NumPart_Total``, a length 6 array of integers that tells the code how many
+  particles of each type are in the initial conditions file. Unlike traditional
+  GADGET-2 files, these can be >2^31.
++ ``NumPart_Total_HighWord``, a historical length-6 array that tells the code
+  the number of high word particles in the initial conditions there are. If you
+  are unsure, just set this to ``[0, 0, 0, 0, 0, 0]``. This does have to be
+  present but can be a set of 0s unless you have more than 2^31 particles and
+  want to be fully compliant with GADGET-2. Note that, as SWIFT supports
+  ``NumPart_Total`` to be >2^31, the use of ``NumPart_Total_HighWord`` is only
+  here for compatibility reasons.
 + ``Flag_Entropy_ICs``, a historical value that tells the code if you have
   included entropy or internal energy values in your intial conditions files.
-  Acceptable values are 0 or 1.
-+ ``NumPart_Total``, a length 6 array of integers that tells the code how many
-  particles are of each type are in the initial conditions file.
-+ ``NumPart_Total_HighWord``, a historical length-6 array that tells the code 
-  the number of high word particles in the initial conditions there are. If
-  you are unsure, just set this to ``[0, 0, 0, 0, 0, 0]``. This does have to be
-  present, but unlike GADGET-2, this can be a set of 0s unless you have more than
-  2^31 particles.
-+ ``NumFilesPerSnapshot``, again a historical integer value that tells the code
-  how many files there are per snapshot. You will probably want to set this to 1
-  and simply have a single HDF5 file for your initial conditions; SWIFT can
-  leverage parallel-HDF5 to read from this single file in parallel.
-+ ``NumPart_ThisFile``, a length 6 array of integers describing the number of
-  particles in this file. If you have followed the above advice, this will be
-  exactly the same as the ``NumPart_Total`` array.
+  Acceptable values are 0 or 1. We recommend using internal energies over
+  entropy in the ICs and hence have this flag set to 0.
 
 You may want to include the following for backwards-compatibility with many
 GADGET-2 based analysis programs:
@@ -83,63 +108,102 @@ GADGET-2 based analysis programs:
 + ``MassTable``, an array of length 6 which gives the masses of each particle
   type. SWIFT ignores this and uses the individual particle masses, but some
   programs will crash if it is not included.
-+ ``Time``, the internal code time of the start (set this to 0).
-
++ ``NumPart_ThisFile``, a length 6 array of integers describing the number of
+  particles in this file. If you have followed the above advice, this will be
+  exactly the same as the ``NumPart_Total`` array. As SWIFT only uses ICs
+  contained in a single file, this is not necessary for SWIFT-only ICs.
++ ``NumFilesPerSnapshot``, again a historical integer value that tells the code
+  how many files there are per snapshot. You will probably want to set this to 1.
++ ``Time``, time of the start of the simulation in internal units or expressed
+  as a scale-factor for cosmological runs. SWIFT ignores this and reads it from
+  the parameter file.
+  
 RuntimePars
 ~~~~~~~~~~~
 
-In ``RuntimePars``, the following attributes are required:
+In the ``/RuntimePars/``, the following attributes are required:
 
 + ``PeriodicBoundaryConditionsOn``, a flag to tell the code whether or not you
   have periodic boundaries switched on. Again, this is historical; it should be
   set to 1 (default) if you have the code running in periodic mode, or 0 otherwise.
 
 
-Units
-~~~~~
-
-In ``Units``, you will need to specify what units your initial conditions are
-in. If these are not present, the code assumes that you are using the same
-units for your initial conditions as are in your parameterfile, but it is best
-to include them to be on the safe side. You will need:
-
-+ ``Unit current in cgs (U_I)``
-+ ``Unit length in cgs (U_L)``
-+ ``Unit mass in cgs (U_M)``
-+ ``Unit temperature in cgs (U_T)``
-+ ``Unit time in cgs (U_t)``
-
-These are all floating point numbers.
-
-
 Particle Data
 ~~~~~~~~~~~~~
 
 Now for the interesting part! You can include particle data groups for each
-individual particle type (e.g. ``PartType0``) that have the following _datasets_:
+individual particle type (e.g. ``/PartType0/``) that have the following *datasets*:
 
 + ``Coordinates``, an array of shape (N, 3) where N is the number of particles
-  of that type, that are the cartesian co-ordinates of the particles. Co-ordinates
-  must be positive, but will be wrapped on reading to be within the periodic box.
-+ ``Velocities``, an array of shape (N, 3) that is the cartesian velocities 
-  of the particles.
+  of that type, that are the cartesian co-ordinates of the
+  particles. Co-ordinates must be within the box so, in the case of a cube
+  within [0, L)^3 where L is the side-length of the simulation volume. In the
+  case of cosmological simulations, these are the co-moving positions.
++ ``Velocities``, an array of shape (N, 3) that is the cartesian velocities of
+  the particles. When running cosmological simulations, these are the peculiar
+  velocities. Note that this is different from GADGET which uses peculiar
+  velocities divided by ``sqrt(a)`` (see below for a fix).
 + ``ParticleIDs``, an array of length N that are unique identifying numbers for
   each particle. Note that these have to be unique to a particle, and cannot be
-  the same even between particle types. Please ensure that your IDs are positive
-  integer numbers.
+  the same even between particle types. The **IDs must be >1**. 0 or negative
+  IDs will be rejected by the code.
 + ``Masses``, an array of length N that gives the masses of the particles.
 
-For ``PartType0`` (i.e. particles that interact through hydrodynamics), you will
+For ``PartType0`` (i.e. particles that interact through hydro-dynamics), you will
 need the following auxilliary items:
 
-+ ``InternalEnergy``, an array of length N that gives the internal energies of
-  the particles. For PressureEntropy, you can specify ``Entropy`` instead.
-+ ``SmoothingLength``, the smoothing lenghts of the particles. These will be
-  tidied up a bit, but it is best if you provide accurate numbers.
++ ``SmoothingLength``, the smoothing lengths of the particles. These will be
+  tidied up a bit, but it is best if you provide accurate numbers. In
+  cosmological runs, these are the co-moving smoothing lengths.
++ ``InternalEnergy``, an array of length N that gives the internal energies per
+  unit mass of the particles. If the hydro-scheme used in the code is based on
+  another thermodynamical quantity (entropy or total energy, etc.), the
+  conversion will happen inside the code. In cosmological runs, this is the
+  **physical** internal energy per unit mass. This has the dimension of velocity
+  squared.
+
+  
+Note that for cosmological runs, all quantities have to be expressed in "h-free"
+dimensions. This means ``Mpc`` and not ``Mpc/h`` for instance. If the ICs have
+been generated for GADGET (where h-full values are expected), the parameter
+``InitialConditions:cleanup_h_factors`` can be set to ``1`` in the
+:ref:`Parameter_File_label` to make SWIFT convert the quantities read in to
+h-free quantities. Switching this parameter on will also affect the box size
+read from the ``/Header/`` group (see above).
+
+Similarly, GADGET cosmological ICs have traditionally used velocities expressed
+as peculiar velocities divided by ``sqrt(a)``. This can be undone by swicthing
+on the parameter ``InitialConditions:cleanup_velocity_factors`` in the
+:ref:`Parameter_File_label`.
+
+     
+Optional Components
+-------------------
+
+In the ``/Units/`` HDF5 group, you cans specify what units your initial conditions are
+in. If this group is not present, the code assumes that you are using the same
+units for your initial conditions as in your :ref:`Parameter_File_label`
+(i.e. as the internal units system used by the code), but it is best to include
+them to be on the safe side. You will need:
+
++ ``Unit length in cgs (U_L)``
++ ``Unit mass in cgs (U_M)``
++ ``Unit time in cgs (U_t)``
++ ``Unit current in cgs (U_I)``
++ ``Unit temperature in cgs (U_T)``
+
+These are all floating point numbers. Note that we specify the time units and
+not the velocity units.
+
+If the units specified in the initial conditions are different from the internal
+units (specified in the parameter file), SWIFT will perform a conversion of all
+the quantities when reading in the ICs. This includes a conversion of the box
+size read from the ``/Header/`` group.
 
 
+     
 Summary
-~~~~~~~
+-------
 
 You should have an HDF5 file with the following structure:
 
@@ -147,11 +211,9 @@ You should have an HDF5 file with the following structure:
 
    Header/
      BoxSize=[x, y, z]
-     Flag_Entropy_ICs=1
-     NumPart_Total=[0, 1, 2, 3, 4, 5]
+     Flag_Entropy_ICs=0
+     NumPart_Total=[0, 1, 0, 0, 4, 5]
      NumPart_Total_HighWord=[0, 0, 0, 0, 0, 0]
-     NumFilesPerSnapshot=1
-     NumPart_ThisFile=[0, 1, 2, 3, 4, 5]
    RuntimePars/
      PeriodicBoundariesOn=1
    Units/
diff --git a/examples/AgoraDisk/agora_disk.yml b/examples/AgoraDisk/agora_disk.yml
new file mode 100644
index 0000000000000000000000000000000000000000..598f1db2858c3e420c55ae31c9ca10d37c2f48b7
--- /dev/null
+++ b/examples/AgoraDisk/agora_disk.yml
@@ -0,0 +1,69 @@
+# Define the system of units to use internally. 
+InternalUnitSystem:
+  UnitMass_in_cgs:     1.989e43      # 10^10 M_sun in grams
+  UnitLength_in_cgs:   3.085e21   # kpc in centimeters
+  UnitVelocity_in_cgs: 1e5           # km/s in centimeters per second
+  UnitCurrent_in_cgs:  1             # Amperes
+  UnitTemp_in_cgs:     1             # Kelvin
+
+Scheduler:
+  max_top_level_cells: 8
+  
+# Parameters governing the time integration
+TimeIntegration:
+  time_begin: 0.    # The starting time of the simulation (in internal units).
+  time_end:   0.5  # The end time of the simulation (in internal units).
+  dt_min:     1e-10 # The minimal time-step size of the simulation (in internal units).
+  dt_max:     1e-4  # The maximal time-step size of the simulation (in internal units).
+  
+# Parameters governing the snapshots
+Snapshots:
+  basename:            agora_disk # Common part of the name of output files
+  time_first:          0.    # Time of the first output (in internal units)
+  delta_time:          1e-2  # Time difference between consecutive outputs (in internal units)
+  compression:         4
+
+# Parameters governing the conserved quantities statistics
+Statistics:
+  delta_time:          1e-3 # Time between statistics output
+
+# Parameters for the self-gravity scheme
+Gravity:
+  eta:                    0.025    # Constant dimensionless multiplier for time integration.
+  theta:                  0.7     # Opening angle (Multipole acceptance criterion)
+  comoving_softening:     0.08 # Comoving softening length (in internal units).
+  max_physical_softening: 0.08    # Physical softening length (in internal units).
+  mesh_side_length:       32        # Number of cells along each axis for the periodic gravity mesh.
+  
+# Parameters for the hydrodynamics scheme
+SPH:
+  resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
+  CFL_condition:         0.1      # Courant-Friedrich-Levy condition for time integration.
+  minimal_temperature:   10      # (internal units)
+
+# Parameters related to the initial conditions
+InitialConditions:
+  file_name:  ./agora_disk.hdf5     # The file to read
+  cleanup_h_factors: 1               # Remove the h-factors inherited from Gadget
+  shift:    [674.1175, 674.1175, 674.1175]   # (Optional) A shift to apply to all particles read from the ICs (in internal units).
+
+# Dimensionless pre-factor for the time-step condition
+LambdaCooling:
+  lambda_cgs:                  1.0e-22    # Cooling rate (in cgs units)
+  minimum_temperature:         1.0e2      # Minimal temperature (Kelvin)
+  mean_molecular_weight:       0.59       # Mean molecular weight
+  hydrogen_mass_abundance:     0.75       # Hydrogen mass abundance (dimensionless)
+  cooling_tstep_mult:          1.0        # Dimensionless pre-factor for the time-step condition
+
+# Cooling with Grackle 2.0
+GrackleCooling:
+  CloudyTable: CloudyData_UVB=HM2012.h5 # Name of the Cloudy Table (available on the grackle bitbucket repository)
+  WithUVbackground: 1 # Enable or not the UV background
+  Redshift: 0 # Redshift to use (-1 means time based redshift)
+  WithMetalCooling: 1 # Enable or not the metal cooling
+  ProvideVolumetricHeatingRates: 0 # User provide volumetric heating rates
+  ProvideSpecificHeatingRates: 0 # User provide specific heating rates
+  SelfShieldingMethod: 0 # Grackle (<= 3) or Gear self shielding method
+  OutputMode: 1 # Write in output corresponding primordial chemistry mode
+  MaxSteps: 1000
+  ConvergenceLimit: 1e-2
diff --git a/examples/AgoraDisk/changeType.py b/examples/AgoraDisk/changeType.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a0eba9def3a07b01f18f727de220d8f7193858f
--- /dev/null
+++ b/examples/AgoraDisk/changeType.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+
+from h5py import File
+from sys import argv
+import numpy as np
+
+"""
+Change particle types in order to match the implemented types
+"""
+
+# number of particle type
+N_type = 6
+
+debug = 0
+
+
+def getOption():
+    if len(argv) != 2:
+        raise IOError("You need to provide a filename")
+
+    # get filename and read it
+    filename = argv[-1]
+
+    return filename
+
+
+def groupName(part_type):
+    return "PartType%i" % part_type
+
+
+def changeType(f, old, new):
+    # check if directory exists
+    old_group = groupName(old)
+    if old_group not in f:
+        raise IOError("Cannot find group '%s'" % old)
+    old = f[old_group]
+
+    new_group = groupName(new)
+    if new_group not in f:
+        f.create_group(new_group)
+    new = f[new_group]
+
+    for name in old:
+        if debug:
+            print("Moving '%s' from '%s' to '%s'"
+                  % (name, old_group, new_group))
+
+        tmp = old[name][:]
+        del old[name]
+        if name in new:
+            new_tmp = new[name][:]
+            if debug:
+                print("Found previous data:", tmp.shape, new_tmp.shape)
+            tmp = np.append(tmp, new_tmp, axis=0)
+            del new[name]
+
+        if debug:
+            print("With new shape:", tmp.shape)
+        new.create_dataset(name, tmp.shape)
+        new[name][:] = tmp
+
+    del f[old_group]
+
+
+def countPart(f):
+    npart = []
+    for i in range(N_type):
+        name = groupName(i)
+        if name in f:
+            grp = f[groupName(i)]
+            N = grp["Masses"].shape[0]
+        else:
+            N = 0
+        npart.append(N)
+
+    f["Header"].attrs["NumPart_ThisFile"] = npart
+    f["Header"].attrs["NumPart_Total"] = npart
+    f["Header"].attrs["NumPart_Total_HighWord"] = [0]*N_type
+
+
+if __name__ == "__main__":
+    filename = getOption()
+
+    f = File(filename)
+
+    changeType(f, 2, 1)
+    changeType(f, 3, 1)
+    changeType(f, 4, 1)
+
+    countPart(f)
+
+    f.close()
diff --git a/examples/AgoraDisk/cleanupSwift.py b/examples/AgoraDisk/cleanupSwift.py
new file mode 100644
index 0000000000000000000000000000000000000000..e3c364081fc82986968727695e1142690781bb67
--- /dev/null
+++ b/examples/AgoraDisk/cleanupSwift.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+
+# ./translate_particles.py filename output_name
+from h5py import File
+import sys
+from shutil import copyfile
+
+NPartType = 1
+filename = sys.argv[-2]
+out = sys.argv[-1]
+
+copyfile(filename, out)
+
+f = File(out)
+
+name = "PartType0/ElementAbundance"
+if name in f:
+    del f[name]
+
+for i in range(NPartType):
+    name = "PartType%i" % i
+    if name not in f:
+        continue
+
+    grp = f[name + "/SmoothingLength"]
+    grp[:] *= 1.823
+
+f.close()
diff --git a/examples/AgoraDisk/getIC.sh b/examples/AgoraDisk/getIC.sh
new file mode 100644
index 0000000000000000000000000000000000000000..620a751bedaf6c646119247270fad6dd3f740fde
--- /dev/null
+++ b/examples/AgoraDisk/getIC.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+if [ "$#" -ne 1 ]; then
+    echo "You need to provide the resolution (e.g. ./getIC.sh low)."
+    echo "The possible options are low, med and high."
+    exit
+fi
+
+wget https://obswww.unige.ch/~lhausamm/swift/IC/AgoraDisk/$1
diff --git a/examples/AgoraDisk/getSolution.sh b/examples/AgoraDisk/getSolution.sh
new file mode 100644
index 0000000000000000000000000000000000000000..41fbab800098bfaa381ca2e83cab0210c8dcf924
--- /dev/null
+++ b/examples/AgoraDisk/getSolution.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+OPTIND=1
+
+with_cooling=0
+
+function show_help {
+    echo "Valid options are:"
+    echo "\t -h \t Show this help"
+    echo "\t -C \t Download solution with cooling"
+}
+
+while getopts "h?C" opt; do
+    case "$opt" in
+	h|\?)
+	    show_help
+	    exit
+	    ;;
+	C)
+	    with_cooling=1
+	    ;;
+    esac
+done
+
+# cleanup work space
+rm snapshot_0000.hdf5 snapshot_0500.hdf5
+
+if [ $with_cooling -eq 1 ]; then
+    wget https://obswww.unige.ch/~lhausamm/swift/IC/AgoraDisk/Gear/with_cooling/snapshot_0000.hdf5
+    wget https://obswww.unige.ch/~lhausamm/swift/IC/AgoraDisk/Gear/with_cooling/snapshot_0500.hdf5
+else
+    wget https://obswww.unige.ch/~lhausamm/swift/IC/AgoraDisk/Gear/without_cooling/snapshot_0000.hdf5
+    wget https://obswww.unige.ch/~lhausamm/swift/IC/AgoraDisk/Gear/without_cooling/snapshot_0500.hdf5
+fi
+
+
diff --git a/examples/AgoraDisk/plotSolution.py b/examples/AgoraDisk/plotSolution.py
new file mode 100644
index 0000000000000000000000000000000000000000..2c3de1728eb6f22bee72361db1e7f0c77613eb25
--- /dev/null
+++ b/examples/AgoraDisk/plotSolution.py
@@ -0,0 +1,2634 @@
+#!/usr/bin/env python2
+#######################################################################
+#
+#  UNIFIED ANALYSIS SCRIPT FOR DISK SIMULATION FOR THE AGORA PROJECT
+#
+#  FOR SCRIPT HISTORY SEE VERSION CONTROL CHANGELOG
+#
+#  Note: This script requires yt-3.2 or yt-dev. Older versions may
+#        yield incorrect results.
+#
+#######################################################################
+# This script is a copy of the AGORA project (https://bitbucket.org/mornkr/agora-analysis-script/)
+# modified in order to take into account SWIFT
+import matplotlib
+matplotlib.use('Agg')
+import sys
+import math
+import copy
+import csv
+import numpy as np
+import matplotlib.colorbar as cb
+import matplotlib.lines as ln
+import yt.utilities.physical_constants as constants
+import matplotlib.pyplot as plt
+import matplotlib.gridspec as gridspec
+from yt.mods import *
+from yt.units.yt_array import YTQuantity
+from mpl_toolkits.axes_grid1 import AxesGrid
+from matplotlib.offsetbox import AnchoredText
+from matplotlib.ticker import MaxNLocator
+from yt.fields.particle_fields import add_volume_weighted_smoothed_field
+from yt.fields.particle_fields import add_nearest_neighbor_field
+from yt.analysis_modules.star_analysis.api import StarFormationRate
+from yt.analysis_modules.halo_analysis.api import *
+from yt.data_objects.particle_filters import add_particle_filter
+from scipy.stats import kde
+from subprocess import call
+#mylog.setLevel(1)
+
+import sys
+
+if "-C" in sys.argv:
+    with_cooling = 1
+else:
+    with_cooling = 0
+    
+draw_density_map                 = 1#1           # 0/1         = OFF/ON
+draw_temperature_map             = 1#1           # 0/1         = OFF/ON
+draw_cellsize_map                = 2#2           # 0/1/2/3     = OFF/ON/ON now with resolution map where particle_size is defined as [M/rho]^(1/3) for SPH/ON with both cell_size and resolution maps
+draw_elevation_map               = 1#1           # 0/1         = OFF/ON
+draw_metal_map                   = 0#0           # 0/1/2       = OFF/ON/ON with total metal mass in the simulation annotated (this will be inaccurate for SPH)
+draw_zvel_map                    = 0#0           # 0/1         = OFF/ON
+draw_star_map                    = 0#0           # 0/1         = OFF/ON
+draw_star_clump_stats            = 0#0           # 0/1/2/3     = OFF/ON/ON with additional star_map with annotated clumps/ON with addtional star_map + extra clump mass function with GIZMO-ps2
+draw_SFR_map                     = 0###0         # 0/1/2       = OFF/ON/ON with local K-S plot using patches
+draw_PDF                         = 0###0         # 0/1/2/3     = OFF/ON/ON with constant pressure/entropy lines/ON with additional annotations such as 1D profile from a specific code (CHANGA)
+draw_pos_vel_PDF                 = 0##0          # 0/1/2/3/4   = OFF/ON/ON with 1D profile/ON also with 1D dispersion profile/ON also with separate 1D vertical dispersion profiles
+draw_star_pos_vel_PDF            = 0##0          # 0/1/2/3/4   = OFF/ON/ON with 1D profile/ON also with 1D dispersion profile/ON also with separate 1D vertical dispersion profiles
+draw_rad_height_PDF              = 0##0          # 0/1/2/3     = OFF/ON/ON with 1D profile/ON with analytic ftn subtracted
+draw_metal_PDF                   = 0##0          # 0/1         = OFF/ON
+draw_density_DF                  = 0#0           # 0/1/2       = OFF/ON/ON with difference plot between 1st and 2nd datasets (when 2, dataset_num should be set to 2)
+draw_radius_DF                   = 0#0           # 0/1         = OFF/ON
+draw_star_radius_DF              = 0#0           # 0/1/2       = OFF/ON/ON with SFR profile and K-S plot (when 2, this automatically turns on draw_radius_DF)
+draw_height_DF                   = 0#0           # 0/1         = OFF/ON
+draw_SFR                         = 0#0           # 0/1/2       = OFF/ON/ON with extra line with GIZMO-ps2
+draw_cut_through                 = 0#0           # 0/1         = OFF/ON
+add_nametag                      = 1#1           # 0/1         = OFF/ON
+add_mean_fractional_dispersion   = 0#0           # 0/1         = OFF/ON
+
+dataset_num                      = 2             # 1/2         = 1st dataset(Grackle+noSF)/2nd dataset(Grackle+SF+ThermalFbck) for AGORA Paper 4
+yt_version_pre_3_2_3             = 0             # 0/1         = NO/YES to "Is the yt version being used pre yt-dev-3.2.3?"
+times                            = [0, 500]      # in Myr
+figure_width                     = 30            # in kpc
+n_ref                            = 64            # 8; for SPH codes
+over_refine_factor               = 1             # 2; for SPH codes
+aperture_size_SFR_map            = 750           # in pc       = Used if draw_SFR_map = 1, 750 matches Bigiel et al. (2008)
+young_star_cutoff_SFR_map        = 20            # in Myr      = Used if draw_SFR_map = 1
+young_star_cutoff_star_radius_DF = 20            # in Myr      = Used if draw_star_radius_DF = 1
+mean_dispersion_radius_range     = [2, 10]       # in kpc      = Used if add_mean_fractional_dispersion = 1, for draw_pos_vel_PDF, draw_star_pos_vel_PDF, draw_rad_height_PDF, draw_radius_DF, draw_star_radius_DF
+mean_dispersion_height_range     = [0, 0.6]      # in kpc      = Used if add_mean_fractional_dispersion = 1, for draw_height_DF
+mean_dispersion_time_range       = [50, 500]     # in Myr      = Used if add_mean_fractional_dispersion = 1, for draw_SFR
+mean_dispersion_density_range    = [1e-25, 1e-22]# in g/cm3    = Used if add_mean_fractional_dispersion = 1, for draw_density_DF
+disk_normal_vector               = [0., 0., 1.]
+
+gadget_default_unit_base = {'UnitLength_in_cm'         : 3.08568e+21,
+                            'UnitMass_in_g'            :   1.989e+43,
+                            'UnitVelocity_in_cm_per_s' :      100000}
+color_names              = ['red', 'magenta', 'orange', 'gold', 'green', 'cyan', 'blue', 'blueviolet', 'black']
+linestyle_names          = ['-']
+marker_names             = ['s', 'o', 'p', 'v', '^', '<', '>', 'h', '*']
+
+# file_location = ['/lustre/ki/pfs/mornkr/080112_CHaRGe/pfs-hyades/AGORA-DISK-repository-for-use/Grackle+noSF/',
+#                '/lustre/ki/pfs/mornkr/080112_CHaRGe/pfs-hyades/AGORA-DISK-repository-for-use/Grackle+SF+ThermalFbck/']
+# file_location = ['/global/project/projectdirs/agora/AGORA-DISK-repository-for-use/Grackle+noSF/',
+#                '/global/project/projectdirs/agora/AGORA-DISK-repository-for-use/Grackle+SF+ThermalFbck/']
+# codes = ['ART-I', 'ART-II', 'ENZO', 'RAMSES', 'CHANGA', 'GASOLINE', 'GADGET-3', 'GEAR', 'GIZMO']
+# filenames = [[[file_location[0]+'ART-I/IC/AGORA_Galaxy_LOW.d', file_location[0]+'ART-I/t0.5Gyr/10MpcBox_csf512_02350.d'],
+#             [file_location[0]+'ART-II/noSF_def_2p/OUT/AGORA_LOW_000000.art', file_location[0]+'ART-II/noSF_def_2p/OUT/AGORA_LOW_000098.art'],
+#             [file_location[0]+'ENZO/DD0000/DD0000', file_location[0]+'ENZO/DD0100/DD0100'],
+#             [file_location[0]+'RAMSES/output_00001/info_00001.txt', file_location[0]+'RAMSES/output_00068/info_00068.txt'],
+#             [file_location[0]+'CHANGA/disklow/disklow.000000', file_location[0]+'CHANGA/disklow/disklow.000500'],
+#             [file_location[0]+'GASOLINE/LOW_dataset1.00001', file_location[0]+'GASOLINE/LOW_dataset1.00335'],
+#             [file_location[0]+'GADGET-3/AGORA_ISO_LOW_DRY/snap_iso_dry_000.hdf5', file_location[0]+'GADGET-3/AGORA_ISO_LOW_DRY/snap_iso_dry_010.hdf5'],
+#             [file_location[0]+'GEAR/snapshot_0000', file_location[0]+'GEAR/snapshot_0500'],
+#             [file_location[0]+'GIZMO/snapshot_temp_000', file_location[0]+'GIZMO/snapshot_temp_100']],
+#            [[file_location[1]+'ART-I/IC/AGORA_Galaxy_LOW.d', file_location[1]+'ART-I/t0.5Gyr/10MpcBox_csf512_02350.d'],
+#             [file_location[1]+'ART-II/SF_FBth_def_2p/OUT/AGORA_LOW_000000.art', file_location[1]+'ART-II/SF_FBth_def_2p/OUT/AGORA_LOW_000311.art'],
+#             [file_location[1]+'ENZO/DD0000/DD0000', file_location[1]+'ENZO/DD0050/DD0050'],
+#             [file_location[1]+'RAMSES/output_00001/info_00001.txt', file_location[1]+'RAMSES/output_00216/info_00216.txt'],
+#             [file_location[1]+'CHANGA/disklow/disklow.000000', file_location[1]+'CHANGA/disklow/disklow.000500'],
+#             [file_location[1]+'GASOLINE/LOW_dataset1.00001', file_location[1]+'GASOLINE/LOW_dataset2.00335'],
+#             [file_location[1]+'GADGET-3/AGORA_ISO_LOW_SF_SNII_Thermal_Chevalier_SFT10/snap_iso_sf_000.hdf5', file_location[1]+'GADGET-3/AGORA_ISO_LOW_SF_SNII_Thermal_Chevalier_SFT10/snap_iso_sf_010.hdf5'],
+#             [file_location[1]+'GEAR/snapshot_0000', file_location[1]+'GEAR/snapshot_0500'],
+#             [file_location[1]+'GIZMO/snapshot_temp_000', file_location[1]+'GIZMO/snapshot_temp_100']]]
+codes = ['SWIFT', 'GEAR']
+filenames = [[["./agora_disk_IC.hdf5", "./agora_disk_500Myr.hdf5"],
+              ["./snapshot_0000.hdf5", "./snapshot_0500.hdf5"]],
+             [["./agora_disk_IC.hdf5", "./agora_disk_500Myr.hdf5"],
+              ["./snapshot_0000.hdf5", "./snapshot_0500.hdf5"]]]
+
+# codes = ["SWIFT"]
+# filenames = [[["./agora_disk_0000.hdf5", "./agora_disk_0050.hdf5"]],
+#             [["./agora_disk_0000.hdf5", "./agora_disk_0050.hdf5"]]]
+# codes = ['ART-I']
+# filenames = [[[file_location[0]+'ART-I/IC/AGORA_Galaxy_LOW.d', file_location[0]+'ART-I/t0.5Gyr/10MpcBox_csf512_02350.d']],
+#            [[file_location[1]+'ART-I/IC/AGORA_Galaxy_LOW.d', file_location[1]+'ART-I/t0.5Gyr/10MpcBox_csf512_02350.d']]]
+# codes = ['ART-II']
+# filenames = [[[file_location[0]+'ART-II/noSF_def_2p/OUT/AGORA_LOW_000000.art', file_location[0]+'ART-II/noSF_def_2p/OUT/AGORA_LOW_000098.art']],
+#            [[file_location[1]+'ART-II/SF_FBth_def_2p/OUT/AGORA_LOW_000000.art', file_location[1]+'ART-II/SF_FBth_def_2p/OUT/AGORA_LOW_000311.art']]]
+# codes = ['ENZO']
+# filenames = [[[file_location[0]+'ENZO/DD0000/DD0000', file_location[0]+'ENZO/DD0100/DD0100']],
+#            [[file_location[1]+'ENZO/DD0000/DD0000', file_location[1]+'ENZO/DD0050/DD0050']]]
+# codes = ['RAMSES']
+# filenames = [[[file_location[0]+'RAMSES/output_00001/info_00001.txt', file_location[0]+'RAMSES/output_00068/info_00068.txt']],
+#            [[file_location[1]+'RAMSES/output_00001/info_00001.txt', file_location[1]+'RAMSES/output_00216/info_00216.txt']]]
+# codes = ['CHANGA']
+# filenames = [[[file_location[0]+'CHANGA/disklow/disklow.000000', file_location[0]+'CHANGA/disklow/disklow.000500']],
+#            [[file_location[1]+'CHANGA/disklow/disklow.000000', file_location[1]+'CHANGA/disklow/disklow.000500']]]
+# codes = ['GASOLINE']
+# filenames = [[[file_location[0]+'GASOLINE/LOW_dataset1.00001', file_location[0]+'GASOLINE/LOW_dataset1.00335']],
+#            [[file_location[1]+'GASOLINE/LOW_dataset1.00001', file_location[1]+'GASOLINE/LOW_dataset2.00335']]]
+# codes = ['GADGET-3']
+# filenames = [[[file_location[0]+'GADGET-3/AGORA_ISO_LOW_DRY/snap_iso_dry_000.hdf5', file_location[0]+'GADGET-3/AGORA_ISO_LOW_DRY/snap_iso_dry_010.hdf5']],
+#            [[file_location[1]+'GADGET-3/AGORA_ISO_LOW_SF_SNII_Thermal_Chevalier_SFT10/snap_iso_sf_000.hdf5', file_location[1]+'GADGET-3/AGORA_ISO_LOW_SF_SNII_Thermal_Chevalier_SFT10/snap_iso_sf_010.hdf5']]]
+# codes = ['GEAR']
+# filenames = [[['snapshot_0000', 'snapshot_0500']],
+#            [['snapshot_0000', 'snapshot_0500']]]
+# codes = ['GIZMO']
+# filenames = [[[file_location[0]+'GIZMO/snapshot_temp_000', file_location[0]+'GIZMO/snapshot_temp_100']],
+#            [[file_location[1]+'GIZMO/snapshot_temp_000', file_location[1]+'GIZMO/snapshot_temp_100']]]
+
+def load_dataset(dataset_num, time, code, codes, filenames_entry):
+        if codes[code] == 'ART-I': # ART frontend doesn't find the accompanying files, so we specify them; see http://yt-project.org/docs/dev/examining/loading_data.html#art-data
+                dirnames = filenames_entry[code][time][:filenames_entry[code][time].rfind('/')+1]
+                if time == 0:
+                        timestamp = ''
+                else:
+                        timestamp = filenames_entry[code][time][filenames_entry[code][time].rfind('_'):filenames_entry[code][time].rfind('.')]
+                pf = load(filenames_entry[code][time], file_particle_header=dirnames+'PMcrd'+timestamp+'.DAT', file_particle_data=dirnames+'PMcrs0'+timestamp+'.DAT', file_particle_stars=dirnames+'stars'+timestamp+'.dat')
+        elif codes[code] == 'CHANGA' or codes[code] == 'GASOLINE': # For TIPSY frontend, always make sure to place your parameter file in the same directory as your datasets
+                pf = load(filenames_entry[code][time], n_ref=n_ref, over_refine_factor=over_refine_factor)
+        elif codes[code] == 'GADGET-3': # For GADGET-3 2nd dataset, there somehow exist particles very far from the center; so we use [-2000, 2000] for a bounding_box
+                pf = load(filenames_entry[code][time], unit_base = gadget_default_unit_base, bounding_box=[[-2000.0, 2000.0], [-2000.0, 2000.0], [-2000.0, 2000.0]], n_ref=n_ref, over_refine_factor=over_refine_factor)
+        elif codes[code] == "SWIFT":
+                pf = load(filenames_entry[code][time], unit_base = gadget_default_unit_base, bounding_box=[[-2000.0, 2000.0], [-2000.0, 2000.0], [-2000.0, 2000.0]], n_ref=n_ref, over_refine_factor=over_refine_factor)
+        elif codes[code] == 'GEAR':
+                pf = load(filenames_entry[code][time], unit_base = gadget_default_unit_base, bounding_box=[[-2000.0, 2000.0], [-2000.0, 2000.0], [-2000.0, 2000.0]], n_ref=n_ref, over_refine_factor=over_refine_factor) 
+               # from yt.frontends.gadget.definitions import gadget_header_specs
+               #  from yt.frontends.gadget.definitions import gadget_ptype_specs
+               #  from yt.frontends.gadget.definitions import gadget_field_specs
+               #  if with_cooling:
+               #          gadget_header_specs["chemistry"] = (('h1',  4, 'c'),('h2',  4, 'c'),('empty',  256, 'c'),)
+               #          header_spec = "default+chemistry"
+               #  else:
+               #          header_spec = "default"
+               #  gear_ptype_specs = ("Gas", "Stars", "Halo", "Disk", "Bulge", "Bndry")
+               #  if dataset_num == 1:
+               #          pf = GadgetDataset(filenames_entry[code][time], unit_base = gadget_default_unit_base, bounding_box=[[-1000.0, 1000.0], [-1000.0, 1000.0], [-1000.0, 1000.0]], header_spec=header_spec,
+               #                             ptype_spec=gear_ptype_specs, n_ref=n_ref, over_refine_factor=over_refine_factor)
+               #  elif dataset_num == 2:
+               #          # For GEAR 2nd dataset (Grackle+SF+ThermalFbck), "Metals" is acutally 10-species field; check how metallicity field is added below.
+               #          if with_cooling:
+               #                  agora_gear  = ( "Coordinates",
+               #                                  "Velocities",
+               #                                  "ParticleIDs",
+               #                                  "Mass",
+               #                                  ("InternalEnergy", "Gas"),
+               #                                  ("Density", "Gas"),
+               #                                  ("SmoothingLength", "Gas"),
+               #                                  ("Metals", "Gas"),
+               #                                  ("StellarFormationTime", "Stars"),
+               #                                  ("StellarInitMass", "Stars"),
+               #                                  ("StellarIDs", "Stars"),
+               #                                  ("StellarDensity", "Stars"),
+               #                                  ("StellarSmoothingLength", "Stars"),
+               #                                  ("StellarMetals", "Stars"),
+               #                                  ("Opt1", "Stars"),
+               #                                  ("Opt2", "Stars"),
+               #                  )
+               #          else:
+               #                  agora_gear  = ( "Coordinates",
+               #                                  "Velocities",
+               #                                  "ParticleIDs",
+               #                                  "Mass",
+               #                                  ("InternalEnergy", "Gas"),
+               #                                  ("Density", "Gas"),
+               #                                  ("SmoothingLength", "Gas"),
+               #                  )
+               #          gadget_field_specs["agora_gear"] = agora_gear
+               #          pf = GadgetDataset(filenames_entry[code][time], unit_base = gadget_default_unit_base, bounding_box=[[-1000.0, 1000.0], [-1000.0, 1000.0], [-1000.0, 1000.0]], header_spec=header_spec,
+               #                             ptype_spec=gear_ptype_specs, field_spec="agora_gear", n_ref=n_ref, over_refine_factor=over_refine_factor)
+        elif codes[code] == 'GIZMO':
+                from yt.frontends.gadget.definitions import gadget_field_specs
+                if dataset_num == 1:
+                        agora_gizmo = ( "Coordinates",
+                                        "Velocities",
+                                        "ParticleIDs",
+                                        "Mass",
+                                        ("Temperature", "Gas"),
+                                        ("Density", "Gas"),
+                                        ("Electron_Number_Density", "Gas"),
+                                        ("HI_NumberDensity", "Gas"),
+                                        ("SmoothingLength", "Gas"),
+                                        )
+                elif dataset_num == 2:
+                        agora_gizmo = ( "Coordinates",
+                                        "Velocities",
+                                        "ParticleIDs",
+                                        "Mass",
+                                        ("Temperature", "Gas"),
+                                        ("Density", "Gas"),
+                                        ("ElectronAbundance", "Gas"),
+                                        ("NeutralHydrogenAbundance", "Gas"),
+                                        ("SmoothingLength", "Gas"),
+                                        ("StarFormationRate", "Gas"),
+                                        ("StellarFormationTime", "Stars"),
+                                        ("Metallicity", ("Gas", "Stars")),
+                                        ("DelayTime", "Stars"),
+                                        ("StellarInitMass", "Stars"),
+                                        )
+                gadget_field_specs["agora_gizmo"] = agora_gizmo
+                pf = load(filenames_entry[code][time], unit_base = gadget_default_unit_base, bounding_box=[[-1000.0, 1000.0], [-1000.0, 1000.0], [-1000.0,1000.0]], field_spec="agora_gizmo",
+                          n_ref=n_ref, over_refine_factor=over_refine_factor)
+        else:
+                pf = load(filenames_entry[code][time])
+        return pf
+
+fig_density_map             = []
+fig_temperature_map         = []
+fig_cellsize_map            = []
+fig_cellsize_map_2          = []
+fig_elevation_map           = []
+fig_metal_map               = []
+fig_zvel_map                = []
+fig_star_map                = []
+fig_star_map_2              = []
+fig_star_map_3              = []
+fig_degr_sfr_map            = []
+fig_degr_density_map        = []
+fig_PDF                     = []
+fig_pos_vel_PDF             = []
+fig_star_pos_vel_PDF        = []
+fig_rad_height_PDF          = []
+fig_metal_PDF               = []
+grid_density_map            = []
+grid_temperature_map        = []
+grid_cellsize_map           = []
+grid_cellsize_map_2         = []
+grid_elevation_map          = []
+grid_metal_map              = []
+grid_zvel_map               = []
+grid_star_map               = []
+grid_star_map_2             = []
+grid_star_map_3             = []
+grid_degr_sfr_map           = []
+grid_degr_density_map       = []
+grid_PDF                    = []
+grid_pos_vel_PDF            = []
+grid_star_pos_vel_PDF       = []
+grid_rad_height_PDF         = []
+grid_metal_PDF              = []
+star_clump_masses_hop       = []
+star_clump_masses_fof       = []
+star_clump_masses_hop_ref   = []
+star_clump_masses_fof_ref   = []
+pos_vel_xs                  = []
+pos_vel_profiles            = []
+pos_disp_xs                 = []
+pos_disp_profiles           = []
+pos_disp_vert_xs            = []
+pos_disp_vert_profiles      = []
+star_pos_vel_xs             = []
+star_pos_vel_profiles       = []
+star_pos_disp_xs            = []
+star_pos_disp_profiles      = []
+star_pos_disp_vert_xs       = []
+star_pos_disp_vert_profiles = []
+rad_height_xs               = []
+rad_height_profiles         = []
+density_DF_xs               = []
+density_DF_profiles         = []
+density_DF_1st_xs           = []
+density_DF_1st_profiles     = []
+radius_DF_xs                = []
+radius_DF_profiles          = []
+surface_density             = []
+star_radius_DF_xs           = []
+star_radius_DF_profiles     = []
+star_surface_density        = []
+sfr_radius_DF_xs            = []
+sfr_radius_DF_profiles      = []
+sfr_surface_density         = []
+height_DF_xs                = []
+height_DF_profiles          = []
+height_surface_density      = []
+sfr_ts                      = []
+sfr_cum_masses              = []
+sfr_sfrs                    = []
+surf_dens_SFR_map           = []
+sfr_surf_dens_SFR_map       = []
+cut_through_zs              = []
+cut_through_zvalues         = []
+cut_through_xs              = []
+cut_through_xvalues         = []
+
+for time in range(len(times)):
+        if draw_density_map == 1:
+                fig_density_map      += [plt.figure(figsize=(100,20))]
+                grid_density_map     += [AxesGrid(fig_density_map[time], (0.01,0.01,0.99,0.99), nrows_ncols = (2, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.02)]
+        if draw_temperature_map == 1:
+                fig_temperature_map  += [plt.figure(figsize=(100,20))]
+                grid_temperature_map += [AxesGrid(fig_temperature_map[time], (0.01,0.01,0.99,0.99), nrows_ncols = (2, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.02)]
+        if draw_cellsize_map >= 1:
+                fig_cellsize_map     += [plt.figure(figsize=(100,20))]
+                grid_cellsize_map    += [AxesGrid(fig_cellsize_map[time], (0.01,0.01,0.99,0.99), nrows_ncols = (2, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.02)]
+                fig_cellsize_map_2   += [plt.figure(figsize=(100,20))]
+                grid_cellsize_map_2  += [AxesGrid(fig_cellsize_map_2[time], (0.01,0.01,0.99,0.99), nrows_ncols = (2, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.02)]
+        if draw_elevation_map == 1:
+                fig_elevation_map    += [plt.figure(figsize=(100,20))]
+                grid_elevation_map   += [AxesGrid(fig_elevation_map[time], (0.01,0.01,0.99,0.99), nrows_ncols = (1, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "6%", cbar_pad = 0.02)]
+        if draw_metal_map >= 1:
+                fig_metal_map        += [plt.figure(figsize=(100,20))]
+                grid_metal_map       += [AxesGrid(fig_metal_map[time], (0.01,0.01,0.99,0.99), nrows_ncols = (2, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.02)]
+        if draw_zvel_map == 1:
+                fig_zvel_map         += [plt.figure(figsize=(100,20))]
+                grid_zvel_map        += [AxesGrid(fig_zvel_map[time], (0.01,0.01,0.99,0.99), nrows_ncols = (2, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.02)]
+        if draw_star_map == 1:
+                fig_star_map         += [plt.figure(figsize=(100,20))]
+                grid_star_map        += [AxesGrid(fig_star_map[time], (0.01,0.01,0.99,0.99), nrows_ncols = (2, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.02)]
+        if draw_star_clump_stats >= 1:
+                star_clump_masses_hop.append([])
+                star_clump_masses_fof.append([])
+                fig_star_map_2       += [plt.figure(figsize=(100,20))]
+                grid_star_map_2      += [AxesGrid(fig_star_map_2[time], (0.01,0.01,0.99,0.99), nrows_ncols = (2, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.02)]
+                fig_star_map_3       += [plt.figure(figsize=(100,20))]
+                grid_star_map_3      += [AxesGrid(fig_star_map_3[time], (0.01,0.01,0.99,0.99), nrows_ncols = (2, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.02)]
+        if draw_SFR_map >= 1:
+                fig_degr_density_map += [plt.figure(figsize=(100,20))]
+                grid_degr_density_map+= [AxesGrid(fig_degr_density_map[time], (0.01,0.01,0.99,0.99), nrows_ncols = (1, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "6%", cbar_pad = 0.02)]
+                fig_degr_sfr_map     += [plt.figure(figsize=(100,20))]
+                grid_degr_sfr_map    += [AxesGrid(fig_degr_sfr_map[time], (0.01,0.01,0.99,0.99), nrows_ncols = (1, len(codes)), axes_pad = 0.02, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "6%", cbar_pad = 0.02)]
+                surf_dens_SFR_map.append([])
+                sfr_surf_dens_SFR_map.append([])
+        if draw_SFR_map >= 2 or draw_star_radius_DF >= 2:
+                def import_text(filename, separator):
+                        for line in csv.reader(open(filename), delimiter=separator, skipinitialspace=True):
+                                if line:
+                                        yield line
+        if draw_PDF >= 1:
+                fig_PDF              += [plt.figure(figsize=(50, 80))]
+                grid_PDF             += [AxesGrid(fig_PDF[time], (0.01,0.01,0.99,0.99), nrows_ncols = (3, int(math.ceil(len(codes)/3.0))), axes_pad = 0.05, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.05, aspect = False)]
+        if draw_pos_vel_PDF >= 1:
+                fig_pos_vel_PDF      += [plt.figure(figsize=(50, 80))]
+                grid_pos_vel_PDF     += [AxesGrid(fig_pos_vel_PDF[time], (0.01,0.01,0.99,0.99), nrows_ncols = (3, int(math.ceil(len(codes)/3.0))), axes_pad = 0.05, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.05, aspect = False)]
+                pos_vel_xs.append([])
+                pos_vel_profiles.append([])
+                pos_disp_xs.append([])
+                pos_disp_profiles.append([])
+                pos_disp_vert_xs.append([])
+                pos_disp_vert_profiles.append([])
+        if draw_star_pos_vel_PDF >= 1:
+                fig_star_pos_vel_PDF += [plt.figure(figsize=(50, 80))]
+                grid_star_pos_vel_PDF+= [AxesGrid(fig_star_pos_vel_PDF[time], (0.01,0.01,0.99,0.99), nrows_ncols = (3, int(math.ceil(len(codes)/3.0))), axes_pad = 0.05, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.05, aspect = False)]
+                star_pos_vel_xs.append([])
+                star_pos_vel_profiles.append([])
+                star_pos_disp_xs.append([])
+                star_pos_disp_profiles.append([])
+                star_pos_disp_vert_xs.append([])
+                star_pos_disp_vert_profiles.append([])
+        if draw_rad_height_PDF >= 1:
+                fig_rad_height_PDF   += [plt.figure(figsize=(50, 80))]
+                grid_rad_height_PDF  += [AxesGrid(fig_rad_height_PDF[time], (0.01,0.01,0.99,0.99), nrows_ncols = (3, int(math.ceil(len(codes)/3.0))), axes_pad = 0.05, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.05, aspect = False)]
+                rad_height_xs.append([])
+                rad_height_profiles.append([])
+        if draw_metal_PDF == 1:
+                fig_metal_PDF        += [plt.figure(figsize=(50, 80))]
+                grid_metal_PDF       += [AxesGrid(fig_metal_PDF[time], (0.01,0.01,0.99,0.99), nrows_ncols = (3, int(math.ceil(len(codes)/3.0))), axes_pad = 0.05, add_all = True, share_all = True,
+                                                  label_mode = "1", cbar_mode = "single", cbar_location = "right", cbar_size = "2%", cbar_pad = 0.05, aspect = False)]
+        if draw_density_DF >= 1:
+                density_DF_xs.append([])
+                density_DF_profiles.append([])
+                density_DF_1st_xs.append([])
+                density_DF_1st_profiles.append([])
+                if draw_density_DF == 2 and dataset_num == 1:
+                        print("This won't work; resetting draw_density_DF to 1...")
+                        draw_density_DF == 1
+        if draw_star_radius_DF >= 1:
+                star_radius_DF_xs.append([])
+                star_radius_DF_profiles.append([])
+                star_surface_density.append([])
+                sfr_radius_DF_xs.append([])
+                sfr_radius_DF_profiles.append([])
+                sfr_surface_density.append([])
+        if draw_star_radius_DF == 2:
+                draw_radius_DF = 1
+        if draw_radius_DF == 1:
+                radius_DF_xs.append([])
+                radius_DF_profiles.append([])
+                surface_density.append([])
+        if draw_height_DF == 1:
+                height_DF_xs.append([])
+                height_DF_profiles.append([])
+                height_surface_density.append([])
+        if draw_SFR >= 1:
+                sfr_ts.append([])
+                sfr_cum_masses.append([])
+                sfr_sfrs.append([])
+        if draw_cut_through == 1:
+                cut_through_zs.append([])
+                cut_through_zvalues.append([])
+                cut_through_xs.append([])
+                cut_through_xvalues.append([])
+
+for time in range(len(times)):
+
+        for code in range(len(codes)):
+
+                if (dataset_num != 1 and dataset_num != 2) or (filenames[dataset_num-1][code] == []):
+                        continue
+
+                ####################################
+                #        PRE-ANALYSIS STEPS        #
+                ####################################
+
+                # LOAD DATASETS
+                pf = load_dataset(dataset_num, time, code, codes, filenames[dataset_num-1])
+
+                # PARTICLE FILED NAMES FOR SPH CODES, AND STELLAR PARTICLE FILTERS
+                PartType_Gas_to_use = "Gas"
+                PartType_Star_to_use = "Stars"
+                PartType_StarBeforeFiltered_to_use = "Stars"
+                MassType_to_use = "Mass"
+                MetallicityType_to_use = "Metallicity"
+                FormationTimeType_to_use = "StellarFormationTime" # for GADGET/GEAR/GIZMO, this field has to be added in frontends/sph/fields.py, in which only "FormationTime" can be recognized
+                SmoothingLengthType_to_use = "SmoothingLength"
+
+                if codes[code] == 'CHANGA' or codes[code] == 'GASOLINE':
+                        MetallicityType_to_use = "Metals"
+                        PartType_Star_to_use = "NewStars"
+                        PartType_StarBeforeFiltered_to_use = "Stars"
+                        FormationTimeType_to_use = "FormationTime"
+                        SmoothingLengthType_to_use = "smoothing_length"
+                        def NewStars(pfilter, data): # see http://yt-project.org/docs/dev/analyzing/filtering.html#filtering-particle-fields
+                                return (data[(pfilter.filtered_type, FormationTimeType_to_use)] > 0)
+                        add_particle_filter(PartType_Star_to_use, function=NewStars, filtered_type=PartType_StarBeforeFiltered_to_use, requires=[FormationTimeType_to_use])
+                        pf.add_particle_filter(PartType_Star_to_use)
+                        pf.periodicity = (True, True, True) # this is needed especially when bPeriodic = 0 in GASOLINE, to avoid RuntimeError in geometry/selection_routines.pyx:855
+                elif codes[code] == 'ART-I':
+                        PartType_StarBeforeFiltered_to_use = "stars"
+                        FormationTimeType_to_use = "particle_creation_time"
+                        def Stars(pfilter, data):
+                                return (data[(pfilter.filtered_type, FormationTimeType_to_use)] > 0)
+#                               return ((data[(pfilter.filtered_type, FormationTimeType_to_use)] > 0) & (data[(pfilter.filtered_type, "particle_index")] >= 212500)) # without the fix metioned above, the above line won't work because all "stars"="specie1" have the same wrong particle_creation_time of 6.851 Gyr; so you will have to use this quick and dirty patch
+                        add_particle_filter(PartType_Star_to_use, function=Stars, filtered_type=PartType_StarBeforeFiltered_to_use, requires=[FormationTimeType_to_use, "particle_index"])
+                        pf.add_particle_filter(PartType_Star_to_use)
+                elif codes[code] == 'ART-II':
+                        PartType_StarBeforeFiltered_to_use = "STAR"
+                        if time != 0: # BIRTH_TIME field exists in ART-II but as a dimensionless quantity for some reason in frontends/artio/fields.py; so we create StellarFormationTime field
+                                def _FormationTime(field, data):
+                                        return pf.arr(data["STAR", "BIRTH_TIME"].d, 'code_time')
+                                pf.add_field(("STAR", FormationTimeType_to_use), function=_FormationTime, particle_type=True, take_log=False, units="code_time")
+                        def Stars(pfilter, data):
+                                return (data[(pfilter.filtered_type, FormationTimeType_to_use)] > 0)
+                        add_particle_filter(PartType_Star_to_use, function=Stars, filtered_type=PartType_StarBeforeFiltered_to_use, requires=[FormationTimeType_to_use])
+                        pf.add_particle_filter(PartType_Star_to_use)
+                elif codes[code] == 'ENZO':
+                        PartType_StarBeforeFiltered_to_use = "all"
+                        FormationTimeType_to_use = "creation_time"
+                        def Stars(pfilter, data):
+                                return ((data[(pfilter.filtered_type, "particle_type")] == 2) & (data[(pfilter.filtered_type, FormationTimeType_to_use)] > 0))
+                        add_particle_filter(PartType_Star_to_use, function=Stars, filtered_type=PartType_StarBeforeFiltered_to_use, requires=["particle_type", FormationTimeType_to_use])
+                        pf.add_particle_filter(PartType_Star_to_use)
+                elif codes[code] == "GADGET-3":
+                        PartType_Gas_to_use = "PartType0"
+                        PartType_Star_to_use = "PartType4"
+                        PartType_StarBeforeFiltered_to_use = "PartType4"
+                        MassType_to_use = "Masses"
+                elif codes[code] == "SWIFT":
+                        PartType_Gas_to_use = "PartType0"
+                        PartType_Star_to_use = "PartType2"
+                        PartType_StarBeforeFiltered_to_use = "PartType2"
+                        MassType_to_use = "Masses"
+                elif codes[code] == "GEAR":
+                        PartType_Gas_to_use = "PartType0"
+                        PartType_Star_to_use = "PartType1"
+                        PartType_StarBeforeFiltered_to_use = "PartType1"
+                        MassType_to_use = "Masses"
+                elif codes[code] == 'RAMSES':
+                        PartType_StarBeforeFiltered_to_use = "all"
+                        pf.current_time = pf.arr(pf.parameters['time'], 'code_time') # reset pf.current_time because it is incorrectly set up in frontends/ramses/data_structure.py, and I don't wish to mess with units there
+                        FormationTimeType_to_use = "particle_age" # particle_age field actually means particle creation time, at least for this particular dataset, so the new field below is not needed
+                        # if time != 0: # Only particle_age field exists in RAMSES (only for new stars + IC stars), so we create StellarFormationTime field
+                        #       def _FormationTime(field, data):
+                        #               return pf.current_time - data["all", "particle_age"].in_units("s")
+                        #       pf.add_field(("all", FormationTimeType_to_use), function=_FormationTime, particle_type=True, take_log=False, units="code_time")
+                        def Stars(pfilter, data):
+                                return (data[(pfilter.filtered_type, "particle_age")] > 0)
+                        add_particle_filter(PartType_Star_to_use, function=Stars, filtered_type=PartType_StarBeforeFiltered_to_use, requires=["particle_age"])
+                        pf.add_particle_filter(PartType_Star_to_use)
+
+                # AXIS SWAP FOR PLOT COLLECTION
+                pf.coordinates.x_axis[1] = 0
+                pf.coordinates.y_axis[1] = 2
+                pf.coordinates.x_axis['y'] = 0
+                pf.coordinates.y_axis['y'] = 2
+
+                # ADDITIONAL FIELDS I: GLOBALLY USED FIELDS
+                def _density_squared(field, data):
+                        return data[("gas", "density")]**2
+                pf.add_field(("gas", "density_squared"), function=_density_squared, units="g**2/cm**6")
+
+                # ADDITIONAL FIELDS II: FOR CELL SIZE AND RESOLUTION MAPS
+                def _CellSizepc(field,data):
+                        return (data[("index", "cell_volume")].in_units('pc**3'))**(1/3.)
+                pf.add_field(("index", "cell_size"), function=_CellSizepc, units='pc', display_name="Resolution $\Delta$ x", take_log=True )
+                def _Inv2CellVolumeCode(field,data):
+                        return data[("index", "cell_volume")]**-2
+                pf.add_field(("index", "cell_volume_inv2"), function=_Inv2CellVolumeCode, units='code_length**(-6)', display_name="Inv2CellVolumeCode", take_log=True)
+                if draw_cellsize_map >= 2:
+                        if codes[code] == 'CHANGA' or codes[code] == 'GEAR' or codes[code] == 'GADGET-3' or codes[code] == 'GASOLINE' or codes[code] == 'GIZMO' or codes[code] == "SWIFT":
+                                def _ParticleSizepc(field, data):
+                                        return (data[(PartType_Gas_to_use, MassType_to_use)]/data[(PartType_Gas_to_use, "Density")])**(1./3.)
+                                pf.add_field((PartType_Gas_to_use, "particle_size"), function=_ParticleSizepc, units="pc", display_name="Resolution $\Delta$ x", particle_type=True, take_log=True)
+                                def _Inv2ParticleVolumepc(field, data):
+                                        return (data[(PartType_Gas_to_use, MassType_to_use)]/data[(PartType_Gas_to_use, "Density")])**(-2.)
+                                pf.add_field((PartType_Gas_to_use, "particle_volume_inv2"), function=_Inv2ParticleVolumepc, units="pc**(-6)", display_name="Inv2ParticleVolumepc", particle_type=True, take_log=True)
+                                # Also creating smoothed field following an example in yt-project.org/docs/dev/cookbook/calculating_information.html; use hardcoded num_neighbors as in frontends/gadget/fields.py
+                                fn = add_volume_weighted_smoothed_field(PartType_Gas_to_use, "Coordinates", MassType_to_use, SmoothingLengthType_to_use, "Density", "particle_size", pf.field_info, nneighbors=64)
+                                fn = add_volume_weighted_smoothed_field(PartType_Gas_to_use, "Coordinates", MassType_to_use, SmoothingLengthType_to_use, "Density", "particle_volume_inv2", pf.field_info, nneighbors=64)
+
+                                # Alias doesn't work -- e.g. pf.field_info.alias(("gas", "particle_size"), fn[0]) -- check alias below; so I simply add ("gas", "particle_size")
+                                def _ParticleSizepc_2(field, data):
+                                        return data["deposit", PartType_Gas_to_use+"_smoothed_"+"particle_size"]
+                                pf.add_field(("gas", "particle_size"), function=_ParticleSizepc_2, units="pc", force_override=True, display_name="Resolution $\Delta$ x", particle_type=False, take_log=True)
+                                def _Inv2ParticleVolumepc_2(field, data):
+                                        return data["deposit", PartType_Gas_to_use+"_smoothed_"+"particle_volume_inv2"]
+                                pf.add_field(("gas", "particle_volume_inv2"), function=_Inv2ParticleVolumepc_2, units="pc**(-6)", force_override=True, display_name="Inv2ParticleVolumepc", particle_type=False, take_log=True)
+
+                # ADDITIONAL FIELDS III: TEMPERATURE
+                if codes[code] == 'GEAR' or codes[code] == 'GADGET-3' or codes[code] == 'RAMSES' or codes[code] == "SWIFT":
+                        # From grackle/src/python/utilities/convenience.py: Calculate a tabulated approximation to mean molecular weight (valid for data that used Grackle 2.0 or below)
+                        def calc_mu_table_local(temperature):
+                                tt = np.array([1.0e+01, 1.0e+02, 1.0e+03, 1.0e+04, 1.3e+04, 2.1e+04, 3.4e+04, 6.3e+04, 1.0e+05, 1.0e+09])
+                                mt = np.array([1.18701555, 1.15484424, 1.09603514, 0.9981496, 0.96346395, 0.65175895, 0.6142901, 0.6056833, 0.5897776, 0.58822635])
+                                logttt= np.log(temperature)
+                                logmu = np.interp(logttt,np.log(tt),np.log(mt)) # linear interpolation in log-log space
+                                return np.exp(logmu)
+                        temperature_values = []
+                        mu_values = []
+                        T_over_mu_values = []
+                        current_temperature = 1e1
+                        final_temperature = 1e7
+                        dlogT = 0.1
+                        while current_temperature < final_temperature:
+                                temperature_values.append(current_temperature)
+                                current_mu = calc_mu_table_local(current_temperature)
+                                mu_values.append(current_mu)
+                                T_over_mu_values.append(current_temperature/current_mu)
+                                current_temperature = np.exp(np.log(current_temperature)+dlogT)
+                        def convert_T_over_mu_to_T(T_over_mu):
+                                logT_over_mu = np.log(T_over_mu)
+                                logT = np.interp(logT_over_mu, np.log(T_over_mu_values), np.log(temperature_values)) # linear interpolation in log-log space
+                                return np.exp(logT)
+                        if codes[code] == 'GEAR' or codes[code] == 'GADGET-3' or codes[code] == "SWIFT":
+                                def _Temperature_3(field, data):
+                                        gamma = 5.0/3.0
+                                        T_over_mu = (data[PartType_Gas_to_use, "InternalEnergy"] * (gamma-1) * constants.mass_hydrogen_cgs / constants.boltzmann_constant_cgs).in_units('K').d # T/mu
+                                        return YTArray(convert_T_over_mu_to_T(T_over_mu), 'K') # now T
+                                pf.add_field((PartType_Gas_to_use, "Temperature"), function=_Temperature_3, particle_type=True, force_override=True, units="K")
+                        elif codes[code] == 'RAMSES':
+                                # The pressure field includes the artificial pressure support term, so one needs to be careful (compare with the exsiting frontends/ramses/fields.py)
+                                def _temperature_3(field, data):
+                                        T_J = 1800.0  # in K
+                                        n_J = 8.0     # in H/cc
+                                        gamma_0 = 2.0
+                                        x_H = 0.76
+                                        mH = 1.66e-24      # from pymses/utils/constants/__init__.py  (vs. in yt, mass_hydrogen_cgs = 1.007947*amu_cgs = 1.007947*1.660538921e-24 = 1.6737352e-24)
+                                        kB = 1.3806504e-16 # from pymses/utils/constants/__init__.py  (vs. in yt, boltzmann_constant_cgs = 1.3806488e-16)
+                                        if time != 0:
+                                                T_over_mu = data["gas", "pressure"].d/data["gas", "density"].d * mH / kB - T_J * (data["gas", "density"].d * x_H / mH / n_J)**(gamma_0 - 1.0) # T/mu = T2 in Ramses
+                                        else:
+                                                T_over_mu = data["gas", "pressure"].d/data["gas", "density"].d * mH / kB # IC: no pressure support
+                                        return YTArray(convert_T_over_mu_to_T(T_over_mu), 'K') # now T
+                                pf.add_field(("gas", "temperature"), function=_temperature_3, force_override=True, units="K")
+
+                # ADDITIONAL FIELDS IV: METALLICITY (IN MASS FRACTION, NOT IN ZSUN)
+                if draw_metal_map >= 1 or draw_metal_PDF == 1:
+                        if codes[code] == 'ART-I': # metallicity field in ART-I has a different meaning (see frontends/art/fields.py), and metallicity field in ART-II is missing
+                                def _metallicity_2(field, data):
+                                        return (data["gas", "metal_ii_density"] + data["gas", "metal_ia_density"]) / data["gas", "density"] # metal_ia_density needs to be added to account for initial 0.5 Zsun, even though we don't have SNe Ia
+                                pf.add_field(("gas", "metallicity"), function=_metallicity_2, force_override=True, display_name="Metallicity", take_log=True, units="")
+                        elif codes[code] == 'ART-II':
+                                def _metallicity_2(field, data):
+                                        return data["gas", "metal_ii_density"] / data["gas", "density"]
+                                pf.add_field(("gas", "metallicity"), function=_metallicity_2, force_override=True, display_name="Metallicity", take_log=True, units="")
+                        elif codes[code] == 'ENZO': # metallicity field in ENZO is in Zsun, so we create a new field
+                                def _metallicity_2(field, data):
+                                        return data["gas", "metal_density"] / data["gas", "density"]
+                                pf.add_field(("gas", "metallicity"), function=_metallicity_2, force_override=True, display_name="Metallicity", take_log=True, units="")
+                        elif codes[code] == 'GEAR': # "Metals" in GEAR is 10-species field ([:,9] is the total metal fraction), so requires a change in _vector_fields in frontends/gadget/io.py: added ("Metals", 10)
+                                def _metallicity_2(field, data):
+                                        if len(data[PartType_Gas_to_use, "Metals"].shape) == 1:
+                                                return data[PartType_Gas_to_use, "Metals"]
+                                        else:
+                                                return data[PartType_Gas_to_use, "Metals"][:,9].in_units("") # in_units("") turned out to be crucial!; otherwise code_metallicity will be used and it will mess things up
+                                # We are creating ("Gas", "Metallicity") here, different from ("Gas", "metallicity") which is auto-generated by yt but doesn't work properly
+                                pf.add_field((PartType_Gas_to_use, MetallicityType_to_use), function=_metallicity_2, display_name="Metallicity", particle_type=True, take_log=True, units="")
+                                # Also creating smoothed field following an example in yt-project.org/docs/dev/cookbook/calculating_information.html; use hardcoded num_neighbors as in frontends/gadget/fields.py
+                                fn = add_volume_weighted_smoothed_field(PartType_Gas_to_use, "Coordinates", MassType_to_use, "SmoothingLength", "Density", MetallicityType_to_use, pf.field_info, nneighbors=64)
+                                # Alias doesn't work -- e.g. pf.field_info.alias(("gas", "metallicity"), fn[0]) -- probably because pf=GadgetDataset()?, not load()?; so I add and replace existing ("gas", "metallicity")
+                                def _metallicity_3(field, data):
+                                        return data["deposit", PartType_Gas_to_use+"_smoothed_"+MetallicityType_to_use]
+                                pf.add_field(("gas", "metallicity"), function=_metallicity_3, force_override=True, display_name="Metallicity", particle_type=False, take_log=True, units="")
+                        if draw_metal_map >= 2:
+                                def _metal_mass(field, data):
+                                        return data["gas", "cell_mass"] * data["gas", "metallicity"]
+                                pf.add_field(("gas", "metal_mass"), function=_metal_mass, force_override=True, display_name="Metal Mass", take_log=True, units="Msun")
+
+                # ADDITIONAL FIELDS V: FAKE PARTICLE FIELDS, CYLINDRICAL COORDINATES, etc.
+                def rho_agora_disk(r, z):
+                        r_d = YTArray(3.432, 'kpc')
+                        z_d = 0.1*r_d
+                        M_d = YTArray(4.297e10, 'Msun')
+                        f_gas = 0.2
+                        r_0 = (f_gas*M_d / (4.0*np.pi*r_d**2*z_d)).in_units('g/cm**3')
+                        return r_0*numpy.exp(-r/r_d)*numpy.exp(-z/z_d)
+
+                if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                        def _cylindrical_z_abs(field, data):
+                                return numpy.abs(data[("index", "cylindrical_z")])
+                        pf.add_field(("index", "cylindrical_z_abs"), function=_cylindrical_z_abs, take_log=False, particle_type=False, units="cm")
+                        def _density_minus_analytic(field, data):
+                                return data[("gas", "density")] - rho_agora_disk(data[("index", "cylindrical_r")], data[("index", "cylindrical_z_abs")])
+                        pf.add_field(("gas", "density_minus_analytic"), function=_density_minus_analytic, take_log=False, particle_type=False, display_name="density residual abs", units="g/cm**3")
+                else:
+                        def _particle_position_cylindrical_z_abs(field, data):
+                                return numpy.abs(data[(PartType_Gas_to_use, "particle_position_cylindrical_z")])
+                        pf.add_field((PartType_Gas_to_use, "particle_position_cylindrical_z_abs"), function=_particle_position_cylindrical_z_abs, take_log=False, particle_type=True, units="cm")
+                        # particle_type=False doesn't make sense, but is critical for PhasePlot/ProfilePlot to work for particle fields
+                        # requires a change in data_objects/data_container.py: remove raise YTFieldTypeNotFound(ftype)
+                        def _Density_2(field, data):
+                                return data[(PartType_Gas_to_use, "Density")].in_units('g/cm**3')
+                        pf.add_field((PartType_Gas_to_use, "Density_2"), function=_Density_2, take_log=True, particle_type=False, display_name="Density", units="g/cm**3")
+                        def _Temperature_2(field, data):
+                                return data[(PartType_Gas_to_use, "Temperature")].in_units('K')
+                        pf.add_field((PartType_Gas_to_use, "Temperature_2"), function=_Temperature_2, take_log=True, particle_type=False, display_name="Temperature", units="K")
+                        def _Mass_2(field, data):
+                                return data[(PartType_Gas_to_use, MassType_to_use)].in_units('Msun')
+                        pf.add_field((PartType_Gas_to_use, "Mass_2"), function=_Mass_2, take_log=True, particle_type=False, display_name="Mass", units="Msun")
+                        if draw_metal_map >= 1 or draw_metal_PDF == 1:
+                                def _Metallicity_2(field, data):
+                                        return data[(PartType_Gas_to_use, MetallicityType_to_use)]
+                                pf.add_field((PartType_Gas_to_use, "Metallicity_2"), function=_Metallicity_2, take_log=True, particle_type=False, display_name="Metallicity", units="")
+                        def _Density_2_minus_analytic(field, data):
+                                return data[(PartType_Gas_to_use, "density")] - rho_agora_disk(data[(PartType_Gas_to_use, "particle_position_cylindrical_radius")], data[(PartType_Gas_to_use, "particle_position_cylindrical_z_abs")])
+                        pf.add_field((PartType_Gas_to_use, "Density_2_minus_analytic"), function=_Density_2_minus_analytic, take_log=False, particle_type=False, display_name="Density Residual", units="g/cm**3")
+
+                ####################################
+                #      MAIN ANALYSIS ROUTINES      #
+                ####################################
+
+                # FIND CENTER AND PROJ_REGION
+                v, cen = pf.h.find_max(("gas", "density")) # find the center to keep the galaxy at the center of all the images; here we assume that the gas disk is no bigger than 30 kpc in radius
+                sp = pf.sphere(cen, (30.0, "kpc"))
+                cen2 = sp.quantities.center_of_mass(use_gas=True, use_particles=False).in_units("kpc")
+                sp2 = pf.sphere(cen2, (1.0, "kpc"))
+                cen3 = sp2.quantities.max_location(("gas", "density"))
+                center = pf.arr([cen3[1].d, cen3[2].d, cen3[3].d], 'code_length') # naive usage such as YTArray([cen3[1], cen3[2], cen3[3]]) doesn't work somehow for ART-II data
+                if yt_version_pre_3_2_3 == 1:
+                        center = pf.arr([cen3[2].d, cen3[3].d, cen3[4].d], 'code_length') # for yt-3.2.3 or before
+                if codes[code] == "GASOLINE" and dataset_num == 2 and time == 1:
+                        #center = pf.arr([2.7912903206399826e+20, 1.5205303149849894e+21, 1.5398968883245956e+21], 'cm') # a temporary hack for GASOLINE (center of the most massive stellar clump)
+                        center = pf.arr([ 0.09045956,  0.49277032,  0.49904659], 'code_length')
+                # if codes[code] == "GADGET-3" and dataset_num == 2 and time == 1:
+                #       #center = pf.arr([6.184520935812296e+21, 4.972678132728082e+21, 6.559067311284074e+21], 'cm') # a temporary hack for GADGET-3 (center of the most massive stellar clump)
+                #       center = pf.arr([ 2.00426673674,  1.61153523084,  2.12564895041], 'code_length')
+                if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                        proj_region = pf.box(center - YTArray([figure_width, figure_width, figure_width], 'kpc'),
+                                             center + YTArray([figure_width, figure_width, figure_width], 'kpc')) # projected images made using a (2*figure_width)^3 box for AMR codes
+                else:
+                        proj_region = pf.all_data()
+
+                # DENSITY MAPS
+                if draw_density_map == 1:
+                        my_cmap = copy.copy(matplotlib.cm.get_cmap('algae'))
+                        my_cmap.set_bad(my_cmap(0)) # cmap range [0, 1)
+                        my_cmap.set_under(my_cmap(0))
+                        for ax in range(1, 3):
+                                p = ProjectionPlot(pf, ax, ("gas", "density"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = None, fontsize=9)
+                                p.set_zlim(("gas", "density"), 1e-5, 1e-1)
+                                p.set_cmap(("gas", "density"), my_cmap)
+                                plot = p.plots[("gas", "density")]
+
+                                plot.figure = fig_density_map[time]
+                                plot.axes = grid_density_map[time][(ax-1)*len(codes)+code].axes
+                                if code == 0: plot.cax = grid_density_map[time].cbar_axes[0]
+                                p._setup_plots()
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                grid_density_map[time][code].axes.add_artist(at)
+
+                # TEMPERATURE MAPS
+                if draw_temperature_map == 1:
+                        my_cmap = copy.copy(matplotlib.cm.get_cmap('algae'))
+                        my_cmap.set_bad(my_cmap(0.6)) # (log(1e4) - log(1e1)) / (log(1e6) - log(1e1)) = 0.6
+                        my_cmap.set_under(my_cmap(0))
+                        for ax in range(1, 3):
+                                p2 = ProjectionPlot(pf, ax, ("gas", "temperature"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = ("gas", "density_squared"), fontsize=9)
+                                p2.set_zlim(("gas", "temperature"), 1e1, 1e6)
+                                p2.set_cmap(("gas", "temperature"), my_cmap)
+                                plot2 = p2.plots[("gas", "temperature")]
+
+                                plot2.figure = fig_temperature_map[time]
+                                plot2.axes = grid_temperature_map[time][(ax-1)*len(codes)+code].axes
+                                if code == 0: plot2.cax = grid_temperature_map[time].cbar_axes[0]
+                                p2._setup_plots()
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                grid_temperature_map[time][code].axes.add_artist(at)
+
+                # CELL-SIZE MAPS
+                if draw_cellsize_map >= 1:
+                        my_cmap = copy.copy(matplotlib.cm.get_cmap('algae'))
+                        my_cmap.set_bad(my_cmap(0.99999)) # 1 doesn't work!
+                        my_cmap.set_under(my_cmap(0))
+                        if draw_cellsize_map == 1 or draw_cellsize_map == 3:
+                                for ax in range(1, 3):
+                                        p25 = ProjectionPlot(pf, ax, ("index", "cell_size"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = ("index", "cell_volume_inv2"), fontsize=9)
+                                        p25.set_zlim(("index", "cell_size"), 10, 1e3)
+                                        p25.set_cmap(("index", "cell_size"), my_cmap)
+                                        plot25 = p25.plots[("index", "cell_size")]
+
+                                        plot25.figure = fig_cellsize_map[time]
+                                        plot25.axes = grid_cellsize_map[time][(ax-1)*len(codes)+code].axes
+                                        if code == 0: plot25.cax = grid_cellsize_map[time].cbar_axes[0]
+                                        p25._setup_plots()
+
+                        # Create another map with a different resolution definition if requested
+                        if draw_cellsize_map == 2 or draw_cellsize_map == 3:
+                                for ax in range(1, 3):
+                                        if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                                p251 = ProjectionPlot(pf, ax, ("index", "cell_size"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), \
+                                                                             weight_field = ("index", "cell_volume_inv2"), fontsize=9)
+                                                p251.set_zlim(("index", "cell_size"), 10, 1e3)
+                                                p251.set_cmap(("index", "cell_size"), my_cmap)
+                                                plot251 = p251.plots[("index", "cell_size")]
+                                        else:
+                                                p251 = ProjectionPlot(pf, ax, ("gas", "particle_size"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), \
+                                                                             weight_field = ("gas", "particle_volume_inv2"), fontsize=9)
+                                                p251.set_zlim(("gas", "particle_size"), 10, 1e3)
+                                                p251.set_cmap(("gas", "particle_size"), my_cmap)
+                                                plot251 = p251.plots[("gas", "particle_size")]
+
+                                        plot251.figure = fig_cellsize_map_2[time]
+                                        plot251.axes = grid_cellsize_map_2[time][(ax-1)*len(codes)+code].axes
+                                        if code == 0: plot251.cax = grid_cellsize_map_2[time].cbar_axes[0]
+                                        p251._setup_plots()
+
+                        if add_nametag == 1:
+                                if draw_cellsize_map == 1 or draw_cellsize_map == 3:
+                                        at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                        grid_cellsize_map[time][code].axes.add_artist(at)
+                                if draw_cellsize_map == 2 or draw_cellsize_map == 3:
+                                        at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                        grid_cellsize_map_2[time][code].axes.add_artist(at)
+
+                # ELEVATION MAPS
+                if draw_elevation_map == 1:
+                        def _CellzElevationpc(field,data):
+                                return ((data[("index", "z")] - center[2]).in_units('pc'))
+                        pf.add_field(("index", "z_elevation"), function=_CellzElevationpc, units='kpc', display_name="$z$ Elevation", take_log=False)
+                        my_cmap = copy.copy(matplotlib.cm.get_cmap('algae'))
+                        my_cmap.set_bad(my_cmap(0.5))
+                        my_cmap.set_under(my_cmap(0))
+                        for ax in range(2, 3):
+                                p255 = ProjectionPlot(pf, ax, ("index", "z_elevation"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = ("gas", "density"), fontsize=9)
+                                p255.set_zlim(("index", "z_elevation"), -1, 1)
+                                p255.set_cmap(("index", "z_elevation"), my_cmap)
+                                plot255 = p255.plots[("index", "z_elevation")]
+
+                                plot255.figure = fig_elevation_map[time]
+                                plot255.axes = grid_elevation_map[time][(ax-2)*len(codes)+code].axes
+                                if code == 0: plot255.cax = grid_elevation_map[time].cbar_axes[0]
+                                p255._setup_plots()
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                grid_elevation_map[time][code].axes.add_artist(at)
+
+                # Z-VELOCITY MAPS
+                if draw_zvel_map == 1:
+                        my_cmap = copy.copy(matplotlib.cm.get_cmap('algae'))
+                        my_cmap.set_bad(my_cmap(0.5))
+                        my_cmap.set_under(my_cmap(0))
+                        for ax in range(1, 3):
+                                p26 = ProjectionPlot(pf, ax, ("gas", "velocity_z"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = ("gas", "density_squared"), fontsize=9)
+                                p26.set_zlim(("gas", "velocity_z"), -1e7, 1e7)
+                                p26.set_cmap(("gas", "velocity_z"), my_cmap)
+                                plot26 = p26.plots[("gas", "velocity_z")]
+
+                                plot26.figure = fig_zvel_map[time]
+                                plot26.axes = grid_zvel_map[time][(ax-1)*len(codes)+code].axes
+                                if code == 0: plot26.cax = grid_zvel_map[time].cbar_axes[0]
+                                p26._setup_plots()
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                grid_zvel_map[time][code].axes.add_artist(at)
+
+                # METAL MAPS
+                if draw_metal_map >= 1:
+                        my_cmap = copy.copy(matplotlib.cm.get_cmap('algae'))
+                        my_cmap.set_bad(my_cmap(0.347)) # (0.02041 - 0.01) / (0.04 - 0.01) = 0.347
+                        my_cmap.set_under(my_cmap(0))
+                        for ax in range(1, 3):
+                                pf.field_info[("gas", "metallicity")].take_log = False
+                                p26 = ProjectionPlot(pf, ax, ("gas", "metallicity"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = ("gas", "density_squared"), fontsize=9)
+                                p26.set_zlim(("gas", "metallicity"), 0.01, 0.04)
+                                p26.set_cmap(("gas", "metallicity"), my_cmap)
+                                plot26 = p26.plots[("gas", "metallicity")]
+
+                                plot26.figure = fig_metal_map[time]
+                                plot26.axes = grid_metal_map[time][(ax-1)*len(codes)+code].axes
+                                if code == 0: plot26.cax = grid_metal_map[time].cbar_axes[0]
+                                p26._setup_plots()
+
+                        if add_nametag == 1:
+                                if draw_metal_map == 2:
+                                        sp = pf.sphere(center, (1, "Mpc"))
+                                        total_metal_mass = sp.quantities.total_quantity([("gas", "metal_mass")])
+                                        at = AnchoredText("%s - %e" % (codes[code], total_metal_mass), loc=2, prop=dict(size=6), frameon=True)
+                                else:
+                                        at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                grid_metal_map[time][code].axes.add_artist(at)
+
+                # STELLAR MAPS
+                if draw_star_map == 1 and time != 0:
+                        for ax in range(1, 3):
+                                p27 = ParticleProjectionPlot(pf, ax, (PartType_Star_to_use, "particle_mass"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = None, fontsize=9)
+                                p27.set_unit((PartType_Star_to_use, "particle_mass"), 'Msun')
+                                p27.set_zlim((PartType_Star_to_use, "particle_mass"), 1e4, 1e7)
+                                p27.set_cmap((PartType_Star_to_use, "particle_mass"), 'algae')
+                                p27.set_buff_size(400) # default is 800
+                                p27.set_colorbar_label((PartType_Star_to_use, "particle_mass"), "Stellar Mass Per Pixel ($\mathrm{M}_{\odot}$)")
+                                plot27 = p27.plots[(PartType_Star_to_use, "particle_mass")]
+                                # p27 = ParticleProjectionPlot(pf, ax, (PartType_Star_to_use, "particle_velocity_cylindrical_theta"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = (PartType_Star_to_use, "particle_mass"), fontsize=9)
+                                # p27.set_unit((PartType_Star_to_use, "particle_velocity_cylindrical_theta"), 'km/s')
+                                # p27.set_buff_size(400)
+                                # p27.set_colorbar_label((PartType_Star_to_use, "particle_velocity_cylindrical_theta"), "Rotational Velocity (km/s)")
+                                # plot27 = p27.plots[(PartType_Star_to_use, "particle_velocity_cylindrical_theta")]
+
+                                plot27.figure = fig_star_map[time]
+                                plot27.axes = grid_star_map[time][(ax-1)*len(codes)+code].axes
+                                if code == 0: plot27.cax = grid_star_map[time].cbar_axes[0]
+                                p27._setup_plots()
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                grid_star_map[time][code].axes.add_artist(at)
+
+                # STELLAR CLUMP STATISTICS AND ANNOTATED STELLAR MAPS
+                if draw_star_clump_stats >= 1 and time != 0:
+                        # For make yt's HaloCatalog to work with non-cosmological dataset, a fix needed to be applied to analysis_modules/halo_finding/halo_objects.py: self.period = ds.arr([3.254, 3.254, 3.254], 'Mpc')
+                        pf.hubble_constant = 0.71; pf.omega_lambda = 0.73; pf.omega_matter = 0.27; pf.omega_curvature = 0.0; pf.current_redshift = 0.0 # another trick to make HaloCatalog work especially for ART-I dataset
+                        if os.path.exists("./halo_catalogs/hop_%s_%05d/hop_%s_%05d.0.h5" % (codes[code], times[time], codes[code], times[time])) == False:
+                                hc = HaloCatalog(data_ds=pf, finder_method='hop', output_dir="./halo_catalogs/hop_%s_%05d" % (codes[code], times[time]), \
+                                                         finder_kwargs={'threshold': 2e8, 'dm_only': False, 'ptype': PartType_Star_to_use})
+#                                                        finder_kwargs={'threshold': 2e5, 'dm_only': False, 'ptype': "all"})
+                                hc.add_filter('quantity_value', 'particle_mass', '>', 2.6e6, 'Msun') # exclude halos with less than 30 particles
+                                hc.add_filter('quantity_value', 'particle_mass', '<', 2.6e8, 'Msun') # exclude the most massive halo (threshold 1e8.4 is hand-picked, so one needs to be careful!)
+                                hc.create()
+                        halo_ds = load("./halo_catalogs/hop_%s_%05d/hop_%s_%05d.0.h5" % (codes[code], times[time], codes[code], times[time]))
+                        hc = HaloCatalog(halos_ds=halo_ds, output_dir="./halo_catalogs/hop_%s_%05d" % (codes[code], times[time]))
+                        hc.load()
+
+                        halo_ad = hc.halos_ds.all_data()
+                        star_clump_masses_hop[time].append(np.log10(halo_ad['particle_mass'][:].in_units("Msun")))
+
+                        if os.path.exists("./halo_catalogs/fof_%s_%05d/fof_%s_%05d.0.h5" % (codes[code], times[time], codes[code], times[time])) == False:
+                                hc2 = HaloCatalog(data_ds=pf, finder_method='fof', output_dir="./halo_catalogs/fof_%s_%05d" % (codes[code], times[time]), \
+                                                          finder_kwargs={'link': 0.0025, 'dm_only': False, 'ptype': PartType_Star_to_use})
+#                                                         finder_kwargs={'link': 0.02, 'dm_only': False, 'ptype': "all"})
+                                hc2.add_filter('quantity_value', 'particle_mass', '>', 2.6e6, 'Msun') # exclude halos with less than 30 particles
+                                hc2.add_filter('quantity_value', 'particle_mass', '<', 2.6e8, 'Msun') # exclude the most massive halo (threshold 1e8.4 is hand-picked, so one needs to be careful!)
+                                hc2.create()
+                        halo_ds2 = load("./halo_catalogs/fof_%s_%05d/fof_%s_%05d.0.h5" % (codes[code], times[time], codes[code], times[time]))
+                        hc2 = HaloCatalog(halos_ds=halo_ds2, output_dir="./halo_catalogs/fof_%s_%05d" % (codes[code], times[time]))
+                        hc2.load()
+
+                        halo_ad2 = hc2.halos_ds.all_data()
+                        star_clump_masses_fof[time].append(np.log10(halo_ad2['particle_mass'][:].in_units("Msun")))
+                        # most_massive = halo_ad['particle_mass'].max().in_units('Msun')
+                        # cen4 = [halo_ad['particle_position_x'][halo_ad['particle_mass'] == most_massive][0].in_units('code_length').d,
+                        #       halo_ad['particle_position_y'][halo_ad['particle_mass'] == most_massive][0].in_units('code_length').d,
+                        #       halo_ad['particle_position_z'][halo_ad['particle_mass'] == most_massive][0].in_units('code_length').d]
+
+
+                        # Add additional star_map with annotated clumps if requested
+                        if draw_star_clump_stats >= 2:
+                                for ax in range(1, 3):
+                                        p271 = ParticleProjectionPlot(pf, ax, (PartType_Star_to_use, "particle_mass"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = None, fontsize=9)
+                                        p271.set_unit((PartType_Star_to_use, "particle_mass"), 'Msun')
+                                        p271.set_zlim((PartType_Star_to_use, "particle_mass"), 1e4, 1e7)
+                                        p271.set_cmap((PartType_Star_to_use, "particle_mass"), 'algae')
+                                        p271.set_buff_size(400) # default is 800
+                                        p271.set_colorbar_label((PartType_Star_to_use, "particle_mass"), "Stellar Mass Per Pixel ($\mathrm{M}_{\odot}$)")
+                                        plot271 = p271.plots[(PartType_Star_to_use, "particle_mass")]
+                                        if ax == 2:
+                                                p271.annotate_halos(hc, factor=1.0, circle_args={'linewidth':0.7, 'alpha':0.8, 'facecolor':'none', 'edgecolor':'k'})
+
+                                        plot271.figure = fig_star_map_2[time]
+                                        plot271.axes = grid_star_map_2[time][(ax-1)*len(codes)+code].axes
+                                        if code == 0: plot271.cax = grid_star_map_2[time].cbar_axes[0]
+                                        p271._setup_plots()
+
+                                if add_nametag == 1:
+                                        at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                        grid_star_map_2[time][code].axes.add_artist(at)
+
+                                for ax in range(1, 3):
+                                        p272 = ParticleProjectionPlot(pf, ax, (PartType_Star_to_use, "particle_mass"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = None, fontsize=9)
+                                        p272.set_unit((PartType_Star_to_use, "particle_mass"), 'Msun')
+                                        p272.set_zlim((PartType_Star_to_use, "particle_mass"), 1e4, 1e7)
+                                        p272.set_cmap((PartType_Star_to_use, "particle_mass"), 'algae')
+                                        p272.set_buff_size(400) # default is 800
+                                        p272.set_colorbar_label((PartType_Star_to_use, "particle_mass"), "Stellar Mass Per Pixel ($\mathrm{M}_{\odot}$)")
+                                        plot272 = p272.plots[(PartType_Star_to_use, "particle_mass")]
+                                        # p272 = ParticleProjectionPlot(pf, ax, ("all", "particle_mass"), center = center, data_source=proj_region, width = (figure_width, 'kpc'), weight_field = None, fontsize=9)
+                                        # p272.set_unit(("all", "particle_mass"), 'Msun')
+                                        # p272.set_zlim(("all", "particle_mass"), 1e4, 1e9)
+                                        # p272.set_cmap(("all", "particle_mass"), 'algae')
+                                        # p272.set_buff_size(400) # default is 800
+                                        # p272.set_colorbar_label(("all", "particle_mass"), "Mass Per Pixel ($\mathrm{M}_{\odot}$)")
+                                        # plot272 = p272.plots[("all", "particle_mass")]
+                                        if ax == 2:
+                                                p272.annotate_halos(hc2, factor=1.0, circle_args={'linewidth':0.7, 'alpha':0.8, 'facecolor':'none', 'edgecolor':'k'})#, annotate_field='particle_mass')
+
+                                        plot272.figure = fig_star_map_3[time]
+                                        plot272.axes = grid_star_map_3[time][(ax-1)*len(codes)+code].axes
+                                        if code == 0: plot272.cax = grid_star_map_3[time].cbar_axes[0]
+                                        p272._setup_plots()
+
+                                if add_nametag == 1:
+                                        at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                        grid_star_map_3[time][code].axes.add_artist(at)
+
+                # SFR MAPS
+                if draw_SFR_map >= 1 and time != 0:
+                        sp = pf.sphere(center, (1.0*figure_width, "kpc"))
+                        xy_bins = int(float(figure_width) / (float(aperture_size_SFR_map/1000.)))
+                        my_cmap = copy.copy(matplotlib.cm.get_cmap('algae'))
+                        my_cmap.set_bad(my_cmap(0))
+                        my_cmap.set_under(my_cmap(0))
+                        if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                def _position_x_from_center(field, data):
+                                        return (data[("index", "x")] - center[0]).in_units('kpc')
+                                pf.add_field(("index", "position_x_from_center"), function=_position_x_from_center, take_log=False, particle_type=False, units="kpc")
+                                def _position_y_from_center(field, data):
+                                        return (data[("index", "y")] - center[1]).in_units('kpc')
+                                pf.add_field(("index", "position_y_from_center"), function=_position_y_from_center, take_log=False, particle_type=False, units="kpc")
+                                def _cell_mass_surface_density_SFR_map(field, data):
+                                        trans = np.zeros(data[("gas", "cell_mass")].shape)
+                                        ind = np.where(data[("gas", "cell_mass")] > 0)
+                                        trans[ind] = data[("gas", "cell_mass")][ind].in_units('Msun').d/(float(aperture_size_SFR_map))**2
+                                        return data.ds.arr(trans, "Msun/pc**2").in_base(data.ds.unit_system.name)
+                                pf.add_field(("gas", "cell_mass_surface_density_SFR_map"), function=_cell_mass_surface_density_SFR_map, \
+                                                     display_name="$\mathrm{\Sigma}_\mathrm{gas}$", units='Msun/pc**2', particle_type=False, take_log=True)
+
+                                p28 = PhasePlot(sp, ("index", "position_x_from_center"), ("index", "position_y_from_center"), \
+                                                        ("gas", "cell_mass_surface_density_SFR_map"), weight_field=None, fontsize=9, x_bins=xy_bins, y_bins=xy_bins)
+                                p28.set_zlim(("gas", "cell_mass_surface_density_SFR_map"), 1e0, 1e3)
+                                p28.set_cmap(("gas", "cell_mass_surface_density_SFR_map"), my_cmap)
+                                plot28 = p28.plots[("gas", "cell_mass_surface_density_SFR_map")]
+                        else:
+                                def _particle_position_x_from_center(field, data):
+                                        return (data[(PartType_Gas_to_use, "particle_position_x")] - center[0]).in_units('kpc')
+                                pf.add_field((PartType_Gas_to_use, "particle_position_x_from_center"), function=_particle_position_x_from_center, take_log=False, particle_type=True, units="kpc")
+                                def _particle_position_y_from_center(field, data):
+                                        return (data[(PartType_Gas_to_use, "particle_position_y")] - center[0]).in_units('kpc')
+                                pf.add_field((PartType_Gas_to_use, "particle_position_y_from_center"), function=_particle_position_y_from_center, take_log=False, particle_type=True, units="kpc")
+                                def _particle_mass_surface_density_SFR_map(field, data):
+                                        trans = np.zeros(data[(PartType_Gas_to_use, "particle_mass")].shape)
+                                        ind = np.where(data[(PartType_Gas_to_use, "particle_mass")] > 0)
+                                        trans[ind] = data[(PartType_Gas_to_use, "particle_mass")][ind].in_units('Msun').d/(float(aperture_size_SFR_map))**2
+                                        return data.ds.arr(trans, "Msun/pc**2").in_base(data.ds.unit_system.name)
+                                pf.add_field((PartType_Gas_to_use, "particle_mass_surface_density_SFR_map"), function=_particle_mass_surface_density_SFR_map, \
+                                                     display_name="$\mathrm{\Sigma}_\mathrm{gas}$", units='Msun/pc**2', particle_type=True, take_log=True)
+
+                                p28 = ParticlePhasePlot(sp, (PartType_Gas_to_use, "particle_position_x_from_center"), (PartType_Gas_to_use, "particle_position_y_from_center"), \
+                                                                (PartType_Gas_to_use, "particle_mass_surface_density_SFR_map"), weight_field=None, deposition='cic', fontsize=9, x_bins=xy_bins, y_bins=xy_bins)
+                                p28.set_zlim((PartType_Gas_to_use, "particle_mass_surface_density_SFR_map"), 1e0, 1e3)
+                                p28.set_cmap((PartType_Gas_to_use, "particle_mass_surface_density_SFR_map"), my_cmap)
+                                plot28 = p28.plots[(PartType_Gas_to_use, "particle_mass_surface_density_SFR_map")]
+
+                        p28.set_xlabel("x (kpc)")
+                        p28.set_ylabel("y (kpc)")
+                        p28.set_xlim(-15, 15)
+                        p28.set_ylim(-15, 15)
+                        plot28.figure = fig_degr_density_map[time]
+                        plot28.axes = grid_degr_density_map[time][code].axes
+                        if code == 0: plot28.cax = grid_degr_density_map[time].cbar_axes[0]
+                        p28._setup_plots()
+
+                        def _particle_position_x_from_center_2(field, data):
+                                return (data[(PartType_StarBeforeFiltered_to_use, "particle_position_x")] - center[0]).in_units('kpc')
+                        pf.add_field((PartType_StarBeforeFiltered_to_use, "particle_position_x_from_center"), function=_particle_position_x_from_center_2, take_log=False, particle_type=True, units="kpc")
+                        pf.add_particle_filter(PartType_Star_to_use) # This is needed for a filtered particle type PartType_Star_to_use to work, because we have just created new particle fields.
+                        def _particle_position_y_from_center_2(field, data):
+                                return (data[(PartType_StarBeforeFiltered_to_use, "particle_position_y")] - center[0]).in_units('kpc')
+                        pf.add_field((PartType_StarBeforeFiltered_to_use, "particle_position_y_from_center"), function=_particle_position_y_from_center_2, take_log=False, particle_type=True, units="kpc")
+                        pf.add_particle_filter(PartType_Star_to_use)
+                        def _particle_mass_young_stars_SFR_surface_density_SFR_map(field, data):
+                                trans = np.zeros(data[(PartType_StarBeforeFiltered_to_use, "particle_mass")].shape)
+                                ind = np.where(data[(PartType_StarBeforeFiltered_to_use, FormationTimeType_to_use)].in_units('Myr') > (pf.current_time.in_units('Myr').d - young_star_cutoff_SFR_map)) # mass for young stars only
+                                trans[ind] = data[(PartType_StarBeforeFiltered_to_use, "particle_mass")][ind].in_units('Msun').d/(young_star_cutoff_SFR_map*1e6)/(float(aperture_size_SFR_map)/1000.)**2
+                                return data.ds.arr(trans, "Msun/yr/kpc**2").in_base(data.ds.unit_system.name)
+                        pf.add_field((PartType_StarBeforeFiltered_to_use, "particle_mass_young_stars_SFR_surface_density_SFR_map"), function=_particle_mass_young_stars_SFR_surface_density_SFR_map, \
+                                             display_name="$\mathrm{\Sigma}_\mathrm{SFR}$", units='Msun/yr/kpc**2', particle_type=True, take_log=True)
+                        pf.add_particle_filter(PartType_Star_to_use)
+
+                        p281 = ParticlePhasePlot(sp, (PartType_Star_to_use, "particle_position_x_from_center"), (PartType_Star_to_use, "particle_position_y_from_center"), \
+                                                         (PartType_Star_to_use, "particle_mass_young_stars_SFR_surface_density_SFR_map"), deposition='cic', weight_field=None, fontsize=9, x_bins=xy_bins, y_bins=xy_bins)
+                        p281.set_zlim((PartType_Star_to_use, "particle_mass_young_stars_SFR_surface_density_SFR_map"), 3e-4, 3e-1)
+                        p281.set_cmap((PartType_Star_to_use, "particle_mass_young_stars_SFR_surface_density_SFR_map"), my_cmap)
+                        plot281 = p281.plots[(PartType_Star_to_use, "particle_mass_young_stars_SFR_surface_density_SFR_map")]
+
+                        p281.set_xlabel("x (kpc)")
+                        p281.set_ylabel("y (kpc)")
+                        p281.set_xlim(-15, 15)
+                        p281.set_ylim(-15, 15)
+                        plot281.figure = fig_degr_sfr_map[time]
+                        plot281.axes = grid_degr_sfr_map[time][code].axes
+                        if code == 0: plot281.cax = grid_degr_sfr_map[time].cbar_axes[0]
+                        p281._setup_plots()
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                grid_degr_density_map[time][code].axes.add_artist(at)
+                                at2 = AnchoredText("%s" % codes[code], loc=2, prop=dict(size=6), frameon=True)
+                                grid_degr_sfr_map[time][code].axes.add_artist(at2)
+
+                        # Record degraded maps for the later use in a local K-S plot
+                        if draw_SFR_map == 2 and time != 0:
+                                fn = p28.profile.save_as_dataset() # see http://yt-project.org/docs/dev/reference/api/generated/yt.data_objects.profiles.ProfileND.save_as_dataset.html
+                                phaseplot_ds = load(fn)
+                                if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                        phaseplot_surf_dens = phaseplot_ds.data[('data', "cell_mass_surface_density_SFR_map")]
+                                else:
+                                        phaseplot_surf_dens = phaseplot_ds.data[('data', "particle_mass_surface_density_SFR_map")]
+                                fn_1 = p281.profile.save_as_dataset()
+                                phaseplot_ds_1 = load(fn_1)
+                                phaseplot_sfr_surf_dens = phaseplot_ds_1.data[('data', "particle_mass_young_stars_SFR_surface_density_SFR_map")]
+                                xy_shape = phaseplot_surf_dens.shape[0]
+                                surf_dens_SFR_map[time].append(phaseplot_surf_dens.reshape(1, xy_shape**2)[0])
+                                sfr_surf_dens_SFR_map[time].append(phaseplot_sfr_surf_dens.reshape(1, xy_shape**2)[0])
+                                call(["rm", "%s_%s.h5" % (str(pf), 'ParticleProfile')]) # Remove unwanted .h5 files saved
+                                if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                        call(["rm", "%s_%s.h5" % (str(pf), 'Profile2D')])
+
+                # DENSITY-TEMPERATURE PDF
+                if draw_PDF >= 1:
+                        sp = pf.sphere(center, (0.5*figure_width, "kpc"))
+                        my_cmap2 = copy.copy(matplotlib.cm.get_cmap('algae'))
+                        my_cmap2.set_under(my_cmap2(0))
+                        if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                p3 = PhasePlot(sp, ("gas", "density"), ("gas", "temperature"), ("gas", "cell_mass"), weight_field=None, fontsize=12, x_bins=300, y_bins=300)
+                                p3.set_unit("cell_mass", 'Msun')
+                                p3.set_zlim(("gas", "cell_mass"), 1e3, 1e8)
+                                p3.set_cmap(("gas", "cell_mass"), my_cmap2)
+                                p3.set_colorbar_label(("gas", "cell_mass"), "Mass ($\mathrm{M}_{\odot}$)")
+                                plot3 = p3.plots[("gas", "cell_mass")]
+                        else:
+                                # Because ParticlePhasePlot doesn't yet work for a log-log PDF for some reason, I will do the following trick.
+                                p3 = PhasePlot(sp, (PartType_Gas_to_use, "Density_2"), (PartType_Gas_to_use, "Temperature_2"), (PartType_Gas_to_use, "Mass_2"), weight_field=None, fontsize=12, x_bins=300, y_bins=300)
+                                p3.set_zlim((PartType_Gas_to_use, "Mass_2"), 1e3, 1e8)
+                                p3.set_cmap((PartType_Gas_to_use, "Mass_2"), my_cmap2)
+                                plot3 = p3.plots[(PartType_Gas_to_use, "Mass_2")]
+
+                        p3.set_xlim(1e-29, 1e-21)
+                        p3.set_ylim(10, 1e7)
+
+                        plot3.figure = fig_PDF[time]
+                        plot3.axes = grid_PDF[time][code].axes
+                        if code == 0: plot3.cax = grid_PDF[time].cbar_axes[0]
+                        p3._setup_plots()
+
+                        # Add constant pressure and constant entropy lines to guide the eyes
+                        if draw_PDF >= 2:
+                                dummy_density = np.logspace(-29, -21, num=4)
+                                for constant_i in range(1, 100):
+                                        constant = 1e-100*100**constant_i
+                                        line = ln.Line2D(dummy_density, constant/dummy_density, linestyle=":", linewidth=0.6, color='k', alpha=0.7) # constant pressure P ~ n*T
+                                        grid_PDF[time][code].axes.add_line(line)
+                                        line2 = ln.Line2D(dummy_density, constant*dummy_density**(2./3.), linestyle="-.", linewidth=0.6, color='k', alpha=0.7) # constant entropy S ~ n**(-2/3)*T
+                                        grid_PDF[time][code].axes.add_line(line2)
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=3, prop=dict(size=10), frameon=True)
+                                grid_PDF[time][code].axes.add_artist(at)
+
+                # POSITION-VELOCITY PDF FOR GAS
+                if draw_pos_vel_PDF >= 1:
+                        sp = pf.sphere(center, (0.5*figure_width, "kpc"))
+                        sp.set_field_parameter("normal", disk_normal_vector)
+                        if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                sp_dense = sp.cut_region(["obj['gas', 'density'].in_units('g/cm**3') > 1.e-25"]) # For AMR codes, consider only the cells that are dense enough
+                                pf.field_info[("index", "cylindrical_r")].take_log = False
+                                pf.field_info[("gas", "cylindrical_tangential_velocity")].take_log = False
+                                p4 = PhasePlot(sp_dense, ("index", "cylindrical_r"), ("gas", "cylindrical_tangential_velocity"), ("gas", "cell_mass"), weight_field=None, fontsize=12, x_bins=300, y_bins=300)
+                                p4.set_unit("cylindrical_r", 'kpc')
+                                p4.set_unit("cylindrical_tangential_velocity", 'km/s')
+                                p4.set_unit("cell_mass", 'Msun')
+                                p4.set_zlim(("gas", "cell_mass"), 1e3, 1e8)
+                                p4.set_cmap(("gas", "cell_mass"), 'algae')
+                                p4.set_colorbar_label(("gas", "cell_mass"), "Mass ($\mathrm{M}_{\odot}$)")
+                                plot4 = p4.plots[("gas", "cell_mass")]
+                        else:
+                                pf.field_info[(PartType_Gas_to_use, "particle_position_cylindrical_radius")].take_log = False
+                                pf.field_info[(PartType_Gas_to_use, "particle_velocity_cylindrical_theta")].take_log = False
+                                p4 = ParticlePhasePlot(sp, (PartType_Gas_to_use, "particle_position_cylindrical_radius"), (PartType_Gas_to_use, "particle_velocity_cylindrical_theta"), \
+                                                               (PartType_Gas_to_use, MassType_to_use), deposition='ngp', weight_field=None, fontsize=12, x_bins=300, y_bins=300)
+                                p4.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                p4.set_unit("particle_velocity_cylindrical_theta", 'km/s')
+                                p4.set_unit(MassType_to_use, 'Msun')
+                                p4.set_zlim((PartType_Gas_to_use, MassType_to_use), 1e3, 1e8)
+                                p4.set_cmap((PartType_Gas_to_use, MassType_to_use), 'algae')
+                                p4.set_colorbar_label((PartType_Gas_to_use, MassType_to_use), "Mass ($\mathrm{M}_{\odot}$)")
+                                plot4 = p4.plots[(PartType_Gas_to_use, MassType_to_use)]
+
+                        p4.set_xlabel("Cylindrical Radius (kpc)")
+                        p4.set_ylabel("Rotational Velocity (km/s)")
+                        p4.set_xlim(0, 14)
+                        p4.set_ylim(-100, 350)
+
+                        plot4.figure = fig_pos_vel_PDF[time]
+                        plot4.axes = grid_pos_vel_PDF[time][code].axes
+                        if code == 0: plot4.cax = grid_pos_vel_PDF[time].cbar_axes[0]
+                        p4._setup_plots()
+
+                        # Add 1D profile line if requested
+                        if draw_pos_vel_PDF >= 2 and time != 0:
+                                if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                        p5 = ProfilePlot(sp_dense, ("index", "cylindrical_r"),  ("gas", "cylindrical_tangential_velocity"), \
+                                                                 weight_field=("gas", "cell_mass"), n_bins=50, x_log=False)
+                                        p5.set_log("cylindrical_tangential_velocity", False)
+                                        p5.set_log("cylindrical_r", False)
+                                        p5.set_unit("cylindrical_r", 'kpc')
+                                        p5.set_xlim(1e-3, 14)
+                                        p5.set_ylim("cylindrical_tangential_velocity", -100, 350)
+                                        line = ln.Line2D(p5.profiles[0].x.in_units('kpc'), p5.profiles[0]["cylindrical_tangential_velocity"].in_units('km/s'), linestyle="-", linewidth=2, color='k', alpha=0.7)
+                                        pos_vel_xs[time].append(p5.profiles[0].x.in_units('kpc').d)
+                                        pos_vel_profiles[time].append(p5.profiles[0]["cylindrical_tangential_velocity"].in_units('km/s').d)
+                                else:
+                                        p5 = ProfilePlot(sp, (PartType_Gas_to_use, "particle_position_cylindrical_radius"), (PartType_Gas_to_use, "particle_velocity_cylindrical_theta"), \
+                                                                 weight_field=(PartType_Gas_to_use, MassType_to_use), n_bins=50, x_log=False)
+                                        p5.set_log("particle_velocity_cylindrical_theta", False)
+                                        p5.set_log("particle_position_cylindrical_radius", False)
+                                        p5.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                        p5.set_xlim(1e-3, 14)
+                                        p5.set_ylim("particle_velocity_cylindrical_theta", -100, 350)
+                                        line = ln.Line2D(p5.profiles[0].x.in_units('kpc'), p5.profiles[0]["particle_velocity_cylindrical_theta"].in_units('km/s'), linestyle="-", linewidth=2, color='k', alpha=0.7)
+                                        pos_vel_xs[time].append(p5.profiles[0].x.in_units('kpc').d)
+                                        pos_vel_profiles[time].append(p5.profiles[0]["particle_velocity_cylindrical_theta"].in_units('km/s').d)
+                                grid_pos_vel_PDF[time][code].axes.add_line(line)
+
+                        # Add velocity dispersion profile if requested
+                        if draw_pos_vel_PDF >= 3 and time != 0:
+                                if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                        # To calculate velocity dispersion -- residual velocity components other than the rotational velocity found above -- we will need a mass-weighted average of [v_i - v_rot_local]**2
+                                        # Here we assumed that the disk is on x-y plane; i.e. the variable disk_normal_vector above needs to be [0.0, 0.0, 1.0]
+                                        def _local_rotational_velocity_x(field, data):
+                                                trans = np.zeros(data[("gas", "velocity_x")].shape)
+                                                dr = 0.5*(pos_vel_xs[time][code][1] - pos_vel_xs[time][code][0])
+                                                for radius, v_rot_local in zip(pos_vel_xs[time][code], pos_vel_profiles[time][code]):
+                                                        ind = np.where((data[("index", "cylindrical_r")].in_units("kpc") >= (radius - dr)) & (data[("index", "cylindrical_r")].in_units("kpc") < (radius + dr)))
+                                                        trans[ind] = -np.sin(data["index", 'cylindrical_theta'][ind]) * v_rot_local * 1e5 # in cm/s
+                                                return data.ds.arr(trans, "cm/s").in_base(data.ds.unit_system.name)
+                                        pf.add_field(("gas", "local_rotational_velocity_x"), function=_local_rotational_velocity_x, take_log=False, particle_type=False, units="cm/s")
+                                        def _local_rotational_velocity_y(field, data):
+                                                trans = np.zeros(data[("gas", "velocity_y")].shape)
+                                                dr = 0.5*(pos_vel_xs[time][code][1] - pos_vel_xs[time][code][0])
+                                                for radius, v_rot_local in zip(pos_vel_xs[time][code], pos_vel_profiles[time][code]):
+                                                        ind = np.where((data[("index", "cylindrical_r")].in_units("kpc") >= (radius - dr)) & (data[("index", "cylindrical_r")].in_units("kpc") < (radius + dr)))
+                                                        trans[ind] =  np.cos(data["index", 'cylindrical_theta'][ind]) * v_rot_local * 1e5
+                                                return data.ds.arr(trans, "cm/s").in_base(data.ds.unit_system.name)
+                                        pf.add_field(("gas", "local_rotational_velocity_y"), function=_local_rotational_velocity_y, take_log=False, particle_type=False, units="cm/s")
+                                        def _velocity_minus_local_rotational_velocity_squared(field, data):
+                                                return (data[("gas", "velocity_x")] - data[("gas", "local_rotational_velocity_x")])**2 + \
+                                                    (data[("gas", "velocity_y")] - data[("gas", "local_rotational_velocity_y")])**2 + \
+                                                    (data[("gas", "velocity_z")])**2
+                                        pf.add_field(("gas", "velocity_minus_local_rotational_velocity_squared"), function=_velocity_minus_local_rotational_velocity_squared,
+                                                     take_log=False, particle_type=False, units="cm**2/s**2")
+#					slc = SlicePlot(pf, 'z', ("gas", "local_rotational_velocity_y"), center = center, width = (figure_width, 'kpc'))
+#					slc = SlicePlot(pf, 'z', ("gas", "velocity_minus_local_rotational_velocity_squared"), center = center, width = (figure_width, 'kpc')) # this should give zeros everywhere for IC at t=0
+#					slc.save()
+
+                                        p55 = ProfilePlot(sp_dense, ("index", "cylindrical_r"),  ("gas", "velocity_minus_local_rotational_velocity_squared"), \
+                                                                  weight_field=("gas", "cell_mass"), n_bins=50, x_log=False)
+                                        p55.set_log("cylindrical_r", False)
+                                        p55.set_unit("cylindrical_r", 'kpc')
+                                        p55.set_xlim(1e-3, 14)
+                                        pos_disp_xs[time].append(p55.profiles[0].x.in_units('kpc').d)
+                                        pos_disp_profiles[time].append(np.sqrt(p55.profiles[0]["velocity_minus_local_rotational_velocity_squared"]).in_units('km/s').d)
+                                else:
+                                        def _particle_local_rotational_velocity_x(field, data):
+                                                trans = np.zeros(data[(PartType_Gas_to_use, "particle_velocity_x")].shape)
+                                                dr = 0.5*(pos_vel_xs[time][code][1] - pos_vel_xs[time][code][0])
+                                                for radius, v_rot_local in zip(pos_vel_xs[time][code], pos_vel_profiles[time][code]):
+                                                        ind = np.where((data[(PartType_Gas_to_use, "particle_position_cylindrical_radius")].in_units("kpc") >= (radius - dr)) & \
+                                                                               (data[(PartType_Gas_to_use, "particle_position_cylindrical_radius")].in_units("kpc") < (radius + dr)))
+                                                        trans[ind] = -np.sin(data[(PartType_Gas_to_use, "particle_position_cylindrical_theta")][ind]) * v_rot_local * 1e5
+                                                return data.ds.arr(trans, "cm/s").in_base(data.ds.unit_system.name)
+                                        pf.add_field((PartType_Gas_to_use, "particle_local_rotational_velocity_x"), function=_particle_local_rotational_velocity_x, take_log=False, particle_type=True, units="cm/s")
+                                        def _particle_local_rotational_velocity_y(field, data):
+                                                trans = np.zeros(data[(PartType_Gas_to_use, "particle_velocity_y")].shape)
+                                                dr = 0.5*(pos_vel_xs[time][code][1] - pos_vel_xs[time][code][0])
+                                                for radius, v_rot_local in zip(pos_vel_xs[time][code], pos_vel_profiles[time][code]):
+                                                        ind = np.where((data[(PartType_Gas_to_use, "particle_position_cylindrical_radius")].in_units("kpc") >= (radius - dr)) & \
+                                                                               (data[(PartType_Gas_to_use, "particle_position_cylindrical_radius")].in_units("kpc") < (radius + dr)))
+                                                        trans[ind] = np.cos(data[(PartType_Gas_to_use, "particle_position_cylindrical_theta")][ind]) * v_rot_local * 1e5
+                                                return data.ds.arr(trans, "cm/s").in_base(data.ds.unit_system.name)
+                                        pf.add_field((PartType_Gas_to_use, "particle_local_rotational_velocity_y"), function=_particle_local_rotational_velocity_y, take_log=False, particle_type=True, units="cm/s")
+                                        def _particle_velocity_minus_local_rotational_velocity_squared(field, data):
+                                                return (data[(PartType_Gas_to_use, "particle_velocity_x")] - data[(PartType_Gas_to_use, "particle_local_rotational_velocity_x")])**2 + \
+                                                    (data[(PartType_Gas_to_use, "particle_velocity_y")] - data[(PartType_Gas_to_use, "particle_local_rotational_velocity_y")])**2 + \
+                                                    (data[(PartType_Gas_to_use, "particle_velocity_z")])**2
+                                        pf.add_field((PartType_Gas_to_use, "particle_velocity_minus_local_rotational_velocity_squared"), function=_particle_velocity_minus_local_rotational_velocity_squared,
+                                                     take_log=False, particle_type=True, units="cm**2/s**2")
+
+                                        p55 = ProfilePlot(sp, (PartType_Gas_to_use, "particle_position_cylindrical_radius"), (PartType_Gas_to_use, "particle_velocity_minus_local_rotational_velocity_squared"), \
+                                                                 weight_field=(PartType_Gas_to_use, MassType_to_use), n_bins=50, x_log=False)
+                                        p55.set_log("particle_position_cylindrical_radius", False)
+                                        p55.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                        p55.set_xlim(1e-3, 14)
+                                        pos_disp_xs[time].append(p55.profiles[0].x.in_units('kpc').d)
+                                        pos_disp_profiles[time].append(np.sqrt(p55.profiles[0]["particle_velocity_minus_local_rotational_velocity_squared"]).in_units('km/s').d)
+
+                                # Add vertical velocity dispersion profile if requested
+                                if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                        def _velocity_z_squared(field, data):
+                                                return (data[("gas", "velocity_z")])**2
+                                        pf.add_field(("gas", "velocity_z_squared"), function=_velocity_z_squared, take_log=False, particle_type=False, units="cm**2/s**2")
+
+                                        p551 = ProfilePlot(sp_dense, ("index", "cylindrical_r"),  ("gas", "velocity_z_squared"), weight_field=("gas", "cell_mass"), n_bins=50, x_log=False)
+                                        p551.set_log("cylindrical_r", False)
+                                        p551.set_unit("cylindrical_r", 'kpc')
+                                        p551.set_xlim(1e-3, 14)
+                                        pos_disp_vert_xs[time].append(p551.profiles[0].x.in_units('kpc').d)
+                                        pos_disp_vert_profiles[time].append(np.sqrt(p551.profiles[0]["velocity_z_squared"]).in_units('km/s').d)
+                                else:
+                                        def _particle_velocity_z_squared(field, data):
+                                                return (data[(PartType_Gas_to_use, "particle_velocity_z")])**2
+                                        pf.add_field((PartType_Gas_to_use, "particle_velocity_z_squared"), function=_particle_velocity_z_squared, take_log=False, particle_type=True, units="cm**2/s**2")
+
+                                        p551 = ProfilePlot(sp, (PartType_Gas_to_use, "particle_position_cylindrical_radius"), (PartType_Gas_to_use, "particle_velocity_z_squared"), \
+                                                                 weight_field=(PartType_Gas_to_use, MassType_to_use), n_bins=50, x_log=False)
+                                        p551.set_log("particle_position_cylindrical_radius", False)
+                                        p551.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                        p551.set_xlim(1e-3, 14)
+                                        pos_disp_vert_xs[time].append(p551.profiles[0].x.in_units('kpc').d)
+                                        pos_disp_vert_profiles[time].append(np.sqrt(p551.profiles[0]["particle_velocity_z_squared"]).in_units('km/s').d)
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=4, prop=dict(size=10), frameon=True)
+                                grid_pos_vel_PDF[time][code].axes.add_artist(at)
+
+                # POSITION-VELOCITY PDF FOR NEW STARS
+                if draw_star_pos_vel_PDF >= 1 and time != 0:
+                        sp = pf.sphere(center, (0.5*figure_width, "kpc"))
+                        sp.set_field_parameter("normal", disk_normal_vector)
+                        pf.field_info[(PartType_Star_to_use, "particle_position_cylindrical_radius")].take_log = False
+                        pf.field_info[(PartType_Star_to_use, "particle_velocity_cylindrical_theta")].take_log = False
+                        pf.field_info[(PartType_Star_to_use, "particle_mass")].output_units = 'code_mass' # this turned out to be crucial!; otherwise wrong output_unit 'g' is assumed in ParticlePhasePlot->create_profile in visualizaiton/particle_plots.py for ART-I/ENZO/RAMSES
+                        p41 = ParticlePhasePlot(sp, (PartType_Star_to_use, "particle_position_cylindrical_radius"), (PartType_Star_to_use, "particle_velocity_cylindrical_theta"), \
+                                                       (PartType_Star_to_use, "particle_mass"), deposition='ngp', weight_field=None, fontsize=12, x_bins=300, y_bins=300)
+                        p41.set_unit("particle_position_cylindrical_radius", 'kpc')
+                        p41.set_unit("particle_velocity_cylindrical_theta", 'km/s')
+                        p41.set_unit("particle_mass", 'Msun') # requires a change in set_unit in visualization/profile_plotter.py: remove self.plots[field].zmin, self.plots[field].zmax = (None, None)
+#			p41.set_unit((PartType_Star_to_use, "particle_mass"), 'Msun') # Neither this nor above works without such change
+                        p41.set_zlim((PartType_Star_to_use, "particle_mass"), 1e3, 1e7)
+                        p41.set_cmap((PartType_Star_to_use, "particle_mass"), 'algae')
+
+                        p41.set_colorbar_label((PartType_Star_to_use, "particle_mass"), "Newly Formed Stellar Mass ($\mathrm{M}_{\odot}$)")
+                        plot41 = p41.plots[(PartType_Star_to_use, "particle_mass")]
+
+                        p41.set_xlabel("Cylindrical Radius (kpc)")
+                        p41.set_ylabel("Rotational Velocity (km/s)")
+                        p41.set_xlim(0, 14)
+                        p41.set_ylim(-100, 350)
+
+                        plot41.figure = fig_star_pos_vel_PDF[time]
+                        plot41.axes = grid_star_pos_vel_PDF[time][code].axes
+                        if code == 0: plot41.cax = grid_star_pos_vel_PDF[time].cbar_axes[0]
+                        p41._setup_plots()
+
+                        # Add 1D profile line if requested
+                        if draw_star_pos_vel_PDF >= 2 and time != 0:
+                                p51 = ProfilePlot(sp, (PartType_Star_to_use, "particle_position_cylindrical_radius"), (PartType_Star_to_use, "particle_velocity_cylindrical_theta"), \
+                                                         weight_field=(PartType_Star_to_use, "particle_mass"), n_bins=50, x_log=False)
+                                p51.set_log((PartType_Star_to_use, "particle_velocity_cylindrical_theta"), False)
+                                p51.set_log((PartType_Star_to_use, "particle_position_cylindrical_radius"), False)
+                                p51.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                p51.set_xlim(1e-3, 14)
+                                p51.set_ylim("particle_velocity_cylindrical_theta", -100, 350)
+                                line = ln.Line2D(p51.profiles[0].x.in_units('kpc'), p51.profiles[0]["particle_velocity_cylindrical_theta"].in_units('km/s'), linestyle="-", linewidth=2, color='k', alpha=0.7)
+                                star_pos_vel_xs[time].append(p51.profiles[0].x.in_units('kpc').d)
+                                star_pos_vel_profiles[time].append(p51.profiles[0]["particle_velocity_cylindrical_theta"].in_units('km/s').d)
+                                grid_star_pos_vel_PDF[time][code].axes.add_line(line)
+
+                        # Add velocity dispersion profile if requested
+                        if draw_star_pos_vel_PDF >= 3 and time != 0:
+                                def _particle_local_rotational_velocity_x(field, data):
+                                        trans = np.zeros(data[(PartType_StarBeforeFiltered_to_use, "particle_velocity_x")].shape)
+                                        dr = 0.5*(star_pos_vel_xs[time][code][1] - star_pos_vel_xs[time][code][0])
+                                        for radius, v_rot_local in zip(star_pos_vel_xs[time][code], star_pos_vel_profiles[time][code]):
+                                                ind = np.where((data[(PartType_StarBeforeFiltered_to_use, "particle_position_cylindrical_radius")].in_units("kpc") >= (radius - dr)) & \
+                                                                       (data[(PartType_StarBeforeFiltered_to_use, "particle_position_cylindrical_radius")].in_units("kpc") < (radius + dr)))
+                                                trans[ind] = -np.sin(data[(PartType_StarBeforeFiltered_to_use, "particle_position_cylindrical_theta")][ind]) * v_rot_local * 1e5
+                                        return data.ds.arr(trans, "cm/s").in_base(data.ds.unit_system.name)
+                                pf.add_field((PartType_StarBeforeFiltered_to_use, "particle_local_rotational_velocity_x"), function=_particle_local_rotational_velocity_x, take_log=False, particle_type=True, units="cm/s")
+                                def _particle_local_rotational_velocity_y(field, data):
+                                        trans = np.zeros(data[(PartType_StarBeforeFiltered_to_use, "particle_velocity_y")].shape)
+                                        dr = 0.5*(star_pos_vel_xs[time][code][1] - star_pos_vel_xs[time][code][0])
+                                        for radius, v_rot_local in zip(star_pos_vel_xs[time][code], star_pos_vel_profiles[time][code]):
+                                                ind = np.where((data[(PartType_StarBeforeFiltered_to_use, "particle_position_cylindrical_radius")].in_units("kpc") >= (radius - dr)) & \
+                                                                       (data[(PartType_StarBeforeFiltered_to_use, "particle_position_cylindrical_radius")].in_units("kpc") < (radius + dr)))
+                                                trans[ind] = np.cos(data[(PartType_StarBeforeFiltered_to_use, "particle_position_cylindrical_theta")][ind]) * v_rot_local * 1e5
+                                        return data.ds.arr(trans, "cm/s").in_base(data.ds.unit_system.name)
+                                pf.add_field((PartType_StarBeforeFiltered_to_use, "particle_local_rotational_velocity_y"), function=_particle_local_rotational_velocity_y, take_log=False, particle_type=True, units="cm/s")
+                                def _particle_velocity_minus_local_rotational_velocity_squared(field, data):
+                                        return (data[(PartType_StarBeforeFiltered_to_use, "particle_velocity_x")] - data[(PartType_StarBeforeFiltered_to_use, "particle_local_rotational_velocity_x")])**2 + \
+                                            (data[(PartType_StarBeforeFiltered_to_use, "particle_velocity_y")] - data[(PartType_StarBeforeFiltered_to_use, "particle_local_rotational_velocity_y")])**2 + \
+                                            (data[(PartType_StarBeforeFiltered_to_use, "particle_velocity_z")])**2
+                                pf.add_field((PartType_StarBeforeFiltered_to_use, "particle_velocity_minus_local_rotational_velocity_squared"), function=_particle_velocity_minus_local_rotational_velocity_squared,
+                                             take_log=False, particle_type=True, units="cm**2/s**2")
+                                pf.add_particle_filter(PartType_Star_to_use) # This is needed for a filtered particle type PartType_Star_to_use to work, because we have just created new particle fields.
+
+                                p515 = ProfilePlot(sp, (PartType_Star_to_use, "particle_position_cylindrical_radius"), (PartType_Star_to_use, "particle_velocity_minus_local_rotational_velocity_squared"), \
+                                                          weight_field=(PartType_Star_to_use, "particle_mass"), n_bins=50, x_log=False)
+                                p515.set_log((PartType_Star_to_use, "particle_position_cylindrical_radius"), False)
+                                p515.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                p515.set_xlim(1e-3, 14)
+                                star_pos_disp_xs[time].append(p515.profiles[0].x.in_units('kpc').d)
+                                star_pos_disp_profiles[time].append(np.sqrt(p515.profiles[0]["particle_velocity_minus_local_rotational_velocity_squared"]).in_units('km/s').d)
+
+                        # Add vertical velocity dispersion profile if requested
+                        if draw_star_pos_vel_PDF >= 4 and time != 0:
+                                def _particle_velocity_z_squared(field, data):
+                                        return (data[(PartType_StarBeforeFiltered_to_use, "particle_velocity_z")])**2
+                                pf.add_field((PartType_StarBeforeFiltered_to_use, "particle_velocity_z_squared"), function=_particle_velocity_z_squared,
+                                             take_log=False, particle_type=True, units="cm**2/s**2")
+                                pf.add_particle_filter(PartType_Star_to_use) # This is needed for a filtered particle type PartType_Star_to_use to work, because we have just created new particle fields.
+
+                                p5151 = ProfilePlot(sp, (PartType_Star_to_use, "particle_position_cylindrical_radius"), (PartType_Star_to_use, "particle_velocity_z_squared"), \
+                                                          weight_field=(PartType_Star_to_use, "particle_mass"), n_bins=50, x_log=False)
+                                p5151.set_log((PartType_Star_to_use, "particle_position_cylindrical_radius"), False)
+                                p5151.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                p5151.set_xlim(1e-3, 14)
+                                star_pos_disp_vert_xs[time].append(p5151.profiles[0].x.in_units('kpc').d)
+                                star_pos_disp_vert_profiles[time].append(np.sqrt(p5151.profiles[0]["particle_velocity_z_squared"]).in_units('km/s').d)
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=4, prop=dict(size=10), frameon=True)
+                                grid_star_pos_vel_PDF[time][code].axes.add_artist(at)
+
+                # RADIUS-HEIGHT PDF
+                if draw_rad_height_PDF >= 1:
+                        sp = pf.sphere(center, (0.5*figure_width, "kpc"))
+                        if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                if draw_rad_height_PDF == 1 or draw_rad_height_PDF == 2:
+                                        p55 = PhasePlot(sp, ("index", "cylindrical_r"), ("index", "cylindrical_z_abs"), ("gas", "density"), weight_field=("gas", "cell_mass"), fontsize=12, x_bins=200, y_bins=200)
+                                        p55.set_zlim(("gas", "density"), 1e-26, 1e-21)
+                                        p55.set_cmap(("gas", "density"), 'algae')
+                                        p55.set_log("cylindrical_r", False)
+                                        p55.set_log("cylindrical_z_abs", False)
+                                        p55.set_unit("cylindrical_r", 'kpc')
+                                        p55.set_unit("cylindrical_z_abs", 'kpc')
+                                        plot55 = p55.plots[("gas", "density")]
+                                elif draw_rad_height_PDF == 3:
+                                        p55 = PhasePlot(sp, ("index", "cylindrical_r"), ("index", "cylindrical_z_abs"), ("gas", "density_minus_analytic"), weight_field=("gas", "cell_mass"), fontsize=12, x_bins=200, y_bins=200)
+                                        p55.set_zlim(("gas", "density_minus_analytic"), -1e-24, 1e-24)
+                                        p55.set_cmap(("gas", "density_minus_analytic"), 'algae')
+                                        p55.set_log("cylindrical_r", False)
+                                        p55.set_log("cylindrical_z_abs", False)
+                                        p55.set_unit("cylindrical_r", 'kpc')
+                                        p55.set_unit("cylindrical_z_abs", 'kpc')
+                                        plot55 = p55.plots[("gas", "density_minus_analytic")]
+                        else:
+                                # Because ParticlePhasePlot doesn't work for these newly created fields for some reason, I will do the following trick.
+                                if draw_rad_height_PDF == 1 or draw_rad_height_PDF == 2:
+                                        p55 = PhasePlot(sp, (PartType_Gas_to_use, "particle_position_cylindrical_radius"), (PartType_Gas_to_use, "particle_position_cylindrical_z_abs"), (PartType_Gas_to_use, "Density_2"), weight_field=(PartType_Gas_to_use, "Mass_2"), fontsize=12, x_bins=200, y_bins=200)
+                                        p55.set_zlim((PartType_Gas_to_use, "Density_2"), 1e-26, 1e-21)
+                                        p55.set_cmap((PartType_Gas_to_use, "Density_2"), 'algae')
+                                        p55.set_log("particle_position_cylindrical_radius", False)
+                                        p55.set_log("particle_position_cylindrical_z_abs", False)
+                                        p55.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                        p55.set_unit("particle_position_cylindrical_z_abs", 'kpc')
+                                        plot55 = p55.plots[(PartType_Gas_to_use, "Density_2")]
+                                elif draw_rad_height_PDF == 3:
+                                        p55 = PhasePlot(sp, (PartType_Gas_to_use, "particle_position_cylindrical_radius"), (PartType_Gas_to_use, "particle_position_cylindrical_z_abs"), (PartType_Gas_to_use, "Density_2_minus_analytic"), weight_field=(PartType_Gas_to_use, "Mass_2"), fontsize=12, x_bins=200, y_bins=200)
+                                        p55.set_zlim((PartType_Gas_to_use, "Density_2_minus_analytic"), -1e-24, 1e-24)
+                                        p55.set_cmap((PartType_Gas_to_use, "Density_2_minus_analytic"), 'algae')
+                                        p55.set_log("particle_position_cylindrical_radius", False)
+                                        p55.set_log("particle_position_cylindrical_z_abs", False)
+                                        p55.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                        p55.set_unit("particle_position_cylindrical_z_abs", 'kpc')
+                                        plot55 = p55.plots[(PartType_Gas_to_use, "Density_2_minus_analytic")]
+
+                        p55.set_xlabel("Cylindrical Radius (kpc)")
+                        p55.set_ylabel("Vertical Height (kpc)")
+                        p55.set_xlim(0, 14)
+                        p55.set_ylim(0, 1.4)
+
+                        plot55.figure = fig_rad_height_PDF[time]
+                        plot55.axes = grid_rad_height_PDF[time][code].axes
+                        if code == 0: plot55.cax = grid_rad_height_PDF[time].cbar_axes[0]
+                        p55._setup_plots()
+
+                        # Add 1D profile line if requested
+                        if draw_rad_height_PDF == 2:
+                                if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                        p56 = ProfilePlot(sp, ("index", "cylindrical_r"),  ("index", "cylindrical_z_abs"), \
+                                                                  weight_field=("gas", "cell_mass"), n_bins=50, x_log=False)
+                                        p56.set_log("cylindrical_r", False)
+                                        p56.set_log("cylindrical_z_abs", False)
+                                        p56.set_unit("cylindrical_r", 'kpc')
+                                        p56.set_unit("cylindrical_z_abs", 'kpc')
+                                        p56.set_xlim(0, 14)
+                                        p56.set_ylim("cylindrical_z_abs", 0, 1.4)
+                                        line = ln.Line2D(p56.profiles[0].x.in_units('kpc'), p56.profiles[0]["cylindrical_z_abs"].in_units('kpc'), linestyle="-", linewidth=2, color='k', alpha=0.7)
+                                        rad_height_xs[time].append(p56.profiles[0].x.in_units('kpc').d)
+                                        rad_height_profiles[time].append(p56.profiles[0]["cylindrical_z_abs"].in_units('kpc').d)
+                                else:
+                                        p56 = ProfilePlot(sp, (PartType_Gas_to_use, "particle_position_cylindrical_radius"), (PartType_Gas_to_use, "particle_position_cylindrical_z_abs"), \
+                                                                  weight_field=(PartType_Gas_to_use, MassType_to_use), n_bins=50, x_log=False)
+                                        p56.set_log("particle_position_cylindrical_radius", False)
+                                        p56.set_log("particle_position_cylindrical_z_abs", False)
+                                        p56.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                        p56.set_unit("particle_position_cylindrical_z_abs", 'kpc')
+                                        p56.set_xlim(0, 14)
+                                        p56.set_ylim("particle_position_cylindrical_z_abs", 0, 1.4)
+                                        line = ln.Line2D(p56.profiles[0].x.in_units('kpc'), p56.profiles[0]["particle_position_cylindrical_z_abs"].in_units('kpc'), linestyle="-", linewidth=2, color='k', alpha=0.7)
+                                        rad_height_xs[time].append(p56.profiles[0].x.in_units('kpc').d)
+                                        rad_height_profiles[time].append(p56.profiles[0]["particle_position_cylindrical_z_abs"].in_units('kpc').d)
+                                grid_rad_height_PDF[time][code].axes.add_line(line)
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=1, prop=dict(size=10), frameon=True)
+                                grid_rad_height_PDF[time][code].axes.add_artist(at)
+
+                # DENSITY-TEMPERATURE-METALLICITY PDF
+                if draw_metal_PDF == 1:
+                        sp = pf.sphere(center, (0.5*figure_width, "kpc"))
+                        my_cmap2 = copy.copy(matplotlib.cm.get_cmap('algae'))
+                        my_cmap2.set_under('w')
+                        if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                pf.field_info[("gas", "metallicity")].take_log = False
+                                p3 = PhasePlot(sp, ("gas", "density"), ("gas", "temperature"), ("gas", "metallicity"), weight_field=("gas", "cell_mass"), fontsize=12, x_bins=300, y_bins=300)
+                                p3.set_zlim(("gas", "metallicity"), 0.01, 0.04)
+                                p3.set_cmap(("gas", "metallicity"), my_cmap2)
+                                p3.set_colorbar_label(("gas", "metallicity"), "Metallicity (Mass-weighted average of mass fraction)")
+                                plot3 = p3.plots[("gas", "metallicity")]
+                        else:
+                                # Because ParticlePhasePlot doesn't yet work for a log-log PDF for some reason, I will do the following trick.
+                                pf.field_info[(PartType_Gas_to_use, "Metallicity_2")].take_log = False
+                                p3 = PhasePlot(sp, (PartType_Gas_to_use, "Density_2"), (PartType_Gas_to_use, "Temperature_2"), (PartType_Gas_to_use, "Metallicity_2"), weight_field=(PartType_Gas_to_use, "Mass_2"), fontsize=12, x_bins=300, y_bins=300)
+                                p3.set_zlim((PartType_Gas_to_use, "Metallicity_2"), 0.01, 0.04)
+                                p3.set_cmap((PartType_Gas_to_use, "Metallicity_2"), my_cmap2)
+                                plot3 = p3.plots[(PartType_Gas_to_use, "Metallicity_2")]
+
+                        p3.set_xlim(1e-29, 1e-21)
+                        p3.set_ylim(10, 1e7)
+
+                        plot3.figure = fig_metal_PDF[time]
+                        plot3.axes = grid_metal_PDF[time][code].axes
+                        if code == 0: plot3.cax = grid_metal_PDF[time].cbar_axes[0]
+                        p3._setup_plots()
+
+                        if add_nametag == 1:
+                                at = AnchoredText("%s" % codes[code], loc=3, prop=dict(size=10), frameon=True)
+                                grid_metal_PDF[time][code].axes.add_artist(at)
+
+                # DENSITY DF (DISTRIBUTION FUNCTION)
+                if draw_density_DF >= 1:
+                        sp = pf.sphere(center, (0.5*figure_width, "kpc"))
+                        if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                p6 = ProfilePlot(sp, ("gas", "density"),  ("gas", "cell_mass"), weight_field=None, n_bins=50, x_log=True, accumulation=False)
+#				p6 = ProfilePlot(sp, ("gas", "density"),  ("gas", "cell_mass"), weight_field=None, n_bins=50, x_log=True, accumulation=True)
+                                p6.set_log("cell_mass", True)
+                                p6.set_xlim(1e-29, 1e-21)
+                                density_DF_xs[time].append(p6.profiles[0].x.in_units('g/cm**3').d)
+                                density_DF_profiles[time].append(p6.profiles[0]["cell_mass"].in_units('Msun').d)
+                        else:
+                                # Because ParticleProfilePlot doesn't exist, I will do the following trick.
+                                p6 = ProfilePlot(sp, (PartType_Gas_to_use, "Density_2"),  (PartType_Gas_to_use, "Mass_2"), weight_field=None, n_bins=50, x_log=True, accumulation=False)
+#				p6 = ProfilePlot(sp, (PartType_Gas_to_use, "Density_2"),  (PartType_Gas_to_use, "Mass_2"), weight_field=None, n_bins=50, x_log=True, accumulation=True)
+                                p6.set_log("Mass_2", True)
+                                p6.set_xlim(1e-29, 1e-21)
+                                density_DF_xs[time].append(p6.profiles[0].x.in_units('g/cm**3').d)
+                                density_DF_profiles[time].append(p6.profiles[0]["Mass_2"].in_units('Msun').d)
+
+                        # Add difference plot between 1st and 2nd datasets, if requested
+                        if draw_density_DF == 2 and time != 0:
+                                if dataset_num == 2:
+                                        pf_1st = load_dataset(1, time, code, codes, filenames[0]) # load 1st datasets
+                                        v, cen = pf_1st.h.find_max(("gas", "density"))
+                                        sp = pf_1st.sphere(cen, (30.0, "kpc"))
+                                        cen2 = sp.quantities.center_of_mass(use_gas=True, use_particles=False).in_units("kpc")
+                                        sp2 = pf_1st.sphere(cen2, (1.0, "kpc"))
+                                        cen3 = sp2.quantities.max_location(("gas", "density"))
+                                        center_1st = pf_1st.arr([cen3[1].d, cen3[2].d, cen3[3].d], 'code_length')
+                                        if yt_version_pre_3_2_3 == 1:
+                                                center_1st = pf_1st.arr([cen3[2].d, cen3[3].d, cen3[4].d], 'code_length') # for yt-3.2.3 or before
+                                        sp_1st = pf_1st.sphere(center_1st, (0.5*figure_width, "kpc"))
+                                        if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                                p61 = ProfilePlot(sp_1st, ("gas", "density"),  ("gas", "cell_mass"), weight_field=None, n_bins=50, x_log=True, accumulation=False)
+                                                p61.set_log("cell_mass", True)
+                                                p61.set_xlim(1e-29, 1e-21)
+                                                density_DF_1st_xs[time].append(p61.profiles[0].x.in_units('g/cm**3').d)
+                                                density_DF_1st_profiles[time].append(p61.profiles[0]["cell_mass"].in_units('Msun').d)
+                                        else:
+                                                def _Density_2(field, data):
+                                                        return data[(PartType_Gas_to_use, "Density")].in_units('g/cm**3')
+                                                pf_1st.add_field((PartType_Gas_to_use, "Density_2"), function=_Density_2, take_log=True, particle_type=False, display_name="Density", units="g/cm**3")
+                                                def _Mass_2(field, data):
+                                                        return data[(PartType_Gas_to_use, MassType_to_use)].in_units('Msun')
+                                                pf_1st.add_field((PartType_Gas_to_use, "Mass_2"), function=_Mass_2, take_log=True, particle_type=False, display_name="Mass", units="Msun")
+                                                p61 = ProfilePlot(sp_1st, (PartType_Gas_to_use, "Density_2"),  (PartType_Gas_to_use, "Mass_2"), weight_field=None, n_bins=50, x_log=True, accumulation=False)
+                                                p61.set_log("Mass_2", True)
+                                                p61.set_xlim(1e-29, 1e-21)
+                                                density_DF_1st_xs[time].append(p61.profiles[0].x.in_units('g/cm**3').d)
+                                                density_DF_1st_profiles[time].append(p61.profiles[0]["Mass_2"].in_units('Msun').d)
+                                else:
+                                        print("This won't work; consider setting dataset_num to 2...")
+                                        continue
+
+                # CYLINDRICAL RADIUS DF + RADIALLY-BINNED GAS SURFACE DENSITY
+                if draw_radius_DF == 1:
+                        sp = pf.sphere(center, (0.5*figure_width, "kpc"))
+                        sp.set_field_parameter("normal", disk_normal_vector)
+                        if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                p7 = ProfilePlot(sp, ("index", "cylindrical_r"),  ("gas", "cell_mass"), weight_field=None, n_bins=50, x_log=False, accumulation=False)
+                                p7.set_log("cell_mass", True)
+                                p7.set_log("cylindrical_r", False)
+                                p7.set_unit("cylindrical_r", 'kpc')
+                                p7.set_xlim(1e-3, 15)
+                                radius_DF_xs[time].append(p7.profiles[0].x.in_units('kpc').d)
+                                radius_DF_profiles[time].append(p7.profiles[0]["cell_mass"].in_units('Msun').d)
+                        else:
+                                p7 = ProfilePlot(sp, (PartType_Gas_to_use, "particle_position_cylindrical_radius"),  (PartType_Gas_to_use, "Mass_2"), weight_field=None, n_bins=50, x_log=False, accumulation=False)
+                                p7.set_log("Mass_2", True)
+                                p7.set_log("particle_position_cylindrical_radius", False)
+                                p7.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                p7.set_xlim(1e-3, 15)
+                                radius_DF_xs[time].append(p7.profiles[0].x.in_units('kpc').d)
+                                radius_DF_profiles[time].append(p7.profiles[0]["Mass_2"].in_units('Msun').d)
+
+                # CYLINDRICAL RADIUS DF + RADIALLY-BINNED SURFACE DENSITY FOR NEW STARS
+                if draw_star_radius_DF >= 1 and time != 0:
+                        sp = pf.sphere(center, (0.5*figure_width, "kpc"))
+                        sp.set_field_parameter("normal", disk_normal_vector)
+                        pf.field_info[(PartType_Star_to_use, "particle_mass")].take_log = True
+                        pf.field_info[(PartType_Star_to_use, "particle_mass")].output_units = 'code_mass' # this turned out to be crucial!; check output_units above
+                        pf.field_info[(PartType_Star_to_use, "particle_position_cylindrical_radius")].take_log = False
+                        p71 = ProfilePlot(sp, (PartType_Star_to_use, "particle_position_cylindrical_radius"),  (PartType_Star_to_use, "particle_mass"), weight_field=None, n_bins=50, x_log=False, accumulation=False)
+                        p71.set_unit("particle_position_cylindrical_radius", 'kpc')
+                        p71.set_xlim(1e-3, 15)
+                        star_radius_DF_xs[time].append(p71.profiles[0].x.in_units('kpc').d)
+                        star_radius_DF_profiles[time].append(p71.profiles[0]["particle_mass"].in_units('Msun').d)
+
+                        # Add RADIALLY-BINNED SFR SURFACE DENSITY PROFILE if requested (SFR estimated using stars younger than 20 Myrs old)
+                        if draw_star_radius_DF == 2 and time != 0:
+                                def _particle_mass_young_stars_star_radius_DF(field, data):
+                                        trans = np.zeros(data[(PartType_StarBeforeFiltered_to_use, "particle_mass")].shape)
+                                        ind = np.where(data[(PartType_StarBeforeFiltered_to_use, FormationTimeType_to_use)].in_units('Myr') > (pf.current_time.in_units('Myr').d - young_star_cutoff_star_radius_DF))
+                                        trans[ind] = data[(PartType_StarBeforeFiltered_to_use, "particle_mass")][ind].in_units('code_mass')
+                                        return data.ds.arr(trans, "code_mass").in_base(data.ds.unit_system.name)
+                                pf.add_field((PartType_StarBeforeFiltered_to_use, "particle_mass_young_stars_star_radius_DF"), function=_particle_mass_young_stars_star_radius_DF, \
+                                                     display_name="Young Stellar Mass", units='code_mass', particle_type=True, take_log=True)
+                                pf.add_particle_filter(PartType_Star_to_use)
+
+                                pf.field_info[(PartType_Star_to_use, "particle_mass_young_stars_star_radius_DF")].take_log = True
+                                pf.field_info[(PartType_Star_to_use, "particle_mass_young_stars_star_radius_DF")].output_units = 'code_mass' # this turned out to be crucial!; check output_units above
+                                pf.field_info[(PartType_Star_to_use, "particle_position_cylindrical_radius")].take_log = False
+                                p72 = ProfilePlot(sp, (PartType_Star_to_use, "particle_position_cylindrical_radius"), (PartType_Star_to_use, "particle_mass_young_stars_star_radius_DF"), \
+                                                          weight_field=None, n_bins=50, x_log=False, accumulation=False)
+                                p72.set_unit("particle_position_cylindrical_radius", 'kpc')
+                                p72.set_xlim(1e-3, 15)
+                                sfr_radius_DF_xs[time].append(p72.profiles[0].x.in_units('kpc').d)
+                                sfr_radius_DF_profiles[time].append(p72.profiles[0]["particle_mass_young_stars_star_radius_DF"].in_units('Msun').d/young_star_cutoff_star_radius_DF/1e6) # in Msun/yr
+
+                # VERTICAL HEIGHT DF + VERTICALLY-BINNED GAS SURFACE DENSITY
+                if draw_height_DF == 1:
+                        sp = pf.sphere(center, (0.5*figure_width, "kpc"))
+                        sp.set_field_parameter("normal", disk_normal_vector)
+                        if codes[code] == "ART-I" or codes[code] == "ART-II" or codes[code] == "ENZO"  or codes[code] == "RAMSES":
+                                p8 = ProfilePlot(sp, ("index", "cylindrical_z_abs"),  ("gas", "cell_mass"), weight_field=None, n_bins=10, x_log=False, accumulation=False)
+                                p8.set_log("cell_mass", True)
+                                p8.set_log("cylindrical_z_abs", False)
+                                p8.set_unit("cylindrical_z_abs", 'kpc')
+                                p8.set_xlim(1e-3, 1.4)
+                                height_DF_xs[time].append(p8.profiles[0].x.in_units('kpc').d)
+                                height_DF_profiles[time].append(p8.profiles[0]["cell_mass"].in_units('Msun').d)
+                        else:
+                                p8 = ProfilePlot(sp, (PartType_Gas_to_use, "particle_position_cylindrical_z_abs"),  (PartType_Gas_to_use, "Mass_2"), weight_field=None, n_bins=10, x_log=False, accumulation=False)
+                                p8.set_log("Mass_2", True)
+                                p8.set_log("particle_position_cylindrical_z_abs", False)
+                                p8.set_unit("particle_position_cylindrical_z_abs", 'kpc')
+                                p8.set_xlim(1e-3, 1.4)
+                                height_DF_xs[time].append(p8.profiles[0].x.in_units('kpc').d)
+                                height_DF_profiles[time].append(p8.profiles[0]["Mass_2"].in_units('Msun').d)
+
+                # STAR FORMATION RATE + CUMULATIVE STELLAR MASS GROWTH IN TIME
+                if draw_SFR >= 1 and time != 0:
+                        from yt.units.dimensions import length # Below are tricks to make StarFormationRate() work, particularly with "volume" argument, as it currently works only with comoving datasets
+                        pf.unit_registry.add('pccm', pf.unit_registry.lut['pc'][0], length, "\\rm{pc}/(1+z)")
+                        pf.hubble_constant = 0.71; pf.omega_lambda = 0.73; pf.omega_matter = 0.27; pf.omega_curvature = 0.0
+
+                        sp = pf.sphere(center, (0.5*figure_width, "kpc"))
+                        draw_SFR_mass = sp[(PartType_Star_to_use, "particle_mass")].in_units('Msun')
+                        draw_SFR_ct   = sp[(PartType_Star_to_use, FormationTimeType_to_use)].in_units('Myr')
+                        sfr = StarFormationRate(pf, star_mass = draw_SFR_mass, star_creation_time = draw_SFR_ct,
+                                                volume = sp.volume(), bins = 25) # 25 bins hardcoded; see: http://yt-project.org/docs/dev/analyzing/analysis_modules/star_analysis.html
+
+                        sfr_ts[time].append(sfr.time.in_units('Myr')) # in Myr
+                        sfr_cum_masses[time].append(sfr.Msol_cumulative) # in Msun
+                        sfr_sfrs[time].append(sfr.Msol_yr) # in Msun/yr
+
+                # DENSITY ALONG THE ORTHO-RAY OBJECT CUTTING THROUGH THE CENTER
+                if draw_cut_through == 1:
+                        ray = pf.ortho_ray(2, (center[0].in_units('code_length'), center[1].in_units('code_length'))) # see: http://yt-project.org/doc/visualizing/manual_plotting.html#line-plots
+                        srt = np.argsort(ray['z'])
+                        cut_through_zs[time].append(np.array(ray['z'][srt].in_units('kpc').d - center[2].in_units('kpc').d))
+                        cut_through_zvalues[time].append(np.array(ray[("gas", "density")][srt].in_units('g/cm**3').d))
+
+                        ray = pf.ortho_ray(0, (center[1].in_units('code_length'), center[2].in_units('code_length')))
+                        srt = np.argsort(ray['x'])
+                        cut_through_xs[time].append(np.array(ray['x'][srt].in_units('kpc').d - center[2].in_units('kpc').d))
+                        cut_through_xvalues[time].append(np.array(ray[("gas", "density")][srt].in_units('g/cm**3').d))
+
+        ####################################
+        #        POST-ANALYSIS STEPS       #
+        ####################################
+
+        # SAVE FIGURES
+        if draw_density_map == 1:
+                fig_density_map[time].savefig("Sigma_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+        if draw_temperature_map == 1:
+                fig_temperature_map[time].savefig("Temp_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+        if draw_cellsize_map == 1 or draw_cellsize_map == 3:
+                fig_cellsize_map[time].savefig("Cell_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+        if draw_cellsize_map == 2 or draw_cellsize_map == 3:
+                fig_cellsize_map_2[time].savefig("Resolution_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+        if draw_elevation_map == 1:
+                fig_elevation_map[time].savefig("Elevation_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+        if draw_metal_map >= 1:
+                fig_metal_map[time].savefig("Metal_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+        if draw_zvel_map == 1:
+                fig_zvel_map[time].savefig("z-vel_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+        if draw_star_map == 1 and time != 0:
+                fig_star_map[time].savefig("Star_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+        if draw_star_clump_stats >= 1 and time != 0:
+                if draw_star_clump_stats >= 2:
+                        fig_star_map_2[time].savefig("Star_with_clumps_HOP_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        fig_star_map_3[time].savefig("Star_with_clumps_FOF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                if draw_star_clump_stats == 3:
+                        pf_clump_ref = load_dataset(2, 1, 0, ['GIZMO'],
+                                                    [['dummy', '/lustre/ki/pfs/mornkr/080112_CHaRGe/pfs-hyades/AGORA-DISK-repository/Grackle+SF+ThermalFbck/GIZMO/AGORA_disk_second_ps1.5/snapshot_temp_100_last']])
+                        PartType_Star_to_use = "Stars"
+                        if os.path.exists("./halo_catalogs/hop_%s_%05d_high_floor/hop_%s_%05d_high_floor.0.h5" % ('GIZMO', 500, 'GIZMO', 500)) == False:
+                                hc_clump_ref = HaloCatalog(data_ds=pf_clump_ref, finder_method='hop', output_dir="./halo_catalogs/hop_%s_%05d_high_floor" % ('GIZMO', 500), \
+                                                         finder_kwargs={'threshold': 2e8, 'dm_only': False, 'ptype': PartType_Star_to_use})
+                                hc_clump_ref.add_filter('quantity_value', 'particle_mass', '>', 2.6e6, 'Msun')
+                                hc_clump_ref.add_filter('quantity_value', 'particle_mass', '<', 2.6e8, 'Msun')
+                                hc_clump_ref.create()
+                        halo_ds_clump_ref = load("./halo_catalogs/hop_%s_%05d_high_floor/hop_%s_%05d_high_floor.0.h5" % ('GIZMO', 500, 'GIZMO', 500))
+                        hc_clump_ref = HaloCatalog(halos_ds=halo_ds_clump_ref, output_dir="./halo_catalogs/hop_%s_%05d_high_floor" % ('GIZMO', 500))
+                        hc_clump_ref.load()
+
+                        halo_ad_clump_ref = hc_clump_ref.halos_ds.all_data()
+                        star_clump_masses_hop_ref.append(np.log10(halo_ad_clump_ref['particle_mass'][:].in_units("Msun")))
+
+                        if os.path.exists("./halo_catalogs/fof_%s_%05d_high_floor/fof_%s_%05d_high_floor.0.h5" % ('GIZMO', 500, 'GIZMO', 500)) == False:
+                                hc2_clump_ref = HaloCatalog(data_ds=pf_clump_ref, finder_method='fof', output_dir="./halo_catalogs/fof_%s_%05d_high_floor" %  ('GIZMO', 500), \
+                                                          finder_kwargs={'link': 0.0025, 'dm_only': False, 'ptype': PartType_Star_to_use})
+                                hc2_clump_ref.add_filter('quantity_value', 'particle_mass', '>', 2.6e6, 'Msun')
+                                hc2_clump_ref.add_filter('quantity_value', 'particle_mass', '<', 2.6e8, 'Msun')
+                                hc2_clump_ref.create()
+                        halo_ds2_clump_ref = load("./halo_catalogs/fof_%s_%05d_high_floor/fof_%s_%05d_high_floor.0.h5" % ('GIZMO', 500, 'GIZMO', 500))
+                        hc2_clump_ref = HaloCatalog(halos_ds=halo_ds2_clump_ref, output_dir="./halo_catalogs/fof_%s_%05d_high_floor" % ('GIZMO', 500))
+                        hc2_clump_ref.load()
+
+                        halo_ad2_clump_ref = hc2_clump_ref.halos_ds.all_data()
+                        star_clump_masses_fof_ref.append(np.log10(halo_ad2_clump_ref['particle_mass'][:].in_units("Msun")))
+                plt.clf()
+                fig = plt.figure(figsize=(8, 4))
+                gridspec.GridSpec(1, 2)
+                for star_clump_stats_i in range(1,3,1):
+                        codes_plotted = []
+#			plt.subplot(1,2,star_clump_stats_i, aspect=0.25)
+                        plt.subplot2grid((1, 2), (0, star_clump_stats_i-1))
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                if (star_clump_stats_i == 1 and (codes[code] == "ART-I" or codes[code] == "ART-II"  or codes[code] == "ENZO" or codes[code] == "RAMSES")) or \
+                                   (star_clump_stats_i == 2 and (codes[code] == "CHANGA" or codes[code] == "GASOLINE" or codes[code] == "GADGET-3" or codes[code] == "GEAR" or codes[code] == "GIZMO" or codes[code] == "SWIFT")):
+                                        hist = np.histogram(star_clump_masses_hop[time][code], bins=10, range=(6., 8.5))
+                                        dbin = 0.5*(hist[1][1] - hist[1][0])
+                                        lines = plt.plot(hist[1][:-1]+dbin, hist[0], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                                        codes_plotted.append(codes[code])
+                        plt.xlim(6, 8.5)
+                        plt.ylim(-0.1, 15)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{log[Newly\ Formed\ Stellar\ Clump\ Mass\ (M_{\odot})]}$")
+                        if star_clump_stats_i == 1:
+                                plt.ylabel("$\mathrm{Stellar\ Clump\ Counts, \ \ N_{clump}(M)}$")
+                        plt.legend(codes_plotted, loc=1, frameon=True, ncol=1, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='xx-small')
+                plt.savefig("star_clump_stats_HOP_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+                # Reiterate for cumulative plots
+                fig = plt.figure(figsize=(8, 4))
+                gridspec.GridSpec(1, 2)
+                for star_clump_stats_i in range(1,3,1):
+                        codes_plotted = []
+#			plt.subplot(1,2,star_clump_stats_i, aspect=0.15)
+                        plt.subplot2grid((1, 2), (0, star_clump_stats_i-1))
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                if (star_clump_stats_i == 1 and (codes[code] == "ART-I" or codes[code] == "ART-II"  or codes[code] == "ENZO" or codes[code] == "RAMSES")) or \
+                                   (star_clump_stats_i == 2 and (codes[code] == "CHANGA" or codes[code] == "GASOLINE" or codes[code] == "GADGET-3" or codes[code] == "GEAR" or codes[code] == "GIZMO" or codes[code] == "SWIFT")):
+                                        hist = np.histogram(star_clump_masses_hop[time][code], bins=10, range=(6., 8.5))
+                                        dbin = 0.5*(hist[1][1] - hist[1][0])
+                                        lines = plt.plot(hist[1][:-1]+dbin, np.cumsum(hist[0][::-1])[::-1], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], \
+                                                                 marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                                        codes_plotted.append(codes[code])
+                        if draw_star_clump_stats == 3 and star_clump_stats_i == 2:
+                                hist_clump_ref = np.histogram(star_clump_masses_hop_ref, bins=10, range=(6., 8.5))
+                                dbin = 0.5*(hist[1][1] - hist[1][0])
+                                lines = plt.plot(hist_clump_ref[1][:-1]+dbin, np.cumsum(hist_clump_ref[0][::-1])[::-1], color='k', linestyle='--', marker='*', markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                                codes_plotted.append('GIZMO-ps2')
+                        plt.xlim(6, 8.5)
+#			plt.ylim(-0.1, 30)
+                        plt.ylim(0.9, 50)
+                        plt.semilogy()
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{log[Newly\ Formed\ Stellar\ Clump\ Mass\ (M_{\odot})]}$")
+                        if star_clump_stats_i == 1:
+                                plt.ylabel("$\mathrm{Cumulative\ Clump\ Counts, \ \ N_{clump}(>M)}}$")
+                        plt.legend(codes_plotted, loc=1, frameon=True, ncol=1, fancybox=True, labelspacing=0.15, borderpad=0.3)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='xx-small')
+                plt.savefig("star_clump_stats_HOP_cumulative_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+
+                fig = plt.figure(figsize=(8, 4))
+                gridspec.GridSpec(1, 2)
+                for star_clump_stats_i in range(1,3,1):
+                        codes_plotted = []
+#			plt.subplot(1,2,star_clump_stats_i, aspect=0.25)
+                        plt.subplot2grid((1, 2), (0, star_clump_stats_i-1))
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                if (star_clump_stats_i == 1 and (codes[code] == "ART-I" or codes[code] == "ART-II"  or codes[code] == "ENZO" or codes[code] == "RAMSES")) or \
+                                   (star_clump_stats_i == 2 and (codes[code] == "CHANGA" or codes[code] == "GASOLINE" or codes[code] == "GADGET-3" or codes[code] == "GEAR" or codes[code] == "GIZMO" or codes[code] == "SWIFT")):
+                                        hist = np.histogram(star_clump_masses_fof[time][code], bins=10, range=(6., 8.5))
+                                        dbin = 0.5*(hist[1][1] - hist[1][0])
+                                        lines = plt.plot(hist[1][:-1]+dbin, hist[0], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                                        codes_plotted.append(codes[code])
+                        plt.xlim(6, 8.5)
+                        plt.ylim(-0.1, 15)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{log[Newly\ Formed\ Stellar\ Clump\ Mass\ (M_{\odot})]}$")
+                        if star_clump_stats_i == 1:
+                                plt.ylabel("$\mathrm{Stellar\ Clump\ Counts, \ \ N_{clump}(M)}$")
+                        plt.legend(codes_plotted, loc=1, frameon=True, ncol=1, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='xx-small')
+                plt.savefig("star_clump_stats_FOF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+                # Reiterate for cumulative plots
+                fig = plt.figure(figsize=(8, 4))
+                gridspec.GridSpec(1, 2)
+                for star_clump_stats_i in range(1,3,1):
+                        codes_plotted = []
+#			plt.subplot(1,2,star_clump_stats_i, aspect=0.15)
+                        plt.subplot2grid((1, 2), (0, star_clump_stats_i-1))
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                if (star_clump_stats_i == 1 and (codes[code] == "ART-I" or codes[code] == "ART-II"  or codes[code] == "ENZO" or codes[code] == "RAMSES")) or \
+                                   (star_clump_stats_i == 2 and (codes[code] == "CHANGA" or codes[code] == "GASOLINE" or codes[code] == "GADGET-3" or codes[code] == "GEAR" or codes[code] == "GIZMO" or codes[code] == "SWIFT")):
+                                        hist = np.histogram(star_clump_masses_fof[time][code], bins=10, range=(6., 8.5))
+                                        dbin = 0.5*(hist[1][1] - hist[1][0])
+                                        lines = plt.plot(hist[1][:-1]+dbin, np.cumsum(hist[0][::-1])[::-1], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], \
+                                                                 marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                                        codes_plotted.append(codes[code])
+                        if draw_star_clump_stats == 3 and star_clump_stats_i == 2:
+                                hist_clump_ref = np.histogram(star_clump_masses_fof_ref, bins=10, range=(6., 8.5))
+                                dbin = 0.5*(hist[1][1] - hist[1][0])
+                                lines = plt.plot(hist_clump_ref[1][:-1]+dbin, np.cumsum(hist_clump_ref[0][::-1])[::-1], color='k', linestyle='--', marker='*', markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                                codes_plotted.append('GIZMO-ps2')
+                        plt.xlim(6, 8.5)
+#			plt.ylim(-0.1, 30)
+                        plt.ylim(0.9, 50)
+                        plt.semilogy()
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{log[Newly\ Formed\ Stellar\ Clump\ Mass\ (M_{\odot})]}$")
+                        if star_clump_stats_i == 1:
+                                plt.ylabel("$\mathrm{Cumulative\ Clump\ Counts, \ \ N_{clump}(>M)}}$")
+                        plt.legend(codes_plotted, loc=1, frameon=True, ncol=1, fancybox=True, labelspacing=0.15, borderpad=0.3)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='xx-small')
+                plt.savefig("star_clump_stats_FOF_cumulative_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+        if draw_SFR_map >= 1 and time != 0:
+                fig_degr_density_map[time].savefig("degraded_Sigma_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                fig_degr_sfr_map[time].savefig("degraded_SFR_map_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                if draw_SFR_map == 2 and time != 0:
+                        # If requested, draw the local K-S plot using the degraded maps created above
+                        plt.clf()
+#			plt.subplot(111)
+                        fig = plt.figure(figsize=(8, 7))
+                        Bigiel_surface_density = []
+                        Bigiel_sfr_surface_density = []
+                        for code in range(len(codes)):
+                                # Remove bins where SFR surface density is zero
+                                KS_x = np.array(surf_dens_SFR_map[time][code])
+                                KS_x[np.where(np.array(sfr_surf_dens_SFR_map[time][code]) < 1e-10)] = 0
+                                KS_x = np.log10(KS_x)
+                                KS_y = np.log10(np.array(sfr_surf_dens_SFR_map[time][code]))
+                                KS_x = KS_x[~np.isinf(KS_x)]
+                                KS_y = KS_y[~np.isinf(KS_y)]
+                                if codes[code] == "CHANGA":
+                                        plt.scatter(KS_x, KS_y, color='k', edgecolor='k', s=20, linewidth=0.7, marker=marker_names[code], alpha=0.1)
+                                # Draw a 80% contour rather than scattering all the datapoints; see http://stackoverflow.com/questions/19390320/scatterplot-contours-in-matplotlib
+                                Gaussian_density_estimation_nbins = 20
+                                kernel = kde.gaussian_kde(np.vstack([KS_x, KS_y]))
+                                xi, yi = np.mgrid[KS_x.min():KS_x.max():Gaussian_density_estimation_nbins*1j, KS_y.min():KS_y.max():Gaussian_density_estimation_nbins*1j]
+                                zi = np.reshape(kernel(np.vstack([xi.flatten(), yi.flatten()])), xi.shape)
+                                contours = plt.contour(xi, yi, zi, np.array([0.2]), colors=color_names[code], linewidths=1.2, alpha=1.0)    # 80%    percentile contour
+#				contours = plt.contour(xi, yi, zi, np.array([0.3173]), colors=color_names[code], linewidths=1.2, alpha=1.0) # 68.27% percentile contour (1-sigma)
+                                contours.collections[0].set_label(codes[code]) # setting names for legend
+                                plt.clabel(contours, fmt=codes[code], inline=True, fontsize=7) # setting labels
+                        plt.xlim(0, 3)
+                        plt.ylim(-4, 1)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{log[Gas\ Surface\ Density\ (M_{\odot}/pc^2)]}$")
+                        plt.ylabel("$\mathrm{log[Star\ Formation\ Rate\ Surface\ Density\ (M_{\odot}/yr/kpc^2)]}$")
+                        plt.legend(loc=2, frameon=True, ncol=2, fancybox=True) # note difference from others since we want the legends to list contours, not scattered points
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+                        t = np.arange(-2, 5, 0.01)
+                        for line in import_text("./Bigieletal2008_Fig8_Contour.txt", " "):
+                                Bigiel_surface_density.append(float(line[0]) + np.log10(1.36)) # for the factor 1.36, see Section 2.3.1 of Bigiel et al. 2008
+                                Bigiel_sfr_surface_density.append(float(line[1]))
+                        plt.fill(Bigiel_surface_density, Bigiel_sfr_surface_density, fill=True, color='b', alpha = 0.1, hatch='\\') # contour by Bigiel et al. 2008 (Fig 8), or Feldmann et al. 2012 (Fig 1)
+                        plt.plot(t, 1.37*t - 3.78, 'k--', linewidth = 2, alpha = 0.7) # observational fit by Kennicutt et al. 2007
+#			plt.axhline(y = np.log10(8.593e4/young_star_cutoff_SFR_map/1e6/(float(aperture_size_SFR_map)/1000.)**2),
+#                                   color='k', linestyle ='-.', linewidth=1, alpha=0.7) # SFR surface density cutoff due to limited star particle mass resolution
+                        plt.savefig("K-S_local_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+        if draw_PDF >= 1:
+                if draw_PDF == 3 and time != 0:
+                        # If requested, find a 1D profile line from a specific snapshot as a reference (in this case ENZO or CHANGA noSF run at 500 Myr), then we add it to all panels
+                        # pf_profile_ref = load_dataset(1, 1, 0, ['ENZO'], [['dummy', file_location[0]+'ENZO/DD0100/DD0100']])
+                        pf_profile_ref = load_dataset(1, 1, 0, ['CHANGA'], [['dummy', file_location[0]+'CHANGA/disklow/disklow.000500']])
+                        def _Density_2(field, data):
+                                return data[(PartType_Gas_to_use, "Density")].in_units('g/cm**3')
+                        pf_profile_ref.add_field((PartType_Gas_to_use, "Density_2"), function=_Density_2, take_log=True, particle_type=False, display_name="Density", units="g/cm**3")
+                        def _Temperature_2(field, data):
+                                return data[(PartType_Gas_to_use, "Temperature")].in_units('K')
+                        pf_profile_ref.add_field((PartType_Gas_to_use, "Temperature_2"), function=_Temperature_2, take_log=True, particle_type=False, display_name="Temperature", units="K")
+                        def _Mass_2(field, data):
+                                return data[(PartType_Gas_to_use, MassType_to_use)].in_units('Msun')
+                        pf_profile_ref.add_field((PartType_Gas_to_use, "Mass_2"), function=_Mass_2, take_log=True, particle_type=False, display_name="Mass", units="Msun")
+
+                        v, cen = pf_profile_ref.h.find_max(("gas", "density"))
+                        sp = pf_profile_ref.sphere(cen, (30.0, "kpc"))
+                        cen2 = sp.quantities.center_of_mass(use_gas=True, use_particles=False).in_units("kpc")
+                        sp2 = pf_profile_ref.sphere(cen2, (1.0, "kpc"))
+                        cen3 = sp2.quantities.max_location(("gas", "density"))
+                        center_profile_ref = pf_profile_ref.arr([cen3[1].d, cen3[2].d, cen3[3].d], 'code_length')
+                        if yt_version_pre_3_2_3 == 1:
+                                center_profile_ref = pf_profile_ref.arr([cen3[2].d, cen3[3].d, cen3[4].d], 'code_length')
+                        sp_profile_ref = pf_profile_ref.sphere(center_profile_ref, (0.5*figure_width, "kpc"))
+
+                        # p35 = ProfilePlot(sp_profile_ref, ("gas", "density"),  ("gas", "temperature"), weight_field=("gas", "cell_mass"), n_bins=30)
+                        # p35.set_xlim(1e-29, 1e-21)
+                        # p35.set_ylim("temperature", 10, 1e7)
+                        p35 = ProfilePlot(sp_profile_ref, (PartType_Gas_to_use, "Density_2"), (PartType_Gas_to_use, "Temperature_2"), weight_field=(PartType_Gas_to_use, "Mass_2"), n_bins=30)
+                        p35.set_xlim(1e-26, 1e-21)
+                        p35.set_ylim("Temperature_2", 10, 1e7)
+                        for code in range(len(codes)):
+#				line_profile_ref = ln.Line2D(p35.profiles[0].x.in_units('g/cm**3'), p35.profiles[0]["temperature"].in_units('K'), linestyle="--", linewidth=2, color='k', alpha=0.7)
+                                line_profile_ref = ln.Line2D(p35.profiles[0].x.in_units('g/cm**3'), p35.profiles[0]["Temperature_2"].in_units('K'), linestyle="--", linewidth=2, color='k', alpha=0.7)
+                                grid_PDF[time][code].axes.add_line(line_profile_ref)
+                fig_PDF[time].savefig("PDF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+        if draw_pos_vel_PDF >= 1:
+                fig_pos_vel_PDF[time].savefig("pos_vel_PDF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                if draw_pos_vel_PDF >= 2 and time != 0:
+                        plt.clf()
+#			plt.subplot(111, aspect=0.04)
+                        fig = plt.figure(figsize=(8, 8))
+                        gridspec.GridSpec(4, 1)
+                        plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                lines = plt.plot(pos_vel_xs[time][code], pos_vel_profiles[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(0, 270)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel("$\mathrm{Rotational\ Velocity\ (km/s)}$", fontsize='large')
+                        plt.legend(codes, loc=4, frameon=True, ncol=2, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+
+                        plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                        ave_profiles = np.mean(np.array(pos_vel_profiles[time]), axis=0)
+                        for code in range(len(codes)):
+                                lines = plt.plot(pos_vel_xs[time][code], (pos_vel_profiles[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(-0.5, 0.5)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{v} - \mathrm{\bar v})/\mathrm{\bar v}$", fontsize='large')
+                        if add_mean_fractional_dispersion == 1:
+                                mean_fractional_dispersion = (np.std(np.array(pos_vel_profiles[time]), axis=0)/ave_profiles)[(mean_dispersion_radius_range[0] < pos_vel_xs[time][0]) & (pos_vel_xs[time][0] < mean_dispersion_radius_range[1])].mean()
+                                mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                                plt.annotate("Mean fractional dispersion for %d < r < %d kpc = %.3f (%.3f dex) " % (mean_dispersion_radius_range[0], mean_dispersion_radius_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.35, 0.08), size=10, xycoords='axes fraction')
+#				plt.text(12, 0.3, "mean dispersion = %.3f or %.3f dex " % (mean_fractional_dispersion, mean_fractional_dispersion_in_dex), ha="center", va="center", size=8, bbox=dict(boxstyle="round", fc="w", ec="0.5", alpha=0.9))
+                        plt.savefig("pos_vel_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+                if draw_pos_vel_PDF >= 3 and time != 0:
+                        plt.clf()
+#			plt.subplot(111, aspect=0.064)
+                        fig = plt.figure(figsize=(8, 10))
+                        gridspec.GridSpec(5, 1)
+                        plt.subplot2grid((5, 1), (0, 0), rowspan=3)
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                lines = plt.plot(pos_disp_xs[time][code], pos_disp_profiles[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(0, 170)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel("$\mathrm{Velocity\ Dispersion\ (km/s)}$", fontsize='large')
+                        plt.legend(codes, loc=1, frameon=True, ncol=2, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+
+                        plt.subplot2grid((5, 1), (3, 0), rowspan=1)
+                        ave_profiles = np.mean(np.array(pos_disp_profiles[time]), axis=0)
+                        for code in range(len(codes)):
+                                lines = plt.plot(pos_disp_xs[time][code], (pos_disp_profiles[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(-1.0, 1.0)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{\sigma} - \mathrm{\bar \sigma})/\mathrm{\bar \sigma}$", fontsize='large')
+                        if add_mean_fractional_dispersion == 1:
+                                mean_fractional_dispersion = (np.std(np.array(pos_disp_profiles[time]), axis=0)/ave_profiles)[(mean_dispersion_radius_range[0] < pos_disp_xs[time][0]) & (pos_disp_xs[time][0] < mean_dispersion_radius_range[1])].mean()
+                                mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                                plt.annotate("Mean fractional dispersion for %d < r < %d kpc = %.3f (%.3f dex) " % (mean_dispersion_radius_range[0], mean_dispersion_radius_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.35, 0.08), size=10, xycoords='axes fraction')
+                        plt.savefig("pos_disp_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.subplot2grid((5, 1), (4, 0), rowspan=1)
+                        for code in range(len(codes)):
+                                lines = plt.plot(pos_disp_xs[time][code], pos_disp_vert_profiles[time][code]/pos_disp_profiles[time][code], color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(0.0, 1.0)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Ratio,}\/\mathrm{\sigma}_{\perp}/\mathrm{\sigma}$", fontsize='large')
+                        plt.savefig("pos_disp_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+                if draw_pos_vel_PDF == 4 and time != 0:
+                        plt.clf()
+#			plt.subplot(111, aspect=0.064)
+                        fig = plt.figure(figsize=(8, 8))
+                        gridspec.GridSpec(4, 1)
+                        plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                lines = plt.plot(pos_disp_vert_xs[time][code], pos_disp_vert_profiles[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(0, 170)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel("$\mathrm{Vertical\ Velocity\ Dispersion\ (km/s)}$", fontsize='large')
+                        plt.legend(codes, loc=1, frameon=True, ncol=2, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+
+                        plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                        ave_profiles = np.mean(np.array(pos_disp_vert_profiles[time]), axis=0)
+                        for code in range(len(codes)):
+                                lines = plt.plot(pos_disp_vert_xs[time][code], (pos_disp_vert_profiles[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(-1.0, 1.0)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{\sigma} - \mathrm{\bar \sigma})/\mathrm{\bar \sigma}$", fontsize='large')
+                        if add_mean_fractional_dispersion == 1:
+                                mean_fractional_dispersion = (np.std(np.array(pos_disp_vert_profiles[time]), axis=0)/ave_profiles)[(mean_dispersion_radius_range[0] < pos_disp_vert_xs[time][0]) & (pos_disp_vert_xs[time][0] < mean_dispersion_radius_range[1])].mean()
+                                mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                                plt.annotate("Mean fractional dispersion for %d < r < %d kpc = %.3f (%.3f dex) " % (mean_dispersion_radius_range[0], mean_dispersion_radius_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.35, 0.08), size=10, xycoords='axes fraction')
+                        plt.savefig("pos_disp_vert_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+        if draw_star_pos_vel_PDF >= 1 and time != 0:
+                fig_star_pos_vel_PDF[time].savefig("star_pos_vel_PDF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                if draw_star_pos_vel_PDF >= 2 and time != 0:
+                        plt.clf()
+#			plt.subplot(111, aspect=0.04)
+                        fig = plt.figure(figsize=(8, 8))
+                        gridspec.GridSpec(4, 1)
+                        plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                lines = plt.plot(star_pos_vel_xs[time][code], star_pos_vel_profiles[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(0, 270)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel("$\mathrm{Rotational\ Velocity\ (km/s)}$", fontsize='large')
+                        plt.legend(codes, loc=4, frameon=True, ncol=2, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+
+                        plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                        ave_profiles = np.mean(np.array(star_pos_vel_profiles[time]), axis=0)
+                        for code in range(len(codes)):
+                                lines = plt.plot(star_pos_vel_xs[time][code], (star_pos_vel_profiles[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(-0.5, 0.5)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{v} - \mathrm{\bar v})/\mathrm{\bar v}$", fontsize='large')
+                        if add_mean_fractional_dispersion == 1:
+                                mean_fractional_dispersion = (np.std(np.array(star_pos_vel_profiles[time]), axis=0)/ave_profiles)[(mean_dispersion_radius_range[0] < star_pos_vel_xs[time][0]) & (star_pos_vel_xs[time][0] < mean_dispersion_radius_range[1])].mean()
+                                mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                                plt.annotate("Mean fractional dispersion for %d < r < %d kpc = %.3f (%.3f dex) " % (mean_dispersion_radius_range[0], mean_dispersion_radius_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.35, 0.08), size=10, xycoords='axes fraction')
+                        plt.savefig("star_pos_vel_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+                if draw_star_pos_vel_PDF >= 3 and time != 0:
+                        plt.clf()
+#			plt.subplot(111, aspect=0.064)
+                        fig = plt.figure(figsize=(8, 10))
+                        gridspec.GridSpec(5, 1)
+                        plt.subplot2grid((5, 1), (0, 0), rowspan=3)
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                lines = plt.plot(star_pos_disp_xs[time][code], star_pos_disp_profiles[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(0, 170)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel("$\mathrm{Velocity\ Dispersion\ (km/s)}$", fontsize='large')
+                        plt.legend(codes, loc=1, frameon=True, ncol=2, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+
+                        plt.subplot2grid((5, 1), (3, 0), rowspan=1)
+                        ave_profiles = np.mean(np.array(star_pos_disp_profiles[time]), axis=0)
+                        for code in range(len(codes)):
+                                lines = plt.plot(star_pos_disp_xs[time][code], (star_pos_disp_profiles[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(-1.0, 1.0)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{\sigma} - \mathrm{\bar \sigma})/\mathrm{\bar \sigma}$", fontsize='large')
+                        if add_mean_fractional_dispersion == 1:
+                                mean_fractional_dispersion = (np.std(np.array(star_pos_disp_profiles[time]), axis=0)/ave_profiles)[(mean_dispersion_radius_range[0] < star_pos_disp_xs[time][0]) & (star_pos_disp_xs[time][0] < mean_dispersion_radius_range[1])].mean()
+                                mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                                plt.annotate("Mean fractional dispersion for %d < r < %d kpc = %.3f (%.3f dex) " % (mean_dispersion_radius_range[0], mean_dispersion_radius_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.35, 0.08), size=10, xycoords='axes fraction')
+                        plt.savefig("star_pos_disp_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.subplot2grid((5, 1), (4, 0), rowspan=1)
+                        for code in range(len(codes)):
+                                lines = plt.plot(star_pos_disp_xs[time][code], star_pos_disp_vert_profiles[time][code]/star_pos_disp_profiles[time][code], color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(0.0, 1.0)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Ratio,}\/\mathrm{\sigma}_{\perp}/\mathrm{\sigma}$", fontsize='large')
+                        plt.savefig("star_pos_disp_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+                if draw_star_pos_vel_PDF == 4 and time != 0:
+                        plt.clf()
+#			plt.subplot(111, aspect=0.064)
+                        fig = plt.figure(figsize=(8, 8))
+                        gridspec.GridSpec(4, 1)
+                        plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                lines = plt.plot(star_pos_disp_vert_xs[time][code], star_pos_disp_vert_profiles[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(0, 170)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel("$\mathrm{Vertical\ Velocity\ Dispersion\ (km/s)}$", fontsize='large')
+                        plt.legend(codes, loc=1, frameon=True, ncol=2, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+
+                        plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                        ave_profiles = np.mean(np.array(star_pos_disp_vert_profiles[time]), axis=0)
+                        for code in range(len(codes)):
+                                lines = plt.plot(star_pos_disp_vert_xs[time][code], (star_pos_disp_vert_profiles[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(-1.0, 1.0)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{\sigma} - \mathrm{\bar \sigma})/\mathrm{\bar \sigma}$", fontsize='large')
+                        if add_mean_fractional_dispersion == 1:
+                                mean_fractional_dispersion = (np.std(np.array(star_pos_disp_vert_profiles[time]), axis=0)/ave_profiles)[(mean_dispersion_radius_range[0] < star_pos_disp_vert_xs[time][0]) & (star_pos_disp_vert_xs[time][0] < mean_dispersion_radius_range[1])].mean()
+                                mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                                plt.annotate("Mean fractional dispersion for %d < r < %d kpc = %.3f (%.3f dex) " % (mean_dispersion_radius_range[0], mean_dispersion_radius_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.35, 0.08), size=10, xycoords='axes fraction')
+                        plt.savefig("star_pos_disp_vert_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+        if draw_rad_height_PDF >= 1:
+                fig_rad_height_PDF[time].savefig("rad_height_PDF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                if draw_rad_height_PDF == 2 and time != 0:
+                        plt.clf()
+#			plt.subplot(111, aspect=18)
+                        fig = plt.figure(figsize=(8, 8))
+                        gridspec.GridSpec(4, 1)
+                        plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                lines = plt.plot(rad_height_xs[time][code], rad_height_profiles[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(0, 0.45)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel("$\mathrm{Average\ Vertical\ Height\ (kpc)}$", fontsize='large')
+                        plt.legend(codes, loc=2, frameon=True, ncol=2, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+
+                        plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                        ave_profiles = np.mean(np.array(rad_height_profiles[time]), axis=0)
+                        for code in range(len(codes)):
+                                lines = plt.plot(rad_height_xs[time][code], (rad_height_profiles[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(-1.0, 1.0)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{h} - \mathrm{\bar h})/\mathrm{\bar h}$", fontsize='large')
+                        if add_mean_fractional_dispersion == 1:
+                                mean_fractional_dispersion = (np.std(np.array(rad_height_profiles[time]), axis=0)/ave_profiles)[(mean_dispersion_radius_range[0] < rad_height_xs[time][0]) & (rad_height_xs[time][0] < mean_dispersion_radius_range[1])].mean()
+                                mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                                plt.annotate("Mean fractional dispersion for %d < r < %d kpc = %.3f (%.3f dex) " % (mean_dispersion_radius_range[0], mean_dispersion_radius_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.35, 0.08), size=10, xycoords='axes fraction')
+                        plt.savefig("rad_height_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+        if draw_metal_PDF == 1:
+                fig_metal_PDF[time].savefig("metal_PDF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+        if draw_density_DF >= 1:
+                plt.clf()
+#		plt.subplot(111, aspect=1)
+                fig = plt.figure(figsize=(8, 8))
+                gridspec.GridSpec(4, 1)
+                plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                for code in range(len(codes)):
+                        lines = plt.plot(density_DF_xs[time][code], density_DF_profiles[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.semilogx()
+                plt.semilogy()
+                plt.xlim(1e-28, 1e-21)
+                plt.ylim(1e4, 1e9) # accumulation=False
+                #plt.ylim(1e5, 2e10) # accumulation=True
+                if time != 0 and dataset_num == 2:
+                        plt.axvline(x = 1.67e-24*10, color='k', linestyle ='--', linewidth=2, alpha=0.7) # SF threshold density
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Density\ (g/cm^3)}$", fontsize='large')
+                plt.ylabel(r"$\mathrm{Mass,}\/\mathrm{d}M\mathrm{/dlog}\/\mathrm{\rho}\/\mathrm{(M_{\odot})}$", fontsize='large')
+                plt.legend(codes, loc=4, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+
+                plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                ave_profiles = np.mean(np.array(density_DF_profiles[time]), axis=0)
+                for code in range(len(codes)):
+                        lines = plt.plot(density_DF_xs[time][code], (density_DF_profiles[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.semilogx()
+                plt.xlim(1e-28, 1e-21)
+                plt.ylim(-1.0, 3.0)
+                plt.grid(True)
+                plt.locator_params(axis='y',nbins=4)
+                plt.xlabel("$\mathrm{Density\ (g/cm^3)}$", fontsize='large')
+                plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{m} - \mathrm{\bar m})/\mathrm{\bar m}$", fontsize='large')
+                if add_mean_fractional_dispersion == 1:
+                        mean_fractional_dispersion = (np.std(np.array(density_DF_profiles[time]), axis=0)/ave_profiles)[(mean_dispersion_density_range[0] < density_DF_xs[time][0]) & (density_DF_xs[time][0] < mean_dispersion_density_range[1])].mean()
+                        mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                        plt.annotate("Mean fractional dispersion for %.1e < rho < %.1e = %.3f (%.3f dex) " % (mean_dispersion_density_range[0], mean_dispersion_density_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.27, 0.84), size=10, xycoords='axes fraction')
+                plt.savefig("density_DF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+                if draw_density_DF == 2 and time != 0 and dataset_num == 2:
+                        fig = plt.figure(figsize=(8, 8))
+                        gridspec.GridSpec(16, 1)
+                        plt.subplot2grid((16, 1), (0, 0), rowspan=9)
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                lines = plt.plot(density_DF_xs[time][code], (density_DF_profiles[time][code] - density_DF_1st_profiles[time][code])/1e8, color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xscale('log')
+                        plt.xlim(1e-28, 1e-21)
+                        plt.ylim(-7, 3)
+                        plt.axvline(x = 1.67e-24*10, color='k', linestyle ='--', linewidth=2, alpha=0.7) # SF threshold density
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Density\ (g/cm^3)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Mass\ Change,}\/\mathrm{\Delta}(\mathrm{d}M\mathrm{/dlog}\/\mathrm{\rho})\/\mathrm{(10^8 M_{\odot})}$", fontsize='large')
+                        plt.legend(codes, loc=3, frameon=True, ncol=2, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+
+                        plt.subplot2grid((16, 1), (9, 0), rowspan=7)
+                        for code in range(len(codes)):
+                                lines = plt.plot(density_DF_xs[time][code], (density_DF_profiles[time][code] - density_DF_1st_profiles[time][code])/1e8, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlabel("$\mathrm{Density\ (g/cm^3)}$", fontsize='large')
+                        plt.ylabel(r"$\mathtt{symlog}[\/\mathrm{\Delta}(\mathrm{d}M\mathrm{/dlog}\/\mathrm{\rho})\/\mathrm{(10^8 M_{\odot})}\/]$", fontsize='large')
+                        plt.xscale('log')
+                        plt.yscale('symlog', linthreshy=0.01)
+                        plt.xlim(1e-28, 1e-21)
+                        plt.ylim(-10, 10)
+                        plt.axvline(x = 1.67e-24*10, color='k', linestyle ='--', linewidth=2, alpha=0.7) # SF threshold density
+                        plt.grid(True)
+                        plt.savefig("density_DF_change_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+        if draw_radius_DF == 1:
+                plt.clf()
+#		plt.subplot(111, aspect=1)
+                fig = plt.figure(figsize=(8, 6))
+                for code in range(len(codes)):
+                        lines = plt.plot(radius_DF_xs[time][code], np.add.accumulate(radius_DF_profiles[time][code]), color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.semilogy()
+                plt.xlim(0, 14)
+                plt.ylim(1e7, 2e10)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                plt.ylabel("$\mathrm{Mass\ (M_{\odot})}$", fontsize='large')
+                plt.legend(codes, loc=4, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+                plt.savefig("radius_DF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+
+                plt.clf()
+#		plt.subplot(111, aspect=1)
+                fig = plt.figure(figsize=(8, 8))
+                gridspec.GridSpec(4, 1)
+                plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                for code in range(len(codes)):
+                        temp = []
+                        dr = 0.5*(radius_DF_xs[time][code][1] - radius_DF_xs[time][code][0]) # Here we assume that ProfilePlot was made with linearly binned radius_DF_xs
+                        for radius in range(len(radius_DF_profiles[time][code])):
+                                surface_area = np.pi*(((radius_DF_xs[time][code][radius]+dr)*1e3)**2 - ((radius_DF_xs[time][code][radius]-dr)*1e3)**2)
+                                temp.append(radius_DF_profiles[time][code][radius] / surface_area)
+                        surface_density[time].append(temp)
+                        lines = plt.plot(radius_DF_xs[time][code], surface_density[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.semilogy()
+                plt.xlim(0, 14)
+                plt.ylim(1e-1, 2e3)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                plt.ylabel("$\mathrm{Surface\ Density\ (M_{\odot}/pc^2)}$", fontsize='large')
+                plt.legend(codes, loc=1, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+
+                plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                ave_profiles = np.mean(np.array(surface_density[time]), axis=0)
+                for code in range(len(codes)):
+                        lines = plt.plot(radius_DF_xs[time][code], (surface_density[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.xlim(0, 14)
+                plt.ylim(-1.0, 1.0)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{\Sigma} - \mathrm{\bar \Sigma})/\mathrm{\bar \Sigma}$", fontsize='large')
+                if add_mean_fractional_dispersion == 1:
+                        mean_fractional_dispersion = (np.std(np.array(surface_density[time]), axis=0)/ave_profiles)[(mean_dispersion_radius_range[0] < radius_DF_xs[time][0]) & (radius_DF_xs[time][0] < mean_dispersion_radius_range[1])].mean()
+                        mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                        plt.annotate("Mean fractional dispersion for %d < r < %d kpc = %.3f (%.3f dex) " % (mean_dispersion_radius_range[0], mean_dispersion_radius_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.35, 0.08), size=10, xycoords='axes fraction')
+                plt.savefig("gas_surface_density_radial_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+        if draw_star_radius_DF >= 1 and time != 0:
+                plt.clf()
+#		plt.subplot(111, aspect=1)
+                fig = plt.figure(figsize=(8, 6))
+                for code in range(len(codes)):
+                        lines = plt.plot(star_radius_DF_xs[time][code], np.add.accumulate(star_radius_DF_profiles[time][code]), color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.semilogy()
+                plt.xlim(0, 14)
+                plt.ylim(1e7, 2e10)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                plt.ylabel("$\mathrm{Newly\ Formed\ Stellar\ Mass\ (M_{\odot})}$", fontsize='large')
+                plt.legend(codes, loc=4, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+                plt.savefig("star_radius_DF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+
+                plt.clf()
+#		plt.subplot(111, aspect=1)
+                fig = plt.figure(figsize=(8, 8))
+                gridspec.GridSpec(4, 1)
+                plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                for code in range(len(codes)):
+                        temp = []
+                        dr = 0.5*(star_radius_DF_xs[time][code][1] - star_radius_DF_xs[time][code][0])
+                        for radius in range(len(star_radius_DF_profiles[time][code])):
+                                surface_area = np.pi*(((star_radius_DF_xs[time][code][radius]+dr)*1e3)**2 - ((star_radius_DF_xs[time][code][radius]-dr)*1e3)**2)
+                                temp.append(star_radius_DF_profiles[time][code][radius] / surface_area)
+                        star_surface_density[time].append(temp)
+                        lines = plt.plot(star_radius_DF_xs[time][code], star_surface_density[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.semilogy()
+                plt.xlim(0, 14)
+                plt.ylim(1e-1, 2e3)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                plt.ylabel("$\mathrm{Newly\ Formed\ Stellar\ Surface\ Density\ (M_{\odot}/pc^2)}$", fontsize='large')
+                plt.legend(codes, loc=1, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+
+                plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                ave_profiles = np.mean(np.array(star_surface_density[time]), axis=0)
+                for code in range(len(codes)):
+                        lines = plt.plot(star_radius_DF_xs[time][code], (star_surface_density[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.xlim(0, 14)
+                plt.ylim(-1.0, 3.0)
+                plt.grid(True)
+                plt.locator_params(axis='y',nbins=4)
+                plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{\Sigma} - \mathrm{\bar \Sigma})/\mathrm{\bar \Sigma}$", fontsize='large')
+                if add_mean_fractional_dispersion == 1:
+                        mean_fractional_dispersion = (np.std(np.array(star_surface_density[time]), axis=0)/ave_profiles)[(mean_dispersion_radius_range[0] < star_radius_DF_xs[time][0]) & (star_radius_DF_xs[time][0] < mean_dispersion_radius_range[1])].mean()
+                        mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                        plt.annotate("Mean fractional dispersion for %d < r < %d kpc = %.3f (%.3f dex) " % (mean_dispersion_radius_range[0], mean_dispersion_radius_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.02, 0.84), size=10, xycoords='axes fraction')
+                plt.savefig("star_surface_density_radial_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+
+                if draw_star_radius_DF == 2 and time != 0:
+#			plt.subplot(111, aspect=1)
+                        fig = plt.figure(figsize=(8, 8))
+                        gridspec.GridSpec(4, 1)
+                        plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                        plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                        for code in range(len(codes)):
+                                temp = []
+                                dr = 0.5*(sfr_radius_DF_xs[time][code][1] - sfr_radius_DF_xs[time][code][0])
+                                for radius in range(len(sfr_radius_DF_profiles[time][code])):
+                                        surface_area = np.pi*((sfr_radius_DF_xs[time][code][radius]+dr)**2 - (sfr_radius_DF_xs[time][code][radius]-dr)**2)
+                                        temp.append(sfr_radius_DF_profiles[time][code][radius] / surface_area)
+                                sfr_surface_density[time].append(temp)
+                                lines = plt.plot(sfr_radius_DF_xs[time][code], sfr_surface_density[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.semilogy()
+                        plt.xlim(0, 14)
+                        plt.ylim(1e-4, 1e1)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel("$\mathrm{Star\ Formation\ Rate\ Surface\ Density\ (M_{\odot}/yr/kpc^2)}$", fontsize='large')
+                        plt.legend(codes, loc=1, frameon=True, ncol=2, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+
+                        plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                        ave_profiles = np.mean(np.array(sfr_surface_density[time]), axis=0)
+                        for code in range(len(codes)):
+                                lines = plt.plot(sfr_radius_DF_xs[time][code], (sfr_surface_density[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                        plt.xlim(0, 14)
+                        plt.ylim(-1.0, 3.0)
+                        plt.grid(True)
+                        plt.locator_params(axis='y',nbins=4)
+                        plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                        plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{\Sigma} - \mathrm{\bar \Sigma})/\mathrm{\bar \Sigma}$", fontsize='large')
+                        # if add_mean_fractional_dispersion == 1:
+                        #       mean_fractional_dispersion = (np.std(np.array(sfr_surface_density[time]), axis=0)/ave_profiles)[(mean_dispersion_radius_range[0] < sfr_radius_DF_xs[time][0]) & (sfr_radius_DF_xs[time][0] < mean_dispersion_radius_range[1])].mean()
+                        #       mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                        #       plt.annotate("Mean fractional dispersion for %d < r < %d kpc = %.3f (%.3f dex) " % (mean_dispersion_radius_range[0], mean_dispersion_radius_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.02, 0.84), size=10, xycoords='axes fraction')
+                        plt.savefig("sfr_surface_density_radial_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+
+                        # Draw K-S plot; below assumes that surface_density (or radius_DF_profiles) and sfr_surface_density (or sfr_radius_DF_profiles) have the identical size (n_bins in ProfilePlot)
+#			plt.subplot(111)
+                        fig = plt.figure(figsize=(8, 7))
+                        KS_fit_t1 = []
+                        KS_fit_t2 = []
+                        Bigiel_surface_density = []
+                        Bigiel_sfr_surface_density = []
+                        for code in range(len(codes)):
+                                # Remove bins where SFR surface density is zero
+                                KS_x = np.array(surface_density[time][code])
+                                KS_x[np.where(np.array(sfr_surface_density[time][code]) < 1e-10)] = 0
+                                KS_x = np.log10(KS_x)
+                                KS_y = np.log10(np.array(sfr_surface_density[time][code]))
+                                KS_x = KS_x[~np.isinf(KS_x)]
+                                KS_y = KS_y[~np.isinf(KS_y)]
+                                t1, t2 = np.polyfit(KS_x, KS_y, 1)
+                                KS_fit_t1.append(t1)
+                                KS_fit_t2.append(t2)
+                                plt.scatter(KS_x, KS_y, color=color_names[code], edgecolor=color_names[code], s=30, linewidth=0.7, marker=marker_names[code], alpha=0.8)
+                        plt.xlim(0, 3)
+                        plt.ylim(-4, 1)
+                        plt.grid(True)
+                        plt.xlabel("$\mathrm{log[Gas\ Surface\ Density\ (M_{\odot}/pc^2)]}$")
+                        plt.ylabel("$\mathrm{log[Star\ Formation\ Rate\ Surface\ Density\ (M_{\odot}/yr/kpc^2)]}$")
+                        plt.legend(codes, loc=2, frameon=True, ncol=2, fancybox=True)
+                        leg = plt.gca().get_legend()
+                        ltext = leg.get_texts()
+                        plt.setp(ltext, fontsize='small')
+                        t = np.arange(-2, 5, 0.01)
+                        for line in import_text("./Bigieletal2008_Fig8_Contour.txt", " "):
+                                Bigiel_surface_density.append(float(line[0]) + np.log10(1.36)) # for the factor 1.36, see Section 2.3.1 of Bigiel et al. 2008
+                                Bigiel_sfr_surface_density.append(float(line[1]))
+                        plt.fill(Bigiel_surface_density, Bigiel_sfr_surface_density, fill=True, color='b', alpha = 0.1, hatch='\\') # contour by Bigiel et al. 2008 (Fig 8), or Feldmann et al. 2012 (Fig 1)
+#			plt.plot(Bigiel_surface_density, Bigiel_sfr_surface_density, 'b-', linewidth = 0.7, alpha = 0.4)
+                        plt.plot(t, 1.37*t - 3.78, 'k--', linewidth = 2, alpha = 0.7) # observational fit by Kennicutt et al. 2007
+                        plt.savefig("K-S_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        for code in range(len(codes)):
+                                plt.plot(t, np.polyval([KS_fit_t1[code], KS_fit_t2[code]], t), color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], alpha = 0.7) # linear fits
+                        plt.savefig("K-S_with_fits_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                        plt.clf()
+        if draw_height_DF == 1:
+                plt.clf()
+#		plt.subplot(111, aspect=0.5)
+                fig = plt.figure(figsize=(8, 6))
+                for code in range(len(codes)):
+                        lines = plt.plot(height_DF_xs[time][code], np.add.accumulate(height_DF_profiles[time][code]), color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.semilogy()
+                plt.xlim(0, 1.4)
+                plt.ylim(1e9, 2e10)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Vertical\ Height\ (kpc)}$", fontsize='large')
+                plt.ylabel("$\mathrm{Mass\ (M_{\odot})}$", fontsize='large')
+                plt.legend(codes, loc=4, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+                plt.savefig("height_DF_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+
+                plt.clf()
+#		plt.subplot(111, aspect=0.8)
+                fig = plt.figure(figsize=(8, 8))
+                gridspec.GridSpec(4, 1)
+                plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                for code in range(len(codes)):
+                        temp = []
+                        dh = height_DF_xs[time][code][1] - height_DF_xs[time][code][0]
+                        for height in range(len(height_DF_profiles[time][code])):
+                                surface_area = 2 * dh*1e3 * figure_width*1e3 # surface_area = 2*d(height)*figure_width in pc^2
+                                temp.append(height_DF_profiles[time][code][height] / surface_area)
+                        height_surface_density[time].append(temp)
+                        lines = plt.plot(height_DF_xs[time][code], height_surface_density[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.semilogy()
+                plt.xlim(0, 1.4)
+                plt.ylim(1e-1, 2e3)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Vertical\ Height\ (kpc)}$", fontsize='large')
+                plt.ylabel("$\mathrm{Surface\ Density\ (M_{\odot}/pc^2)}$", fontsize='large')
+                plt.legend(codes, loc=1, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+
+                plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                ave_profiles = np.mean(np.array(height_surface_density[time]), axis=0)
+                for code in range(len(codes)):
+                        lines = plt.plot(height_DF_xs[time][code], (height_surface_density[time][code] - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.xlim(0, 1.4)
+                plt.ylim(-1.0, 3.0)
+                plt.grid(True)
+                plt.locator_params(axis='y',nbins=4)
+                plt.xlabel("$\mathrm{Vertical\ Height\ (kpc)}$", fontsize='large')
+                plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{\Sigma} - \mathrm{\bar \Sigma})/\mathrm{\bar \Sigma}$", fontsize='large')
+                if add_mean_fractional_dispersion == 1:
+                        mean_fractional_dispersion = (np.std(np.array(height_surface_density[time]), axis=0)/ave_profiles)[(mean_dispersion_height_range[0] < height_DF_xs[time][0]) & (height_DF_xs[time][0] < mean_dispersion_height_range[1])].mean()
+                        mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                        plt.annotate("Mean fractional dispersion for %.1f < z < %.1f kpc = %.3f (%.3f dex) " % (mean_dispersion_height_range[0], mean_dispersion_height_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.02, 0.84), size=10, xycoords='axes fraction')
+                plt.savefig("gas_surface_density_vertical_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+        if draw_SFR >= 1 and time != 0:
+                plt.clf()
+#		plt.subplot(111)#, aspect=1e-7)
+                fig = plt.figure(figsize=(8, 6))
+                for code in range(len(codes)):
+                        lines = plt.plot(sfr_ts[time][code], sfr_cum_masses[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.xlim(0, times[time])
+                plt.ylim(0, 2.5e9)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Time\ (Myr)}$", fontsize='large')
+                plt.ylabel("$\mathrm{Stellar\ Mass\ (M_{\odot})}$", fontsize='large')
+                plt.legend(codes, loc=2, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+                plt.savefig("Stellar_mass_evolution_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+#		plt.subplot(111, aspect=55)
+                fig = plt.figure(figsize=(8, 8))
+                gridspec.GridSpec(4, 1)
+                plt.subplot2grid((4, 1), (0, 0), rowspan=3)
+                plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
+                for code in range(len(codes)):
+                        lines = plt.plot(sfr_ts[time][code], sfr_sfrs[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.xlim(0, times[time])
+                plt.ylim(0, 8)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Time\ (Myr)}$", fontsize='large')
+                plt.ylabel("$\mathrm{Star\ Formation\ Rate\ (M_{\odot}/yr)}$", fontsize='large')
+                if draw_SFR == 2:
+                        pf_sfr_ref = load_dataset(2, 1, 0, ['GIZMO'],
+                                                  [['dummy', '/lustre/ki/pfs/mornkr/080112_CHaRGe/pfs-hyades/AGORA-DISK-repository/Grackle+SF+ThermalFbck/GIZMO/AGORA_disk_second_ps1.5/snapshot_temp_100_last']])
+                        pf_sfr_ref.unit_registry.add('pccm', pf_sfr_ref.unit_registry.lut['pc'][0], length, "\\rm{pc}/(1+z)")
+                        pf_sfr_ref.hubble_constant = 0.71; pf_sfr_ref.omega_lambda = 0.73; pf_sfr_ref.omega_matter = 0.27; pf_sfr_ref.omega_curvature = 0.0
+                        sp_sfr_ref = pf_sfr_ref.sphere(center, (0.5*figure_width, "kpc"))
+                        draw_SFR_mass_ref = sp_sfr_ref[(PartType_Star_to_use, "particle_mass")].in_units('Msun')
+                        draw_SFR_ct_ref   = sp_sfr_ref[(PartType_Star_to_use, FormationTimeType_to_use)].in_units('Myr')
+                        sfr_ref = StarFormationRate(pf_sfr_ref, star_mass = draw_SFR_mass_ref, star_creation_time = draw_SFR_ct_ref,
+                                                    volume = sp_sfr_ref.volume(), bins = 25)
+                        lines = plt.plot(sfr_ref.time.in_units('Myr'), sfr_ref.Msol_yr, color='k', linestyle='--', marker='*', markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.legend(codes+['GIZMO-ps2'], loc=2, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+                plt.subplot2grid((4, 1), (3, 0), rowspan=1)
+                ave_profiles = np.mean(np.array(sfr_sfrs[time]), axis=0)
+                for code in range(len(codes)):
+                        lines = plt.plot(sfr_ts[time][code], (sfr_sfrs[time][code].d - ave_profiles)/ave_profiles, color=color_names[code], linestyle='none', marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.xlim(0, times[time])
+                plt.ylim(-1.0, 1.0)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Time\ (Myr)}$", fontsize='large')
+                plt.ylabel(r"$\mathrm{Residual,}\/(\mathrm{\dot{\rho}_\star} - \mathrm{\bar{\dot{\rho}_\star}})/\mathrm{\bar{\dot{\rho}_\star}}$", fontsize='large')
+                if add_mean_fractional_dispersion == 1:
+                        mean_fractional_dispersion = (np.std(np.array(sfr_sfrs[time]), axis=0)/ave_profiles)[(mean_dispersion_time_range[0] < sfr_ts[time][0]) & (sfr_ts[time][0] < mean_dispersion_time_range[1])].mean()
+                        mean_fractional_dispersion_in_dex = np.log10(1.+mean_fractional_dispersion)
+                        plt.annotate("Mean fractional dispersion for %d < t < %d Myr = %.3f (%.3f dex) " % (mean_dispersion_time_range[0], mean_dispersion_time_range[1], mean_fractional_dispersion, mean_fractional_dispersion_in_dex), xy=(0.35, 0.08), size=10, xycoords='axes fraction')
+                plt.savefig("SFR_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+        if draw_cut_through == 1:
+                plt.clf()
+#		plt.subplot(111, aspect=0.5)
+                fig = plt.figure(figsize=(8, 6))
+                for code in range(len(codes)):
+                        lines = plt.plot(cut_through_zs[time][code], cut_through_zvalues[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.semilogy()
+                plt.xlim(-1.4, 1.4)
+                plt.ylim(1e-26, 1e-22)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Vertical\ Height\ (kpc)}$", fontsize='large')
+                plt.ylabel("$\mathrm{Density\ (g/cm^3)}$", fontsize='large')
+                plt.legend(codes, loc=1, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+                z = np.arange(-1.4, 1.4, 0.05)
+                plt.plot(z, rho_agora_disk(0, np.abs(z)), linestyle="--", linewidth=2, color='k', alpha=0.7)
+                plt.savefig("cut_through_z_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
+#		plt.subplot(111, aspect=0.5)
+                fig = plt.figure(figsize=(8, 6))
+                for code in range(len(codes)):
+                        lines = plt.plot(cut_through_xs[time][code], cut_through_xvalues[time][code], color=color_names[code], linestyle=linestyle_names[np.mod(code, len(linestyle_names))], marker=marker_names[code], markeredgecolor='none', linewidth=1.2, alpha=0.8)
+                plt.semilogy()
+                plt.xlim(-14, 14)
+                plt.ylim(1e-26, 1e-22)
+                plt.grid(True)
+                plt.xlabel("$\mathrm{Cylindrical\ Radius\ (kpc)}$", fontsize='large')
+                plt.ylabel("$\mathrm{Density\ (g/cm^3)}$", fontsize='large')
+                plt.legend(codes, loc=1, frameon=True, ncol=2, fancybox=True)
+                leg = plt.gca().get_legend()
+                ltext = leg.get_texts()
+                plt.setp(ltext, fontsize='small')
+                x = np.arange(-14, 14, 0.05)
+                plt.plot(x, rho_agora_disk(np.abs(x), 0), linestyle="--", linewidth=2, color='k', alpha=0.7)
+                plt.savefig("cut_through_x_%dMyr" % times[time], bbox_inches='tight', pad_inches=0.03, dpi=300)
+                plt.clf()
diff --git a/examples/AgoraDisk/run.sh b/examples/AgoraDisk/run.sh
new file mode 100644
index 0000000000000000000000000000000000000000..d7e284db52c2e6750fd713b3607a7f423bac7769
--- /dev/null
+++ b/examples/AgoraDisk/run.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+# This example is based on the AGORA disk article (DOI: 10.3847/1538-4357/833/2/202)
+
+# currently only the low resolution is available
+sim=low
+
+# enable cooling or not
+cooling=0
+
+# make run.sh fail if a subcommand fails
+set -e
+
+# define flags
+flag=
+if [ $cooling -eq 1 ]
+then
+    flag=-C
+fi
+
+# Generate the initial conditions if they are not present.
+if [ ! -e $sim.hdf5 ]
+then
+    echo "Fetching initial glass file for the Sedov blast example..."
+    ./getIC.sh $sim.hdf5
+fi
+
+# Get the Grackle cooling table
+if [ ! -e CloudyData_UVB=HM2012.h5 ]
+then
+    echo "Fetching the Cloudy tables required by Grackle..."
+    ../getCoolingTable.sh
+fi
+
+# copy the initial conditions
+cp $sim.hdf5 agora_disk.hdf5
+# Update the particle types
+python3 changeType.py agora_disk.hdf5
+
+# Run SWIFT
+#../swift $flag -s -G -t 4 agora_disk.yml 2>&1 | tee output.log
+
+
+echo "Changing smoothing length to be Gadget compatible"
+python3 cleanupSwift.py agora_disk_0000.hdf5 agora_disk_IC.hdf5
+python3 cleanupSwift.py agora_disk_0050.hdf5 agora_disk_500Myr.hdf5
+
+echo "Fetching GEAR solution..."
+./getSolution.sh $flag
+
+echo "Plotting..."
+python3 plotSolution.py $flag
diff --git a/examples/CoolingBox/run.sh b/examples/CoolingBox/run.sh
index 61106d1f4819145ad4fb3a017918ca0e074a87c2..30b2177a6e8bb95a20146397f8b6a5021161b27f 100755
--- a/examples/CoolingBox/run.sh
+++ b/examples/CoolingBox/run.sh
@@ -17,7 +17,7 @@ fi
 if [ ! -e CloudyData_UVB=HM2012.h5 ]
 then
     echo "Fetching the Cloudy tables required by Grackle..."
-    ./getCoolingTable.sh
+    ../getCoolingTable.sh
 fi
 
 # Run SWIFT
diff --git a/examples/KeplerianRing/README.md b/examples/KeplerianRing/README.md
index d486cbfe412c7ff9ca121c87bbc548d0ece078dd..1c361f275d60ef1ca46d696e2e9507bb749e531c 100644
--- a/examples/KeplerianRing/README.md
+++ b/examples/KeplerianRing/README.md
@@ -2,7 +2,8 @@ Keplerian Ring Test
 ===================
 
 This test uses the '2D Keplerian Ring' to assess the accuracy of SPH
-calculations. For more information on the test, please see Cullen & Dehnen 2009
+calculations. It is known to fail with all schemes in SWIFT. For more
+information on the test, please see Cullen & Dehnen 2009
 (http://arxiv.org/abs/1006.1524) Section 4.3.
 
 It is key that for this test in particular that the initial conditions are
diff --git a/examples/KeplerianRing/run.sh b/examples/KeplerianRing/run.sh
index ee8f7b247f38b74a204f9caf2bd543b72c4f94fa..0195846a8839a27083594c20569b1fd4d49f4c16 100755
--- a/examples/KeplerianRing/run.sh
+++ b/examples/KeplerianRing/run.sh
@@ -10,3 +10,9 @@ fi
 
 rm -rf keplerian_ring_*.hdf5
 ../swift -g -s -t 1 -v 1 keplerian_ring.yml 2>&1 | tee output.log
+
+echo
+echo
+echo "This test is expected to fail, please read the README.md file"
+echo
+echo
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 2c5376a678b9d816e9575509b094e0a4168a6e42..b9c601e039d3f7566e56b0220935e63e42994b28 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -56,19 +56,23 @@ swift_mpi_CFLAGS = $(MYFLAGS) $(AM_CFLAGS) $(MPI_FLAGS) -DENGINE_POLICY="engine_
 swift_mpi_LDADD =  ../src/.libs/libswiftsim_mpi.a $(MPI_LIBS) $(EXTRA_LIBS)
 
 # Scripts to generate ICs
-EXTRA_DIST = BigCosmoVolume/makeIC.py \
-	     BigPerturbedBox/makeIC_fcc.py \
-	     CosmoVolume/cosmoVolume.yml CosmoVolume/getIC.sh CosmoVolume/run.sh \
-	     CoolingBox/coolingBox.yml CoolingBox/energy_plot.py CoolingBox/makeIC.py CoolingBox/run.sh \
+EXTRA_DIST = CoolingBox/coolingBox.yml CoolingBox/energy_plot.py CoolingBox/makeIC.py CoolingBox/run.sh \
 	     EAGLE_6/eagle_6.yml EAGLE_6/getIC.sh EAGLE_6/README EAGLE_6/run.sh \
 	     EAGLE_12/eagle_12.yml EAGLE_12/getIC.sh EAGLE_12/README EAGLE_12/run.sh \
 	     EAGLE_25/eagle_25.yml EAGLE_25/getIC.sh EAGLE_25/README EAGLE_25/run.sh \
 	     EAGLE_50/eagle_50.yml EAGLE_50/getIC.sh EAGLE_50/README EAGLE_50/run.sh \
 	     EAGLE_100/eagle_100.yml EAGLE_100/getIC.sh EAGLE_100/README EAGLE_100/run.sh \
+	     EAGLE_DMO_12/eagle_12.yml EAGLE_DMO_12/getIC.sh EAGLE_DMO_12/README EAGLE_DMO_12/run.sh \
+	     EAGLE_DMO_25/eagle_25.yml EAGLE_DMO_25/getIC.sh EAGLE_DMO_25/README EAGLE_DMO_25/run.sh \
+	     EAGLE_DMO_50/eagle_50.yml EAGLE_DMO_50/getIC.sh EAGLE_DMO_50/README EAGLE_DMO_50/run.sh \
+	     EAGLE_DMO_100/eagle_100.yml EAGLE_DMO_100/getIC.sh EAGLE_DMO_100/README EAGLE_DMO_100/run.sh \
+	     EvrardCollapse_3D/evrard.yml EvrardCollapse_3D/makeIC.py EvrardCollapse_3D/plotSolution.py EvrardCollapse_3D/run.sh EvrardCollapse_3D/getReference.sh \
 	     ExternalPointMass/externalPointMass.yml ExternalPointMass/makeIC.py ExternalPointMass/run.sh ExternalPointMass/energy_plot.py \
 	     GreshoVortex_2D/getGlass.sh GreshoVortex_2D/gresho.yml GreshoVortex_2D/makeIC.py GreshoVortex_2D/plotSolution.py GreshoVortex_2D/run.sh \
+	     GreshoVortex_3D/getGlass.sh GreshoVortex_3D/gresho.yml GreshoVortex_3D/makeIC.py GreshoVortex_3D/plotSolution.py GreshoVortex_3D/run.sh \
 	     HydrostaticHalo/README HydrostaticHalo/hydrostatic.yml HydrostaticHalo/makeIC.py HydrostaticHalo/run.sh \
 	     HydrostaticHalo/density_profile.py HydrostaticHalo/velocity_profile.py HydrostaticHalo/internal_energy_profile.py HydrostaticHalo/test_energy_conservation.py \
+	     InteractingBlastWaves_1D/run.sh InteractingBlastWaves_1D/makeIC.py InteractingBlastWaves_1D/plotSolution.py InteractingBlastWaves_1D/interactingBlastWaves.yml InteractingBlastWaves_1D/getReference.sh \
 	     IsothermalPotential/README IsothermalPotential/run.sh IsothermalPotential/energy_plot.py IsothermalPotential/isothermal.yml IsothermalPotential/makeIC.py \
 	     KelvinHelmholtz_2D/kelvinHelmholtz.yml KelvinHelmholtz_2D/makeIC.py KelvinHelmholtz_2D/plotSolution.py KelvinHelmholtz_2D/run.sh \
 	     MultiTypes/makeIC.py  MultiTypes/multiTypes.yml MultiTypes/run.sh \
@@ -83,13 +87,15 @@ EXTRA_DIST = BigCosmoVolume/makeIC.py \
              SineWavePotential_1D/makeIC.py SineWavePotential_1D/plotSolution.py SineWavePotential_1D/run.sh SineWavePotential_1D/sineWavePotential.yml \
              SineWavePotential_2D/makeIC.py SineWavePotential_2D/plotSolution.py SineWavePotential_2D/run.sh SineWavePotential_2D/sineWavePotential.yml \
              SineWavePotential_3D/makeIC.py SineWavePotential_3D/plotSolution.py SineWavePotential_3D/run.sh SineWavePotential_3D/sineWavePotential.yml \
+             SmallCosmoVolume/README SmallCosmoVolume/getIC.sh SmallCosmoVolume/run.sh SmallCosmoVolume/small_cosmo_volume.yml \
 	     SodShock_1D/makeIC.py SodShock_1D/plotSolution.py SodShock_1D/run.sh SodShock_1D/sodShock.yml \
 	     SodShock_2D/getGlass.sh SodShock_2D/makeIC.py SodShock_2D/plotSolution.py SodShock_2D/run.sh SodShock_2D/sodShock.yml \
 	     SodShock_3D/getGlass.sh SodShock_3D/makeIC.py SodShock_3D/plotSolution.py SodShock_3D/run.sh SodShock_3D/sodShock.yml \
 	     SquareTest_2D/makeIC.py SquareTest_2D/plotSolution.py SquareTest_2D/run.sh SquareTest_2D/square.yml \
 	     UniformBox_2D/makeIC.py UniformBox_2D/run.sh UniformBox_2D/uniformPlane.yml \
 	     UniformBox_3D/makeICbig.py UniformBox_3D/makeIC.py UniformBox_3D/run.sh UniformBox_3D/uniformBox.yml \
-	     UniformDMBox/makeIC.py
+	     UniformDMBox/makeIC.py \
+             ZeldovichPancake_3D/makeIC.py ZeldovichPancake_3D/zeldovichPancake.yml ZeldovichPancake_3D/run.sh ZeldovichPancake_3D/plotSolution.py
 
 # Default parameter file
 EXTRA_DIST += parameter_example.yml
@@ -106,3 +112,5 @@ EXTRA_DIST += analyse_threadpool_tasks.py \
 EXTRA_DIST += plot_scaling_results.py \
               plot_scaling_results_breakdown.py
 
+# Script for gravity accuracy
+EXTRA_DIST += plot_gravity_checks.py
diff --git a/examples/ZeldovichPancake_3D/makeIC.py b/examples/ZeldovichPancake_3D/makeIC.py
index 170be68a59552a8d346ac5ad346b5dc0f2d43399..15fb8bdef95f6e830e78f4d1b2c419051a6f00af 100644
--- a/examples/ZeldovichPancake_3D/makeIC.py
+++ b/examples/ZeldovichPancake_3D/makeIC.py
@@ -40,7 +40,6 @@ k_in_J_K = 1.38064852e-23
 # Parameters
 rho_0 = 1.8788e-26 # h^2 kg m^-3
 H_0 = 1. / Mpc_in_m * 10**5 # s^-1
-#lambda_i = 1.975e24    # h^-1 m (= 64 h^-1 Mpc)
 lambda_i = 64. / H_0 * 10**5 # h^-1 m (= 64 h^-1 Mpc)
 x_min = -0.5 * lambda_i
 x_max = 0.5 * lambda_i
diff --git a/examples/CoolingBox/getCoolingTable.sh b/examples/getCoolingTable.sh
old mode 100755
new mode 100644
similarity index 100%
rename from examples/CoolingBox/getCoolingTable.sh
rename to examples/getCoolingTable.sh
diff --git a/examples/plot_gravity_checks.py b/examples/plot_gravity_checks.py
old mode 100644
new mode 100755
diff --git a/src/hydro/Shadowswift/hydro.h b/src/hydro/Shadowswift/hydro.h
index 025779f17496e7bf30fdf12353c4381c7d6292ce..d70d58c6ba508ba4282ac9dd32565478afb40692 100644
--- a/src/hydro/Shadowswift/hydro.h
+++ b/src/hydro/Shadowswift/hydro.h
@@ -16,6 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  ******************************************************************************/
+#ifndef SWIFT_SHADOWSWIFT_HYDRO_H
+#define SWIFT_SHADOWSWIFT_HYDRO_H
 
 #include <float.h>
 #include "adiabatic_index.h"
@@ -41,15 +43,23 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep(
 
   const float CFL_condition = hydro_properties->CFL_condition;
 
-  float R = get_radius_dimension_sphere(p->cell.volume);
-
-  if (p->timestepvars.vmax == 0.) {
-    /* vmax can be zero in vacuum. We force the time step to become the maximal
-       time step in this case */
-    return FLT_MAX;
-  } else {
-    return CFL_condition * R / fabsf(p->timestepvars.vmax);
+  float vrel[3];
+  vrel[0] = p->primitives.v[0] - xp->v_full[0];
+  vrel[1] = p->primitives.v[1] - xp->v_full[1];
+  vrel[2] = p->primitives.v[2] - xp->v_full[2];
+  float vmax =
+      sqrtf(vrel[0] * vrel[0] + vrel[1] * vrel[1] + vrel[2] * vrel[2]) +
+      sqrtf(hydro_gamma * p->primitives.P / p->primitives.rho);
+  vmax = max(vmax, p->timestepvars.vmax);
+
+  const float psize =
+      cosmo->a *
+      powf(p->cell.volume / hydro_dimension_unit_sphere, hydro_dimension_inv);
+  float dt = FLT_MAX;
+  if (vmax > 0.) {
+    dt = psize / vmax;
   }
+  return CFL_condition * dt;
 }
 
 /**
@@ -102,7 +112,7 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part(
   p->conserved.momentum[2] = mass * p->primitives.v[2];
 
 #ifdef EOS_ISOTHERMAL_GAS
-  p->conserved.energy = mass * const_isothermal_internal_energy;
+  p->conserved.energy = mass * gas_internal_energy_from_entropy(0.f, 0.f);
 #else
   p->conserved.energy *= mass;
 #endif
@@ -117,12 +127,21 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part(
   p->v[0] = 0.;
   p->v[1] = 0.;
   p->v[2] = 0.;
+#else
+  p->v[0] = p->primitives.v[0];
+  p->v[1] = p->primitives.v[1];
+  p->v[2] = p->primitives.v[2];
 #endif
 
   /* set the initial velocity of the cells */
   xp->v_full[0] = p->v[0];
   xp->v_full[1] = p->v[1];
   xp->v_full[2] = p->v[2];
+
+  /* ignore accelerations present in the initial condition */
+  p->a_hydro[0] = 0.0f;
+  p->a_hydro[1] = 0.0f;
+  p->a_hydro[2] = 0.0f;
 }
 
 /**
@@ -137,7 +156,8 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part(
 __attribute__((always_inline)) INLINE static void hydro_init_part(
     struct part* p, const struct hydro_space* hs) {
 
-  p->density.wcount = 0.0f;
+  /* make sure we don't enter the no neighbour case in runner.c */
+  p->density.wcount = 1.0f;
   p->density.wcount_dh = 0.0f;
 
   voronoi_cell_init(&p->cell, p->x, hs->anchor, hs->side);
@@ -180,12 +200,13 @@ __attribute__((always_inline)) INLINE static void hydro_end_density(
   if (hnew < p->h) {
     /* Iteration succesful: we accept, but manually set h to a smaller value
        for the next time step */
-    p->density.wcount = 1.0f;
+    const float hinvdim = pow_dimension(1.0f / p->h);
+    p->density.wcount = hinvdim;
     p->h = 1.1f * hnew;
   } else {
     /* Iteration not succesful: we force h to become 1.1*hnew */
     p->density.wcount = 0.0f;
-    p->density.wcount_dh = 1.0f / (1.1f * hnew - p->h);
+    p->density.wcount_dh = p->h / (1.1f * hnew - p->h);
     return;
   }
   volume = p->cell.volume;
@@ -286,8 +307,48 @@ __attribute__((always_inline)) INLINE static void hydro_prepare_force(
   p->force.v_full[0] = xp->v_full[0];
   p->force.v_full[1] = xp->v_full[1];
   p->force.v_full[2] = xp->v_full[2];
+
+  p->conserved.flux.mass = 0.0f;
+  p->conserved.flux.momentum[0] = 0.0f;
+  p->conserved.flux.momentum[1] = 0.0f;
+  p->conserved.flux.momentum[2] = 0.0f;
+  p->conserved.flux.energy = 0.0f;
+}
+
+/**
+ * @brief Prepare a particle for the gradient calculation.
+ *
+ * This function is called after the density loop and before the gradient loop.
+ *
+ * We use it to set the physical timestep for the particle and to copy the
+ * actual velocities, which we need to boost our interfaces during the flux
+ * calculation. We also initialize the variables used for the time step
+ * calculation.
+ *
+ * @param p The particle to act upon.
+ * @param xp The extended particle data to act upon.
+ * @param cosmo The cosmological model.
+ */
+__attribute__((always_inline)) INLINE static void hydro_prepare_gradient(
+    struct part* restrict p, struct xpart* restrict xp,
+    const struct cosmology* cosmo) {
+
+  /* Initialize time step criterion variables */
+  p->timestepvars.vmax = 0.;
 }
 
+/**
+ * @brief Resets the variables that are required for a gradient calculation.
+ *
+ * This function is called after hydro_prepare_gradient.
+ *
+ * @param p The particle to act upon.
+ * @param xp The extended particle data to act upon.
+ * @param cosmo The cosmological model.
+ */
+__attribute__((always_inline)) INLINE static void hydro_reset_gradient(
+    struct part* restrict p) {}
+
 /**
  * @brief Finishes the gradient calculation.
  *
@@ -385,53 +446,36 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
     struct part* p, struct xpart* xp, float dt, const struct cosmology* cosmo,
     const struct hydro_props* hydro_props) {
 
-  float vcell[3];
-
   /* Update the conserved variables. We do this here and not in the kick,
      since we need the updated variables below. */
-  p->conserved.mass += p->conserved.flux.mass;
-  p->conserved.momentum[0] += p->conserved.flux.momentum[0];
-  p->conserved.momentum[1] += p->conserved.flux.momentum[1];
-  p->conserved.momentum[2] += p->conserved.flux.momentum[2];
-  p->conserved.energy += p->conserved.flux.energy;
+  p->conserved.mass += p->conserved.flux.mass * dt;
+  p->conserved.momentum[0] += p->conserved.flux.momentum[0] * dt;
+  p->conserved.momentum[1] += p->conserved.flux.momentum[1] * dt;
+  p->conserved.momentum[2] += p->conserved.flux.momentum[2] * dt;
 
 #ifdef EOS_ISOTHERMAL_GAS
   /* reset the thermal energy */
-  p->conserved.energy = p->conserved.mass * const_isothermal_internal_energy;
-
-#ifdef SHADOWFAX_TOTAL_ENERGY
-  p->conserved.energy += 0.5f * (p->conserved.momentum[0] * p->primitives.v[0] +
-                                 p->conserved.momentum[1] * p->primitives.v[1] +
-                                 p->conserved.momentum[2] * p->primitives.v[2]);
+  p->conserved.energy =
+      p->conserved.mass * gas_internal_energy_from_entropy(0.f, 0.f);
+#else
+  p->conserved.energy += p->conserved.flux.energy * dt;
 #endif
 
-#endif
+#if defined(SHADOWFAX_FIX_CELLS)
+  p->v[0] = 0.0f;
+  p->v[1] = 0.0f;
+  p->v[2] = 0.0f;
+#else
+  if (p->conserved.mass > 0.0f && p->primitives.rho > 0.0f) {
 
-  /* reset fluxes */
-  /* we can only do this here, since we need to keep the fluxes for inactive
-     particles */
-  p->conserved.flux.mass = 0.0f;
-  p->conserved.flux.momentum[0] = 0.0f;
-  p->conserved.flux.momentum[1] = 0.0f;
-  p->conserved.flux.momentum[2] = 0.0f;
-  p->conserved.flux.energy = 0.0f;
+    const float inverse_mass = 1.f / p->conserved.mass;
 
-  if (p->conserved.mass > 0.) {
-    /* We want the cell velocity to be as close as possible to the fluid
-       velocity */
-    vcell[0] = p->conserved.momentum[0] / p->conserved.mass;
-    vcell[1] = p->conserved.momentum[1] / p->conserved.mass;
-    vcell[2] = p->conserved.momentum[2] / p->conserved.mass;
-  } else {
-    vcell[0] = 0.;
-    vcell[1] = 0.;
-    vcell[2] = 0.;
-  }
+    /* Normal case: set particle velocity to fluid velocity. */
+    p->v[0] = p->conserved.momentum[0] * inverse_mass;
+    p->v[1] = p->conserved.momentum[1] * inverse_mass;
+    p->v[2] = p->conserved.momentum[2] * inverse_mass;
 
 #ifdef SHADOWFAX_STEER_CELL_MOTION
-  /* To prevent stupid things like cell crossovers or generators that move
-     outside their cell, we steer the motion of the cell somewhat */
-  if (p->primitives.rho) {
     float centroid[3], d[3];
     float volume, csnd, R, vfac, fac, dnrm;
     voronoi_get_centroid(&p->cell, centroid);
@@ -449,32 +493,29 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
       } else {
         vfac = csnd / dnrm;
       }
-    } else {
-      vfac = 0.0f;
+      p->v[0] += vfac * d[0];
+      p->v[1] += vfac * d[1];
+      p->v[2] += vfac * d[2];
     }
-    vcell[0] += vfac * d[0];
-    vcell[1] += vfac * d[1];
-    vcell[2] += vfac * d[2];
-  }
 #endif
 
-#if defined(SHADOWFAX_FIX_CELLS)
-  xp->v_full[0] = 0.;
-  xp->v_full[1] = 0.;
-  xp->v_full[2] = 0.;
+  } else {
+    p->v[0] = 0.;
+    p->v[1] = 0.;
+    p->v[2] = 0.;
+  }
+#endif
 
-  p->v[0] = 0.;
-  p->v[1] = 0.;
-  p->v[2] = 0.;
-#else
-  xp->v_full[0] = vcell[0];
-  xp->v_full[1] = vcell[1];
-  xp->v_full[2] = vcell[2];
+  /* Now make sure all velocity variables are up to date. */
+  xp->v_full[0] = p->v[0];
+  xp->v_full[1] = p->v[1];
+  xp->v_full[2] = p->v[2];
 
-  p->v[0] = xp->v_full[0];
-  p->v[1] = xp->v_full[1];
-  p->v[2] = xp->v_full[2];
-#endif
+  if (p->gpart) {
+    p->gpart->v_full[0] = p->v[0];
+    p->gpart->v_full[1] = p->v[1];
+    p->gpart->v_full[2] = p->v[2];
+  }
 }
 
 /**
@@ -799,3 +840,5 @@ __attribute__((always_inline)) INLINE static float hydro_get_physical_density(
 
   return cosmo->a3_inv * p->primitives.rho;
 }
+
+#endif /* SWIFT_SHADOWSWIFT_HYDRO_H */
diff --git a/src/hydro/Shadowswift/hydro_gradients.h b/src/hydro/Shadowswift/hydro_gradients.h
index 285d889a1a6e10662a06979f69290aabd4206059..4e7a9911d8d4fc586fe7a56687dd4c4ae9ec8de2 100644
--- a/src/hydro/Shadowswift/hydro_gradients.h
+++ b/src/hydro/Shadowswift/hydro_gradients.h
@@ -86,7 +86,7 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_finalize(
  */
 __attribute__((always_inline)) INLINE static void hydro_gradients_predict(
     struct part* pi, struct part* pj, float hi, float hj, const float* dx,
-    float r, float* xij_i, float* Wi, float* Wj, float mindt) {
+    float r, float* xij_i, float* Wi, float* Wj) {
 
   float dWi[5], dWj[5];
   float xij_j[3];
@@ -132,59 +132,6 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_predict(
 
   hydro_slope_limit_face(Wi, Wj, dWi, dWj, xij_i, xij_j, r);
 
-  /* time */
-  dWi[0] -= 0.5 * mindt * (Wi[1] * pi->primitives.gradients.rho[0] +
-                           Wi[2] * pi->primitives.gradients.rho[1] +
-                           Wi[3] * pi->primitives.gradients.rho[2] +
-                           Wi[0] * (pi->primitives.gradients.v[0][0] +
-                                    pi->primitives.gradients.v[1][1] +
-                                    pi->primitives.gradients.v[2][2]));
-  dWi[1] -= 0.5 * mindt * (Wi[1] * pi->primitives.gradients.v[0][0] +
-                           Wi[2] * pi->primitives.gradients.v[0][1] +
-                           Wi[3] * pi->primitives.gradients.v[0][2] +
-                           pi->primitives.gradients.P[0] / Wi[0]);
-  dWi[2] -= 0.5 * mindt * (Wi[1] * pi->primitives.gradients.v[1][0] +
-                           Wi[2] * pi->primitives.gradients.v[1][1] +
-                           Wi[3] * pi->primitives.gradients.v[1][2] +
-                           pi->primitives.gradients.P[1] / Wi[0]);
-  dWi[3] -= 0.5 * mindt * (Wi[1] * pi->primitives.gradients.v[2][0] +
-                           Wi[2] * pi->primitives.gradients.v[2][1] +
-                           Wi[3] * pi->primitives.gradients.v[2][2] +
-                           pi->primitives.gradients.P[2] / Wi[0]);
-  dWi[4] -=
-      0.5 * mindt * (Wi[1] * pi->primitives.gradients.P[0] +
-                     Wi[2] * pi->primitives.gradients.P[1] +
-                     Wi[3] * pi->primitives.gradients.P[2] +
-                     hydro_gamma * Wi[4] * (pi->primitives.gradients.v[0][0] +
-                                            pi->primitives.gradients.v[1][1] +
-                                            pi->primitives.gradients.v[2][2]));
-
-  dWj[0] -= 0.5 * mindt * (Wj[1] * pj->primitives.gradients.rho[0] +
-                           Wj[2] * pj->primitives.gradients.rho[1] +
-                           Wj[3] * pj->primitives.gradients.rho[2] +
-                           Wj[0] * (pj->primitives.gradients.v[0][0] +
-                                    pj->primitives.gradients.v[1][1] +
-                                    pj->primitives.gradients.v[2][2]));
-  dWj[1] -= 0.5 * mindt * (Wj[1] * pj->primitives.gradients.v[0][0] +
-                           Wj[2] * pj->primitives.gradients.v[0][1] +
-                           Wj[3] * pj->primitives.gradients.v[0][2] +
-                           pj->primitives.gradients.P[0] / Wj[0]);
-  dWj[2] -= 0.5 * mindt * (Wj[1] * pj->primitives.gradients.v[1][0] +
-                           Wj[2] * pj->primitives.gradients.v[1][1] +
-                           Wj[3] * pj->primitives.gradients.v[1][2] +
-                           pj->primitives.gradients.P[1] / Wj[0]);
-  dWj[3] -= 0.5 * mindt * (Wj[1] * pj->primitives.gradients.v[2][0] +
-                           Wj[2] * pj->primitives.gradients.v[2][1] +
-                           Wj[3] * pj->primitives.gradients.v[2][2] +
-                           pj->primitives.gradients.P[2] / Wj[0]);
-  dWj[4] -=
-      0.5 * mindt * (Wj[1] * pj->primitives.gradients.P[0] +
-                     Wj[2] * pj->primitives.gradients.P[1] +
-                     Wj[3] * pj->primitives.gradients.P[2] +
-                     hydro_gamma * Wj[4] * (pj->primitives.gradients.v[0][0] +
-                                            pj->primitives.gradients.v[1][1] +
-                                            pj->primitives.gradients.v[2][2]));
-
   Wi[0] += dWi[0];
   Wi[1] += dWi[1];
   Wi[2] += dWi[2];
diff --git a/src/hydro/Shadowswift/hydro_iact.h b/src/hydro/Shadowswift/hydro_iact.h
index 9ac1debf3184c25603412867c41c62a1131345f3..eda8e3759d9e08dac8073ebed9fb36dd0c5b99f6 100644
--- a/src/hydro/Shadowswift/hydro_iact.h
+++ b/src/hydro/Shadowswift/hydro_iact.h
@@ -143,7 +143,6 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   float vmax, dvdotdx;
   float vi[3], vj[3], vij[3];
   float Wi[5], Wj[5];
-  float dti, dtj, mindt;
   float n_unit[3];
 
   A = voronoi_get_face(&pi->cell, pj->id, xij_i);
@@ -168,9 +167,6 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   Wj[3] = pj->primitives.v[2];
   Wj[4] = pj->primitives.P;
 
-  dti = pi->force.dt;
-  dtj = pj->force.dt;
-
   /* calculate the maximal signal velocity */
   vmax = 0.0f;
   if (Wi[0] > 0.) {
@@ -192,10 +188,6 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
     pj->timestepvars.vmax = fmaxf(pj->timestepvars.vmax, vmax);
   }
 
-  /* The flux will be exchanged using the smallest time step of the two
-   * particles */
-  mindt = fminf(dti, dtj);
-
   /* compute the normal vector of the interface */
   for (k = 0; k < 3; ++k) {
     n_unit[k] = -dx[k] / r;
@@ -219,13 +211,12 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   Wj[2] -= vij[1];
   Wj[3] -= vij[2];
 
-  hydro_gradients_predict(pi, pj, hi, hj, dx, r, xij_i, Wi, Wj, mindt);
+  hydro_gradients_predict(pi, pj, hi, hj, dx, r, xij_i, Wi, Wj);
 
   /* we don't need to rotate, we can use the unit vector in the Riemann problem
    * itself (see GIZMO) */
 
   if (Wi[0] < 0.0f || Wj[0] < 0.0f || Wi[4] < 0.0f || Wj[4] < 0.0f) {
-    printf("mindt: %g\n", mindt);
     printf("WL: %g %g %g %g %g\n", pi->primitives.rho, pi->primitives.v[0],
            pi->primitives.v[1], pi->primitives.v[2], pi->primitives.P);
 #ifdef USE_GRADIENTS
@@ -266,20 +257,20 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
 
   /* Update conserved variables */
   /* eqn. (16) */
-  pi->conserved.flux.mass -= mindt * A * totflux[0];
-  pi->conserved.flux.momentum[0] -= mindt * A * totflux[1];
-  pi->conserved.flux.momentum[1] -= mindt * A * totflux[2];
-  pi->conserved.flux.momentum[2] -= mindt * A * totflux[3];
-  pi->conserved.flux.energy -= mindt * A * totflux[4];
+  pi->conserved.flux.mass -= A * totflux[0];
+  pi->conserved.flux.momentum[0] -= A * totflux[1];
+  pi->conserved.flux.momentum[1] -= A * totflux[2];
+  pi->conserved.flux.momentum[2] -= A * totflux[3];
+  pi->conserved.flux.energy -= A * totflux[4];
 
 #ifndef SHADOWFAX_TOTAL_ENERGY
   float ekin = 0.5f * (pi->primitives.v[0] * pi->primitives.v[0] +
                        pi->primitives.v[1] * pi->primitives.v[1] +
                        pi->primitives.v[2] * pi->primitives.v[2]);
-  pi->conserved.flux.energy += mindt * A * totflux[1] * pi->primitives.v[0];
-  pi->conserved.flux.energy += mindt * A * totflux[2] * pi->primitives.v[1];
-  pi->conserved.flux.energy += mindt * A * totflux[3] * pi->primitives.v[2];
-  pi->conserved.flux.energy -= mindt * A * totflux[0] * ekin;
+  pi->conserved.flux.energy += A * totflux[1] * pi->primitives.v[0];
+  pi->conserved.flux.energy += A * totflux[2] * pi->primitives.v[1];
+  pi->conserved.flux.energy += A * totflux[3] * pi->primitives.v[2];
+  pi->conserved.flux.energy -= A * totflux[0] * ekin;
 #endif
 
   /* here is how it works:
@@ -295,20 +286,20 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
      ==> we update particle j if (MODE IS 1) OR (j IS INACTIVE)
   */
   if (mode == 1 || pj->force.active == 0) {
-    pj->conserved.flux.mass += mindt * A * totflux[0];
-    pj->conserved.flux.momentum[0] += mindt * A * totflux[1];
-    pj->conserved.flux.momentum[1] += mindt * A * totflux[2];
-    pj->conserved.flux.momentum[2] += mindt * A * totflux[3];
-    pj->conserved.flux.energy += mindt * A * totflux[4];
+    pj->conserved.flux.mass += A * totflux[0];
+    pj->conserved.flux.momentum[0] += A * totflux[1];
+    pj->conserved.flux.momentum[1] += A * totflux[2];
+    pj->conserved.flux.momentum[2] += A * totflux[3];
+    pj->conserved.flux.energy += A * totflux[4];
 
 #ifndef SHADOWFAX_TOTAL_ENERGY
     ekin = 0.5f * (pj->primitives.v[0] * pj->primitives.v[0] +
                    pj->primitives.v[1] * pj->primitives.v[1] +
                    pj->primitives.v[2] * pj->primitives.v[2]);
-    pj->conserved.flux.energy -= mindt * A * totflux[1] * pj->primitives.v[0];
-    pj->conserved.flux.energy -= mindt * A * totflux[2] * pj->primitives.v[1];
-    pj->conserved.flux.energy -= mindt * A * totflux[3] * pj->primitives.v[2];
-    pj->conserved.flux.energy += mindt * A * totflux[0] * ekin;
+    pj->conserved.flux.energy -= A * totflux[1] * pj->primitives.v[0];
+    pj->conserved.flux.energy -= A * totflux[2] * pj->primitives.v[1];
+    pj->conserved.flux.energy -= A * totflux[3] * pj->primitives.v[2];
+    pj->conserved.flux.energy += A * totflux[0] * ekin;
 #endif
   }
 }
diff --git a/src/hydro_properties.c b/src/hydro_properties.c
index c5448f77353e1859c1f8853394bbefbe26d0a3a9..f79fd832248fba8fbc55bd9fcec57e645be93159 100644
--- a/src/hydro_properties.c
+++ b/src/hydro_properties.c
@@ -72,6 +72,7 @@ void hydro_props_init(struct hydro_props *p,
   /* change the meaning of target_neighbours and delta_neighbours */
   p->target_neighbours = 1.0f;
   p->delta_neighbours = 0.0f;
+  p->eta_neighbours = 1.0f;
 #endif
 
   /* Maximal smoothing length */
@@ -122,7 +123,7 @@ void hydro_props_init(struct hydro_props *p,
 
   /* Compute the minimal energy (Note the temp. read is in internal units) */
   double u_min = phys_const->const_boltzmann_k / phys_const->const_proton_mass;
-  u_min *= p->initial_temperature;
+  u_min *= p->minimal_temperature;
   u_min *= hydro_one_over_gamma_minus_one;
 
   /* Correct for hydrogen mass fraction */
diff --git a/src/mesh_gravity.c b/src/mesh_gravity.c
index be24117fd7947e467c0ceca36a68e339952f7815..49e66763f7f9ef47ca79d0024fa65b9ce7803fc1 100644
--- a/src/mesh_gravity.c
+++ b/src/mesh_gravity.c
@@ -38,6 +38,8 @@
 #include "runner.h"
 #include "space.h"
 
+#ifdef HAVE_FFTW
+
 /**
  * @brief Returns 1D index of a 3D NxNxN array using row-major style.
  *
@@ -264,6 +266,8 @@ void mesh_to_gparts_CIC(struct gpart* gp, const double* pot, int N, double fac,
 #endif
 }
 
+#endif
+
 /**
  * @brief Compute the potential, including periodic correction on the mesh.
  *
@@ -532,7 +536,7 @@ void pm_mesh_struct_restore(struct pm_mesh* mesh, FILE* stream) {
 
   restart_read_blocks((void*)mesh, sizeof(struct pm_mesh), 1, stream, NULL,
                       "gravity props");
-
+#ifdef HAVE_FFTW
   const int N = mesh->N;
 
   /* Allocate the memory for the combined density and potential array */
@@ -540,7 +544,6 @@ void pm_mesh_struct_restore(struct pm_mesh* mesh, FILE* stream) {
   if (mesh->potential == NULL)
     error("Error allocating memory for the long-range gravity mesh.");
 
-#ifdef HAVE_FFTW
 #else
   error("No FFTW library found. Cannot compute periodic long-range forces.");
 #endif
diff --git a/src/partition.c b/src/partition.c
index f59187c7aea2abb8521d932770e25d544341f798..f39bcb1e2baf7916df1e369a6681435560fe9d41 100644
--- a/src/partition.c
+++ b/src/partition.c
@@ -1072,7 +1072,7 @@ static void repart_edge_parmetis(int vweights, int eweights, int timebins,
     struct task *t = &tasks[j];
 
     /* Skip un-interesting tasks. */
-    if (t->cost == 0) continue;
+    if (t->cost == 0.f) continue;
 
     /* Get the task weight based on costs. */
     double w = (double)t->cost;
diff --git a/src/queue.c b/src/queue.c
index b22313d71d733ae1a6b3419d492356f9d914f61f..3a9919163a4fb9d146c055e58859a175858c17eb 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -259,7 +259,7 @@ struct task *queue_gettask(struct queue *q, const struct task *prev,
     int k = ind;
     if (k < qcount) {
       qtid[k] = qtid[qcount];
-      int w = qtasks[qtid[k]].weight;
+      const float w = qtasks[qtid[k]].weight;
       while (k > 0 && w > qtasks[qtid[(k - 1) / 2]].weight) {
         int temp = q->tid[k];
         q->tid[k] = q->tid[(k - 1) / 2];
diff --git a/src/scheduler.c b/src/scheduler.c
index 844939ba1643379ff0ab5be4355212f80098d37d..38313251b89f9f7dd6a6e8dd5d93a7eba3894f5a 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -1185,12 +1185,14 @@ void scheduler_reweight(struct scheduler *s, int verbose) {
   /* Run through the tasks backwards and set their weights. */
   for (int k = nr_tasks - 1; k >= 0; k--) {
     struct task *t = &tasks[tid[k]];
-    t->weight = 0;
+    t->weight = 0.f;
     for (int j = 0; j < t->nr_unlock_tasks; j++)
       if (t->unlock_tasks[j]->weight > t->weight)
         t->weight = t->unlock_tasks[j]->weight;
-    float cost = 0;
+    float cost = 0.f;
+#if defined(WITH_MPI) && defined(HAVE_PARMETIS)
     int partcost = 1;
+#endif
 
     const float count_i = (t->ci != NULL) ? t->ci->count : 0.f;
     const float count_j = (t->cj != NULL) ? t->cj->count : 0.f;
@@ -1277,14 +1279,18 @@ void scheduler_reweight(struct scheduler *s, int verbose) {
         cost = wscale * count_i + wscale * gcount_i;
         break;
       case task_type_send:
+#if defined(WITH_MPI) && defined(HAVE_PARMETIS)
         partcost = 0;
+#endif
         if (count_i < 1e5)
           cost = 10.f * (wscale * count_i) * count_i;
         else
           cost = 2e9;
         break;
       case task_type_recv:
+#if defined(WITH_MPI) && defined(HAVE_PARMETIS)
         partcost = 0;
+#endif
         if (count_i < 1e5)
           cost = 5.f * (wscale * count_i) * count_i;
         else
@@ -1295,12 +1301,10 @@ void scheduler_reweight(struct scheduler *s, int verbose) {
         break;
     }
 
-/* Note if the cost is > 1e9 we cap it as we don't care. That's large
- * compared to other possible costs.  */
-#if defined(WITH_MPI) && defined(HAVE_METIS)
-    if (partcost) t->cost = (cost < 1e9) ? cost : 1e9;
+#if defined(WITH_MPI) && defined(HAVE_PARMETIS)
+    if (partcost) t->cost = cost;
 #endif
-    t->weight += (cost < 1e9) ? cost : 1e9;
+    t->weight += cost;
   }
 
   if (verbose)
diff --git a/src/single_io.c b/src/single_io.c
index be33bba4d7c95454892b02836f073c085e07b2ea..a0f02878b52c89beca94d15c09ef7d456ce0a4eb 100644
--- a/src/single_io.c
+++ b/src/single_io.c
@@ -347,8 +347,8 @@ void read_ic_single(const char* fileName,
   /* GADGET has only cubic boxes (in cosmological mode) */
   double boxSize[3] = {0.0, -1.0, -1.0};
   /* GADGET has 6 particle types. We only keep the type 0 & 1 for now...*/
-  int numParticles[swift_type_count] = {0};
-  int numParticles_highWord[swift_type_count] = {0};
+  long long numParticles[swift_type_count] = {0};
+  long long numParticles_highWord[swift_type_count] = {0};
   size_t N[swift_type_count] = {0};
   int dimension = 3; /* Assume 3D if nothing is specified */
   size_t Ndm = 0;
@@ -388,13 +388,12 @@ void read_ic_single(const char* fileName,
   io_read_attribute(h_grp, "Flag_Entropy_ICs", INT, flag_entropy_temp);
   *flag_entropy = flag_entropy_temp[0];
   io_read_attribute(h_grp, "BoxSize", DOUBLE, boxSize);
-  io_read_attribute(h_grp, "NumPart_Total", UINT, numParticles);
-  io_read_attribute(h_grp, "NumPart_Total_HighWord", UINT,
+  io_read_attribute(h_grp, "NumPart_Total", LONGLONG, numParticles);
+  io_read_attribute(h_grp, "NumPart_Total_HighWord", LONGLONG,
                     numParticles_highWord);
 
   for (int ptype = 0; ptype < swift_type_count; ++ptype)
-    N[ptype] = ((long long)numParticles[ptype]) +
-               ((long long)numParticles_highWord[ptype] << 32);
+    N[ptype] = (numParticles[ptype]) + (numParticles_highWord[ptype] << 32);
 
   /* Get the box size if not cubic */
   dim[0] = boxSize[0];
diff --git a/src/task.h b/src/task.h
index a345d4a29522a709afa5e3abd2a163f7550fb7ed..eb352f272e2f3599b57d8c8b4559fbb6236442e4 100644
--- a/src/task.h
+++ b/src/task.h
@@ -136,11 +136,11 @@ struct task {
   int rank;
 
   /*! Weight of the task */
-  int weight;
+  float weight;
 
 #if defined(WITH_MPI) && defined(HAVE_PARMETIS)
   /*! Individual cost estimate for this task. */
-  int cost;
+  float cost;
 #endif
 
   /*! Number of tasks unlocked by this one */
diff --git a/src/units.c b/src/units.c
index 6152d7f42f9a409bea9d057862c04d0ae9fb6a75..04e74bc4d7040ed1bde73184b125eec5d8a7fe97 100644
--- a/src/units.c
+++ b/src/units.c
@@ -50,6 +50,20 @@ void units_init_cgs(struct unit_system* us) {
   us->UnitTemperature_in_cgs = 1.;
 }
 
+/**
+ * @brief Initialises the unit_system structure with SI system
+ *
+ * @param us The unit_system to initialize
+ */
+void units_init_si(struct unit_system* us) {
+
+  us->UnitMass_in_cgs = 1000.;
+  us->UnitLength_in_cgs = 100.;
+  us->UnitTime_in_cgs = 1.;
+  us->UnitCurrent_in_cgs = 1.;
+  us->UnitTemperature_in_cgs = 1.;
+}
+
 /**
  * @brief Initialise the unit_system with values for the base units.
  *
diff --git a/src/units.h b/src/units.h
index da2c209815b07d1d5597a598ee4a61f3132e39db..08b738c5303db8b40dfbe51799d67da8df3936ce 100644
--- a/src/units.h
+++ b/src/units.h
@@ -96,6 +96,7 @@ enum unit_conversion_factor {
 };
 
 void units_init_cgs(struct unit_system*);
+void units_init_si(struct unit_system*);
 void units_init(struct unit_system* us, double U_M_in_cgs, double U_L_in_cgs,
                 double U_t_in_cgs, double U_C_in_cgs, double U_T_in_cgs);
 void units_init_from_params(struct unit_system*, struct swift_params*,
diff --git a/tests/test27cells.c b/tests/test27cells.c
index ada1b782cfff3866bf26937391007947e9c9a175..f62c169486250ba940c22f21ba1556cca4060c1a 100644
--- a/tests/test27cells.c
+++ b/tests/test27cells.c
@@ -217,8 +217,20 @@ void clean_up(struct cell *ci) {
  * @brief Initializes all particles field to be ready for a density calculation
  */
 void zero_particle_fields(struct cell *c) {
+#ifdef SHADOWFAX_SPH
+  struct hydro_space hs;
+  hs.anchor[0] = 0.;
+  hs.anchor[1] = 0.;
+  hs.anchor[2] = 0.;
+  hs.side[0] = 1.;
+  hs.side[1] = 1.;
+  hs.side[2] = 1.;
+  struct hydro_space *hspointer = &hs;
+#else
+  struct hydro_space *hspointer = NULL;
+#endif
   for (int pid = 0; pid < c->count; pid++) {
-    hydro_init_part(&c->parts[pid], NULL);
+    hydro_init_part(&c->parts[pid], hspointer);
   }
 }
 
diff --git a/tests/testPotentialPair.c b/tests/testPotentialPair.c
index 526a7661eaf67a63ca5ce3497c5ff366ffcbed8e..0ca3d0ca9aa2adfc5d6237a668ee93c7c4daba63 100644
--- a/tests/testPotentialPair.c
+++ b/tests/testPotentialPair.c
@@ -95,11 +95,6 @@ int main(int argc, char *argv[]) {
   unsigned long long cpufreq = 0;
   clocks_set_cpufreq(cpufreq);
 
-/* Choke on FPEs */
-#ifdef HAVE_FE_ENABLE_EXCEPT
-  feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
-#endif
-
   /* Initialise a few things to get us going */
 
   /* Non-truncated forces first */