Read mrc file using file name
authorChristian Blau <cblau@gwdg.de>
Mon, 2 Sep 2019 08:12:31 +0000 (10:12 +0200)
committerMark Abraham <mark.j.abraham@gmail.com>
Wed, 4 Sep 2019 12:43:21 +0000 (14:43 +0200)
Provide a higher level class for reading an mrc file given file name and
convert the information read from the density file into coordinate
transformation and three-dimensional density data.

Change-Id: I30ac5c044c5433043224be288340b794455f8fc9

src/gromacs/fileio/mrcdensitymap.cpp
src/gromacs/fileio/mrcdensitymap.h
src/gromacs/fileio/tests/mrcdensitymap.cpp
src/gromacs/fileio/tests/refdata/MrcDensityMap_ReadsDensityDataFromFile.xml [new file with mode: 0644]
src/testutils/simulationdatabase/ellipsoid-density.mrc [new file with mode: 0644]

index 9c8385c7c2ef4112142d3abcb09b82a93266e295..0e251ee4e9dd6002ca62d2dd055fbd051b6d75be 100644 (file)
 #include <algorithm>
 #include <vector>
 
+#include "gromacs/fileio/gmxfio.h"
+#include "gromacs/fileio/gmxfio_xdr.h"
 #include "gromacs/fileio/mrcdensitymapheader.h"
 #include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/inmemoryserializer.h"
 #include "gromacs/utility/iserializer.h"
 
 #include "mrcserializer.h"
 namespace gmx
 {
 
+namespace
+{
+
+/*! \brief Read file into memory as vector of chars
+ *
+ * \param[in] filename of the file to be read
+ * \returns the file contents as a vector
+ * \throws FileIOError if file not found
+ * \throws FileIOError if reading was not successful
+ */
+std::vector<char> readCharBufferFromFile(const std::string &filename)
+{
+    if (!gmx_fexist(filename))
+    {
+        GMX_THROW(FileIOError("Error while reading '" + filename + "' - file not found."));
+    }
+    t_fileio *mrcFile = gmx_fio_open(filename.c_str(), "r");
+
+    // Determine file size
+    gmx_fseek(gmx_fio_getfp(mrcFile), 0, SEEK_END);
+    gmx_off_t fileSize = gmx_fio_ftell(mrcFile);
+    gmx_fseek(gmx_fio_getfp(mrcFile), 0, SEEK_SET);
+    // Read whole file into buffer the size of the file
+    std::vector<char> fileContentBuffer(fileSize);
+    size_t            readSize = fread(fileContentBuffer.data(), sizeof(char), fileContentBuffer.size(), gmx_fio_getfp(mrcFile));
+    gmx_fio_close(mrcFile);
+
+    if (fileContentBuffer.size() != readSize)
+    {
+        GMX_THROW(FileIOError("Error while reading '" + filename + "' - file size and read buffer size do not match."));
+    }
+
+    return fileContentBuffer;
+}
+
+}   // namespace
+
 /********************************************************************
  * MrcDensityMapOfFloatReader::Impl
  */
@@ -100,7 +140,7 @@ MrcDensityMapOfFloatReader::MrcDensityMapOfFloatReader(ISerializer *serializer)
 {
 }
 
-ArrayRef<const float> MrcDensityMapOfFloatReader::data() const
+ArrayRef<const float> MrcDensityMapOfFloatReader::constView() const
 {
     return impl_->data_;
 }
@@ -114,6 +154,65 @@ MrcDensityMapOfFloatReader::~MrcDensityMapOfFloatReader()
 {
 }
 
+/********************************************************************
+ * MrcDensityMapOfFloatFromFileReader::Impl
+ */
+
+
+class MrcDensityMapOfFloatFromFileReader::Impl
+{
+    public:
+        explicit Impl(const std::string &fileName);
+        ~Impl() = default;
+        const MrcDensityMapOfFloatReader &reader() const;
+    private:
+        std::vector<char>                 buffer_;
+        InMemoryDeserializer              serializer_;
+        const MrcDensityMapOfFloatReader  reader_;
+};
+
+MrcDensityMapOfFloatFromFileReader::Impl::Impl(const std::string &filename) :
+    buffer_(readCharBufferFromFile(filename)),
+    serializer_(buffer_, false),
+    reader_(&serializer_)
+{
+    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"));
+    }
+}
+
+const MrcDensityMapOfFloatReader &MrcDensityMapOfFloatFromFileReader::Impl::reader() const
+{
+    return reader_;
+}
+
+/********************************************************************
+ * MrcDensityMapOfFloatFromFileReader
+ */
+
+MrcDensityMapOfFloatFromFileReader::MrcDensityMapOfFloatFromFileReader(const std::string &filename)
+    : impl_(new Impl(filename))
+{}
+
+MrcDensityMapOfFloatFromFileReader::~MrcDensityMapOfFloatFromFileReader() = default;
+
+TranslateAndScale
+MrcDensityMapOfFloatFromFileReader::transformationToDensityLattice() const
+{
+    return getCoordinateTransformationToLattice(impl_->reader().header());
+}
+
+MultiDimArray<std::vector<float>, dynamicExtents3D>
+MrcDensityMapOfFloatFromFileReader::densityDataCopy() const
+{
+    MultiDimArray<std::vector<float>, dynamicExtents3D> result(getDynamicExtents3D(impl_->reader().header()));
+    std::copy(std::begin(impl_->reader().constView()), std::end(impl_->reader().constView()), begin(result.asView()));
+    return result;
+}
+
 /********************************************************************
  * MrcDensityMapOfFloatWriter::Impl
  */
index 164859c309019f3952e4b46e9e3e38417de93085..6b9d0ec004a390c82e4af4e12a5883de8727b89f 100644 (file)
  * \inlibraryapi
  * \ingroup module_fileio
  */
+#include <string>
+#include <vector>
+
+#include "gromacs/math/multidimarray.h"
+#include "gromacs/mdspan/extensions.h"
 #include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/classhelpers.h"
 
@@ -49,6 +54,7 @@ namespace gmx
 
 struct MrcDensityMapHeader;
 class ISerializer;
+class TranslateAndScale;
 
 /*! \libinternal \brief Read an mrc/ccp4 file that contains float values.
  */
@@ -65,8 +71,8 @@ class MrcDensityMapOfFloatReader
 
         ~MrcDensityMapOfFloatReader();
 
-        //! Return the data vector that holds the data on the density grid
-        ArrayRef<const float> data() const;
+        //! Return a view on the data of the density grid
+        ArrayRef<const float> constView() const;
         //! Return the header
         const MrcDensityMapHeader &header() const;
 
@@ -76,6 +82,43 @@ class MrcDensityMapOfFloatReader
 
 };
 
+/*! \libinternal \brief Read an mrc density map from a given file.
+ *
+ * Higher level class than MrcDensityMapOfFloatReader that takes a file name
+ * upon construction and returns coordinate transformation into the density
+ * lattice as well as the density data.
+ *
+ * \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.
+ */
+class MrcDensityMapOfFloatFromFileReader
+{
+    public:
+
+        MrcDensityMapOfFloatFromFileReader();
+
+        /*! \brief Read from filename.
+         * \throws FileIOError if file does not exist
+         * \throws FileIOError if read in buffer size does not match file size
+         * \throws FileIOError if header information does not match density
+         *                     data size
+         */
+        explicit MrcDensityMapOfFloatFromFileReader(const std::string &filename);
+
+        ~MrcDensityMapOfFloatFromFileReader();
+
+        //! Return the coordinate transformation into the density
+        TranslateAndScale transformationToDensityLattice() const;
+
+        //! Return a copy of the density data
+        MultiDimArray<std::vector<float>, dynamicExtents3D> densityDataCopy() const;
+
+    private:
+        class Impl;
+        PrivateImplPointer<Impl> impl_;
+};
+
 /*! \libinternal \brief Write an mrc/ccp4 file that contains float values.
  */
 class MrcDensityMapOfFloatWriter
index e7272d22f0275adb451a19a658ee7bcd80a82424..a7cc86c905f1a8944053339e11c4db366b201003 100644 (file)
 
 #include "gromacs/fileio/mrcdensitymap.h"
 
+#include <string>
+
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
 #include "gromacs/fileio/mrcdensitymapheader.h"
 #include "gromacs/utility/inmemoryserializer.h"
 
+#include "testutils/refdata.h"
 #include "testutils/testasserts.h"
+#include "testutils/testfilemanager.h"
 
 namespace gmx
 {
-
+namespace test
+{
 namespace
 {
 
@@ -76,7 +81,7 @@ TEST(MrcDensityMap, RoundTripIsIdempotent)
     InMemoryDeserializer       deserializer(serializedFile, false);
     MrcDensityMapOfFloatReader mrcDensityMapReader(&deserializer);
 
-    MrcDensityMapOfFloatWriter writerOfDeserializedOutput(mrcDensityMapReader.header(), mrcDensityMapReader.data());
+    MrcDensityMapOfFloatWriter writerOfDeserializedOutput(mrcDensityMapReader.header(), mrcDensityMapReader.constView());
     writerOfDeserializedOutput.write(&serializer);
 
     const auto roundTripResult = serializer.finishAndGetBuffer();
@@ -85,6 +90,53 @@ TEST(MrcDensityMap, RoundTripIsIdempotent)
     EXPECT_THAT(serializedFile, testing::Pointwise(testing::Eq(), roundTripResult));
 }
 
-} // namespace
+TEST(MrcDensityMap, ThrowsFileIOErrorWhenFileNotPresent)
+{
+    EXPECT_THROW(MrcDensityMapOfFloatFromFileReader(""), FileIOError);
+}
+
+TEST(MrcDensityMap, ReadsCoordinateTransformationFromFile)
+{
+    RVec coordinate1(0, 0, 0);
+    RVec coordinate2(0, 0, 1);
+    RVec coordinate3(1, 0, 0);
+    RVec coordinate4(0, 1, 0);
+
+    MrcDensityMapOfFloatFromFileReader mrcFileReader(TestFileManager::getInputFilePath("ellipsoid-density.mrc"));
+    TranslateAndScale                  coordinateTransformation(mrcFileReader.transformationToDensityLattice());
+
+    coordinateTransformation({&coordinate1, &coordinate1+1});
+    coordinateTransformation({&coordinate2, &coordinate2+1});
 
+    EXPECT_REAL_EQ(0, coordinate1[XX]);
+    EXPECT_REAL_EQ(-2, coordinate1[YY]);
+    EXPECT_REAL_EQ(0, coordinate1[ZZ]);
+
+    EXPECT_REAL_EQ(0, coordinate2[XX]);
+    EXPECT_REAL_EQ(-2, coordinate2[YY]);
+    EXPECT_REAL_EQ(1.25, coordinate2[ZZ]);
+
+    EXPECT_REAL_EQ(1, coordinate3[XX]);
+    EXPECT_REAL_EQ(0, coordinate3[YY]);
+    EXPECT_REAL_EQ(0, coordinate3[ZZ]);
+
+    EXPECT_REAL_EQ(0, coordinate4[XX]);
+    EXPECT_REAL_EQ(1, coordinate4[YY]);
+    EXPECT_REAL_EQ(0, coordinate4[ZZ]);
+}
+
+TEST(MrcDensityMap, ReadsDensityDataFromFile)
+{
+    MrcDensityMapOfFloatFromFileReader mrcFileReader(
+            TestFileManager::getInputFilePath("ellipsoid-density.mrc"));
+    const auto                         densityData = mrcFileReader.densityDataCopy();
+
+    TestReferenceData                  refData;
+    TestReferenceChecker               checker(refData.rootChecker());
+    checker.checkSequence(begin(densityData.asConstView()), end(densityData.asConstView()),
+                          "data ellipsoid density");
+}
+
+} // namespace
+} // namespace test
 } // namespace gmx
diff --git a/src/gromacs/fileio/tests/refdata/MrcDensityMap_ReadsDensityDataFromFile.xml b/src/gromacs/fileio/tests/refdata/MrcDensityMap_ReadsDensityDataFromFile.xml
new file mode 100644 (file)
index 0000000..a4399fa
--- /dev/null
@@ -0,0 +1,493 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <Sequence Name="data ellipsoid density">
+    <Int Name="Length">486</Int>
+    <Real>1.1953919</Real>
+    <Real>1.6435194</Real>
+    <Real>2.1393259</Real>
+    <Real>2.632971</Real>
+    <Real>3.0569184</Real>
+    <Real>3.3383296</Real>
+    <Real>3.4184613</Real>
+    <Real>3.2725449</Real>
+    <Real>2.9209843</Real>
+    <Real>1.5880153</Real>
+    <Real>2.1353097</Real>
+    <Real>2.7187419</Real>
+    <Real>3.2769456</Real>
+    <Real>3.733645</Real>
+    <Real>4.0116081</Real>
+    <Real>4.0526991</Real>
+    <Real>3.8375888</Real>
+    <Real>3.3960304</Real>
+    <Real>1.984187</Real>
+    <Real>2.6113653</Real>
+    <Real>3.2516041</Real>
+    <Real>3.8339429</Real>
+    <Real>4.2789373</Real>
+    <Real>4.5131307</Real>
+    <Real>4.48736</Real>
+    <Real>4.1934929</Real>
+    <Real>3.671828</Real>
+    <Real>2.3286476</Real>
+    <Real>3.004149</Real>
+    <Real>3.6606741</Real>
+    <Real>4.2210531</Real>
+    <Real>4.6090021</Real>
+    <Real>4.7629418</Real>
+    <Real>4.6502719</Real>
+    <Real>4.2785668</Real>
+    <Real>3.698462</Real>
+    <Real>2.5623231</Real>
+    <Real>3.2468846</Real>
+    <Real>3.8772998</Real>
+    <Real>4.3745785</Real>
+    <Real>4.6712222</Real>
+    <Real>4.7233577</Real>
+    <Real>4.5194492</Real>
+    <Real>4.0844345</Real>
+    <Real>3.4772677</Real>
+    <Real>2.6380663</Real>
+    <Real>3.2911048</Real>
+    <Real>3.859076</Real>
+    <Real>4.2658768</Real>
+    <Real>4.4565029</Real>
+    <Real>4.406836</Real>
+    <Real>4.1264491</Real>
+    <Real>3.6556504</Real>
+    <Real>3.057991</Real>
+    <Real>2.536021</Real>
+    <Real>3.1222515</Real>
+    <Real>3.6031699</Real>
+    <Real>3.9098086</Real>
+    <Real>4.0009212</Real>
+    <Real>3.8702214</Real>
+    <Real>3.5441294</Real>
+    <Real>3.0731406</Real>
+    <Real>2.5206385</Real>
+    <Real>2.2718213</Real>
+    <Real>2.7665424</Real>
+    <Real>3.1496816</Real>
+    <Real>3.3625264</Real>
+    <Real>3.3766482</Real>
+    <Real>3.1987944</Real>
+    <Real>2.8652463</Real>
+    <Real>2.4298441</Real>
+    <Real>1.951046</Real>
+    <Real>1.8931036</Real>
+    <Real>2.2849646</Real>
+    <Real>2.5722942</Real>
+    <Real>2.708225</Real>
+    <Real>2.6747751</Real>
+    <Real>2.4858599</Real>
+    <Real>2.1801627</Real>
+    <Real>1.8083122</Real>
+    <Real>1.4201462</Real>
+    <Real>1.4388323</Real>
+    <Real>1.9656296</Real>
+    <Real>2.5426836</Real>
+    <Real>3.1112742</Real>
+    <Real>3.5936351</Real>
+    <Real>3.9072165</Real>
+    <Real>3.9865294</Real>
+    <Real>3.8053207</Real>
+    <Real>3.388844</Real>
+    <Real>1.9218614</Real>
+    <Real>2.568121</Real>
+    <Real>3.2490001</Real>
+    <Real>3.8918545</Real>
+    <Real>4.4088783</Real>
+    <Real>4.7131481</Real>
+    <Real>4.7409744</Real>
+    <Real>4.4735146</Real>
+    <Real>3.9476643</Real>
+    <Real>2.4136472</Real>
+    <Real>3.1579394</Real>
+    <Real>3.9075642</Real>
+    <Real>4.5780811</Real>
+    <Real>5.0780678</Real>
+    <Real>5.3257465</Real>
+    <Real>5.2690363</Real>
+    <Real>4.9033108</Real>
+    <Real>4.2786202</Real>
+    <Real>2.84584</Real>
+    <Real>3.6517956</Real>
+    <Real>4.4234724</Real>
+    <Real>5.0685349</Real>
+    <Real>5.4992366</Real>
+    <Real>5.6482835</Real>
+    <Real>5.4839458</Real>
+    <Real>5.0210161</Real>
+    <Real>4.322453</Real>
+    <Real>3.1441929</Real>
+    <Real>3.9655199</Real>
+    <Real>4.7098174</Real>
+    <Real>5.2820435</Real>
+    <Real>5.6046038</Real>
+    <Real>5.6312628</Real>
+    <Real>5.3556099</Real>
+    <Real>4.8135314</Real>
+    <Real>4.0783992</Real>
+    <Real>3.2483988</Real>
+    <Real>4.0362701</Real>
+    <Real>4.710187</Real>
+    <Real>5.1780796</Real>
+    <Real>5.3767667</Real>
+    <Real>5.2831607</Real>
+    <Real>4.9157839</Real>
+    <Real>4.3288655</Real>
+    <Real>3.6015549</Real>
+    <Real>3.1317849</Real>
+    <Real>3.8428361</Real>
+    <Real>4.4165297</Real>
+    <Real>4.7689962</Real>
+    <Real>4.8529115</Real>
+    <Real>4.6657567</Real>
+    <Real>4.2455049</Real>
+    <Real>3.6581583</Real>
+    <Real>2.9827034</Real>
+    <Real>2.8121417</Real>
+    <Real>3.4151664</Real>
+    <Real>3.8747685</Real>
+    <Real>4.1192169</Real>
+    <Real>4.115941</Real>
+    <Real>3.8771</Real>
+    <Real>3.4514832</Real>
+    <Real>2.9083812</Real>
+    <Real>2.3206725</Real>
+    <Real>2.3477883</Real>
+    <Real>2.827544</Real>
+    <Real>3.1741381</Real>
+    <Real>3.3300729</Real>
+    <Real>3.2747903</Real>
+    <Real>3.0280783</Real>
+    <Real>2.6404901</Real>
+    <Real>2.1765728</Real>
+    <Real>1.6984779</Real>
+    <Real>1.6012269</Real>
+    <Real>2.1735911</Real>
+    <Real>2.7940156</Real>
+    <Real>3.3985541</Real>
+    <Real>3.9045522</Real>
+    <Real>4.2257919</Real>
+    <Real>4.2951498</Real>
+    <Real>4.087337</Real>
+    <Real>3.6312225</Real>
+    <Real>2.1503007</Real>
+    <Real>2.8557208</Real>
+    <Real>3.5898733</Real>
+    <Real>4.2732606</Real>
+    <Real>4.8125825</Real>
+    <Real>5.1177659</Real>
+    <Real>5.124867</Real>
+    <Real>4.8177958</Real>
+    <Real>4.2388067</Real>
+    <Real>2.7140679</Real>
+    <Real>3.5306599</Real>
+    <Real>4.3417253</Real>
+    <Real>5.0543671</Real>
+    <Real>5.5714765</Real>
+    <Real>5.809371</Real>
+    <Real>5.7179155</Real>
+    <Real>5.2976604</Real>
+    <Real>4.6060057</Real>
+    <Real>3.2144389</Real>
+    <Real>4.1035142</Real>
+    <Real>4.9418221</Real>
+    <Real>5.6272144</Real>
+    <Real>6.0665331</Real>
+    <Real>6.1924181</Real>
+    <Real>5.9778452</Real>
+    <Real>5.4455352</Real>
+    <Real>4.6677752</Real>
+    <Real>3.5653193</Real>
+    <Real>4.476428</Real>
+    <Real>5.2887335</Real>
+    <Real>5.8965044</Real>
+    <Real>6.2174139</Real>
+    <Real>6.2072616</Real>
+    <Real>5.8671603</Real>
+    <Real>5.2435188</Real>
+    <Real>4.4206529</Real>
+    <Real>3.6956697</Real>
+    <Real>4.5744967</Real>
+    <Real>5.3137517</Real>
+    <Real>5.8104548</Real>
+    <Real>5.997632</Real>
+    <Real>5.8561454</Real>
+    <Real>5.41433</Real>
+    <Real>4.7388363</Real>
+    <Real>3.9206791</Real>
+    <Real>3.5727487</Real>
+    <Real>4.3700495</Real>
+    <Real>5.0027966</Real>
+    <Real>5.3767109</Real>
+    <Real>5.4416862</Real>
+    <Real>5.20049</Real>
+    <Real>4.7021894</Real>
+    <Real>4.0260005</Real>
+    <Real>3.2627959</Real>
+    <Real>3.2152205</Real>
+    <Real>3.8946393</Real>
+    <Real>4.4043908</Real>
+    <Real>4.6634746</Real>
+    <Real>4.6374626</Real>
+    <Real>4.3443403</Real>
+    <Real>3.8440521</Real>
+    <Real>3.2186575</Real>
+    <Real>2.5520351</Real>
+    <Real>2.6890678</Real>
+    <Real>3.2319</Real>
+    <Real>3.6184392</Real>
+    <Real>3.7835035</Real>
+    <Real>3.70541</Real>
+    <Real>3.409534</Real>
+    <Real>2.9565368</Real>
+    <Real>2.4222329</Real>
+    <Real>1.878175</Real>
+    <Real>1.6475232</Real>
+    <Real>2.2223122</Real>
+    <Real>2.8385506</Real>
+    <Real>3.4318674</Real>
+    <Real>3.9211726</Real>
+    <Real>4.2235007</Real>
+    <Real>4.2756395</Real>
+    <Real>4.0555625</Real>
+    <Real>3.5937521</Real>
+    <Real>2.2241931</Real>
+    <Real>2.935997</Real>
+    <Real>3.6674056</Real>
+    <Real>4.3379908</Real>
+    <Real>4.8562441</Real>
+    <Real>5.1362615</Real>
+    <Real>5.1193008</Real>
+    <Real>4.7937689</Real>
+    <Real>4.2043557</Real>
+    <Real>2.8210127</Real>
+    <Real>3.649313</Real>
+    <Real>4.4602737</Real>
+    <Real>5.1594019</Real>
+    <Real>5.6514935</Real>
+    <Real>5.857893</Real>
+    <Real>5.7349739</Real>
+    <Real>5.2890925</Real>
+    <Real>4.5810418</Real>
+    <Real>3.3555751</Real>
+    <Real>4.2623796</Real>
+    <Real>5.1041174</Real>
+    <Real>5.7763052</Real>
+    <Real>6.1876583</Real>
+    <Real>6.2765284</Real>
+    <Real>6.0235319</Real>
+    <Real>5.4584122</Real>
+    <Real>4.6578059</Real>
+    <Real>3.7357712</Real>
+    <Real>4.6702561</Real>
+    <Real>5.4897809</Real>
+    <Real>6.0855961</Real>
+    <Real>6.3770885</Real>
+    <Real>6.3261538</Real>
+    <Real>5.9423218</Real>
+    <Real>5.2799263</Real>
+    <Real>4.4284258</Real>
+    <Real>3.8845158</Real>
+    <Real>4.7908192</Real>
+    <Real>5.5405436</Real>
+    <Real>6.0272064</Real>
+    <Real>6.1852903</Real>
+    <Real>6.00177</Real>
+    <Real>5.5136518</Real>
+    <Real>4.7959204</Real>
+    <Real>3.9452024</Real>
+    <Real>3.7650101</Real>
+    <Real>4.5914612</Real>
+    <Real>5.2367101</Real>
+    <Real>5.6027937</Real>
+    <Real>5.640759</Real>
+    <Real>5.3591185</Real>
+    <Real>4.8152781</Real>
+    <Real>4.0966096</Real>
+    <Real>3.2996311</Real>
+    <Real>3.3953056</Real>
+    <Real>4.1028419</Real>
+    <Real>4.6255789</Real>
+    <Real>4.8789816</Real>
+    <Real>4.8294759</Real>
+    <Real>4.5000954</Real>
+    <Real>3.9582601</Real>
+    <Real>3.2934358</Real>
+    <Real>2.5947468</Real>
+    <Real>2.844394</Real>
+    <Real>3.4119992</Real>
+    <Real>3.8105557</Real>
+    <Real>3.9717791</Real>
+    <Real>3.8745785</Real>
+    <Real>3.5484703</Real>
+    <Real>3.0603485</Real>
+    <Real>2.4922667</Real>
+    <Real>1.9202743</Real>
+    <Real>1.5672455</Real>
+    <Real>2.100791</Real>
+    <Real>2.6662679</Real>
+    <Real>3.2037778</Real>
+    <Real>3.6398871</Real>
+    <Real>3.9010558</Real>
+    <Real>3.9326377</Real>
+    <Real>3.717422</Real>
+    <Real>3.2851353</Real>
+    <Real>2.1268008</Real>
+    <Real>2.7907901</Real>
+    <Real>3.4640956</Real>
+    <Real>4.0714903</Real>
+    <Real>4.5301342</Real>
+    <Real>4.7646532</Real>
+    <Real>4.7257776</Real>
+    <Real>4.4071264</Real>
+    <Real>3.8523524</Real>
+    <Real>2.7102392</Real>
+    <Real>3.4870253</Real>
+    <Real>4.2363963</Real>
+    <Real>4.8694849</Real>
+    <Real>5.3001413</Real>
+    <Real>5.4605227</Real>
+    <Real>5.3165836</Real>
+    <Real>4.8798008</Real>
+    <Real>4.2096257</Real>
+    <Real>3.2372391</Real>
+    <Real>4.0923829</Real>
+    <Real>4.8736057</Real>
+    <Real>5.4820938</Real>
+    <Real>5.8352928</Real>
+    <Real>5.881731</Real>
+    <Real>5.6108675</Real>
+    <Real>5.0569601</Real>
+    <Real>4.2950273</Real>
+    <Real>3.6168756</Real>
+    <Real>4.503046</Real>
+    <Real>5.2673941</Real>
+    <Real>5.8065042</Real>
+    <Real>6.0475302</Real>
+    <Real>5.961133</Real>
+    <Real>5.5642366</Real>
+    <Real>4.9146962</Real>
+    <Real>4.1001482</Real>
+    <Real>3.7720785</Real>
+    <Real>4.6361575</Real>
+    <Real>5.3391314</Real>
+    <Real>5.779213</Real>
+    <Real>5.8972578</Real>
+    <Real>5.6871204</Real>
+    <Real>5.1913652</Real>
+    <Real>4.4873257</Real>
+    <Real>3.669714</Real>
+    <Real>3.6649275</Real>
+    <Real>4.4568224</Real>
+    <Real>5.0652027</Real>
+    <Real>5.3959775</Real>
+    <Real>5.4050202</Real>
+    <Real>5.1057348</Real>
+    <Real>4.5592198</Real>
+    <Real>3.85408</Real>
+    <Real>3.0849638</Real>
+    <Real>3.3115139</Real>
+    <Real>3.9925156</Real>
+    <Real>4.4881387</Real>
+    <Real>4.7168498</Real>
+    <Real>4.6484432</Real>
+    <Real>4.3090754</Real>
+    <Real>3.7682614</Real>
+    <Real>3.1158257</Real>
+    <Real>2.4391923</Real>
+    <Real>2.7784989</Real>
+    <Real>3.3269546</Real>
+    <Real>3.7068789</Real>
+    <Real>3.8521752</Real>
+    <Real>3.7439198</Real>
+    <Real>3.4133866</Real>
+    <Real>2.9284062</Real>
+    <Real>2.3708279</Real>
+    <Real>1.815269</Real>
+    <Real>1.3783464</Real>
+    <Real>1.8361511</Real>
+    <Real>2.3155618</Real>
+    <Real>2.7650533</Real>
+    <Real>3.1232433</Real>
+    <Real>3.3301055</Real>
+    <Real>3.3423195</Real>
+    <Real>3.1479793</Real>
+    <Real>2.7738605</Real>
+    <Real>1.8799469</Real>
+    <Real>2.452564</Real>
+    <Real>3.0253124</Real>
+    <Real>3.5331407</Real>
+    <Real>3.906827</Real>
+    <Real>4.0855651</Real>
+    <Real>4.0317311</Real>
+    <Real>3.7437301</Real>
+    <Real>3.2609353</Real>
+    <Real>2.406625</Real>
+    <Real>3.0801511</Real>
+    <Real>3.7201333</Real>
+    <Real>4.2492986</Real>
+    <Real>4.5956936</Real>
+    <Real>4.7056813</Real>
+    <Real>4.5557613</Real>
+    <Real>4.1607161</Real>
+    <Real>3.5742323</Real>
+    <Real>2.8860726</Real>
+    <Real>3.63169</Real>
+    <Real>4.3019085</Real>
+    <Real>4.8103256</Real>
+    <Real>5.0880337</Real>
+    <Real>5.0959649</Real>
+    <Real>4.8316669</Real>
+    <Real>4.3304205</Real>
+    <Real>3.6600327</Real>
+    <Real>3.2354705</Real>
+    <Real>4.0124297</Real>
+    <Real>4.671484</Real>
+    <Real>5.1217132</Real>
+    <Real>5.3023643</Real>
+    <Real>5.1936049</Real>
+    <Real>4.8171062</Real>
+    <Real>4.2290797</Real>
+    <Real>3.5087883</Real>
+    <Real>3.3838058</Real>
+    <Real>4.145411</Real>
+    <Real>4.7548289</Real>
+    <Real>5.1221147</Real>
+    <Real>5.198</Real>
+    <Real>4.9824762</Real>
+    <Real>4.5193329</Real>
+    <Real>3.8817692</Real>
+    <Real>3.1554947</Real>
+    <Real>3.2952113</Real>
+    <Real>3.9965956</Real>
+    <Real>4.5269589</Real>
+    <Real>4.8027754</Real>
+    <Real>4.7873435</Real>
+    <Real>4.4970365</Real>
+    <Real>3.9911914</Real>
+    <Real>3.3524802</Real>
+    <Real>2.6665878</Real>
+    <Real>2.9829059</Real>
+    <Real>3.588686</Real>
+    <Real>4.0231533</Real>
+    <Real>4.2136354</Real>
+    <Real>4.1350641</Real>
+    <Real>3.8141093</Real>
+    <Real>3.3165569</Real>
+    <Real>2.7254782</Real>
+    <Real>2.1200433</Real>
+    <Real>2.5064065</Real>
+    <Real>2.9961061</Real>
+    <Real>3.3309193</Real>
+    <Real>3.451731</Real>
+    <Real>3.3428841</Real>
+    <Real>3.034642</Real>
+    <Real>2.5902851</Real>
+    <Real>2.0850737</Real>
+    <Real>1.5865968</Real>
+  </Sequence>
+</ReferenceData>
diff --git a/src/testutils/simulationdatabase/ellipsoid-density.mrc b/src/testutils/simulationdatabase/ellipsoid-density.mrc
new file mode 100644 (file)
index 0000000..44ed22c
Binary files /dev/null and b/src/testutils/simulationdatabase/ellipsoid-density.mrc differ