def get_block(self, block_index): """ Returns Block at position specified by block_index. Parameters ---------- block_index : int Index of Block to be retrieved. Returns ------- block : dict Block at position specified by block_index. """ block = {} event_ind = self.block_events[block_index] if event_ind[0] > 0: delay = Holder() delay.type = 'delay' delay.delay = self.delay_library.data[event_ind[0]] block['delay'] = delay elif event_ind[1] > 0: rf = Holder() rf.type = 'rf' lib_data = self.rf_library.data[event_ind[1]] amplitude, mag_shape, phase_shape = lib_data[0], lib_data[1], lib_data[ 2] shape_data = self.shape_library.data[mag_shape] compressed = Holder() compressed.num_samples = shape_data[0][0] compressed.data = shape_data[0][1:] compressed.data = compressed.data.reshape( (1, compressed.data.shape[0])) mag = decompress_shape(compressed) shape_data = self.shape_library.data[phase_shape] compressed.num_samples = shape_data[0][0] compressed.data = shape_data[0][1:] compressed.data = compressed.data.reshape( (1, compressed.data.shape[0])) phase = decompress_shape(compressed) rf.signal = 1j * 2 * np.pi * phase rf.signal = amplitude * mag * np.exp(rf.signal) rf.t = [(x * self.rf_raster_time) for x in range(1, max(mag.shape) + 1)] rf.t = np.reshape(rf.t, (1, len(rf.t))) rf.freq_offset = lib_data[3] rf.phase_offset = lib_data[4] if max(lib_data.shape) < 6: lib_data = np.append(lib_data, 0) rf.dead_time = lib_data[5] block['rf'] = rf grad_channels = ['gx', 'gy', 'gz'] for i in range(1, len(grad_channels) + 1): if event_ind[2 + (i - 1)] > 0: grad, compressed = Holder(), Holder() type = self.grad_library.type[event_ind[2 + (i - 1)]] lib_data = self.grad_library.data[event_ind[2 + (i - 1)]] grad.type = 'trap' if type == 't' else 'grad' grad.channel = grad_channels[i - 1][1] if grad.type == 'grad': amplitude = lib_data[0] shape_id = lib_data[1] shape_data = self.shape_library.data[shape_id] compressed.num_samples = shape_data[0][0] compressed.data = np.array([shape_data[0][1:]]) g = decompress_shape(compressed) grad.waveform = amplitude * g grad.t = np.array([[ x * self.grad_raster_time for x in range(1, g.size + 1) ]]) else: grad.amplitude, grad.rise_time, grad.flat_time, grad.fall_time = [ lib_data[x] for x in range(4) ] grad.area = grad.amplitude * ( grad.flat_time + grad.rise_time / 2 + grad.fall_time / 2) grad.flat_area = grad.amplitude * grad.flat_time block[grad_channels[i - 1]] = grad if event_ind[5] > 0: lib_data = self.adc_library.data[event_ind[5]] if max(lib_data.shape) < 6: lib_data = np.append(lib_data, 0) adc = Holder() adc.num_samples, adc.dwell, adc.delay, adc.freq_offset, adc.phase_offset, adc.dead_time = [ lib_data[x] for x in range(6) ] adc.type = 'adc' block['adc'] = adc return block
def makearbitraryrf(kwargs, nargout=1): """ Makes a Holder object for an arbitrary RF pulse Event. Parameters ---------- kwargs : dict Key value mappings of RF Event parameters_params and values. nargout: int Number of output arguments to be returned. Default is 1, only RF Event is returned. Passing any number greater than 1 will return the Gz Event along with the RF Event. Returns ------- rf : Holder RF Event configured based on supplied kwargs. gz : Holder Slice select trapezoidal gradient Event. """ flip_angle = kwargs.get("flip_angle") system = kwargs.get("system", Opts()) signal = kwargs.get("signal", 0) freq_offset = kwargs.get("freq_offset", 0) phase_offset = kwargs.get("phase_offset", 0) time_bw_product = kwargs.get("time_bw_product", 0) bandwidth = kwargs.get("bandwidth", 0) max_grad = kwargs.get("max_grad", 0) max_slew = kwargs.get("max_slew", 0) slice_thickness = kwargs.get("slice_thickness", 0) signal = signal / sum( signal * system.rf_raster_time) * flip_angle / (2 * pi) N = len(signal) duration = N * system.rf_raster_time t = [x * system.rfRasterTime for x in range(0, N)] rf = Holder() rf.type = 'rf' rf.signal = signal rf.t = t rf.freq_offset = freq_offset rf.phase_offset = phase_offset rf.rf_dead_time = system.rf_dead_time if nargout > 1: if slice_thickness <= 0: raise ValueError('Slice thickness must be provided') if bandwidth <= 0: raise ValueError('Bandwdith of pulse must be provided') system.maxgrad = max_grad if max_grad > 0 else system.maxgrad system.max_slew = max_slew if max_slew > 0 else system.max_slew BW = bandwidth if time_bw_product > 0: BW = time_bw_product / duration amplitude = BW / slice_thickness area = amplitude * duration kwargs_for_trap = { "channel": 'z', "system": system, "flat_time": duration, "flat_area": area } gz = maketrapezoid(**kwargs_for_trap) t_fill = [x * 1e-6 for x in range(1, round(gz.riseTime / 1e-6))] rf.t = [t_fill, rf.t + t_fill[-1], t_fill + rf.t[-1] + t_fill[-1]] rf.signal = [np.zeros(len(t_fill)), rf.signal, np.zeros(len(t_fill))] return rf, gz
def makeblockpulse(kwargs, nargout=1): """ Makes a Holder object for an RF pulse Event. Parameters ---------- kwargs : dict Key value mappings of RF Event parameters_params and values. nargout: int Number of output arguments to be returned. Default is 1, only RF Event is returned. Passing any number greater than 1 will return the Gz Event along with the RF Event. Returns ------- Tuple consisting of: rf : Holder RF Event configured based on supplied kwargs. gz : Holder Slice select trapezoidal gradient Event. """ flip_angle = kwargs.get("flip_angle") system = kwargs.get("system", Opts()) duration = kwargs.get("duration", 0) freq_offset = kwargs.get("freq_offset", 0) phase_offset = kwargs.get("phase_offset", 0) time_bw_product = kwargs.get("time_bw_product", 4) bandwidth = kwargs.get("bandwidth", 0) max_grad = kwargs.get("max_grad", 0) max_slew = kwargs.get("max_slew", 0) slice_thickness = kwargs.get("slice_thickness", 0) if duration == 0: if time_bw_product > 0: duration = time_bw_product / bandwidth elif bandwidth > 0: duration = 1 / (4 * bandwidth) else: raise ValueError('Either bandwidth or duration must be defined') BW = 1 / (4 * duration) N = round(duration / 1e-6) t = [x * system.rf_raster_time for x in range(N)] signal = flip_angle / (2 * np.pi) / duration * np.ones(len(t)) rf = Holder() rf.type = 'rf' rf.signal = signal rf.t = t rf.freq_offset = freq_offset rf.phase_offset = phase_offset rf.dead_time = system.rf_dead_time fill_time = 0 if nargout > 1: if slice_thickness < 0: raise ValueError('Slice thickness must be provided') if max_grad > 0: system.max_grad = max_grad if max_slew > 0: system.max_slew = max_slew amplitude = BW / slice_thickness area = amplitude * duration kwargs_for_trap = {'channel': 'z', 'system': system, 'flat_time': duration, 'flat_area': area} gz = maketrapezoid(kwargs_for_trap) fill_time = gz.rise_time t_fill = np.array([x * 1e-6 for x in range(int(round(fill_time / 1e-6)))]) rf.t = np.array([t_fill, rf.t + t_fill[-1], t_fill + rf.t[-1] + t_fill[-1]]) rf.signal = np.array([np.zeros(t_fill.size), rf.signal, np.zeros(t_fill.size)]) if fill_time < rf.dead_time: fill_time = rf.dead_time - fill_time t_fill = np.array([x * 1e-6 for x in range(int(round(fill_time / 1e-6)))]) rf.t = np.insert(rf.t, 0, t_fill) + t_fill[-1] rf.t = np.reshape(rf.t, (1, len(rf.t))) rf.signal = np.insert(rf.signal, 0, np.zeros(t_fill.size)) rf.signal = np.reshape(rf.signal, (1, len(rf.signal))) if nargout > 1: return rf, gz else: return rf
def makesincpulse(kwargs, nargout=1): """ Makes a Holder object for an RF pulse Event. Parameters ---------- kwargs : dict Key value mappings of RF Event parameters_params and values. nargout: int Number of output arguments to be returned. Default is 1, only RF Event is returned. Passing any number greater than 1 will return the Gz Event along with the RF Event. Returns ------- Tuple consisting of: rf : Holder RF Event configured based on supplied kwargs. gz : Holder Slice select trapezoidal gradient Event. """ flip_angle = kwargs.get("flip_angle") system = kwargs.get("system", Opts()) duration = kwargs.get("duration", 0) freq_offset = kwargs.get("freq_offset", 0) phase_offset = kwargs.get("phase_offset", 0) time_bw_product = kwargs.get("time_bw_product", 4) apodization = kwargs.get("apodization", 0) max_grad = kwargs.get("max_grad", 0) max_slew = kwargs.get("max_slew", 0) slice_thickness = kwargs.get("slice_thickness", 0) BW = time_bw_product / duration alpha = apodization N = int(round(duration / 1e-6)) t = np.zeros((1, N)) for x in range(1, N + 1): t[0][x - 1] = x * system.rf_raster_time tt = t - (duration / 2) window = np.zeros((1, tt.shape[1])) for x in range(0, tt.shape[1]): window[0][x] = 1.0 - alpha + alpha * np.cos( 2 * np.pi * tt[0][x] / duration) signal = np.multiply(window, np.sinc(BW * tt)) flip = np.sum(signal) * system.rf_raster_time * 2 * np.pi signal = signal * flip_angle / flip rf = Holder() rf.type = 'rf' rf.signal = signal rf.t = t rf.freq_offset = freq_offset rf.phase_offset = phase_offset rf.dead_time = system.rf_dead_time fill_time = 0 if nargout > 1: if slice_thickness == 0: raise ValueError('Slice thickness must be provided') system.max_grad = max_grad if max_grad > 0 else system.max_grad system.max_slew = max_slew if max_slew > 0 else system.max_slew amplitude = BW / slice_thickness area = amplitude * duration kwargs_for_trap = { "channel": 'z', "system": system, "flat_time": duration, "flat_area": area } gz = maketrapezoid(kwargs_for_trap) fill_time = gz.rise_time nfill_time = int(round(fill_time / 1e-6)) t_fill = np.zeros((1, nfill_time)) for x in range(1, nfill_time + 1): t_fill[0][x - 1] = x * 1e-6 temp = np.concatenate((t_fill[0], rf.t[0] + t_fill[0][-1])) temp = temp.reshape((1, len(temp))) rf.t = np.resize(rf.t, temp.shape) rf.t[0] = temp z = np.zeros((1, t_fill.shape[1])) temp2 = np.concatenate((z[0], rf.signal[0])) temp2 = temp2.reshape((1, len(temp2))) rf.signal = np.resize(rf.signal, temp2.shape) rf.signal[0] = temp2 if fill_time < rf.dead_time: fill_time = rf.dead_time - fill_time t_fill = np.array( [x * 1e-6 for x in range(int(round(fill_time / 1e-6)))]) rf.t = np.insert(rf.t, 0, t_fill) + t_fill[-1] rf.t = np.reshape(rf.t, (1, len(rf.t))) rf.signal = np.insert(rf.signal, 0, (np.zeros(t_fill.size))) rf.signal = np.reshape(rf.signal, (1, len(rf.signal))) # Following 2 lines of code are workarounds for numpy returning 3.14... for np.angle(-0.00...) negative_zero_indices = np.where(rf.signal == -0.0) rf.signal[negative_zero_indices] = 0 if nargout > 1: return rf, gz else: return rf