diff --git a/src/mrseq/sequences/t1_molli_bssfp.py b/src/mrseq/sequences/t1_molli_bssfp.py index 45979a1..0558bcd 100644 --- a/src/mrseq/sequences/t1_molli_bssfp.py +++ b/src/mrseq/sequences/t1_molli_bssfp.py @@ -19,6 +19,7 @@ def t1_molli_bssfp_kernel( tr: float | None, inversion_times: np.ndarray, min_cardiac_trigger_delay: float, + use_soft_delay: bool, fov_xy: float, n_readout: int, readout_oversampling: float, @@ -48,6 +49,9 @@ def t1_molli_bssfp_kernel( min_cardiac_trigger_delay Minimum delay after cardiac trigger (in seconds). The total trigger delay is implemented as a soft delay and can be chosen by the user in the UI. + use_soft_delay + Use soft-delay functionality available from pulseq version 1.5.0 to allow UI adaption of trigger delay. + If set to false only the min_cardiac_trigger_delay is used. fov_xy Field of view in x and y direction (in meters). n_readout @@ -174,12 +178,13 @@ def t1_molli_bssfp_kernel( print(f'Acquisition window per cardiac cycle = {current_tr * len(pe_steps) * 1000:.3f} ms') # create trigger soft delay (total duration: user_input/1.0 - min_cardiac_trigger_delay) - trig_soft_delay = pp.make_soft_delay( - hint='trig_delay', - offset=-min_cardiac_trigger_delay, - factor=1.0, - default_duration=0.8 - min_cardiac_trigger_delay, - ) + if use_soft_delay: + trig_soft_delay = pp.make_soft_delay( + hint='trig_delay', + offset=-min_cardiac_trigger_delay, + factor=1.0, + default_duration=0.8 - min_cardiac_trigger_delay, + ) # obtain noise samples seq.add_block(pp.make_label(label='LIN', type='SET', value=0), pp.make_label(label='SLC', type='SET', value=0)) @@ -219,7 +224,8 @@ def t1_molli_bssfp_kernel( seq.add_block(pp.make_trigger(channel='physio1', duration=constant_trig_delay)) # add variable part of trigger delay (soft delay) - seq.add_block(trig_soft_delay) + if use_soft_delay: + seq.add_block(trig_soft_delay) # add inversion pulse for idx in t1_inv_prep.block_events: @@ -244,7 +250,8 @@ def t1_molli_bssfp_kernel( seq.add_block(pp.make_trigger(channel='physio1', duration=constant_trig_delay)) # add variable part of trigger delay (soft delay) - seq.add_block(trig_soft_delay) + if use_soft_delay: + seq.add_block(trig_soft_delay) rf_signal = rf.signal.copy() for pe_index in range(-n_bssfp_startup_pulses, len(pe_steps)): @@ -307,7 +314,8 @@ def t1_molli_bssfp_kernel( seq.add_block(pp.make_trigger(channel='physio1', duration=min_cardiac_trigger_delay)) # add variable part of trigger delay (soft delay) - seq.add_block(trig_soft_delay) + if use_soft_delay: + seq.add_block(trig_soft_delay) # write all required parameters in the seq-file header/definitions seq.set_definition('FOV', [fov_xy, fov_xy, slice_thickness]) @@ -417,6 +425,7 @@ def main( inversion_times=inversion_times, min_cardiac_trigger_delay=np.max(inversion_times) + 0.02, # max inversion time + approx inversion pulse duration + use_soft_delay=True, fov_xy=fov_xy, n_readout=n_readout, readout_oversampling=readout_oversampling, diff --git a/src/mrseq/sequences/t1_t2_spiral_cmrf.py b/src/mrseq/sequences/t1_t2_spiral_cmrf.py index d8b79d3..eb8c73e 100644 --- a/src/mrseq/sequences/t1_t2_spiral_cmrf.py +++ b/src/mrseq/sequences/t1_t2_spiral_cmrf.py @@ -24,6 +24,7 @@ def t1_t2_spiral_cmrf_kernel( t2_prep_echo_times: np.ndarray, tr: float | None, min_cardiac_trigger_delay: float, + use_soft_delay: bool, fov_xy: float, n_readout: int, readout_oversampling: Literal[1, 2, 4], @@ -50,6 +51,9 @@ def t1_t2_spiral_cmrf_kernel( min_cardiac_trigger_delay Minimum delay after cardiac trigger (in seconds). The total trigger delay is implemented as a soft delay and can be chosen by the user in the UI. + use_soft_delay + Use soft-delay functionality available from pulseq version 1.5.0 to allow UI adaption of trigger delay. + If set to false only the min_cardiac_trigger_delay is used. fov_xy Field of view in x and y direction (in meters). n_readout @@ -196,12 +200,13 @@ def t1_t2_spiral_cmrf_kernel( prot.write_xml_header(hdr.toXML('utf-8')) # create trigger soft delay (total duration: user_input/1.0 - min_cardiac_trigger_delay) - trig_soft_delay = pp.make_soft_delay( - hint='trig_delay', - offset=-min_cardiac_trigger_delay, - factor=1.0, - default_duration=0.5 - min_cardiac_trigger_delay, - ) + if use_soft_delay: + trig_soft_delay = pp.make_soft_delay( + hint='trig_delay', + offset=-min_cardiac_trigger_delay, + factor=1.0, + default_duration=0.5 - min_cardiac_trigger_delay, + ) # obtain noise samples seq.add_block(pp.make_label(label='LIN', type='SET', value=0), pp.make_label(label='SLC', type='SET', value=0)) @@ -238,7 +243,8 @@ def t1_t2_spiral_cmrf_kernel( seq.add_block(pp.make_trigger(channel='physio1', duration=constant_trig_delay)) # add variable part of trigger delay (soft delay) - seq.add_block(trig_soft_delay) + if use_soft_delay: + seq.add_block(trig_soft_delay) # add all events of T1prep block for idx in t1prep_block.block_events: @@ -248,7 +254,8 @@ def t1_t2_spiral_cmrf_kernel( elif block % 5 == 1: # add trigger and trigger delay(s) seq.add_block(pp.make_trigger(channel='physio1', duration=min_cardiac_trigger_delay)) - seq.add_block(trig_soft_delay) + if use_soft_delay: + seq.add_block(trig_soft_delay) # add T2prep for every other block else: @@ -263,7 +270,8 @@ def t1_t2_spiral_cmrf_kernel( seq.add_block(pp.make_trigger(channel='physio1', duration=constant_trig_delay)) # add variable part of trigger delay (soft delay) - seq.add_block(trig_soft_delay) + if use_soft_delay: + seq.add_block(trig_soft_delay) # add all events of T2prep block for idx in t2prep_block.block_events: @@ -425,6 +433,7 @@ def main( t2_prep_echo_times=t2_prep_echo_times, tr=tr, min_cardiac_trigger_delay=np.max(t2_prep_echo_times) + 0.05, # max T2prep echo time and buffer for spoiler + use_soft_delay=True, fov_xy=fov_xy, n_readout=n_readout, readout_oversampling=readout_oversampling, diff --git a/src/mrseq/sequences/t2_t2prep_flash.py b/src/mrseq/sequences/t2_t2prep_flash.py index a22789c..6f8a736 100644 --- a/src/mrseq/sequences/t2_t2prep_flash.py +++ b/src/mrseq/sequences/t2_t2prep_flash.py @@ -20,6 +20,7 @@ def t2_t2prep_flash_kernel( t2_prep_echo_times: np.ndarray, n_recovery_cardiac_cycles: int, min_cardiac_trigger_delay: float, + use_soft_delay: bool, fov_xy: float, n_readout: int, readout_oversampling: float, @@ -54,6 +55,9 @@ def t2_t2prep_flash_kernel( min_cardiac_trigger_delay Minimum delay after cardiac trigger (in seconds). The total trigger delay is implemented as a soft delay and can be chosen by the user in the UI. + use_soft_delay + Use soft-delay functionality available from pulseq version 1.5.0 to allow UI adaption of trigger delay. + If set to false only the min_cardiac_trigger_delay is used. fov_xy Field of view in x and y direction (in meters). n_readout @@ -200,12 +204,13 @@ def t2_t2prep_flash_kernel( rf_inc = 0.0 # create trigger soft delay (total duration: user_input/1.0 - min_cardiac_trigger_delay) - trig_soft_delay = pp.make_soft_delay( - hint='trig_delay', - offset=-min_cardiac_trigger_delay, - factor=1.0, - default_duration=0.8 - min_cardiac_trigger_delay, - ) + if use_soft_delay: + trig_soft_delay = pp.make_soft_delay( + hint='trig_delay', + offset=-min_cardiac_trigger_delay, + factor=1.0, + default_duration=0.8 - min_cardiac_trigger_delay, + ) # obtain noise samples seq.add_block(pp.make_label(label='LIN', type='SET', value=0), pp.make_label(label='SLC', type='SET', value=0)) @@ -229,7 +234,8 @@ def t2_t2prep_flash_kernel( seq.add_block(pp.make_trigger(channel='physio1', duration=constant_trig_delay)) # add variable part of trigger delay (soft delay) - seq.add_block(trig_soft_delay) + if use_soft_delay: + seq.add_block(trig_soft_delay) # add all events of T2prep block for idx in t2prep_block.block_events: @@ -246,7 +252,8 @@ def t2_t2prep_flash_kernel( seq.add_block(pp.make_trigger(channel='physio1', duration=constant_trig_delay)) # add variable part of trigger delay (soft delay) - seq.add_block(trig_soft_delay) + if use_soft_delay: + seq.add_block(trig_soft_delay) for shot_idx in range(n_pe_points_per_cardiac_cycle): pe_index_ = pe_steps[shot_idx + n_pe_points_per_cardiac_cycle * cardiac_cycle_idx] @@ -297,7 +304,8 @@ def t2_t2prep_flash_kernel( seq.add_block(pp.make_trigger(channel='physio1', duration=min_cardiac_trigger_delay)) # add variable part of trigger delay (soft delay) - seq.add_block(trig_soft_delay) + if use_soft_delay: + seq.add_block(trig_soft_delay) # write all required parameters in the seq-file header/definitions seq.set_definition('FOV', [fov_xy, fov_xy, slice_thickness]) @@ -414,6 +422,7 @@ def main( t2_prep_echo_times=t2_prep_echo_times, n_recovery_cardiac_cycles=n_recovery_cardiac_cycles, min_cardiac_trigger_delay=np.max(t2_prep_echo_times) + 0.05, # max T2prep echo time + buffer for spoiler + use_soft_delay=True, fov_xy=fov_xy, n_readout=n_readout, readout_oversampling=readout_oversampling, diff --git a/src/mrseq/sequences/t2star_multi_echo_flash.py b/src/mrseq/sequences/t2star_multi_echo_flash.py index 8b08c58..63bc0b3 100644 --- a/src/mrseq/sequences/t2star_multi_echo_flash.py +++ b/src/mrseq/sequences/t2star_multi_echo_flash.py @@ -25,6 +25,7 @@ def t2star_multi_echo_flash_kernel( tr: float | None, n_echoes: int, min_cardiac_trigger_delay: float, + use_soft_delay: bool, fov_xy: float, n_readout: int, readout_oversampling: float, @@ -61,6 +62,9 @@ def t2star_multi_echo_flash_kernel( min_cardiac_trigger_delay Minimum delay after cardiac trigger (in seconds). The total trigger delay is implemented as a soft delay and can be chosen by the user in the UI. + use_soft_delay + Use soft-delay functionality available from pulseq version 1.5.0 to allow UI adaption of trigger delay. + If set to false only the min_cardiac_trigger_delay is used. fov_xy Field of view in x and y direction (in meters). n_readout @@ -220,12 +224,13 @@ def t2star_multi_echo_flash_kernel( prot.write_xml_header(hdr.toXML('utf-8')) # create trigger soft delay (total duration: user_input/1.0 - min_cardiac_trigger_delay) - trig_soft_delay = pp.make_soft_delay( - hint='trig_delay', - offset=-min_cardiac_trigger_delay, - factor=1.0, - default_duration=0.4 - min_cardiac_trigger_delay, - ) + if use_soft_delay: + trig_soft_delay = pp.make_soft_delay( + hint='trig_delay', + offset=-min_cardiac_trigger_delay, + factor=1.0, + default_duration=0.4 - min_cardiac_trigger_delay, + ) constant_trig_delay = round_to_raster( min_cardiac_trigger_delay - current_te / 2, raster_time=system.block_duration_raster ) @@ -252,7 +257,8 @@ def t2star_multi_echo_flash_kernel( seq.add_block(pp.make_trigger(channel='physio1', duration=constant_trig_delay)) # add variable part of trigger delay (soft delay) - seq.add_block(trig_soft_delay) + if use_soft_delay: + seq.add_block(trig_soft_delay) for shot_idx in range(n_pe_points_per_cardiac_cycle): pe_index = pe_steps[shot_idx + n_pe_points_per_cardiac_cycle * cardiac_cycle_idx] @@ -436,6 +442,7 @@ def main( tr=tr, n_echoes=n_echoes, min_cardiac_trigger_delay=0.1, # has to be smaller than half the echo time + use_soft_delay=True, fov_xy=fov_xy, n_readout=n_readout, partial_echo_factor=partial_echo_factor,