diff --git a/plotting.py b/plotting.py
index f13a461a0030b66d1b9d20544fbd61facbfdf636..0ed8aec32c2381060a027d987489d1b148937153 100644
--- a/plotting.py
+++ b/plotting.py
@@ -12,6 +12,10 @@ import numpy as np
 from .keras_visualize_activations.read_activations import get_activations
 from .tfhelpers import get_grad_function, max_activation_wrt_input, create_random_event
 
+import logging
+logger = logging.getLogger(__name__)
+logger.addHandler(logging.NullHandler())
+
 """
 Some further plotting functions
 """
@@ -24,12 +28,12 @@ def plot_NN_vs_var_1D(plotname, means, scorefun, var_index, var_range, var_label
     "Plot the NN output vs one variable with the other variables set to the given mean values"
 
     # example: vary var1
-    print("Creating varied events (1d)")
+    logger.info("Creating varied events (1d)")
     sequence = np.arange(*var_range)
     events = np.tile(means, len(sequence)).reshape(-1, len(means))
     events[:,var_index] = sequence
 
-    print("Predicting scores")
+    logger.info("Predicting scores")
     scores = scorefun(events)
 
     fig, ax = plt.subplots()
@@ -43,20 +47,23 @@ def plot_NN_vs_var_1D(plotname, means, scorefun, var_index, var_range, var_label
 
 def plot_NN_vs_var_2D(plotname, means,
                       scorefun,
-                      var1_index, var1_range,
-                      var2_index, var2_range,
-                      var1_label=None,
-                      var2_label=None,
+                      varx_index,
+                      vary_index,
+                      nbinsx, xmin, xmax,
+                      nbinsy, ymin, ymax,
+                      varx_label=None,
+                      vary_label=None,
                       logscale=False,
                       ncontours=20,
                       only_pixels=False,
                       black_contourlines=False,
                       cmap="inferno"):
 
-    print("Creating varied events (2d)")
-    # example: vary var1 vs var2
-    sequence1 = np.arange(*var1_range)
-    sequence2 = np.arange(*var2_range)
+    logger.info("Creating varied events (2d)")
+
+    sequence1 = np.linspace(xmin, xmax, nbinsx)
+    sequence2 = np.linspace(ymin, ymax, nbinsy)
+
     # the following is a 2d array of events (so effectively 3D)
     events = np.tile(means, len(sequence1)*len(sequence2)).reshape(len(sequence2), len(sequence1), -1)
 
@@ -64,13 +71,13 @@ def plot_NN_vs_var_2D(plotname, means,
     # (probably there is a more clever way, but sufficient here)
     for i, y in enumerate(sequence2):
         for j, x in enumerate(sequence1):
-            events[i][j][var1_index] = x
-            events[i][j][var2_index] = y
+            events[i][j][varx_index] = x
+            events[i][j][vary_index] = y
 
     # convert back into 1d array
     events = events.reshape(-1, len(means))
 
-    print("Predicting scores")
+    logger.info("Predicting scores")
     scores = scorefun(events)
 
     # convert scores into 2d array
@@ -84,7 +91,7 @@ def plot_NN_vs_var_2D(plotname, means,
     if logscale:
         if zmin <= 0:
             zmin = 1e-5
-            print("Setting zmin to {}".format(zmin))
+            logger.info("Setting zmin to {}".format(zmin))
         lvls = np.logspace(math.log10(zmin), math.log10(zmax), ncontours)
         if only_pixels:
             pcm = ax.pcolormesh(sequence1, sequence2, scores, norm=matplotlib.colors.LogNorm(vmin=zmin, vmax=zmax), cmap=cmap, linewidth=0, rasterized=True)
@@ -104,10 +111,10 @@ def plot_NN_vs_var_2D(plotname, means,
         cbar = fig.colorbar(pcm, ax=ax, extend='max')
 
     cbar.set_label("NN output")
-    if var1_label is not None:
-        ax.set_xlabel(var1_label)
-    if var2_label is not None:
-        ax.set_ylabel(var2_label)
+    if varx_label is not None:
+        ax.set_xlabel(varx_label)
+    if vary_label is not None:
+        ax.set_ylabel(vary_label)
     fig.savefig(plotname)
     plt.close(fig)
 
@@ -166,15 +173,15 @@ def plot_NN_vs_var_2D_all(plotname, model, means,
     global_min = min([np.min(ar_layer) for ar_layer in acts[:-1]])
     global_max = max([np.max(ar_layer) for ar_layer in acts[:-1]])
 
-    print("global_min: {}".format(global_min))
-    print("global_max: {}".format(global_max))
+    logger.info("global_min: {}".format(global_min))
+    logger.info("global_max: {}".format(global_max))
 
     output_min_default = 0
     output_max_default = 1
 
     if global_min <= 0 and logz:
         global_min = log_default_ymin
-        print("Changing global_min to {}".format(log_default_ymin))
+        logger.info("Changing global_min to {}".format(log_default_ymin))
 
     ims = []
     for layer in range(layers):
@@ -231,10 +238,6 @@ def plot_hist_2D(plotname, xedges, yedges, hist, varx_label=None, vary_label=Non
 
 def plot_hist_2D_events(plotname, valsx, valsy, nbinsx, xmin, xmax, nbinsy, ymin, ymax, varx_label=None, vary_label=None, log=False):
 
-
-    print(valsx)
-    print(valsy)
-
     xedges = np.linspace(xmin, xmax, nbinsx)
     yedges = np.linspace(ymin, ymax, nbinsy)
 
@@ -312,6 +315,7 @@ if __name__ == "__main__":
     import logging
     logging.basicConfig()
     logging.getLogger("tfhelpers").setLevel(logging.DEBUG)
+    logging.getLogger(__name__).setLevel(logging.DEBUG)
 
     from .tfhelpers import get_single_neuron_function, get_max_activation_events
 
@@ -319,7 +323,7 @@ if __name__ == "__main__":
     # meme.setOptions(overrideCache="/scratch-local/nhartmann/meme_cache")
 
     if len(sys.argv) < 2:
-        c = ClassificationProject(os.path.expanduser("~/p/scripts/keras/008-allhighlevel/all_highlevel_985"))
+        c = ClassificationProject("/project/etp/nhartmann/p/keras/021-check-low-vs-high-fewvar/all_high")
     else:
         c = ClassificationProject(sys.argv[1])
 
@@ -345,9 +349,11 @@ if __name__ == "__main__":
 
         plot_NN_vs_var_2D("mt_vs_met.pdf", means=mean_signal,
                           scorefun=c.evaluate,
-                          var1_index=c.branches.index("met"), var1_range=(0, 1000, 10),
-                          var2_index=c.branches.index("mt"), var2_range=(0, 500, 10),
-                          var1_label="met [GeV]", var2_label="mt [GeV]")
+                          varx_index=c.branches.index("met"),
+                          vary_index=c.branches.index("mt"),
+                          nbinsx=100, xmin=0, xmax=1000,
+                          nbinsy=100, ymin=0, ymax=500,
+                          varx_label="met [GeV]", vary_label="mt [GeV]")
 
 
         plot_NN_vs_var_2D_all("mt_vs_met_all.pdf", means=mean_signal,
@@ -358,9 +364,11 @@ if __name__ == "__main__":
 
         plot_NN_vs_var_2D("mt_vs_met_crosscheck.pdf", means=mean_signal,
                           scorefun=get_single_neuron_function(c.model, layer=3, neuron=0, scaler=c.scaler),
-                          var1_index=c.branches.index("met"), var1_range=(0, 1000, 10),
-                          var2_index=c.branches.index("mt"), var2_range=(0, 500, 10),
-                          var1_label="met [GeV]", var2_label="mt [GeV]")
+                          varx_index=c.branches.index("met"),
+                          vary_index=c.branches.index("mt"),
+                          nbinsx=100, xmin=0, xmax=1000,
+                          nbinsy=100, ymin=0, ymax=500,
+                          varx_label="met [GeV]", vary_label="mt [GeV]")
 
 
     def test_max_act():
@@ -426,6 +434,29 @@ if __name__ == "__main__":
             log=True,
         )
 
+        plot_hist_2D_events(
+            "mt_vs_met_signal.pdf",
+            utrf_x_test[c.y_test==1][:,c.branches.index("met")],
+            utrf_x_test[c.y_test==1][:,c.branches.index("mt")],
+            100, 0, 1000,
+            100, 0, 500,
+            varx_label="met [GeV]",
+            vary_label="mt [GeV]",
+            log=True,
+        )
+
+        plot_hist_2D_events(
+            "mt_vs_met_backgound.pdf",
+            utrf_x_test[c.y_test==0][:,c.branches.index("met")],
+            utrf_x_test[c.y_test==0][:,c.branches.index("mt")],
+            100, 0, 1000,
+            100, 0, 500,
+            varx_label="met [GeV]",
+            vary_label="mt [GeV]",
+            log=True,
+        )
+
+
         # plot_hist_2D_events(
         #     "apl_vs_output_actmax.pdf",
         #     events[:,c.branches.index("LepAplanarity")],
diff --git a/scripts/plot_single_neuron.py b/scripts/plot_single_neuron.py
new file mode 100755
index 0000000000000000000000000000000000000000..7e255b95bd11ff60254469a35c66785ba690732e
--- /dev/null
+++ b/scripts/plot_single_neuron.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+
+import sys
+import argparse
+
+import numpy as np
+
+from KerasROOTClassification import ClassificationProject
+from KerasROOTClassification.plotting import get_mean_event, plot_NN_vs_var_2D
+from KerasROOTClassification.tfhelpers import get_single_neuron_function
+
+parser = argparse.ArgumentParser(description='Create various 2D plots for a single neuron')
+parser.add_argument("project_dir")
+parser.add_argument("output_filename")
+parser.add_argument("varx")
+parser.add_argument("vary")
+parser.add_argument("-m", "--mode", choices=["mean_sig", "mean_bkg"], default="mean_sig")
+parser.add_argument("-l", "--layer", type=int, help="Layer index (takes last layer by default)")
+parser.add_argument("-n", "--neuron", type=int, default=0, help="Neuron index (takes first neuron by default)")
+parser.add_argument("--log", action="store_true", help="Plot in color in log scale")
+parser.add_argument("--contour", action="store_true", help="Interpolate with contours")
+parser.add_argument("-b", "--nbins", default=20, type=int, help="Number of bins in x and y direction")
+parser.add_argument("-x", "--xrange", type=float, nargs="+", help="xrange (low, high)")
+parser.add_argument("-y", "--yrange", type=float, nargs="+", help="yrange (low, high)")
+args = parser.parse_args()
+
+c = ClassificationProject(args.project_dir)
+
+layer = args.layer
+neuron = args.neuron
+
+if layer is None:
+    layer = c.layers
+
+varx_index = c.branches.index(args.varx)
+vary_index = c.branches.index(args.vary)
+
+x_test = c.x_test
+
+percentilesx = np.percentile(x_test[:,varx_index], [1,99])
+percentilesy = np.percentile(x_test[:,vary_index], [1,99])
+
+if args.xrange is not None:
+    if len(args.xrange) < 3:
+        args.xrange.append(args.nbins)
+    varx_range = args.xrange
+else:
+    varx_range = (percentilesx[0], percentilesx[1], args.nbins)
+
+if args.yrange is not None:
+    if len(args.yrange) < 3:
+        args.yrange.append(args.nbins)
+    vary_range = args.yrange
+else:
+    vary_range = (percentilesy[0], percentilesy[1], args.nbins)
+
+if args.mode == "mean_sig":
+    means = get_mean_event(c.x_test, c.y_test, 1)
+elif args.mode == "mean_bkg":
+    means = get_mean_event(c.x_test, c.y_test, 0)
+
+plot_NN_vs_var_2D(args.output_filename,
+                  means=means,
+                  varx_index=varx_index,
+                  vary_index=vary_index,
+                  scorefun=get_single_neuron_function(c.model, layer, neuron, scaler=c.scaler),
+                  xmin=varx_range[0], xmax=varx_range[1], nbinsx=varx_range[2],
+                  ymin=vary_range[0], ymax=vary_range[1], nbinsy=vary_range[2],
+                  varx_label=args.varx, vary_label=args.vary,
+                  logscale=args.log, only_pixels=(not args.contour))