Nmrtype development documentation
From NMR Wiki
Contents |
Concepts
Drawing
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
element | function | when fuction is called | what is done |
AnchorGroup | PulseSequence._parse_disp() PulseSequence._init() | removed from use (r15) still in use (r15) | N/A <head_group>.xcoor = 0 |
Anchor | AnchorGroup.time() | called from PulseSequence._compile_init() (r15) | xcoor relative to timing anchor calculated |
Delay | Delay.calc_drawing_coordinates() | currently (r15) not in use | xcoor = average(start_anchor.xcoor,end_anchor.xcoor) |
PulseSequenceElement | PulseSequence._draw() | removed in r16 | N/A |
Element drawing size calculations
default action: calculate elements .drawing_pre_width, .drawing_post_width, .drawing_width
element | function | when fuction is called | what is done |
AnchorGroup | AnchorGroup.calc_drawing_width() | called by AnchorGroup.time() after .set_xcoor(0) - i.e. when relative anchor coordinates become known | default 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)
Issues
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
Drawing
- 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
Expressions
- 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
Todo
- Implement PulseSequence._validate_anchor_order
Goals
- make drawings in SVG format
- finish compiling inkscape
- svg -> ps (inkscape should do it)
- 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
PSTricks latex package (recommended by John Forkosh who wrote mimetex)
Todo
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.