Simulator#
- class torchsim.model.Simulator(*args, **kwargs)[source]#
Bases:
_SignalModelA protocol: what a sequence plays, and the physics behind it.
The one thing anything downstream takes. Parameter inference, model-based reconstruction and sequence design are written against this and never ask how the signal is arrived at.
Subclasses set
modeland implementlayout(), which returns the operators of one repetition in the order they are played. A protocol with a closed form – a steady state that needs no state machine – implementsevaluate()instead and never reacheslayout(); itsmodelthen carries only the property declaration, since there are no events for operators to realize.The constructor takes the keywords
simulate()takes, and fixes them; a call overrides. So a sequence is written once with the tissue it is being asked about already on it, and what is left to give per call is whatever is actually varying – the design under optimization, the map being fitted.A model that composes others rather than declaring physics of its own names its properties in the class body and writes whatever constructor suits it: every setting has a value at the class level, so one that never reaches this constructor still answers
simulate().- model#
The physics behind the protocol.
- Type:
SpinPhysics, optional
- states#
Configuration orders to carry, or
Noneto size them from the winding the description asks for.- Type:
int, optional
Methods
This simulator with more fixed on it, values or settings alike.
Return the description this protocol plays.
Run one simulation of the described protocol.
Return a simulator over a stream someone else assembled.
Return a simulator over one repetition of a Pulseq sequence.
jacobianReturn the signal and its derivative with respect to
diff.Return the operators of one repetition, in the order they play.
Return the protocol as it will be laid out.
Return how long one repetition lasts, given what the layout played.
simulateReturn the recorded signal.
- bind(**values)[source]#
This simulator with more fixed on it, values or settings alike.
A property or a protocol argument is held for the next call; a setting – the pulse the events drive, where across the slice to work it out, how many orders to carry – is applied to the copy instead, because it changes what is simulated rather than what is simulated with.
- property operators#
What plays each kind of event, from this simulator’s physics.
A layout reads its operators here. Each is resolved while a description is being assembled and never again: what the layout produces carries its own action word, and the run consults no slot.
- property variables#
The protocol arguments this simulator’s layout takes.
What a sequence is written in, as against the tissue it is played on:
exposesandacceptsname the properties, this names the flip angles, spacings and times. Everything here can be fixed on the constructor, given at the call, or carried as a tensor a cost is differentiated back through.
- to(device)[source]#
This simulator, with everything it holds on
device.A simulator carries its protocol – echo times, a flip train – and whatever tissue is fixed on it, and the two have to arrive on a card together: properties moved on their own would be multiplied against echo times still on the host.
- layout(**protocol)[source]#
Return the operators of one repetition, in the order they play.
A bare operator starts where the one before it ended; one given as
(offset_s, operator)starts that far into the repetition instead, which is how a sequence that times itself from an echo says so.- Raises:
NotImplementedError – If the subclass implements neither this nor
describe().
- repetition_s(played_s, **protocol)[source]#
Return how long one repetition lasts, given what the layout played.
The default is the span the layout covers. A sequence whose TR is longer than what it plays – a refocused train waiting out its recovery – says so here, and only a run of more than one repetition can tell the difference.
- played(**sequence)[source]#
Return the protocol as it will be laid out.
The constructor’s arguments, with anything given at the call overriding them, every array read as torch. Anything naming a run setting is left out: those describe the run, and a layout has no use for them.
- property rf_raster_time_s#
The dwell this simulator’s RF shapes are sampled on.
- classmethod from_pulseq(source, *, tr_index=None, **settings)[source]#
Return a simulator over one repetition of a Pulseq sequence.
The offline half of
from_description(): the same events, read from the file a scanner would be given rather than from the stream it sends back. The file states how many blocks a repetition holds, so nothing here searches for the period; naming the simulator is what says how those events are to be played.- Parameters:
source (str, Path or sequence) – A
.seqfile, or a sequence in memory with pypulseq’s reading interface – pypulseq’s ownSequence, or pypulseqpp’s.tr_index (int, optional) – Which repetition to read, counted in whole repetitions. Defaults to the file’s
TRRefdefinition, and otherwise to the first repetition that acquires – which is refused when the repetitions differ in their pulses.settings (Any) – Run settings and tissue, as the constructor takes them.
- Return type:
A simulator playing that repetition.
- classmethod from_description(description, model=None, **settings)[source]#
Return a simulator over a stream someone else assembled.
This is the path a description arriving from a scanner takes:
FSESimulator.from_description(stream)says the events are to be read as a refocused train, and the only thing left to give is the tissue. Echo spacing, echo train length, flip angles and pulse shapes are in the stream and are not named again.Which simulator you call it on is the whole of what you choose, and it matters. A description says what was played – an RF pulse, tagged with the use its designer gave it, and an ADC window – and says nothing about the gradients between them, because the transport carries none. The dephasing lives in the handlers instead: a
SSFPFidReadout()winds one order after every sample, aSSFPEchoReadout()winds it before, aSPGRReadout()spoils, and a refocusing pulse is crushed either side. So the events are re-emitted through this model’s own operators rather than taken as they arrive.- Parameters:
description (SequenceDescription) – The stream, as the MRD client decodes it or a Pulseq design exports it.
model (SpinPhysics, optional) – The physics to read it with. Defaults to this simulator’s own, which is what naming a concrete one is for.
settings (Any, optional) – Run settings and tissue, as the constructor takes them.
- Raises:
ValueError – If called on
Simulatoritself, which names no handlers and so says nothing about how the stream is to be read.