Nmrtype development documentation

From NMR Wiki

Revision as of 01:13, 20 April 2009 by Evgeny Fadeev (Talk | contribs)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search




drawing_pre_width - width in pixels from timed anchor to the left edge of the leftmost element in the anchor group
drawing_post_width - width in pixels from timed anchor to the right edge of the rightmost element in the anchor group

Some drawing parameters are initialized in PulseSequence.__init__() function, others in the draw() routines of individual elements. This probably needs to be changed since this way parameters are hard to track.

One possibility is doing this through external .css files. Looks like there are some css parsers written in python.

While some parameters are hard-coded numbers and constants, others are calculated, e.g. drawing_width of pulse sequence can be only calculated after source code is parsed.

AnchorGroup.set_xcoor() and Anchor.set_xcoor() calculate x drawing coordinate of anchors.

Drawing width of delays is calculated depending on the size of the label that needs to be shown and amount of empty space available on the drawing channel. If label is hidden, then default minimum width is assigned.

Drawing coordinate calculations

Searched code for xcoor.*=. ycoor calculations are handled differently - within PulseSequence.draw() call

elementfunctionwhen fuction is calledwhat is done
AnchorGroup PulseSequence._parse_disp()


removed from use (r15)

still in use (r15)


<head_group>.xcoor = 0

AnchorAnchorGroup.time()called from PulseSequence._compile_init() (r15)xcoor relative to timing anchor calculated
DelayDelay.calc_drawing_coordinates()currently (r15) not in usexcoor = average(start_anchor.xcoor,end_anchor.xcoor)
PulseSequenceElementPulseSequence._draw()removed in r16N/A

Element drawing size calculations

default action: calculate elements .drawing_pre_width, .drawing_post_width, .drawing_width

elementfunctionwhen fuction is calledwhat is done
AnchorGroupAnchorGroup.calc_drawing_width()called by AnchorGroup.time() after .set_xcoor(0) - i.e. when relative anchor coordinates become knowndefault action

Platform-specific object properties

  • Pulse.varian_power_level - name of power level parameter
  • Pulse.varian_pulse_name - name of pulse (width) variable
  • Delay.varian_delay_name - varian name of delay variable (only "hardware" delays have it so far)


Coding style

  • functions with the same name in different classes must be commented #ClassName.function_name() otherwise it's hard to know what part of code you're reading
  • same semantically kinds of things are sometimes private, sometimes public attributes and are named inconsistently, e.g: PulseSequence._glist, AnchorGroup.anchor_list, Anchor.events
  • remove magic numbers


  • currently labels on wide events don't impact drawing layout - needs to be fixed
  • routine paste_image has reversed order of yplacement, then xplacement parameters - weird
  • remove MAGIC NUMBERS from drawing routines (places like that are labeled "magic number" in code comments
  • default units are pixels - better have physical units - this will be changed when drawing is implemented in LaTeX
  • delays are currently deliniated by tic marks. maybe there should be an option to show delay like in engineering drawing - this can work well when delay start can be obscured by preceding events on the same channel


  • potential for infinite recursion?
  • add symbolic algebra simplification to expressions
  • expression object can be improved by reloading operators

NMR logic

  • there is no check that pulse is 90 degree where compensation delay is added

Object model

  • functions of type get_events() give events on one channel at once - there maybe has to be a way for more flexible queries
  • now there is PulseSequence.get_all_events() because get_events() function is inflexible - needs to be fixed
  • nearly all objects need access to the parent PulseSequence object now it's done via .pulse_sequence property that is set to all elements. would getter function be better?
  • WideEventToggle pulse sequence element does not have channel field
  • does Phase have to be a PulseSequenceElement, really I should probably define PulseSequenceEvent object!!!
  • if I'm redoing handling of wide events, then event.type == "pegging" is obsolete?
  • rf channels and pfg channels are handled separately in different tables - may be better to merge and use .type parameter
 PulseSequence.get_rf_channel() and PulseSequence.get_channel_key() are associated with this.
 .get_channel_key() will look into both channel tables, will report collisions as fatal errors
 still it's probably better to have one common channel table
  • in quite a few places _private object members are used outside classes - need to replace those with getter and setter functions
  • since wide events are to be replaced with toggles, for now there's redundancy toggle_on->event, toggle_on.channel=event.channel, same with toggle_off
  • Pulse.channel contains only key to channel, not the link to object
  • WideEventToggle expression set to N(0), maybe they are not 0, also maybe I need to consider "edge-aligning" these toggles by default "on":"left" "off":"right"? not sure. If so, then custom time() function is needed
  • PulseSequence._varian_print_events() only supports H,C,N on channels 1,2,3 - no general channel mapping scheme yet
  • _dim_table currently only contains info about indirect dimensions

Error handling

  • internal error handling through raise without objects??? a problem?
  • current error handling does not return line in source that causes problem
  • error handling from PulseSequence.get_channel_key() should be moved to parsing stage

Design problems

  • delays in compiled pulse sequence object won't be in correct order
  • latex functions are outside classes
  • _private_functions: I've started naming some _compile_..., then previous should be named _parser_ should I have separate class for parser methods???
  • get_channel_key() is error checking function - maybe it's not necessary in this form


  • Implement PulseSequence._validate_anchor_order


  1. make drawings in SVG format
  2. finish compiling inkscape
  3. svg -> ps (inkscape should do it)
  4. svg -> png

Latex -> svg


A method recommended to convert LaTeX -> svg:

latex comm.tex
dvips -E -y 2500 -o comm.eps comm.dvi
eps2eps -dNOCACHE comm.eps comm2.eps
pstoedit -f sk comm2.eps comm.sk
inkscape -z -f comm.sk -l comm.svg

eps2eps converts fonts to outlines...

...stuck installing inkscape

./configure does not recognize installed lcms and libsigc++ librarires - why?

Here is the inkscape compilation link

Rasterizing svg, etc.

rsvg (LGPL licensed)


cairo LGPL

SVG1.1 spec @w3c

svg wiki

PSTricks latex package (recommended by John Forkosh who wrote mimetex)


in pulse sequence drawing extension add "alt" tag for the image

Considering to change format of main record

Option 1 (original)

anchors:       @a          @a1,b      @b1,c     @c1,d,d1         @e     @f     @g     @h    @j0,j,j1    @i--k        @l
disp:         3@a           5@b       3@c          3@d          9@e    9@f    4@g    4@h      3@j      3@i         10@l
time:    rlx   @a  t1         @b  t2     @c t3      @d  T1a      @e T1b @f T12 @g T12 @h d     @j     d @i--k   aq   @l
rf H:        90@a                                                           180@g                       acq@k---------l
rf 13C:                     90@b       90@c       90@d        180@e   90@f=p1               180@j     90@i=p1
pfg  z:                  g1@a1      g2@b1     g3@c1 g4@d1                                 g5@j0  g6@j1

Option 2

  • limit anchor names to strings of alphabetic characters
  • all anchor within a group should have same base name, and have an integer index >0
  • anchor groups can then be declared like arrays in some programming languages
anchors:       @a          @b[2]      @c[2]       @d[3]           @e     @f      @g     @h    @j[3]      @i[2]          @l
disp:         3@a         5@b2        3@c2        3@d2           9@e    9@f     4@g    4@h    3@j2      3@i1          10@l
time:    rlx   @a  t1      @b2  t2     @c2 t3      @d2   T1a      @e T1b @f T12  @g T12 @h  d  @j2     d @i1--i2   aq   @l
rf H:        90@a                                                             180@g                       acq@i2---------l
rf 13C:                  90@b2       90@c2       90@d2         180@e   90@f=p1              180@j2     90@i1=p1
pfg  z:                 g1@b1      g2@c1      g3@d1  g4@d3                                g5@j1  g6@j3

This is better for anchor groups with more then two anchors, because the anchors line becomes more concise.

Also it is better because all anchors within group have same base name.

Personal tools