diff --git a/matlab/spins_QSP_csv.m b/matlab/spins_QSP_csv.m
index 63f60d07bd5011503a0587b9d266f0edfb3e7bd9..d544e59fa3bae91a8c6c2480384a0ae9f6cfae0b 100644
--- a/matlab/spins_QSP_csv.m
+++ b/matlab/spins_QSP_csv.m
@@ -1,15 +1,19 @@
-function [T1_max, T1_min, S1_max, S1_min, pdfCount] = spins_QSP_reader(filename)
-  % Reads in the csv file and interprets it in the correct way for the user.
-  %
-  % Input: Filename (string) name of csv file.
-  %
-  % Output: Returns the max/min values for T1 and S1 (as specified in
-  % spins.conf) and the (normalized) pdfCount histogram.
+function [T1_max, T1_min, S1_max, S1_min, pdfCount] = spins_QSP_csv(filename)
+  %% Reads in the csv file and interprets it in the correct way for the user.
+  %%
+  %% Input:
+  %%    Filename (string): name of csv file.
+  %%
+  %% Output:
+  %%    T1_max (float): upper limit of the maximum-valued bin of T1 tracer
+  %%    T1_min (float): lower limit of the minimum-valued bin of T1 tracer
+  %%    S1_max (float): upper limit of the maximum-valued bin of S1 tracer
+  %%    S1_min (float): lower limit of the minimum-valued bin of S1 tracer
   A = importdata(filename);
   T1_max = A(1, 1);
   T1_min = A(1, 2);
   S1_max = A(1, 3);
   S1_min = A(1, 4);
   pdfCount = A(2:end, :);
-  pdfCount /= sum(sum(pdfCount));
+  pdfCount = pdfCount / sum(sum(pdfCount));
 end
diff --git a/src/Science.hpp b/src/Science.hpp
index fb54033a5ee0319deec510c765a344621a100317..89d4c884a0dc956dabc65d9630cf030f65cd980a 100644
--- a/src/Science.hpp
+++ b/src/Science.hpp
@@ -258,7 +258,9 @@ void QSPCount(const TArrayn::DTArray &t, const TArrayn::DTArray &u,
               const char T1_name, const char S1_name, const int NS,
               const int NT, double T1_max, double S1_max, double T1_min,
               double S1_min, const int Nx, const int Ny, const int Nz,
-              string filename, const int plotnum);
+              string filename, const int plotnum, bool mapped,
+              TArrayn::DTArray *xgrid, TArrayn::DTArray *ygrid,
+              TArrayn::DTArray *zgrid);
 
 // Equation of state for seawater, polynomial fit from
 // Brydon, Sun, Bleck (1999) (JGR)
diff --git a/src/Science/QSPCount.cpp b/src/Science/QSPCount.cpp
index c2d2df524437e0fd2bea3d8485cfae37a9cfcc02..e2f73e92bb97613f1a849e3312a7bc6e926bcded 100644
--- a/src/Science/QSPCount.cpp
+++ b/src/Science/QSPCount.cpp
@@ -15,6 +15,49 @@
 using namespace Transformer;
 using namespace blitz;
 
+class QSPVector {
+private:
+  double *data;
+  int length;
+  int rows;
+  int cols;
+
+public:
+  explicit QSPVector(int length)
+      : data((double *)calloc(length, sizeof(double))), length(length), rows(0),
+        cols(0) {
+    if (!data) {
+      std::cout << "Error! Data could not be initialized.\n";
+    }
+  }
+  QSPVector(int Nx, int Ny)
+      : data((double *)calloc(Nx * Ny, sizeof(double))), length(Nx * Ny),
+        rows(Nx), cols(Ny) {
+    if (!data) {
+      std::cout << "Error! Data could not be initialized.\n";
+    }
+  }
+  double *raw() const { return data; }
+  int Length() const { return length; }
+  int Rows() const { return rows; }
+  int Cols() const { return cols; }
+  double operator[](int i) const {
+    assert(i >= 0 && i < length);
+    return data[i];
+  }
+  double operator()(int row, int col) const {
+    assert(row >= 0 && row < rows);
+    assert(col >= 0 && col < cols);
+    return data[(row * cols) + col];
+  }
+  double &operator()(int row, int col) {
+    assert(row >= 0 && row < rows);
+    assert(col >= 0 && col < cols);
+    return data[(row * cols) + col];
+  }
+  ~QSPVector() { free(data); }
+};
+
 int index(int row, int col, int rows, int cols) {
   assert(row >= 0 && row < rows);
   assert(col >= 0 && col < cols);
@@ -26,7 +69,9 @@ void QSPCount(const TArrayn::DTArray &t, const TArrayn::DTArray &u,
               const char T1_name, const char S1_name, const int NS,
               const int NT, double T1_max, double S1_max, double T1_min,
               double S1_min, const int Nx, const int Ny, const int Nz,
-              string filename, const int plotnum) {
+              string filename, const int plotnum, bool mapped,
+              TArrayn::DTArray *xgrid, TArrayn::DTArray *ygrid,
+              TArrayn::DTArray *zgrid) {
 
   int local_rank;
   MPI_Comm_rank(MPI_COMM_WORLD, &local_rank);
@@ -175,10 +220,37 @@ void QSPCount(const TArrayn::DTArray &t, const TArrayn::DTArray &u,
   double hS_inv = 1 / hS;
   double hT_inv = 1 / hT;
 
-  int *local_hist = (int *)calloc(NS * NT, sizeof(int));
-  if (!local_hist) {
-    std::cout << "Bad memory allocation. Exiting QSPCount" << std::endl;
-    return;
+  QSPVector local_hist(NS, NT);
+  QSPVector global_z_max(Nx, Ny);
+  QSPVector global_z_min(Nx, Ny);
+  // Find the range of Lz values per 2D-slice
+  if (mapped) {
+    QSPVector local_z_max(Nx, Ny);
+    QSPVector local_z_min(Nx, Ny);
+    //  We are slicing as if we are doing zgrid[i, j, :]
+    for (int ii = i_low; ii <= i_high; ii++) {
+      for (int jj = j_low; jj <= j_high; jj++) {
+        // min is set to the highest possible value so it always gets changed
+        double tmp_z_min = std::numeric_limits<double>::max();
+        // max is set to the lowest possible value so it always gets changed
+        double tmp_z_max = -tmp_z_min;
+        double tmp;
+        for (int kk = k_low; kk <= k_high; kk++) {
+          tmp = (*zgrid)(ii, jj, kk);
+          if (tmp > tmp_z_max) {
+            tmp_z_max = tmp;
+          } else if (tmp < tmp_z_min) {
+            tmp_z_min = tmp;
+          }
+        }
+        local_z_max(ii, jj) = tmp_z_max;
+        local_z_min(ii, jj) = tmp_z_min;
+      }
+    }
+    MPI_Allreduce(local_z_min.raw(), global_z_min.raw(), Nx * Ny, MPI_DOUBLE,
+                  MPI_MIN, MPI_COMM_WORLD);
+    MPI_Allreduce(local_z_max.raw(), global_z_max.raw(), Nx * Ny, MPI_DOUBLE,
+                  MPI_MAX, MPI_COMM_WORLD);
   }
 
   // Main loop for QSP
@@ -242,23 +314,51 @@ void QSPCount(const TArrayn::DTArray &t, const TArrayn::DTArray &u,
         } else if (idxS >= NS) {
           idxS = 0;
         }
-        local_hist[index(idxS, idxT, NS, NT)] += 1;
+
+        double volume_weight;
+        if (mapped) {
+          // Calculate the Lz range
+          double Lzmax_now = global_z_max(i, j);
+          double Lzmin_now = global_z_min(i, j);
+
+          // Calculate the arc length
+          double arc, z_high, z_low, cos_high, cos_low;
+          if (k > 0 && k < Nz - 1) {
+            z_high = (double)(k + 1);
+            z_low = (double)(k - 1);
+          } else if (k == 0) {
+            z_high = (double)(k + 1);
+            z_low = (double)(k);
+          } else if (k == Nz - 1) {
+            z_high = (double)(k);
+            z_low = (double)(k - 1);
+          } else { // Failure
+            std::cout << "k was out of bounds somehow. Failing...\n";
+            return;
+          }
+          cos_high = std::cos(M_PI * z_high / (double)Nz);
+          cos_low = std::cos(M_PI * z_low / (double)Nz);
+          arc = 0.5 * (cos_low - cos_high);
+
+          // Calculate the volume weight
+          volume_weight = arc * (Lzmax_now - Lzmin_now);
+        } else {
+          volume_weight = 1.0;
+        }
+
+        // local_hist[index(idxS, idxT, NS, NT)] += volume_weight;
+        local_hist(idxS, idxT) += volume_weight;
       }
     }
   }
 
   MPI_Barrier(MPI_COMM_WORLD); // Wait for everyone to finish
   if (local_rank == 0) {
-    int *glob_hist = (int *)calloc(NS * NT, sizeof(int));
-    if (!glob_hist) {
-      std::cout << "Bad memory allocation. Exiting QSPCount" << std::endl;
-      free(local_hist);
-      return;
-    }
-    MPI_Reduce(local_hist, glob_hist, // send and receive buffers
-               NS * NT, MPI_INT,      // count and datatype
-               MPI_SUM, 0,            // Reduction operator and root process #
-               MPI_COMM_WORLD);       // Communicator
+    QSPVector glob_hist(NS, NT);
+    MPI_Reduce(local_hist.raw(), glob_hist.raw(), // send and receive buffers
+               NS * NT, MPI_DOUBLE,               // count and datatype
+               MPI_SUM, 0,      // Reduction operator and root process #
+               MPI_COMM_WORLD); // Communicator
     filename = filename + "." + boost::lexical_cast<string>(plotnum) + ".csv";
     std::fstream outfile;
     outfile.open(filename.c_str(), std::ios_base::out);
@@ -276,12 +376,10 @@ void QSPCount(const TArrayn::DTArray &t, const TArrayn::DTArray &u,
         outfile << std::endl;
       }
     }
-    free(glob_hist);
   } else {
-    MPI_Reduce(local_hist, NULL, // send and receive buffers
-               NS * NT, MPI_INT, // count and datatype
-               MPI_SUM, 0,       // Reduction operator and root process #
-               MPI_COMM_WORLD);  // Communicator
+    MPI_Reduce(local_hist.raw(), NULL, // send and receive buffers
+               NS * NT, MPI_DOUBLE,    // count and datatype
+               MPI_SUM, 0,             // Reduction operator and root process #
+               MPI_COMM_WORLD);        // Communicator
   }
-  free(local_hist);
 }
diff --git a/src/cases/derivatives/derivatives.cpp b/src/cases/derivatives/derivatives.cpp
index 99b158abab73d374d9a00df52328ea5a1cbe9dcd..e4a962af4207f110fa56fa18f339170dd57869c3 100644
--- a/src/cases/derivatives/derivatives.cpp
+++ b/src/cases/derivatives/derivatives.cpp
@@ -10,6 +10,7 @@
 
 // Defines limits of intrinsic types. Used as default values for
 // T1_max, T1_min, S1_max and/orS1_min
+#include <cassert>
 #include <limits>
 
 // Tensor variables for indexing
@@ -38,6 +39,7 @@ double T1_max, S1_max, T1_min, S1_min;
 char T1_name, S1_name;
 int NT, NS;
 string QSP_filename;
+bool use_salinity;
 
 // physical parameters
 double visco;                       // viscosity (m^2/s)
@@ -76,6 +78,7 @@ class userControl : public BaseCase {
         DTArray *temp1, *temp2, *temp3;   // arrays for vortex stretching / enstrophy production
         DTArray *temp4; // array for storing temporary array for baroclinic vorticity
         DTArray *A11, *A12, *A13, *A22, *A23, *A33; //Arrays for components of S^2+Omega^2
+        DTArray *xgrid, *ygrid, *zgrid;   // Arrays for storing grid data
 
         /* Size of domain */
         double length_x() const { return Lx; }
@@ -129,10 +132,27 @@ class userControl : public BaseCase {
             split(deriv_filenames.c_str(), ' ', fields);    // populate that vector
             if ( do_vort_stretch or do_enst_stretch or do_Q or do_R or
                  do_Q_and_R or do_lambda2 or do_hist ) {
+
                 temp1 = alloc_array(Nx,Ny,Nz);
                 temp2 = alloc_array(Nx,Ny,Nz);
-                if ( do_enst_stretch )
-                    temp3 = alloc_array(Nx,Ny,Nz);
+
+                // If user asks to grab the grids, we allocate arrays to store
+                // them in memory
+                if (mapped) {
+                  xgrid = alloc_array(Nx, Ny, Nz);
+                  if (Ny > 1) {
+                    ygrid = alloc_array(Nx, Ny, Nz);
+                  }
+                  zgrid = alloc_array(Nx, Ny, Nz);
+                } else {
+                  // If user doesn't want to grab grids, we make sure not to
+                  // allocate arrays for them and to set the pointers to NULL.
+                  xgrid = NULL;
+                  ygrid = NULL;
+                  zgrid = NULL;
+                }
+
+                if ( do_enst_stretch ) temp3 = alloc_array(Nx,Ny,Nz);
             }
 
             if ( do_barvor ) {
@@ -409,18 +429,34 @@ class userControl : public BaseCase {
                 // Compute QSP data. The code promises to not mutate the arrays,
                 // nor to make deep copies of them
                 if ( do_hist ){
-                    // Read in T to temp1 if required.
-                    if (T1_name == 't' || S1_name == 't' || T1_name == 'T' ||
+
+                    if (use_salinity) {
+                      init_tracer_restart("s", *temp1);
+                    } else if (T1_name == 't' || S1_name == 't' || T1_name == 'T' ||
                         S1_name == 'T') {
                         init_tracer_restart("t", *temp1);
                     }
-                    QSPCount(*temp1, u, v, w, T1_name, S1_name, NS, NT,
-                             T1_max, S1_max, T1_min, S1_min,
-                             Nx, Ny, Nz, QSP_filename, plotnum);
+
+                    // If user asked to grab the grids, we populate the grids
+                    // with the correct data from disk
+                    if (mapped) {
+                      do_mapping(*xgrid, *ygrid, *zgrid);
+                    } else {
+                      // Make sure that if the user didn't want us to grab the
+                      // grids then we haven't allocated data to store them!
+                      assert(xgrid == NULL);
+                      assert(ygrid == NULL);
+                      assert(zgrid == NULL);
+                    }
+
+                    QSPCount(*temp1, u, v, w, T1_name, S1_name, NS, NT, T1_max,
+                             S1_max, T1_min, S1_min, Nx, Ny, Nz, QSP_filename,
+                             plotnum, mapped, xgrid, ygrid, zgrid);
                     if (master()) {
                       fprintf(stdout, "Completed the write for QSP.%d\n", plotnum);
                     }
                 }
+
             }
         }
 
@@ -500,6 +536,7 @@ int main(int argc, char ** argv) {
     add_option("T1_min",&T1_min,std::numeric_limits<double>::min(), "Minimum explicit bin for T1 in QSP.");
     add_option("S1_max",&S1_max,std::numeric_limits<double>::max(), "Maximum explicit bin for S1 in QSP.");
     add_option("S1_min",&S1_min,std::numeric_limits<double>::min(), "Minimum explicit bin for S1 in QSP.");
+    add_option("QSP_salinity",&use_salinity, false, "Should salinity be read in from filename s?.");
     add_option("QSP_filename",&QSP_filename,"QSP_default", "Filename to save data to. Don't include file extension.");
     add_option("NS",&NS,10,"Number of bins for tracer S");
     add_option("NT",&NT,10,"Number of bins for tracer T");