LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Pulse gating/triggering MRI - generate rising voltage (AO) for each peak in pulse signal (AI)

Hi there,

 

Collecting voltage signal corresponding to invasive blood pressure using NI9215, and trying to send rising voltage trigger signal from 9923 (AO) upon detection of each systolic peak. Both on 9174 cDAQ chassis. The purpose is to trigger (cyclically) acquisition in MRI machine.

 

I have attempted to modify code (producer-consumer) we were using for a different experiment to trigger a high speed camera with a single threshold acceleration. Please see attached VI.  However, this response is a single trigger rather than a trigger for each peak.

 

Is there a completely better approach for this problem, or changes that can be made to the attached to achieve this? I have looked at the waveform peak detector type VIs but they output number of peaks detected, rather than a boolean at the time of each detection event.

 

Thanks in advance for any help,

Claire

 

0 Kudos
Message 1 of 10
(3,766 Views)

Hi ClaireJ,

 

1) With respect to sending voltage trigger signal on detection of each peak, you can add a while loop outside the flat sequence based on original vi. Each time 'wait on notification' fuction receive a message from 'send notification' function,while loop will wait for evevt occuring and case structure will determine whether it meets the trigger condition or not. See the attached vi picture below.

 

2) As for waveform peak detector type VI, you can use amplitute and location at each detect event. Each time waveform peak detector acquire an array of amplitute, elements of array could be indexed to be compared to systolic pressure trigger threshold which determine whether it is time to sending notification to generate a trigger signal. See the attached vi picture below.

 

3) Solutions above on can not ensure that sending trigger signal each systolic peak because there are several systolic peaks in a set of array. In that case, sample rate should be increased and samples per channel should be decearsed.

 

Let us know how you get on.

 

Best regard

 

Eriksen

0 Kudos
Message 2 of 10
(3,679 Views)

It sounds to me like you might be wanting pretty precise sync -- you refer to cyclically triggering acquisition in an MRI in response to a systolic peak.  Any kind of buffered acquisition followed by software peak detection is going to throw you *out* of sync in an irregular way.  (I.E., you can't just figure out how *far* out of sync you'll be ahead of time and then compensate.  It's gonna keep varying.)

 

This seems like something you need to do in hardware.  I don't know your cDAQ devices, but I'd be recommending that you use an AI module capable of analog triggering.  Then you'd configure an appropriate analog trigger trip point, and use the (hardware-driven) "analog comparison event" to drive your output pulse.  One method would be an analog output module capable of retriggerable finite acquisition.

 

Sorry, I can't lay out all details, just a few breadcrumbs to point you down a path I think you'll end up needing.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 3 of 10
(3,657 Views)

Hi Kevin,

My understanding is that I can't do hardware-based triggering on the cDAQ.

I've got hold of an old cRIO chassis (9074) and a number of I/O units (9403, 9205, 9264) and I hope that will provide the hardware-based triggering function. I haven't worked with cRIO at all before as my applications have all been pure DAQ, so it might take some time to get my head around it. I'll try to post updates of any success here.

Thanks for taking the time to respond. If you have any further advice, happy to hear it!

Claire.

0 Kudos
Message 4 of 10
(3,626 Views)

Hi Kevin, Erik,

 

Over the last week I have tried working with a borrowed cRIO9035 (9260, 9239) but having never worked with FPGA before, and not able to find any examples that are similar to what I want to achieve, I have not been able to make progress. Many futile hours in the lab with nothing to show for it.

 

Therefore, I have gone back to the cDAQ, with a 9205 module, with fingers crossed that the accuracy of the timing will be ok. I did try implementing this (https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z000000P6WTSA0&l=en-AU), which I thought might address Kevin's suggestion to keep the triggering on the hardware itself, but I couldn't figure out how to make this applicable to my situation.

 

So, now I am working with implementing this code (https://forums.ni.com/t5/LabVIEW/Generate-Finite-Analog-Output-Waveform-on-Demand/td-p/3354071?profi...) which incidentally Kevin helped a user with in 2016.  I've got it to the point that it is embedded in my overarching VI, and I have a boolean control on the front panel as the trigger (I will later change this to the blood pressure systolic threshold boolean).

 

However, I have two main issues at this stage:

1) The signal provided by the AO is a sine wave, even through I believe I have requested a square wave.

2) I can't figure out how to limit the signal to a single cycle of the wave. I need to provide a rising step voltage with a 10ms duration at the peak. I have reasoned that this is equivalent to a square wave of 50 Hz (1s/20ms).

 

Does anyone have a suggestion for correcting this portion of the code?  [or, if someone is able to supply some fairly formed code for the cRIO I can attempt that again]

 

Thanks in advance,

Claire

 

0 Kudos
Message 5 of 10
(3,581 Views)

Your immediate questions:

1. Yes, I see that you have a hard-coded constant requesting square wave.  That function worked fine here and gave me a square wave.  When I switched to sine it gave me a sine.  The *default* behavior is to produce a sine if the "square wave" wire is somehow not actually connected to the input terminal.

2. You haven't accounted for the inherent relationships among waveform frequency, sample rate, # samples, and signal duration.

    For Finite Acquisition, you are correctly feeding the same # into the 'samples per channel' input of DAQmx Timing and to the 'sampling info' cluster input for the function generator.  This way you've *defined* a waveform with the same # samples that your task is configured to generate.  The problem is that you've chosen the wrong # to feed.

    Because you want 1 cycle of a 50 Hz square wave, you need to ask for a # of samples that require 20 msec to generate.  With your sample rate of 10 kHz, you should be defining and generating 200 samples rather than 10000.

 

All that said, your earlier description suggests to me that this entire approach might be doomed.  It just isn't capable of yielding precise, repeatable, low-latency timing from systolic peak detection to pulse generation.  I'll look at that analog triggering example and take a shot at modifying it for your app.  No guarantees -- I have no hardware here and don't have specific familiarity with your cDAQ devices' capabilities and limitations.  But I'll give it a shot.

 

 

-Kevin P

 

 

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 6 of 10
(3,572 Views)

Code and snippet.  Added fairly extensive notes to explain the mods I made from the linked example.  If it doesn't work, keep a record of specific errors, where they occur, and the result from any other experiments or mods.  This should at least be pretty close IF your devices support the modes/features I'm trying to exercise.

 

 

-Kevin P

 

Re-triggered AO from AI analog triggering on CompactDAQ.png

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 7 of 10
(3,567 Views)

Hi Kevin,

 

Thanks for this, really appreciate it. 

So far, I've loaded your VI and changed the channels to match mine. When I run it, I get the following error:Reriggerable error_ScreenCapture.PNG

 

This article seems to imply that only modules starting with 6xxx can be re-triggerable. (https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z0000019MXxSAM&l=en-AU).  All of my modules are 9xxx cDAQ/cRIO modules.  The AI I'm using is a 9205, and the AO is a 9264.

I'll keep playing with the code you sent.

Thoughts?

Claire

0 Kudos
Message 8 of 10
(3,542 Views)

Hi Kevin, hope you're having/had a good day.

 

After my lack of success with cDAQ chassis and modules (despite your great help, see previous post), I've switched back to the cRIO, which I'm making more progress with today than I did last week. I wonder if you also work with FPGA and if you would be willing to help me with this?

 

I've decided to ignore the layers of VIs needed, and just concentrate on the FPGA VI for now. I've simplified it to just the triggering requirement, and I'll add back in the data acquisition and writing to file later once I've got this working.

 

I've implemented the example shown in this video (13. Custom Analog Triggering in LabVIEW FPGA, http://www.ni.com/tutorial/14532/en/ ), and got it working copying their code exactly (I'm using a 9264 and 9205 in a cRIO-9035). In this example they use the trigger to start an acquisition event. So, I've tried to change it to using an AI to trigger an AO output (squarewave).

 

To this point, the first three panels of the GUI are working, but I see no output on the 4th panel, which should show outputs on the boolean indicator and slide indicator if the square wave signal is actually being output.

 

My questions:

1) Does this approach look like it might work?

2) Can you see what I'm doing wrong with the square wave output? the trigger for it is working (i.e. a "true" boolean is sent to the lower loop) but no signal is output.

3) Once I have that working, how can I ensure that the square wave output is a single cycle only per each trigger event (I'm sorry I didn't really understand your explanation in the previous post)?

 

I have to go home to see my kids for the last hour of their Sunday, but I'll check in again later. Thanks again for your help, I really appreciate it.  I've attached the whole project here in case you need it, but all that I've worked on is the FPGA file.

 

Claire.

 

0 Kudos
Message 9 of 10
(3,533 Views)

Unfortunately, I have only passing familiarity with FPGA and can't really offer anything there.  The best solution possible via FPGA will be better than the best one using only DAQmx, but it may be a fairly long & complicated road to get you there if you aren't already moderately expert with it.  That's my impression at least.

 

I still think I can help with the DAQmx part which should get you to a pretty good solution fairly quickly.  The main detriments of the DAQmx approach are:

- you're stuck with a fixed trigger threshold value unless you stop the task to change it.   My earlier suggestion that a voltage equivalent of 100 mmHg might be a good starting point is not foolproof.   Some systolics won't exceed 100, some diastolics might.  This would lead to missed triggers and false triggers respectively.  

- An FPGA approach could be more sophisticated and adaptive in how it detects peaks, and how it identifies them as systolic vs diastolic.  But I wouldn't assume it's trivial to implement a sophisticated approach in FPGA either.

 

Sticking with just DAQmx, I think we can get something going that will at least be pretty useful, if not perfect.  I'll modify the previous code I posted to give you a workaround for hardware that doesn't natively support retriggering of AO tasks.  The idea is illustrated and explained more here.  I'm just adapting the concept to your particular situation.

 

The main idea is to make a retriggerable finite pulse train task which *should* be supported by your chassis, then use that pulse train as the AO sample clock.  (We also treat the AO task as continuous, knowing that we drive it with an intermittent finite sample clock from the counter task.)

 

The code is attached below.  I've changed the constant that references the "Analog Comparison Event" so it comes from the chassis not the individual module.  That's how it showed up when I made simulated devices to test the code.  (It ran without error with a simulated 9174 chassis, a simulated 9205 AI module capable of analog triggering, and a simulated 9923 AO module.)

 

 

-Kevin P

 

 

 

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 10 of 10
(3,497 Views)