diff --git a/python/genericio.cpp b/python/genericio.cpp
index 9fd9e475e1a1ae22b2be3eb336e7251196f25610..b189e9ee966c06b84b64c4441f5ba5b40f25a708 100644
--- a/python/genericio.cpp
+++ b/python/genericio.cpp
@@ -192,6 +192,18 @@ public:
     return sr;
   }
 
+  std::array<int, 3> read_dims() {
+    std::array<int, 3> sd;
+    readDims(sd.data());
+    return sd;
+  }
+
+  std::array<int, 3> read_coords(int eff_rank=-1) {
+    std::array<int, 3> sc;
+    readCoords(sc.data(), eff_rank);
+    return sc;
+  }
+
 private:
   int num_ranks;
   std::vector<VariableInfo> variables;
@@ -237,6 +249,25 @@ std::array<double, 3> read_phys_origin(
   return reader.read_phys_origin();
 }
 
+std::array<int, 3> read_dims(
+    std::string filename,
+    PyGenericIO::FileIO method=PyGenericIO::FileIO::FileIOPOSIX,
+    PyGenericIO::MismatchBehavior redistribute=PyGenericIO::MismatchBehavior::MismatchRedistribute
+) {
+  PyGenericIO reader(filename, method, redistribute);
+  return reader.read_dims();
+}
+
+std::array<int, 3> read_coords(
+    std::string filename,
+    PyGenericIO::FileIO method=PyGenericIO::FileIO::FileIOPOSIX,
+    PyGenericIO::MismatchBehavior redistribute=PyGenericIO::MismatchBehavior::MismatchRedistribute,
+    int eff_rank=-1
+) {
+  PyGenericIO reader(filename, method, redistribute);
+  return reader.read_coords(eff_rank);
+}
+
 std::vector<std::string> read_variable_names(
     std::string filename,
     PyGenericIO::FileIO method=PyGenericIO::FileIO::FileIOPOSIX,
@@ -365,6 +396,8 @@ PYBIND11_MODULE(pygio_impl, m) {
       .def("read_total_num_elems", (uint64_t (PyGenericIO::*)(void))(&PyGenericIO::readTotalNumElems))
       .def("read_phys_origin", &PyGenericIO::read_phys_origin)
       .def("read_phys_scale", &PyGenericIO::read_phys_scale)
+      .def("read_dims", &PyGenericIO::read_dims)
+      .def("read_coords", &PyGenericIO::read_coords)
       .def("read", &PyGenericIO::read,
         py::arg("variables")=nullptr,
         py::kw_only(),
@@ -611,6 +644,64 @@ PYBIND11_MODULE(pygio_impl, m) {
         py::arg("method")=PyGenericIO::FileIO::FileIOPOSIX,
         py::arg("redistribute")=PyGenericIO::MismatchBehavior::MismatchRedistribute);
 
+m.def("read_dims", &read_dims, R"Delim(
+        Read the topological decomposition of the box that is stored in the GenericIO file
+
+        Parameters
+        ----------
+        filename: str
+            path to the GenericIO file
+
+        method: PyGenericIO.FileIO
+            file handling method (POSIX)
+
+        redistribute: PyGenericIO.MismatchBehavior
+            whether to allow mismatching ranks
+
+        Returns
+        -------
+        dims: List[int]
+            the box decomposition (3 elements long)
+  )Delim",
+  py::arg("filename"),
+  py::kw_only(),
+  py::arg("method")=PyGenericIO::FileIO::FileIOPOSIX,
+  py::arg("redistribute")=PyGenericIO::MismatchBehavior::MismatchRedistribute);
+
+m.def("read_coords", &read_coords, R"Delim(
+        Read the rank coordinates of the source_rank this rank is reading
+
+        Parameters
+        ----------
+        filename: str
+            path to the GenericIO file
+
+        method: PyGenericIO.FileIO
+            file handling method (POSIX)
+
+        redistribute: PyGenericIO.MismatchBehavior
+            whether to allow mismatching ranks
+
+        eff_rank: int
+            if -1, use the MPI rank of the calling process (or redistribute if
+            redistribute is set to MismatchRedistribute). Otherwise, use the
+            specified rank (if using MPI).
+
+        Returns
+        -------
+        coords: List[int]
+            the rank coordinates (3 elements long)
+
+        Note
+        ----
+        If eff_rank == -1 and redistribute is enabled, the rank coordinates
+        will be [0, 0, 0]
+  )Delim",
+  py::arg("filename"),
+  py::kw_only(),
+  py::arg("method")=PyGenericIO::FileIO::FileIOPOSIX,
+  py::arg("redistribute")=PyGenericIO::MismatchBehavior::MismatchRedistribute,
+  py::arg("eff_rank")=-1);
 
 
 #ifndef GENERICIO_NO_MPI