diff --git a/math/vecops/CMakeLists.txt b/math/vecops/CMakeLists.txt
index 70d3b466a45404f50a112ef9a03808e6734ff694..d7ebf17079aac724f68c5c4ab981b017c1c2c878 100644
--- a/math/vecops/CMakeLists.txt
+++ b/math/vecops/CMakeLists.txt
@@ -31,6 +31,7 @@ endif()
 
 if(MSVC)
   target_compile_options(ROOTVecOps PRIVATE -O2 /fp:fast)
+  target_compile_definitions(ROOTVecOps PRIVATE _USE_MATH_DEFINES)
 else()
   target_compile_options(ROOTVecOps PRIVATE -O3 -ffast-math)
 endif()
diff --git a/math/vecops/inc/ROOT/RVec.hxx b/math/vecops/inc/ROOT/RVec.hxx
index a2d9663c9da1f12c83b8cd2cf788610f8617c4cf..0bcdf8a37a5418a505e2df0df91ef36fbdd62999 100644
--- a/math/vecops/inc/ROOT/RVec.hxx
+++ b/math/vecops/inc/ROOT/RVec.hxx
@@ -26,7 +26,6 @@
 #include <ROOT/TypeTraits.hxx>
 
 #include <algorithm>
-#define _USE_MATH_DEFINES // for M_PI on windows in cmath
 #include <cmath>
 #include <numeric> // for inner_product
 #include <sstream>
@@ -1882,6 +1881,4 @@ using ROOT::VecOps::RVec;
 
 } // namespace ROOT
 
-#undef _USE_MATH_DEFINES // for M_PI on windows in cmath
-
 #endif // ROOT_TVEC
diff --git a/tutorials/dataframe/df102_NanoAODDimuonAnalysis.py b/tutorials/dataframe/df102_NanoAODDimuonAnalysis.py
new file mode 100644
index 0000000000000000000000000000000000000000..836b834edffc5747b4679773abe2c6bb3cfa76f2
--- /dev/null
+++ b/tutorials/dataframe/df102_NanoAODDimuonAnalysis.py
@@ -0,0 +1,72 @@
+## \file
+## \ingroup tutorial_dataframe
+## \notebook -draw
+## This tutorial illustrates how NanoAOD files can be processed with ROOT
+## dataframes. The NanoAOD-like input files are filled with 66 mio. events
+## from CMS OpenData containing muon candidates part of 2012 dataset
+## ([DOI: 10.7483/OPENDATA.CMS.YLIC.86ZZ](http://opendata.cern.ch/record/6004)
+## and [DOI: 10.7483/OPENDATA.CMS.M5AD.Y3V3](http://opendata.cern.ch/record/6030)).
+## The macro matches muon pairs and produces an histogram of the dimuon mass
+## spectrum showing resonances up to the Z mass.
+## Note that the bump at 30 GeV is not a resonance but a trigger effect.
+##
+## Some more details about the dataset:
+##   - It contains about 66 millions events (muon and electron collections, plus some other information, e.g. about primary vertices)
+##   - It spans two compressed ROOT files located on EOS for about a total size of 7.5 GB.
+##
+## \macro_image
+## \macro_code
+## \macro_output
+##
+## \date April 2019
+## \author Stefan Wunsch (KIT, CERN)
+
+import ROOT
+
+# Enable multi-threading
+ROOT.ROOT.EnableImplicitMT()
+
+# Create dataframe from NanoAOD files
+files = ROOT.std.vector("string")(2)
+files[0] = "root://eospublic.cern.ch//eos/root-eos/cms_opendata_2012_nanoaod/Run2012B_DoubleMuParked.root"
+files[1] = "root://eospublic.cern.ch//eos/root-eos/cms_opendata_2012_nanoaod/Run2012C_DoubleMuParked.root"
+df = ROOT.ROOT.RDataFrame("Events", files)
+
+# For simplicity, select only events with exactly two muons and require opposite charge
+df_2mu = df.Filter("nMuon == 2", "Events with exactly two muons")
+df_os = df_2mu.Filter("Muon_charge[0] != Muon_charge[1]", "Muons with opposite charge")
+
+# Compute invariant mass of the dimuon system
+df_mass = df_os.Define("Dimuon_mass", "InvariantMass(Muon_pt, Muon_eta, Muon_phi, Muon_mass)")
+
+# Make histogram of dimuon mass spectrum
+h = df_mass.Histo1D(("Dimuon_mass", "Dimuon_mass", 30000, 0.25, 300), "Dimuon_mass")
+
+# Request cut-flow report
+report = df_mass.Report()
+
+# Produce plot
+ROOT.gStyle.SetOptStat(0); ROOT.gStyle.SetTextFont(42)
+c = ROOT.TCanvas("c", "", 800, 700)
+c.SetLogx(); c.SetLogy()
+
+h.SetTitle("")
+h.GetXaxis().SetTitle("m_{#mu#mu} (GeV)"); h.GetXaxis().SetTitleSize(0.04)
+h.GetYaxis().SetTitle("N_{Events}"); h.GetYaxis().SetTitleSize(0.04)
+h.Draw()
+
+label = ROOT.TLatex(); label.SetNDC(True)
+label.DrawLatex(0.175, 0.740, "#eta")
+label.DrawLatex(0.205, 0.775, "#rho,#omega")
+label.DrawLatex(0.270, 0.740, "#phi")
+label.DrawLatex(0.400, 0.800, "J/#psi")
+label.DrawLatex(0.415, 0.670, "#psi'")
+label.DrawLatex(0.485, 0.700, "Y(1,2,3S)")
+label.DrawLatex(0.755, 0.680, "Z")
+label.SetTextSize(0.040); label.DrawLatex(0.100, 0.920, "#bf{CMS Open Data}")
+label.SetTextSize(0.030); label.DrawLatex(0.630, 0.920, "#sqrt{s} = 8 TeV, L_{int} = 11.6 fb^{-1}")
+
+c.SaveAs("dimuon_spectrum.pdf")
+
+# Print cut-flow report
+report.Print()