diff --git a/Detector/MagneticFieldMap/CMakeLists.txt b/Detector/MagneticFieldMap/CMakeLists.txt
index ac154c8ae17f339802d26b7a1e5f638a87c62542..7c65b50318a2d0040922057a2fcc36a84db3ec50 100644
--- a/Detector/MagneticFieldMap/CMakeLists.txt
+++ b/Detector/MagneticFieldMap/CMakeLists.txt
@@ -5,6 +5,7 @@
 gaudi_add_module(MagneticFieldMap
                  SOURCES src/GenericBFieldMapBrBz.cpp
                          src/GenericBFieldMapBrBzFactory.cpp
+                         src/FieldMapFileProvider.cpp
                  LINK Gaudi::GaudiKernel
                       ${DD4hep_COMPONENT_LIBRARIES}
                       ${ROOT_LIBRARIES}
diff --git a/Detector/MagneticFieldMap/src/FieldMapFileProvider.cpp b/Detector/MagneticFieldMap/src/FieldMapFileProvider.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..388ea22e00e2ddeb218178a7330a92702472413e
--- /dev/null
+++ b/Detector/MagneticFieldMap/src/FieldMapFileProvider.cpp
@@ -0,0 +1,229 @@
+#include "FieldMapFileProvider.h"
+
+#include <cmath>
+#include <string>
+#include <map>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+FieldMapFileProvider::FieldMapFileProvider(const std::string& url_)
+    : m_url(url_), rBinMax(-1), zBinMax(-1), drBin(-1), dzBin(-1) {
+    init();
+}
+
+int FieldMapFileProvider::rBinIdx(double r) {
+    double absr = std::fabs(r);
+    
+    return -1;
+}
+
+int FieldMapFileProvider::zBinIdx(double z) {
+    double absz = std::fabs(z);
+    
+    return -1;
+}
+
+void FieldMapFileProvider::access(int rbin, int zbin, double& Br, double& Bz) {
+
+}
+
+// ======================
+// Below are private impl
+// ======================
+
+void FieldMapFileProvider::init() {
+    // parse the url
+    //   Br=/tmp/lint/CEPCSW/Br.csv;Bz=/tmp/lint/CEPCSW/Bz.csv
+
+    std::map<std::string, std::string> url_parsed;
+    
+    size_t idx_begin = 0;
+    size_t idx_end = m_url.find(";");
+
+    while (true) {
+        std::string keyval = m_url.substr(idx_begin, idx_end-idx_begin);
+
+        if (keyval.size()) {
+            std::cout << "---> keyval: " << keyval << std::endl;
+            // separate by '='
+            size_t idx_sep = keyval.find("=");
+            if (idx_sep == std::string::npos) {
+                std::string error_msg = "[ERROR] FieldMapFileProvider: Pleaes specify label=path. ";
+                throw std::runtime_error(error_msg);
+
+            }
+            std::string key = keyval.substr(0, idx_sep);
+            std::string val = keyval.substr(idx_sep+1);
+            std::cout << "-----> key: " << key << std::endl;
+            std::cout << "-----> val: " << val << std::endl;
+            // insert into map
+
+            // duplicated
+            if (url_parsed.count(key)) {
+                std::string error_msg = "[ERROR] FieldMapFileProvider: duplicated key '" + key + "'";
+                throw std::runtime_error(error_msg);
+            }
+
+            url_parsed[key] = val;
+        }
+
+        if (idx_end == std::string::npos) {
+            break;
+        }
+
+        idx_begin = idx_end+1;
+        idx_end = m_url.find(';', idx_begin);
+    }
+
+    // access the map 'url_parsed'
+    std::string key;
+
+    // load Br
+    key = "Br";
+    if (url_parsed.count(key) == 0) {
+        std::string error_msg = "[ERROR] FieldMapFileProvider: missing key '" + key + "'";
+        throw std::runtime_error(error_msg);
+    }
+    loadBr(url_parsed[key]);
+
+    // load Bz
+    key = "Bz";
+    if (url_parsed.count(key) == 0) {
+        std::string error_msg = "[ERROR] FieldMapFileProvider: missing key '" + key + "'";
+        throw std::runtime_error(error_msg);
+    }
+    loadBz(url_parsed[key]);
+
+}
+
+
+
+bool FieldMapFileProvider::loadBr(const std::string& fn) {
+
+    //  ----> r
+    // |
+    // v
+    // z
+    // the shape
+    int ncol = -1;
+    int nrow = -1;
+
+    // load data
+    bool st = loadCSV(fn, Brdata, ncol, nrow);
+
+    // update the metadata
+    // for (int i = 0; i < ncol; ++i) {
+    //     std::cout << "i: " << i << " data[i]: " << data[i] << std::endl;
+    // }
+    nr = ncol-1; // skip the top row and left col
+    nz = nrow-1; 
+
+    rBinMax = Brdata[ncol-1];
+    zBinMax = Brdata[ncol*(nrow-1)];
+
+    drBin = rBinMax / (nr-1);
+    dzBin = zBinMax / (nz-1);
+
+    std::cout << "nr: " << nr << std::endl;
+    std::cout << "nz: " << nz << std::endl;
+    std::cout << "rBinMax: " << rBinMax << std::endl;
+    std::cout << "zBinMax: " << zBinMax << std::endl;
+    std::cout << "drBin: " << drBin << std::endl;
+    std::cout << "dzBin: " << dzBin << std::endl;
+
+
+
+    return true;
+}
+
+bool FieldMapFileProvider::loadBz(const std::string& fn) {
+
+    // the shape
+    int ncol = -1;
+    int nrow = -1;
+    bool st = loadCSV(fn, Bzdata, ncol, nrow);
+
+    return true;
+}
+
+bool FieldMapFileProvider::loadCSV(const std::string& fn, 
+                                   std::vector<double>& data, 
+                                   int& ncol, int& nrow) {
+
+    std::ifstream input(fn);
+    std::string tmpline;
+
+    ncol = 0;
+    nrow = 0;
+
+
+    while(std::getline(input, tmpline)) {
+        std::cout << "------> " << tmpline << std::endl;
+        ++nrow;
+
+        // split by ,
+        int col_per_line = 0;
+        
+        size_t idx_begin = 0;
+        size_t idx_end = tmpline.find(",");
+
+        while (true) {
+            std::cout << "----------------> idx: "
+                      << idx_begin << "->" << idx_end << std::endl;
+            std::string val = tmpline.substr(idx_begin, idx_end-idx_begin);
+            double v = 0.0;
+            // parse val
+            std::stringstream ss;
+            ss << val;
+            ss >> v;
+            // if (not ss.good()) {
+            //     v = 0;
+            //     ss.clear();
+            // }
+
+            std::cout << "----------------> v: " << v << std::endl;
+            // if (val.size()==0 || ) { // if it is empty or not number, use 0
+            //     data.push_back(0.0);
+            // } else {
+            // }
+            data.push_back(v);
+
+            ++col_per_line;
+
+            // break
+            if (idx_end == std::string::npos) {
+                break;
+            }
+
+            // goto next val
+            idx_begin = idx_end+1;
+            idx_end = tmpline.find(',', idx_begin);
+
+        }
+
+        // if it is the first line, we need to store the column sizes
+        if (ncol == 0) {
+            ncol = col_per_line;
+        }
+
+        std::cout << "--> ncol: " << ncol
+                  << " col_per_line: " << col_per_line
+                  << std::endl;
+
+        if (ncol != col_per_line) {
+            std::string error_msg = "[ERROR] FieldMapFileProvider: Mismatch columns. ";
+            throw std::runtime_error(error_msg);
+        }
+
+    }
+
+    std::cout << "SUMMARY: "
+              << " size of the data: " << data.size()
+              << " shape (ncol: " << ncol
+              << " , nrow: " << nrow
+              << ")" << std::endl;
+
+    return true;
+}
diff --git a/Detector/MagneticFieldMap/src/FieldMapFileProvider.h b/Detector/MagneticFieldMap/src/FieldMapFileProvider.h
new file mode 100644
index 0000000000000000000000000000000000000000..3661863bf49032ebe7c6b1f0c5943c153b856ad7
--- /dev/null
+++ b/Detector/MagneticFieldMap/src/FieldMapFileProvider.h
@@ -0,0 +1,49 @@
+#ifndef FieldMapFileProvider_h
+#define FieldMapFileProvider_h
+
+#include "IFieldMapProvider.h"
+
+#include <string>
+#include <vector>
+
+class FieldMapFileProvider: public IFieldMapProvider {
+
+public:
+    FieldMapFileProvider(const std::string& url_);
+
+    // Meta data about the map
+    virtual int rBinIdx(double r);
+    virtual int zBinIdx(double z);
+
+    // The Br and Bz
+    virtual void access(int rbin, int zbin, double& Br, double& Bz);
+
+private:
+    void init();
+
+    bool loadBr(const std::string& fn);
+    bool loadBz(const std::string& fn);
+
+    bool loadCSV(const std::string& fn, std::vector<double>& data, int& ncol, int& nrow);
+private:
+    std::string m_url; // the url passed from GenericBFieldMapBrBz
+
+    std::string m_filename_Br;
+    std::string m_filename_Bz;
+
+    // the data will include the left col (z) and top row (r)
+    std::vector<double> Brdata;
+    std::vector<double> Bzdata;
+
+    // in this impl, the rBin/zBin should be consistent between Br and Bz.
+    int nr; // include the two endpoints, so nr = nrBin + 1
+    int nz;
+
+    double rBinMax;
+    double zBinMax;
+
+    double drBin;
+    double dzBin;
+};
+
+#endif
diff --git a/Detector/MagneticFieldMap/src/GenericBFieldMapBrBz.cpp b/Detector/MagneticFieldMap/src/GenericBFieldMapBrBz.cpp
index fe268217c0b0376cd09c45ff3d3cf51db36f7585..568d70c80d14275e7bd2bd6d41b868e9844c147a 100644
--- a/Detector/MagneticFieldMap/src/GenericBFieldMapBrBz.cpp
+++ b/Detector/MagneticFieldMap/src/GenericBFieldMapBrBz.cpp
@@ -1,6 +1,8 @@
 
 #include "GenericBFieldMapBrBz.h"
 
+#include "FieldMapFileProvider.h"
+
 GenericBFieldMapBrBz::GenericBFieldMapBrBz()
     : m_provider(nullptr) {
     type = dd4hep::CartesianField::MAGNETIC;
@@ -17,9 +19,10 @@ void GenericBFieldMapBrBz::fieldComponents(const double* pos, double* field) {
     return;
 }
 
-void GenericBFieldMapBrBz::init_provider(const std::string& provider) {
+void GenericBFieldMapBrBz::init_provider(const std::string& provider, const std::string& url) {
     if (provider == "file") {
         std::cout << "Initialize provider with file. " << std::endl;
+        m_provider = new FieldMapFileProvider(url);
     } else if (provider == "db") {
         std::cout << "Initialize provider with file. " << std::endl;
     } else {
diff --git a/Detector/MagneticFieldMap/src/GenericBFieldMapBrBz.h b/Detector/MagneticFieldMap/src/GenericBFieldMapBrBz.h
index 3b1711f5abcf411253dfd8901510510fab8bfd0c..93abfcfbbb5650d5e5945b774280e6586b1c17c3 100644
--- a/Detector/MagneticFieldMap/src/GenericBFieldMapBrBz.h
+++ b/Detector/MagneticFieldMap/src/GenericBFieldMapBrBz.h
@@ -24,7 +24,7 @@ public:
 
 public:
     // following are interfaces to configure this field map
-    void init_provider(const std::string& provider);
+    void init_provider(const std::string& provider, const std::string& url);
 
 private:
 
diff --git a/Detector/MagneticFieldMap/src/GenericBFieldMapBrBzFactory.cpp b/Detector/MagneticFieldMap/src/GenericBFieldMapBrBzFactory.cpp
index b738332c12f8f8396aa79de1cbf9751ae906885a..d7d9fe302d75e214e290f52ebf2382441df305c0 100644
--- a/Detector/MagneticFieldMap/src/GenericBFieldMapBrBzFactory.cpp
+++ b/Detector/MagneticFieldMap/src/GenericBFieldMapBrBzFactory.cpp
@@ -53,11 +53,22 @@ static dd4hep::Ref_t create_GenericBFieldMapBrBz(dd4hep::Detector& ,
 
     }
 
+    dd4hep::xml::Component source(xmlParameter.child(_Unicode(source)));
+    
+    // get the url
+    bool hasUrl = source.hasAttr(_Unicode(url));
+    if (!hasUrl) {
+        std::string error_msg = "[ERROR] GenericBFieldMapBrBz: Must specify the 'url' in 'source' tag. ";
+        throw std::runtime_error(error_msg);
+    }
+
+    std::string url = source.attr<std::string>(_Unicode(url));
+
     // 2. create the CartesianField
     dd4hep::CartesianField obj;
     GenericBFieldMapBrBz* ptr = new GenericBFieldMapBrBz();
 
-    ptr->init_provider(provider);
+    ptr->init_provider(provider, url);
 
     obj.assign(ptr, xmlParameter.nameStr(), xmlParameter.typeStr());
 
diff --git a/Detector/MagneticFieldMap/src/IFieldMapProvider.h b/Detector/MagneticFieldMap/src/IFieldMapProvider.h
index e3eda83f9653e33f8fc24967a32685b16d250d09..3d2384224d27c05c5cdd22175ef0f3f871151683 100644
--- a/Detector/MagneticFieldMap/src/IFieldMapProvider.h
+++ b/Detector/MagneticFieldMap/src/IFieldMapProvider.h
@@ -11,7 +11,7 @@
  */
 
 class IFieldMapProvider {
-
+public:
     // Meta data about the map
     virtual int rBinIdx(double r) = 0;
     virtual int zBinIdx(double z) = 0;