PTB-MR / mrpro

MR image reconstruction and processing.
https://ptb-mr.github.io/mrpro/
Apache License 2.0
19 stars 2 forks source link

Siemens Special Tab #23

Open mxlutz opened 1 year ago

mxlutz commented 1 year ago

It would be nice if we could load in the attruibutes from the Siemens special tab automatically.

Would it be easiest to add a Dictionary Attribute to the KData Header?

Also to save the Special Tab in the ismrmrd files some small changes in the xls and xlm of siemens_to_ismrmrd are necessary, is that something we want to standardize?

fzimmermann89 commented 1 year ago

Good point!

Can you provide an example of an xsl and an ismrmrd file? (Does not have to be public)

I believe it would be good to consider this already now when were are designing the header class

mxlutz commented 1 year ago

Yes sure! I did that for VB17, so probably for the new scanner we have to adapt it again (or maybe its already in the default one for XA or what file siemens_to_ismrmrd will use). I had to change the filendings to txt to attach it here

In the xsl the following lines are important:

                <xsl:for-each select="siemens/MEAS/sWipMemBlock/alFree">
                    <xsl:if test=". &gt; 0">
                      <userParameterDouble>
                            <name>alWipMemBlock</name>
                        <value>
                            <xsl:value-of select=". " />
                        </value>
                        </userParameterDouble>
                    </xsl:if>
                </xsl:for-each> 

                <xsl:for-each select="siemens/MEAS/sWipMemBlock/adFree">
                    <xsl:if test=". &gt; 0">
                        <userParameterDouble>
                            <name>adWipMemBlock</name>
                            <value>
                                <xsl:value-of select=". " />
                            </value>
                        </userParameterDouble>    
                    </xsl:if>
                </xsl:for-each> 

The filoper.py shows how to pass the custom files to siemens_to_ismrmrd

I think the xml was actually not important, I also added some lines to read out the RF Amplifer reference amplitude that is important for me but usually not read, I dont know whether we want to add that?

fileoper.py.txt IsmrmrdParameterMap_Siemens_custom_Max.xsl.txt IsmrmrdParameterMap_Siemens_VB17_custom_Max.xml.txt

mxlutz commented 1 year ago

I just checked it and in the current version its already included (so I guess that should work with XA61?), so we wouldnt need any specific files for siemens_to_ismrmrd

https://github.com/ismrmrd/siemens_to_ismrmrd/blob/master/parameter_maps/IsmrmrdParameterMap_Siemens.xsl

fzimmermann89 commented 1 year ago

Not sure if I understood everything. The current scope of MRPro start with ismrmrd files. So the "interesting" XML would be the final one after the conversion which is saved inside the ismrmrd h5.

We just have to take care that all user parameters are copied to from the ismrmrd header to our header.

So maybe you could point me to a converted file somewhere on echo that contains these parameters in the header?

mxlutz commented 1 year ago

Ah sorry I think that was unclear from me.

As I understood the XML file is not included in the ismrmrd header, but tells the siemens_to_ismrmrd converter what attributes from the Siemens RAW file(.dat) to write where into the header of the ismrmrd (.h5) file. So thats actually even one step before and probably not part of this repo but something we should think of how to handle that?

fzimmermann89 commented 1 year ago

There is still some confusion. The data flow is:

Siemens XML->XSL Transformation --> ISMRMRD XML embedded in the h5-> ismrmrd python uses xsd file and xsdata to transform this into a dataclass -> our code reads the ismrmrd dataclass

The XSL is helpful as this defines the names to be used within ismrmrd and therefore later on in the python code.

But it would also be helpful to either get the XML which is emedded in the ismrmrd .h5 (under dataset/XML as a as string. Or just an ISMRMRD h5- on echo.

How do you in the end access these values in ptbpyrecon?

Afaik we currently only read in a fixed list of attributes. So this might get lost in the ismrmrd to MRPro Kdata code.

mxlutz commented 1 year ago

Ah okay sorry, I got confused with XSL and XML.

So to be sure: XSL: Translates one sort of XML to another XML XML: is actually embedded in the h5

I put an example file on echo under Y:\_allgemein\projects\Max\ForFelix

I played around a little, might be helpful:

import h5py
import numpy as np
import xml.etree.ElementTree as ET
import ismrmrd

file = '/echo3/allgemein/projects/Max/ForFelix/meas_MID68_ml_MRF_v026_br128_tr4_4_te2_2_bw590_60deg_CP_FID24628.h5'
#%% xml hdr
f = h5py.File(file, 'r')
xml = np.array(f['dataset']['xml'][0])
f.close()

root = ET.fromstring(xml)

print('\n\nThis is the userParameters section from xml: \n')
for child in root[-1]:
    print(child[0].text, child[1].text)

#%% ismrmrd hdr
dset = ismrmrd.Dataset(file)
acq = dset.read_acquisition(0)
dset.close()

print('\n\nThis is the Head from ismrmrd Object: \n')
print(acq.getHead())

So in the XML the Special card is under userParameters and then adWipMemBlock or alWipMemBlock (one is double, the other int). They dont translate into the user_int and user_float in ismrmrd, which could be a place to store that or what is that reserved for?

In my PTBRecon branch I added something to read in the WipMemBlock: https://github.com/ckolbPTB/PtbPyRecon/commit/096632c1803a98f8c6e7b15c7ac1912217dfb243

fzimmermann89 commented 1 year ago

So to summarize: All that you ask for is that ismrmrdHeader/userParameters/* is accessible from our header, correct?

This is currently accessible via KData.header.misc['userParameters'] (i.e. a bit hidden and not considered part of our stable and tested API)

But we could also promote it to one of our "important" Parameters that we put directly under the KData.header This sounds somewhat reasonable - if somebody makes an effort to put something there when converting the file, they most likely need it.

For now, we will wait with adding it the KHeader directly, as this is not that crucial for now.

But please voice your opinions regarding the promotion, @schuenke @ckolbPTB

mxlutz commented 1 year ago

Yes, so if it is accessible from KData.header.misc['userParameters'] that should be fine. There could also be other parameters that people want to access (for me it's e.g. the RF Reference Voltage, which can be saved in the ismrmrd file with a custom XML/XSL file), so if the whole header from the ismrmrd file is accessible in KData that seems like a good solution to me.

Should we close this issue for now? We could reopen it if necessary

fzimmermann89 commented 1 year ago

Let's keep it open, till the KHeader fields are a bit more settled ;)

fzimmermann89 commented 1 month ago

@ckolbPTB In #425, we make misc more private. Maybe it would be good to discuss parsing userParameters into our header?

ckolbPTB commented 1 month ago

The parameters in the special card are very specific to different uses cases and I don't think image reconstruction algorithms provided via MRpro should depend on them. Also for different sequences the same parameter means something differenet. Therefore I think _misc is the right place for them. If we parse them into our header, it would suggest that they can be used like any other header parameter.

fzimmermann89 commented 2 weeks ago

Maybe you missunderstood me, I was wondering if we should provide userParameters as userParameters in the header, similar to userids, userint, and userfloat for each acquisition -- just as a value. What it means etc is up to the caller.