ismrmrd / ismrmrd

ISMRM Raw Data Format
Other
106 stars 81 forks source link

The method readHeader generates empty string #88

Closed roshtha closed 2 years ago

roshtha commented 7 years ago

Hello all,

I am trying to read simple_gre.h5 file using ISMRMRD api. I use Windows 10 64 bit and QT developement environment. The code is as follows:

#include "ismrmrd/ismrmrd.h"
#include "ismrmrd/dataset.h"
#include "ismrmrd/xml.h"
...... ........
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    <declarations>

    po::options_description desc("Allowed options");

    desc.add_options()
           ("help,h", "produce help message")
           ("query,q", "Dependency query mode")
           ("port,p", po::value<std::string>(&port)->default_value("9002"), "Port")
           ("address,a", po::value<std::string>(&host_name)->default_value("localhost"), "Address (hostname) of Gadgetron host")
           ("filename,f", po::value<std::string>(&in_filename), "Input file")
           ("outfile,o", po::value<std::string>(&out_filename)->default_value("out.h5"), "Output file")
           ("in-group,g", po::value<std::string>(&hdf5_in_group)->default_value("/dataset"), "Input data group")
           ("out-group,G", po::value<std::string>(&hdf5_out_group)->default_value(get_date_time_string()), "Output group name")
           ("config,c", po::value<std::string>(&config_file)->default_value("default.xml"), "Configuration file (remote)")
           ("config-local,C", po::value<std::string>(&config_file_local), "Configuration file (local)")
           ("loops,l", po::value<unsigned int>(&loops)->default_value(1), "Loops")
           ("outformat,F", po::value<std::string>(&out_fileformat)->default_value("h5"), "Out format, h5 for hdf5 and hdr for analyze image")
           ;
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    // Add check to see if input file exists
    if(QFileInfo(in_filename.c_str()).exists()){
        std::cout<<"File exists"<<std::endl;
    }
    else{
        std::cout<<"File does not exist"<<std::endl;
    }

    //Let's open the input file
    boost::shared_ptr<ISMRMRD::Dataset> ismrmrd_dataset;
    std::string xml_config;
    if (open_input_file) {
        ismrmrd_dataset = boost::shared_ptr<ISMRMRD::Dataset>(new ISMRMRD::Dataset(in_filename.c_str(), hdf5_in_group.c_str(), false));
        // Read the header
        ismrmrd_dataset->readHeader(xml_config);
    }
    std::cout << "in_filename.c_str(): " << in_filename.c_str()  << std::endl;
    std::cout << "hdf5_in_group.c_str(): " << hdf5_in_group.c_str() << std::endl;
    std::cout << "xml config:"<< xml_config << std::endl;
    std::cout << "xml config c_str:"<< xml_config.c_str() << std::endl;

    if (!vm.count("query")) {
        ISMRMRD::IsmrmrdHeader h;
        ISMRMRD::deserialize(xml_config.c_str(),h);
    }
    return a.exec();
}

The console output is:

File exists in_filename.c_str(): E:\h5data\simple_gre.h5 hdf5_in_group.c_str(): /dataset xml config: --prints some unreadable text xml config c_str: --prints nothing

And finally, the statement ISMRMRD::deserialize(xml_config.c_str(),h); produces the following error window.

err

Thanks.

hansenms commented 7 years ago

Are you sure you are opening the file? The code:

    if (open_input_file) {
        ismrmrd_dataset = boost::shared_ptr<ISMRMRD::Dataset>(new ISMRMRD::Dataset(in_filename.c_str(), hdf5_in_group.c_str(), false));
        // Read the header
        ismrmrd_dataset->readHeader(xml_config);
    }

is only executed if open_input_file is true. Where is it defined?

roshtha commented 7 years ago

The variable open_input_file is initialized inside main() method itself and the code inside ifblock is getting executed. bool open_input_file = true;

roshtha commented 7 years ago

I edit source code and hardcode input file names and group names.

#include <QCoreApplication>

#include "boost/shared_ptr.hpp"

#include "ismrmrd/ismrmrd.h"
#include "ismrmrd/dataset.h"
#include "ismrmrd/xml.h"
#include <QFileInfo>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::string in_filename;
    std::string hdf5_in_group;

    in_filename = "E:\\h5data\\simple_gre.h5";
    hdf5_in_group = "/dataset";

    if(QFileInfo(in_filename.c_str()).exists()){
        std::cout<<"File exists"<<std::endl;
    }
    else{
        std::cout<<"File does not exist"<<std::endl;
    }

    boost::shared_ptr<ISMRMRD::Dataset> ismrmrd_dataset;
    std::string xml_config;

    ismrmrd_dataset = boost::shared_ptr<ISMRMRD::Dataset>(new ISMRMRD::Dataset(in_filename.c_str(), hdf5_in_group.c_str(), false));
    ismrmrd_dataset->readHeader(xml_config);

    std::cout << "in_filename.c_str():  " << in_filename.c_str()  << std::endl;
    std::cout << "hdf5_in_group.c_str():  " << hdf5_in_group.c_str() << std::endl;
    std::cout << "xml config:  "<< xml_config.c_str() << std::endl;

    ISMRMRD::IsmrmrdHeader h;
    ISMRMRD::deserialize(xml_config.c_str(),h);
    return a.exec();
}

The console output is: untitled

hansenms commented 7 years ago

Not quite sure what is going on on your machine, but here is a test case for you that I have confirmed works:

First a main.cpp file:

#include "boost/shared_ptr.hpp"

#include "ismrmrd/ismrmrd.h"
#include "ismrmrd/dataset.h"
#include "ismrmrd/xml.h"

int main(int argc, char *argv[])
{
    std::string in_filename;
    std::string hdf5_in_group;

    in_filename = "simple_gre.h5";
    hdf5_in_group = "/dataset";

    boost::shared_ptr<ISMRMRD::Dataset> ismrmrd_dataset;
    std::string xml_config;

    ismrmrd_dataset = boost::shared_ptr<ISMRMRD::Dataset>(new ISMRMRD::Dataset(in_filename.c_str(), hdf5_in_group.c_str(), false));
    ismrmrd_dataset->readHeader(xml_config);

    std::cout << "in_filename.c_str():  " << in_filename.c_str()  << std::endl;
    std::cout << "hdf5_in_group.c_str():  " << hdf5_in_group.c_str() << std::endl;
    std::cout << "xml config:  "<< xml_config.c_str() << std::endl;

    ISMRMRD::IsmrmrdHeader h;
    ISMRMRD::deserialize(xml_config.c_str(),h);
    return 0;
}

And a CMakeLists.txt file to go with it:

cmake_minimum_required (VERSION 2.8.11)
project (simple_ismrmrd)

find_package(Boost COMPONENTS thread system program_options filesystem REQUIRED)
find_package(ISMRMRD REQUIRED)
find_package(HDF5 1.8 REQUIRED COMPONENTS C)

include_directories(${Boost_INCLUDE_DIR} ${ISMRMRD_INCLUDE_DIR})
link_directories( ${ISMRMRD_LIB_DIR} )

add_executable(simple_ismrmrd main.cpp)
target_link_libraries(simple_ismrmrd ${ISMRMRD_LIBRARIES} ${Boost_LIBRARIES} )

I compile that with:

mkdir -p build
cd build
cmake ../
make

Then I place simple_gre.h5 in the same folder and run:

./simple_ismrmrd

The output is:

in_filename.c_str():  simple_gre.h5
hdf5_in_group.c_str():  /dataset
xml config:  <?xml version="1.0"?>
<ismrmrdHeader xmlns="http://www.ismrm.org/ISMRMRD" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="http://www.ismrm.org/ISMRMRD ismrmrd.xsd">
    <studyInformation>
        <studyTime>15:27:49</studyTime>
    </studyInformation>
    <acquisitionSystemInformation>
        <systemVendor>SIEMENS</systemVendor>
        <systemModel>Avanto</systemModel>
        <systemFieldStrength_T>1.494000</systemFieldStrength_T>
        <relativeReceiverNoiseBandwidth>0.790000</relativeReceiverNoiseBandwidth>
        <receiverChannels>32</receiverChannels>
        <coilLabel>
            <coilNumber>0</coilNumber>
            <coilName>16Ch_Body_P:P7A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>1</coilNumber>
            <coilName>16Ch_Body_P:P7B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>2</coilNumber>
            <coilName>16Ch_Body_P:P8B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>3</coilNumber>
            <coilName>16Ch_Body_P:P8A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>4</coilNumber>
            <coilName>16Ch_Body_P:P5A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>5</coilNumber>
            <coilName>16Ch_Body_P:P5B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>6</coilNumber>
            <coilName>16Ch_Body_P:P6B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>7</coilNumber>
            <coilName>16Ch_Body_P:P6A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>8</coilNumber>
            <coilName>16Ch_Body_P:P3A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>9</coilNumber>
            <coilName>16Ch_Body_P:P3B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>10</coilNumber>
            <coilName>16Ch_Body_P:P4B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>11</coilNumber>
            <coilName>16Ch_Body_P:P4A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>12</coilNumber>
            <coilName>16Ch_Body_P:P1A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>13</coilNumber>
            <coilName>16Ch_Body_P:P1B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>14</coilNumber>
            <coilName>16Ch_Body_P:P2B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>15</coilNumber>
            <coilName>16Ch_Body_P:P2A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>16</coilNumber>
            <coilName>16Ch_Body_A:A7A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>17</coilNumber>
            <coilName>16Ch_Body_A:A7B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>18</coilNumber>
            <coilName>16Ch_Body_A:A8B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>19</coilNumber>
            <coilName>16Ch_Body_A:A8A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>20</coilNumber>
            <coilName>16Ch_Body_A:A5A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>21</coilNumber>
            <coilName>16Ch_Body_A:A5B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>22</coilNumber>
            <coilName>16Ch_Body_A:A6B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>23</coilNumber>
            <coilName>16Ch_Body_A:A6A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>24</coilNumber>
            <coilName>16Ch_Body_A:A3A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>25</coilNumber>
            <coilName>16Ch_Body_A:A3B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>26</coilNumber>
            <coilName>16Ch_Body_A:A4B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>27</coilNumber>
            <coilName>16Ch_Body_A:A4A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>28</coilNumber>
            <coilName>16Ch_Body_A:A1A</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>29</coilNumber>
            <coilName>16Ch_Body_A:A1B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>30</coilNumber>
            <coilName>16Ch_Body_A:A2B</coilName>
        </coilLabel>
        <coilLabel>
            <coilNumber>31</coilNumber>
            <coilName>16Ch_Body_A:A2A</coilName>
        </coilLabel>
    </acquisitionSystemInformation>
    <experimentalConditions>
        <H1resonanceFrequency_Hz>63620740</H1resonanceFrequency_Hz>
    </experimentalConditions>
    <encoding>
        <encodedSpace>
            <matrixSize>
                <x>256</x>
                <y>128</y>
                <z>1</z>
            </matrixSize>
            <fieldOfView_mm>
                <x>600.000000</x>
                <y>300.000000</y>
                <z>5.000000</z>
            </fieldOfView_mm>
        </encodedSpace>
        <reconSpace>
            <matrixSize>
                <x>128</x>
                <y>128</y>
                <z>1</z>
            </matrixSize>
            <fieldOfView_mm>
                <x>300.000000</x>
                <y>300.000000</y>
                <z>5.000000</z>
            </fieldOfView_mm>
        </reconSpace>
        <encodingLimits>
            <kspace_encoding_step_1>
                <minimum>0</minimum>
                <maximum>127</maximum>
                <center>64</center>
            </kspace_encoding_step_1>
            <kspace_encoding_step_2>
                <minimum>0</minimum>
                <maximum>0</maximum>
                <center>0</center>
            </kspace_encoding_step_2>
            <slice>
                <minimum>0</minimum>
                <maximum>0</maximum>
                <center>0</center>
            </slice>
            <set>
                <minimum>0</minimum>
                <maximum>0</maximum>
                <center>0</center>
            </set>
        </encodingLimits>
        <trajectory>cartesian</trajectory>
        <parallelImaging>
            <accelerationFactor>
                <kspace_encoding_step_1>1</kspace_encoding_step_1>
                <kspace_encoding_step_2>1</kspace_encoding_step_2>
            </accelerationFactor>
            <calibrationMode>other</calibrationMode>
        </parallelImaging>
    </encoding>
    <sequenceParameters>
        <TR>5.860000</TR>
        <TE>2.960000</TE>
    </sequenceParameters>
</ismrmrdHeader>

It is not really possible for me to debug your system any further. It could be any number of problems with dependent libraries, etc. etc. but try if you can get the working example that I attached to work and then start from there.

Hope this helps.

I will close this issues if you have no other information.

roshtha commented 7 years ago

Thanks for your reply. I could not run the above code and still getting the same error.

Now I tried the following: I build ismrmrd library in debug mode using Visual Studio 2015 community edition (64 bit). Then I run my main() function in debug mode from QT Creator (QT 5.8), The methods readHeader and ismrmrd_read_header run successfully till the statement free(temp); in readHeader method.

At statement free(temp); in dataset.cpp an errror occurs: HEAP[Clientcode.exe]: Invalid address specified to RtlValidateHeap( 00000258DF050000, 00000258E0CC9230 ) and execution stops.

When I tried by commenting this line and executing again, the method returns the header information from .h5 file.

Is this something specific to Visual studio compiler I am using? Instead of commenting out, how can I correct this error? I am new to C++ development.

Thanks.

hansenms commented 7 years ago

I don't understand how you can get the same QT related error when using the code I wrote above. It has no QT stuff in it.

commenting out the free(temp); is not a good path. That creates a leak.