Read mrc density map format with all endianesses.
authorChristian Blau <cblau@gwdg.de>
Fri, 22 Nov 2019 16:51:23 +0000 (17:51 +0100)
committerPaul Bauer <paul.bauer.q@gmail.com>
Mon, 25 Nov 2019 13:34:34 +0000 (14:34 +0100)
Swaps the endianess of reading mrc density maps if header is not sane.

refs: #2282

Change-Id: I417e402b2ab801c22d9963fabb0e60b186288651

docs/reference-manual/special/density-guided-simulation.rst
src/gromacs/fileio/mrcdensitymap.cpp
src/gromacs/fileio/mrcdensitymap.h

index 8be48bbd82aee3953d463aceca5199fc799f9db5..36968f2dbe468a5889dfe193686ae2fe6feeadf3 100644 (file)
@@ -176,8 +176,6 @@ Closely related formats like `ccp4` and `map` might work.
 
 Be aware that different visualization software handles map formats differently.
 During simulations, reference densities are interpreted as visualised by `VMD`.
-If the reference map shows unexpected behaviour, swapping endianess with a map
-conversion tool like `em2em` might help.
 
 Output
 ^^^^^^
index 3104463806782ab5ffed914f327636aa0be5c08f..ff866adfde4a91c514c13215ea874a43b8438cd7 100644 (file)
@@ -168,18 +168,30 @@ public:
     const MrcDensityMapOfFloatReader& reader() const;
 
 private:
-    std::vector<char>                buffer_;
-    InMemoryDeserializer             serializer_;
-    const MrcDensityMapOfFloatReader reader_;
+    const std::vector<char>                     buffer_;
+    std::unique_ptr<InMemoryDeserializer>       serializer_;
+    std::unique_ptr<MrcDensityMapOfFloatReader> reader_;
 };
 
 MrcDensityMapOfFloatFromFileReader::Impl::Impl(const std::string& filename) :
     buffer_(readCharBufferFromFile(filename)),
-    serializer_(buffer_, false),
-    reader_(&serializer_)
+    serializer_(std::make_unique<InMemoryDeserializer>(buffer_, false)),
+    reader_(std::make_unique<MrcDensityMapOfFloatReader>(serializer_.get()))
 {
-    layout_right::mapping<dynamicExtents3D> map(getDynamicExtents3D(reader_.header()));
-    if (map.required_span_size() != reader_.constView().ssize())
+    if (!mrcHeaderIsSane(reader_->header()))
+    {
+        serializer_ = std::make_unique<InMemoryDeserializer>(buffer_, false, EndianSwapBehavior::DoSwap);
+        reader_ = std::make_unique<MrcDensityMapOfFloatReader>(serializer_.get());
+        if (!mrcHeaderIsSane(reader_->header()))
+        {
+            GMX_THROW(FileIOError(
+                    "Header of '" + filename
+                    + "' fails sanity check for little- as well as big-endian reading."));
+        }
+    }
+
+    layout_right::mapping<dynamicExtents3D> map(getDynamicExtents3D(reader_->header()));
+    if (map.required_span_size() != reader_->constView().ssize())
     {
         GMX_THROW(FileIOError("File header density extent information of " + filename
                               + "' does not match density data size"));
@@ -188,7 +200,7 @@ MrcDensityMapOfFloatFromFileReader::Impl::Impl(const std::string& filename) :
 
 const MrcDensityMapOfFloatReader& MrcDensityMapOfFloatFromFileReader::Impl::reader() const
 {
-    return reader_;
+    return *reader_;
 }
 
 /********************************************************************
index 85ef1e55105c408ecbe9ac50cb7a017fc3f480d7..7f746567306c96948bce6d7509a65de00c8f9815 100644 (file)
@@ -87,6 +87,10 @@ private:
  * upon construction and returns coordinate transformation into the density
  * lattice as well as the density data.
  *
+ * Attempts reading with swapped endianess if header is not sane.
+ *
+ * Performs basic sanity checks on header information and data size.
+ *
  * \note File reading is completed during construction. When the constructor
  *       completes succesfully, transformation to density lattice and density
  *       data are valid, irrespective of the state of the read file.