================= Sequence Explorer ================= The menu selection :menuselection:`Pulse Sequence --> Sequence Explorer...` opens the Sequence Explorer. The Sequence Explorer provides tools to manage and edit both "Standard" tabular pulse sequences and textually-defined "Industrial"-type Pulse Sequences. This window/interface can be very difficult to use on a small screen, such as an iPhone, and is therefore often disabled (unavailable) if the screen is too small. .. drops:: I1z :width: 99% :sequence: Standard/PulDel100msec :class: border :window: SequenceExplWindow :caption: The sequence 'Standard/PulDel100msec' selected in the Sequence Explorer. :link: Sequence Selector ================= At the top left of the Sequence Explorer is a sequence category selection, and under it, a list of sequences that belong to the selected category. The sequences available in the regular :menuselection:`Pulse Sequence` :ref:`menu ` appear in the category :menuselection:`Standard`. Other sequences appear under the category :menuselection:`Industrial`, and user-created sequences appear under the category :menuselection:`User`. :menuselection:`Standard` sequences are stored internally in a JSON structure. The easies way to edit these sequences is with the normal :ref:`Edit Sequence...` :ref:`Sequence Editor`. The JSON can also be directly edited by by advanced users. By default the raw JSON is hidden, but can be displayed by checking the :ref:`Show Raw Sequence` checkbox in the upper right corner. :menuselection:`Industrial` sequences are written in a pulse-sequence language very similar to the Bruker industry-standard NMR pulse sequence language. Indeed, some Bruker sequences can be simulated un-modified in SpinDrops. :menuselection:`User` sequences can be of either form - either JSON or Industrial (Bruker-style). Auto-Apply mode =============== When a sequence is selected from the list, it is shown in the Sequence Explorer, but not automatically loaded into the main SpinDrops simulation window. It is only displayed in the Sequence Explorer until the :guilabel:`Apply` button is clicked or when the checkbox :ref:`Apply to Simulation` is active, which enables automatic and immediate application of sequence selection or edits to the main SpinDrops simulation. `Industrial` Sequence Language ============================== The `Industrial` sequence language may look strange at first sight, but in reality is quite simple. The sequences are plain text files, and have three parts: an initial :ref:`Definitions` section, then :ref:`the commands that generate pulses and delays `, and finally a so-called :ref:`Phase Programs` section. The language is very similar to the pulse language used by a well-known industrial NMR instrument manufacturer. Because of this, you can find a lot of example programs and ideas for pulse programs on the internet. However, be aware that the possibilities of a simulation software are somewhat different from an actual spectrometer, so not everything in the pulse programming is exactly the same. The main difference in terms of the spin system is that in simulation we primarily look at a single, or a small number of spin systems, whereas in a real spectrometer, we're interacting with a large number of similar spin systems with imperfect coupling to the experimental machinery. This means we can, in the simulator, specify exact starting states, and exact (and arbitrary) Hamiltonians -- an impossibility for the experimentalist. .. drops:: I2z :width: 99% :sequence: Industrial/IM12 :class: border :window: SequenceExplWindow Definitions ----------- Before using any pulses, it is possible (though not necessary) to specify some values and operators that can be used later in the description of the sequence. Usefully, we set some parameters to the time durations needed to achieve a certain pulse rotation, or time duration for certain relaxations or mixing periods. Also we can specify arbitrary Hamiltonians to be applied during certain time periods, or specify literal Propagators that can be applied to the state. All of these definitions (using the `define` statement) should be at the beginning of the pulse program: .. code-block:: none define pulse ... define delay ... define channel ... define propagator ... Pulse Definition ++++++++++++++++ .. code-block:: none define channel Hiso12 = 'pi*(J12*(2I1xI2x + 2I1yI2y + 2I1zI2z))' Delay Definition ++++++++++++++++ .. code-block:: none define delay mydelay "mydelay = 1s" Hamiltonian Channel Definition ++++++++++++++++++++++++++++++ This Isotropic Mixing sequence uses a special type of definition to associate a channel in the pulse sequence with a specific Hamiltonian in the simulation. Later use of this "channel" in the experiment will apply this Hamiltonian to the simulation. This example creates a isotropic mixing Hamiltonian between spins 1 and 2 on a new channel called `Hiso12`. .. code-block:: none define channel Hiso12 = 'pi*(J12*(2I1xI2x + 2I1yI2y + 2I1zI2z))' The :code:`define channel` statement can be used to define a channel in terms of the Hamiltonian that will be in effect when the channel is actively "pulsing" (that is, when this channel's Hamiltonian is added to the global system propagator Hamiltonian). After the definition, a delay and the actual "pulsing" of the Hamiltonian are accomplished with the pulse program: .. code-block:: none "d1=1/(2*cnst2)" ; set the delay d1 to 1/(2*J12) (d1) pulse(auto):Hiso12 ; pulse the Hiso12 channel for duration (d1) Propagator Channel Definition +++++++++++++++++++++++++++++ Another kind of definition is the propagator definition, it defines a special "channel" with an arbitrary :ref:`propagator `, rather than :ref:`hamiltonian `. In order to make the propagator non-instantaneous, for display purposes, a pseudo-Hamiltonian is internally calculated that, when applied for :math:`1 s` (using the "one second pulse" command :code:`1sp`), will have the same effect as the requested propagator. This example is a special case of the `nop` (*no* *op*\ eration) propagator that does not affect the system state at all, it is the same as the identity operator: .. code-block:: none define propagator nop = 'Id' ; define the identity propagator ; To apply this propagator to the current state, make a 1-second pulse ; on it's channel: 1sp:nop To use the `nop` propagator again, for example, in the definition of a spin-selective inverting `notA` channel, it is necessary to assign the expression to a name, within the definition string: .. code-block:: none define propagator nop = 'nop=2*Ie' ; define a 2x2 identity matrix define propagator not = 'not=[0,1;1,0]' ; define a 2x2 inversion matrix define propagator notA = 'kron(not,nop)' ; define a 4x4 spinA not propagator 1sp:notA ; invert spin A in a 2-spin system Pulse Lines ----------- This is the "meat" of the pulse program, and it lies between the definitions and the first :ref:`Exit`. There are two main types of lines in this part of the pulse program: - pulse/delay lines which take up time and create either pulses or delays, - and calculation lines surrounded by double-quotes "", which do not take up time but can alter values in the program. These two types of lines may be interspersed. Here is an example pulse program: .. code-block:: none "d1=1/(2*cnst2)" ; set delay to 1/(2*J12) start, p1 ; 90deg pulse d1 ; delay p2 ; 180deg pulse d1 ; delay (d1) pulse(auto):Hiso12 ; pulse the Hiso12 channel for duration (d1) exit The first line sets the delay variable `d1` to the value :pton:`1/(2J_{12})`. The value :code:`cnst2` is a special symbol that is set to the coupling J12 of the current simulation. If that value is 0, the pulse sequence becomes ill-defined. Next there is a label :code:`start,` which does nothing, but marks a place in the sequence where later looping commands (such as acquisition loops) could jump back to (see for example, the phase cycling experiments). Then follows a (nonsense) sequence of :code:`p1`, :code:`d1`, :code:`p2`, :code:`d1`, which are, respectively: 90 degree pulse, delay of :pton:`1/(2J_{12})` (as defined earlier), 180 degree pulse, and another delay of :pton:`1/(2J_{12})`. And finally, the line that starts with :code:`(d1)` will create a delay of `d1` in parallel with a pulse of automatic length (:code:`auto`) on the :code:`Hiso12` channel -- or in other words, the isotropic mixing Hamiltonian will be in effect for a time of `d1` or :pton:`1/(2J_{12})`. Such pulses with `auto`\ matic length will expand to fill the time of the `line upon which it is specified` -- a time determined by the longest of the other elements which are active in parallel. The :code:`exit` is unnecessary in this pulse program, because there are no phase programs to define, but it does not hurt to add it to clarify where the program ends. Preset Pulse Lengths ++++++++++++++++++++ SpinDrops implicitly sets the maximum pulse amplitude to 10 Hz, although this completely unrealistic. Pulse durations (:code:`p1` - :code:`p31`) are also automatically calculated for 90 and 180 degree pulses on the available spins. On a real spectrometer, you would use an experimental procedure to discover the pulse amplitude, and set these values accordingly. SpinDrops adopts the same convention as Bruker for the meanings of these pulse durations: .. list-table:: :class: no-cap-num table-lefty :header-rows: 1 :widths: 20 40 40 :align: center * - Pulse duration - Meaning - Pulse on channel * - :code:`p1` - duration of 90° pulse on spin **I1** - :code:`f1` (this is the default when omitted) * - :code:`p2` - duration of 180° pulse on spin **I1** - :code:`f1` (this is the default when omitted) * - :code:`p3` - duration of 90° pulse on spin **I2** - :code:`f2` (do not omit!) * - :code:`p4` - duration of 180° pulse on spin **I2** - :code:`f2` (do not omit!) * - :code:`p21` - duration of 90° pulse on spin **I3** - :code:`f3` (do not omit!) * - :code:`p22` - duration of 180° pulse on spin **I3** - :code:`f3` (do not omit!) Since these pulse durations are simply durations, is important to remember to send the pulse to the correct "channel" so that it affects the correct spin! This is done by appending a colon and the channel to the pulse, ie: :code:`p3:f2`, or :code:`p22:f3`. Preset Durations ++++++++++++++++ There are also a number of pre-calculated durations available for use in pulse programs. These are constants describing the spin system's coupling parameters: :math:`J_{12}`, :math:`J_{13}`, and :math:`J_{23}`. These are contained in the parameters: .. list-table:: :class: no-cap-num table-lefty :header-rows: 1 :widths: 20 50 :align: center * - delay duration - meaning * - :code:`cnst2` - :math:`J_{12}` * - :code:`cnst4` - :math:`J_{13}` * - :code:`cnst5` - :math:`J_{23}` The value of these parameters will change whenever the corresponding Spin System parameters/sliders are changed using the :ref:`System Parameters Window`. Shaped Pulses +++++++++++++ Using shaped pulses in the advanced language is quite similar to on an actual spectrometer. Available pulses, and their names, can be seen in the :ref:`Pulse Explorer Window`. It is also possible to import shaped pulse files in either Bruker or Valerian format from there. There is a small difference from the normal industrial syntax to make setting the pulse names easier, it is done by assigning a pulse name to the corresponding :code:`sp` parameter, as follows to set the name of the **sp1** pulse file: .. code-block:: none "sp1='Standard/sinc3_100.exc'" start, ; shape pulse using default amplitude (typically in SpinDrops 10 Hz) p1:sp1 ; a shaped pulse, flip defined, amplitude defined pulse(90 deg, 40 hz, auto):sp1 ph1 pulse(180 deg, 40 hz, auto):sp1 ph2 pulse(180 deg, 20 hz, auto):sp1 ph3 p1:sp1 ph4 ; default amplitude (10 Hz), duration of p1 ; hard pulse, defined amp and duration pulse(auto, 120hz, 2m) ; shaped pulses, defined flip and duration, implicit amplitude pulse(90 deg, auto, 10m):sp1 ph1 pulse(180 deg, auto, 10m):sp1 ph2 pulse(180 deg, auto, p1):sp1 ph3 ; duration of p1 exit It is useful to think of a shaped pulse as a series of complex values with amplitudes between 0 and 1. These complex values determine the vector of the transverse RF magnetization while the pulse is being `played`. Shaped pulse files usually contain (at least) two additional important parameters to assist in their use. These parameters must be set correctly in order for SpinDrops to calculate the correct pulse amplitude and duration. - a scaling parameter :math:`S_p` (or "shape factor") that tells you or the spectrometer how to set the pulse's amplitude. Shaped pulses are typically either `excitation` or `inversion` pulses, that is, designed to tip spins either 90° or 180° degrees. A shaped pulse which is purely on-resonance (has no phase variation). Some pulses are designed for other purposes, but even those pulses' amplitude information can be encoded this way. Bruker shape files store this value in a parameter called :code:`$SHAPE_INTEGFAC`. Varian .RF pulse files store this in a comment line tagged with :code:`INTEGRAL`. The `shape factor` is defined relative to a hard pulse of the same flip angle. For example, say a shaped pulse was designed for 90°, has three pulse elements of equal duration, equal phase, and amplitudes of :math:`.1,.5, \text{ and } .8`, then the `shape factor` will be :math:`0.46667`. Coming from the other direction, let's say you calculate a shaped pulse that has an effective bandwidth of 20kHz, should be 15ms long, and whose maximum amplitude is 8 kHz, and is designed for a flip angle (arbitrarily) of 76°. An equivalent hard pulse (15 ms long, 76°) would have an amplitude of :math:`\frac{76/360}{15 \text{ ms}} = 14.074 \text{ Hz}`, so our shaped pulse's :math:`S_p = \frac{14.074 \text{ Hz}}{8 \text{ kHz}} = 0.0017593`. - the pulse's time-bandwidth product (:math:`T_p*\text{bw}`) which is mostly used for pulses which are designed to act across a bandwidth. (:math:`T_p*\text{bw}`) is simply the relationship between the pulse's duration and its effective bandwidth. A pulse with :math:`T_p*\text{bw}=10` played for :math:`1 \text{ ms}` will affect a range of spins across a bandwidth of :math:`\text{bw}=\frac{10}{0.001}=10 \text{ kHz}`. Bruker shape files store this value in a parameter called :code:`$SHAPE_BWFAC`. Varian .RF pulse files store this in a comment line tagged with :code:`EXCITEWIDTH` or :code:`INVERTWIDTH`. Acquisition ----------- Adding an acquisition statement (either :code:`adc` or :code:`go`) to a pulse sequence tells SpinDrops that you would also like to see the FID created by the sequence. The simplest acquisition can be created with :code:`adc` - this statement will perform a `readout` of `np` complex points at a bandwidth of `sw` (having a delay of :math:`1/sw` between each point). The `readout` of a single point is the expectation value of the density matrix for the acquisition operator -- for example, for a single-spin system this operator is simply :pton:`I1m` or :pton:`I1p` (depending on the whims of your spectrometer manufacturer). For a two-spin homonuclear system, an acquisition operator could be :pton:`I1m+I2m`. For heteronuclear systems there are separate acquisition channels, where all of the spins of a type can be recorded on a single channel (ie all the `H` together, and all of the `C` together). We refer to a single acquisition as a `trace`, and we call the combination of one or more `traces` into a single vector an `acquisition` -- this is because as a processing shortcut, spectrometers often only record the `traces` into temporary buffers which contain, at any given time, some phase-modulated summation of traces until the current time. SpinDrops calculates and displays traces separately to let the user see what is really happening in the experiments. The combined `acquisition` is also displayed (or it will be - this feature is still being developed!). Here is a simple pulse-acquire program, it is simply a 90° pulse followed by an acquisition. .. code-block:: none start, p1 adc exit Assuming that the :ref:`Initial State ` is :pton:`I1z`, and that spin 1 has some offset, we can see the trace recorded by this sequence (:numref:`ppg_editor_acq`). .. drops:: I1z :nspin: 1; Homonuclear=1; v1=0 :aspect: 200 :name: ppg_editor_acq :sequence: { "Spin System": "Homonuclear", "name": "PulAcq", "desc": "Simple Pulse-Acquire", "table":["start,", " p1", " adc", "", "exit"] } :view: Cp110 :class: border :caption: Pulse Acquire :link: Exit ---- The :code:`exit` command ends the pulse program execution. There can be multiple :code:`exit` commands in the text file, but the first one will always be the end of the sequence. A pulse program does not need to have an :code:`exit`, if there are no :ref:`Phase Programs`, since it just serves to separate the body of the sequence from their definition. .. code-block:: none exit Phase Programs -------------- `Phase Programs` must be forgiven for their archaic name dating to an earlier era of computing terminology. What is meant here by "program" is simply a repeating sequences of phases. Values from this sequence can be referenced from pulses and acquisitions. When so referenced, they return the phase at the list's `current position`, which of course starts at the first position and advances either explicitly or implicitly, depending on what is happening in the pulse sequence. In the case of pulses, specifying a `Phase Program` along with a pulse determines what phase the pulse will have. The `current position` of all of the `Phase Program`\ s is implicitly advanced to the next element every time there is a `go` command. This automatic increment can be avoided by using the related command `gonp` used (which cryptically means "go with no phase increment"). .. code-block:: none ; phase programs ph2 = 0 1 2 3