I intend to implement the real-time communication between Philips hardware and Gadgetron. Philips is now keen in supporting this effort and but resources are limited on their side.
Right now, we have a somewhat working converter, which can read a finished scan saved in a proprietary Philips format and translate it to an ISMRMRD file. This file can then be sent to Gadgetron via the mriclient.
Now, we want to move to real-time communication bewteen the Philips scanner and Gadgetron, which is the interesting bit. Philips is happy to help converting the real-time raw data to a format suitable for streaming and implementing the streaming part if an example / mockup were available.
I am a bit confused regarding where to start on this, hence this post. Should I get to know a bit of ACE first, and if so how far ? Would making a mockup real-time client, for instance taking an ISMRMRD file, sending the acq data one by one and displaying an update of the reconstruction in a visualization window, be of any use ? Should I wait for you guys whilst you're making the networking components of Gadgetron independent ?
Thoughts ?
Any suggestion will be warmly welcome. Maybe a topic for next Friday's meeting.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The mriclient included with the Gadgetron does the mockup that I think you
are talking about. It basically simulates what a scanner would do when
sending the data and receiving the images. If that is not helpful, we can
discuss in more detail on one of the Friday meetings. But I would start by
walking through that client.
BTW, at the moment that client depends on a lot of Gadgetron components and
in the long run it would be nice to make it more standalone so it is easy
to install a client on a local computer to send and receive data and the
recon could then be done on a "server".
I intend to implement the real-time communication between Philips hardware
and Gadgetron. Philips is now keen in supporting this effort and but
resources are limited on their side.
Right now, we have a somewhat working converter, which can read a finished
scan saved in a proprietary Philips format and translate it to an ISMRMRD
file. This file can then be sent to Gadgetron via the mriclient.
Now, we want to move to real-time communication bewteen the Philips
scanner and Gadgetron, which is the interesting bit. Philips is happy to
help converting the real-time raw data to a format suitable for streaming
and implementing the streaming part if an example / mockup were available.
I am a bit confused regarding where to start on this, hence this post.
Should I get to know a bit of ACE first, and if so how far ? Would making a
mockup real-time client, for instance taking an ISMRMRD file, sending the
acq data one by one and displaying an update of the reconstruction in a
visualization window, be of any use ? Should I wait for you guys whilst
you're making the networking components of Gadgetron independent ?
Thoughts ?
Any suggestion will be warmly welcome. Maybe a topic for next Friday's
meeting.
So far, my understanding is that the connection is handled in 3 steps, which I named initialisation, transfer and termination.
On initialisation, a GagdetronConnector instance is created, a connection request is made with the right port and hostname config, and the general parameters are sent:
On data transfer, an Acquisition instance is filled, then wrapped to a GadgetContainerMessage instance with the right ID:
ISMRMRD::Acquisitionacq;acq.setFlags(0)// reset acquisition flagsacq.setData(data)// concatenated coil data as vector of floatacq.setTraj(traj)// optional trajectory as vector of floatacq.getIdx().kspace_encode_step_1=kes1;// current PE index acq.getIdx().kspace_encode_step_2=kes2;// current SE index, for M2D or 3D// plus many other set stuff for NumberOfSamples, ActiveChannels...GadgetContainerMessage<ISMRMRD::Acquisition>gcm_acq=newGadgetContainerMessage<ISMRMRD::Acquisition>();*(gcm_acq->getObjectPtr())=acq;GadgetContainerMessage<GadgetMessageIdentifier>*message=newGadgetContainerMessage<GadgetMessageIdentifier>();message->getObjectPtr()->id=GADGET_MESSAGE_ISMRMRD_ACQUISITION;message->cont(gcm_acq);error=connector.putq(message);
On termination, an empty GadgetContainerMessage instance is sent with an id corresponding for a request to close the connection:
So far, my understanding is that the connection is handled in 3 steps, which I named initialisation, transfer and termination.
On initialisation, a GagdetronConnector instance is created, a connection request is made with the right port and hostname config, and the general parameters are sent:
On data transfer, an Acquisition instance is filled, then wrapped to a GadgetContainerMessage instance with the right ID:
ISMRMRD::Acquisition acq;
acq.setFlags(0) // reset acquisition flags
acq.setData(data) // concatenated coil data as vector of float
acq.setTraj(traj) // optional trajectory as vector of float
acq.getIdx().kspace_encode_step_1 = kes1; // current PE index
acq.getIdx().kspace_encode_step_2 = kes2; // current SE index, for M2D or 3D
// plus many other set stuff for NumberOfSamples, ActiveChannels...
GadgetContainerMessage<ismrmrd::acquisition> gcm_acq =
new GadgetContainerMessage<ismrmrd::acquisition>(); (gcm_acq->getObjectPtr()) = acq;
GadgetContainerMessage<gadgetmessageidentifier></gadgetmessageidentifier> message =
new GadgetContainerMessage<gadgetmessageidentifier>();
message->getObjectPtr()->id = GADGET_MESSAGE_ISMRMRD_ACQUISITION;
message->cont(gcm_acq);
error = connector.putq(message);</gadgetmessageidentifier></ismrmrd::acquisition></ismrmrd::acquisition>
On termination, an empty GadgetContainerMessage instance is sent with an id corresponding for a request to close the connection:
There has to be something reading the images as they return. You can choose to manage your own threading for that or use the GadgetronConnector class and build your application around that. You just need something that reads and writes on the socket, you are free to implement that from scratch or use the helper classes that are provided.
Hope this helps,
Michael
Sent from a mobile device - please excuse brevity and/or typos.
So far, my understanding is that the connection is handled in 3 steps, which I named initialisation, transfer and termination.
On initialisation, a GagdetronConnector instance is created, a connection request is made with the right port and hostname config, and the general parameters are sent:
GagdetronConnector connector;
connector.register_writer(...);
connector.register_reader(...);
connector.open(hostname, port);
connector.send_gadgetron_configuration_file(xml_config_file);
connector.send_gadgetron_parameters(xml_header);
On data transfer, an Acquisition instance is filled, then wrapped to a GadgetContainerMessage instance with the right ID:
ISMRMRD::Acquisition acq;
acq.setFlags(0) // reset acquisition flags
acq.setData(data) // concatenated coil data as vector of float
acq.setTraj(traj) // optional trajectory as vector of float
acq.getIdx().kspace_encode_step_1 = kes1; // current PE index
acq.getIdx().kspace_encode_step_2 = kes2; // current SE index, for M2D or 3D
// plus many other set stuff for NumberOfSamples, ActiveChannels...
GadgetContainerMessage<ismrmrd::acquisition> gcm_acq =
new GadgetContainerMessage<ismrmrd::acquisition>(); (gcm_acq->getObjectPtr()) = acq;
GadgetContainerMessage<gadgetmessageidentifier></gadgetmessageidentifier> message =
new GadgetContainerMessage<gadgetmessageidentifier>();
message->getObjectPtr()->id = GADGET_MESSAGE_ISMRMRD_ACQUISITION;
message->cont(gcm_acq);
error = connector.putq(message);
On termination, an empty GadgetContainerMessage instance is sent with an id corresponding for a request to close the connection:</gadgetmessageidentifier></ismrmrd::acquisition></ismrmrd::acquisition>
GadgetContainerMessage<gadgetmessageidentifier>* message =
new GadgetContainerMessage<gadgetmessageidentifier>();
message->getObjectPtr()->id = GADGET_MESSAGE_CLOSE;
error = connector.putq(message);
Please feel free to comment on or rectify this set of steps if some things are inaccurate.</gadgetmessageidentifier></gadgetmessageidentifier>
How can the client read back the images reconstructed by Gadgetron ? Do I need to manage a separate event loop for it ?
getting started with the network protocol for real-time reconstruction
Hi everyone,
I intend to implement the real-time communication between Philips hardware and Gadgetron. Philips is now keen in supporting this effort and but resources are limited on their side.
Right now, we have a somewhat working converter, which can read a finished scan saved in a proprietary Philips format and translate it to an ISMRMRD file. This file can then be sent to Gadgetron via the mriclient.
Now, we want to move to real-time communication bewteen the Philips scanner and Gadgetron, which is the interesting bit. Philips is happy to help converting the real-time raw data to a format suitable for streaming and implementing the streaming part if an example / mockup were available.
I am a bit confused regarding where to start on this, hence this post. Should I get to know a bit of ACE first, and if so how far ? Would making a mockup real-time client, for instance taking an ISMRMRD file, sending the acq data one by one and displaying an update of the reconstruction in a visualization window, be of any use ? Should I wait for you guys whilst you're making the networking components of Gadgetron independent ?
Thoughts ?
Any suggestion will be warmly welcome. Maybe a topic for next Friday's meeting.
Hi Ghislain,
The mriclient included with the Gadgetron does the mockup that I think you
are talking about. It basically simulates what a scanner would do when
sending the data and receiving the images. If that is not helpful, we can
discuss in more detail on one of the Friday meetings. But I would start by
walking through that client.
BTW, at the moment that client depends on a lot of Gadgetron components and
in the long run it would be nice to make it more standalone so it is easy
to install a client on a local computer to send and receive data and the
recon could then be done on a "server".
On Wed, Jun 11, 2014 at 3:22 PM, Ghislain Vaillant ghisvail@users.sf.net
wrote:
So far, my understanding is that the connection is handled in 3 steps, which I named initialisation, transfer and termination.
On initialisation, a GagdetronConnector instance is created, a connection request is made with the right port and hostname config, and the general parameters are sent:
On data transfer, an Acquisition instance is filled, then wrapped to a GadgetContainerMessage instance with the right ID:
On termination, an empty GadgetContainerMessage instance is sent with an id corresponding for a request to close the connection:
Please feel free to comment on or rectify this set of steps if some things are inaccurate.
How can the client read back the images reconstructed by Gadgetron ? Do I need to manage a separate event loop for it ?
The client reader is what handles images sent back from the gadgetron. You registered it at the top with:
connector.register_reader(...);
On Jun 17, 2014, at 10:42 AM, Ghislain Vaillant ghisvail@users.sf.netamp#103;amp#104;amp#105;amp#115;amp#118;amp#97;amp#105;amp#108;amp#64;amp#117;amp#115;amp#101;amp#114;amp#115;amp#46;amp#115;amp#102;amp#46;amp#110;amp#101;amp#116; wrote:
So far, my understanding is that the connection is handled in 3 steps, which I named initialisation, transfer and termination.
On initialisation, a GagdetronConnector instance is created, a connection request is made with the right port and hostname config, and the general parameters are sent:
GagdetronConnector connector;
connector.register_writer(...);
connector.register_reader(...);
connector.open(hostname, port);
connector.send_gadgetron_configuration_file(xml_config_file);
connector.send_gadgetron_parameters(xml_header);
On data transfer, an Acquisition instance is filled, then wrapped to a GadgetContainerMessage instance with the right ID:
ISMRMRD::Acquisition acq;
acq.setFlags(0) // reset acquisition flags
acq.setData(data) // concatenated coil data as vector of float
acq.setTraj(traj) // optional trajectory as vector of float
acq.getIdx().kspace_encode_step_1 = kes1; // current PE index
acq.getIdx().kspace_encode_step_2 = kes2; // current SE index, for M2D or 3D
// plus many other set stuff for NumberOfSamples, ActiveChannels...
GadgetContainerMessage<ismrmrd::acquisition> gcm_acq =
new GadgetContainerMessage<ismrmrd::acquisition>();
(gcm_acq->getObjectPtr()) = acq;
GadgetContainerMessage<gadgetmessageidentifier></gadgetmessageidentifier> message =
new GadgetContainerMessage<gadgetmessageidentifier>();
message->getObjectPtr()->id = GADGET_MESSAGE_ISMRMRD_ACQUISITION;
message->cont(gcm_acq);
error = connector.putq(message);</gadgetmessageidentifier></ismrmrd::acquisition></ismrmrd::acquisition>
On termination, an empty GadgetContainerMessage instance is sent with an id corresponding for a request to close the connection:
GadgetContainerMessage<gadgetmessageidentifier>* message =
new GadgetContainerMessage<gadgetmessageidentifier>();
message->getObjectPtr()->id = GADGET_MESSAGE_CLOSE;
error = connector.putq(message);</gadgetmessageidentifier></gadgetmessageidentifier>
Please feel free to comment on or rectify this set of steps if some things are inaccurate.
How can the client read back the images reconstructed by Gadgetron ? Do I need to manage a separate event loop for it ?
getting started with the network protocol for real-time reconstructionhttps://sourceforge.net/p/gadgetron/discussion/general/thread/adcc4e0a/?limit=25#b020
Sent from sourceforge.nethttp://sourceforge.net because you indicated interest in https://sourceforge.net/p/gadgetron/discussion/general/
To unsubscribe from further messages, please visit https://sourceforge.net/auth/subscriptions/
It's hard to answer your questions in general.
I would not describe it like you do exactly. I wrote this in the manual:
http://sourceforge.net/p/gadgetron/home/Gadgetron%20Streaming%20Architecture/
Does that help?
There has to be something reading the images as they return. You can choose to manage your own threading for that or use the GadgetronConnector class and build your application around that. You just need something that reads and writes on the socket, you are free to implement that from scratch or use the helper classes that are provided.
Hope this helps,
Michael
Sent from a mobile device - please excuse brevity and/or typos.