diff --git a/Device/IO/DataFormatUtil.cpp b/Device/IO/DataFormatUtil.cpp
index c676fec308c7dcc4866eb1401606757d459afb94..5bd1fcba51e7a22229998c0e69bc9055c213b3e2 100644
--- a/Device/IO/DataFormatUtil.cpp
+++ b/Device/IO/DataFormatUtil.cpp
@@ -40,15 +40,6 @@ std::istringstream getAxisStringRepresentation(std::istream& input_stream)
     return std::istringstream(line);
 }
 
-std::string uncompressedFilename(const std::string& name)
-{
-    if (DataUtil::Format::isGZipped(name))
-        return name.substr(0, name.size() - GzipExtension.size());
-    if (DataUtil::Format::isBZipped(name))
-        return name.substr(0, name.size() - BzipExtension.size());
-    return name;
-}
-
 void readLineOfDoubles(std::vector<double>& buffer, std::istringstream& iss)
 {
     iss.imbue(std::locale::classic());
@@ -58,6 +49,14 @@ void readLineOfDoubles(std::vector<double>& buffer, std::istringstream& iss)
 
 } // namespace
 
+std::string DataUtil::Format::uncompressedFilename(const std::string& name)
+{
+    if (DataUtil::Format::isGZipped(name))
+        return name.substr(0, name.size() - GzipExtension.size());
+    if (DataUtil::Format::isBZipped(name))
+        return name.substr(0, name.size() - BzipExtension.size());
+    return name;
+}
 
 bool DataUtil::Format::isCompressed(const std::string& name)
 {
@@ -78,18 +77,18 @@ bool DataUtil::Format::isBZipped(const std::string& name)
 
 bool DataUtil::Format::isIntFile(const std::string& file_name)
 {
-    return BaseUtil::Filesystem::hasExtension(::uncompressedFilename(file_name), IntExtension);
+    return BaseUtil::Filesystem::hasExtension(uncompressedFilename(file_name), IntExtension);
 }
 
 bool DataUtil::Format::isNicosFile(const std::string& file_name)
 {
-    return BaseUtil::Filesystem::hasExtension(::uncompressedFilename(file_name), NicosExtension);
+    return BaseUtil::Filesystem::hasExtension(uncompressedFilename(file_name), NicosExtension);
 }
 
 bool DataUtil::Format::isTiffFile(const std::string& file_name)
 {
-    return BaseUtil::Filesystem::hasExtension(::uncompressedFilename(file_name), TiffExtension)
-           || BaseUtil::Filesystem::hasExtension(::uncompressedFilename(file_name), TiffExtension2);
+    return BaseUtil::Filesystem::hasExtension(uncompressedFilename(file_name), TiffExtension)
+           || BaseUtil::Filesystem::hasExtension(uncompressedFilename(file_name), TiffExtension2);
 }
 
 //! Creates axis of certain type from input stream
diff --git a/Device/IO/DataFormatUtil.h b/Device/IO/DataFormatUtil.h
index 0da07f286671563eb5c4116f1dec405f2cd0ab86..56bd90b2b35f437a01f467601ccccf810261c3a0 100644
--- a/Device/IO/DataFormatUtil.h
+++ b/Device/IO/DataFormatUtil.h
@@ -28,6 +28,8 @@ class Datafield;
 
 namespace DataUtil::Format {
 
+std::string uncompressedFilename(const std::string& name);
+
 //! Returns true if name contains *.gz extension
 bool isCompressed(const std::string& name);
 
diff --git a/Device/IO/IOFactory.cpp b/Device/IO/IOFactory.cpp
index 3b5782c80866c53801129c5a382e38c4ae2a0b2e..c12e364ac221cb3e9038332cfa0352fe4d7e3144 100644
--- a/Device/IO/IOFactory.cpp
+++ b/Device/IO/IOFactory.cpp
@@ -15,6 +15,7 @@
 #include "Device/IO/IOFactory.h"
 #include "Base/Util/Assert.h"
 #include "Base/Util/FileSystemUtil.h"
+#include "Base/Util/StringUtil.h"
 #include "Device/Data/Datafield.h"
 #include "Device/Histo/DiffUtil.h"
 #include "Device/Histo/SimulationResult.h"
@@ -24,6 +25,8 @@
 #include "Device/IO/ReadWriteNicos.h"
 #include "Device/IO/ReadWriteNumpyTXT.h"
 #include "Device/IO/ReadWriteTiff.h"
+#include <algorithm>
+#include <cctype>
 #include <exception>
 #include <fstream>
 #include <iostream>
@@ -108,50 +111,48 @@ void stream2file(const std::string& file_name, std::stringstream& s)
     fout.close();
 }
 
-bool fileTypeMatchesFiletype(const std::string& fileName, IO::Filetype selector)
+IO::Filetype filename2type(const std::string& filename)
 {
-    switch (selector) {
-    case IO::bornagain:
-        return DataUtil::Format::isIntFile(fileName);
-    case IO::nicos:
-        return DataUtil::Format::isNicosFile(fileName);
-    case IO::tiff:
-        return DataUtil::Format::isTiffFile(fileName);
-    default:
-        return false;
-    }
-
-    return false;
+    std::string s = DataUtil::Format::uncompressedFilename(filename);
+    s = BaseUtil::Filesystem::extension(s);
+    s = BaseUtil::String::to_lower(s);
+
+    if (s == ".int")
+        return IO::bornagain;
+    if (s == ".001")
+        return IO::nicos;
+    if (s == ".tif" || s == ".tiff")
+        return IO::tiff;
+    if (s == ".mft")
+        return IO::mft;
+    return IO::nil;
 }
 
 } // namespace
 
 
-Datafield* IO::readData2D(const std::string& file_name, Filetype selector)
+Datafield* IO::readData2D(const std::string& file_name, Filetype ftype)
 {
-    const auto readAs = [=](Filetype testForSelector) {
-        return (selector == testForSelector)
-               || (selector == nil && ::fileTypeMatchesFiletype(file_name, testForSelector));
-    };
+    if (ftype == nil)
+        ftype = ::filename2type(file_name);
 
     auto s = ::file2stream(file_name);
 
-    if (readAs(bornagain))
+    if (ftype == bornagain)
         return Util::RW::readBAInt(s);
 
-    else if (readAs(nicos))
+    if (ftype == nicos)
         return Util::RW::readNicos(s);
 
 #ifdef BA_TIFF_SUPPORT
-    else if (readAs(tiff))
+    if (ftype == tiff)
         return Util::RW::readTiff(s);
 #endif
 
-    else
-        // Try to read ASCII by default. Binary maps to ASCII.
-        // If the file is not actually a matrix of numbers,
-        // the error will be thrown during the reading.
-        return Util::RW::readNumpyTxt(s);
+    // Try to read ASCII by default. Binary maps to ASCII.
+    // If the file is not actually a matrix of numbers,
+    // the error will be thrown during the reading.
+    return Util::RW::readNumpyTxt(s);
 }
 
 Datafield* IO::readData1D(const std::string& file_name, Filetype /*selector*/)