1 # demo_parm.py:
2
3 # Demonstrates the following MeqTree features:
4 # Simple Tree with a solver and several parameters, demonstartes paramter options
5
6 # Tips:
7
8 # The parameters are stored in the meptable. you can browse this to view the solutions
9
10
11
12 #********************************************************************************
13 # Initialisation:
14 #********************************************************************************
15
16 from Timba.TDL import *
17 from Timba.Meq import meq
18 # from qt import *
19 # from numarray import *
20
21 # from Timba.Contrib.JEN.util import JEN_bookmarks
22
23 # Make sure that all nodes retain their results in their caches,
24 # for your viewing pleasure.
25 Settings.forest_state.cache_policy = 100
26 Settings.forest_state.bookmarks = []
27
28
29
30 #********************************************************************************
31 # The function under the 'blue button':
32 #********************************************************************************
33
34 def _define_forest (ns, **kwargs):
35 """Definition of a 'forest' of one or more trees"""
36 #You can attach a meptable to a Parm by setting the field table_name,
37 # the funklet will then be initialized (if available) from
38 # and (after solving) stored in the table.
39 meptable ="test.mep"
40 #set this as the table for all our parms
41
42
43 # Make a Parm node, initialize it with constant 1.
44 # The node_groups='Parm' options is needed to be recognized by the solver
45 #tiling means that you have independent solutions for different time/freq slots.
46 #We make our simple_parm less simple, by tiling it in freq and time:
47
48
49 simple_parm = ns['simple_parm'] << Meq.Parm(1.,node_groups='Parm',table_name=meptable,
50 tiling= record(freq=1,time=2)
51 #Gives an independent solution per freq. cell
52 # and per 2 time cells
53 )
54
55 # a parm is initialized with a 'funklet' the most common funklet is the 'polc' a
56 # 2-dim polynomial in freq. and time, you can define the polc by giving a 2d array of its coefficients
57 # The shape of the array determinse the polynomial
58 polc = meq.polc([[1.,.02,.03],[.04,.005,.00001]]); #1.+0.02*f +0.03*f^2 +0.04*t +0.005*t*f +0.00001*t*f^2
59 polc_parm = ns['polc_parm'] <<Meq.Parm(init_funklet = polc,node_groups='Parm',table_name=meptable);
60
61
62 # Alternatively, you can fix the shape of the Polc by setting the shape field of the connected Parm.
63 # All missing coeffs will be initialized wiht zero's.
64 shape_parm = ns['shape_parm']<<Meq.Parm(1.,shape=[2,3],node_groups = 'Parm',table_name=meptable); #results in a [[1,0.0],[0.0.0]] polc.
65
66 # A more general, but sometimes slow, option is to make use of the Aips++ functional interpreter
67 # to create any real function. This is done by setting the "function" field of the polc.
68 functional = meq.polc([1.,2.,1.5]); # The number of coeffs should match the number of p# in function
69 functional.function = "p0+p1*exp(-0.01*x0^2)*sin(x1*p2)";
70 functional_parm = ns['functional_parm'] <<Meq.Parm(init_funklet = functional ,node_groups='Parm',table_name=meptable);
71
72
73
74
75
76
77 # Now a nonsense fit. lets fit simple_parm to the functional_parm, and shape_parm to polc_parm
78 # The final difference between the shape_parm and the polc_parm can be explained by the fact that for
79 # solvable polcs per default the lower right triangle of coefficients is kept to 0.
80 # i.e. all c_nm with (n+m) > max(n,m)
81 #
82 # The Condeq has exactly 2 children: the 'model' (in this case the parm)
83 # and the 'data' on which you want to fit the 'model'.
84 # solvable parm can be on both sides, so there is no real distinction between 'model' and 'data' here.
85 condeq_polc_shape = ns['condeq_polc_shape'] << Meq.Condeq(children=(polc_parm,shape_parm))
86 condeq_simple_functional = ns['condeq_simple_functional'] << Meq.Condeq(children=(simple_parm,functional_parm))
87
88 # Now create a solver node. A solver can have several children, but they all must be condeqs.
89 solver = ns['solver'] << Meq.Solver(children=(condeq_polc_shape,
90 condeq_simple_functional),
91 solvable = ['simple_parm','shape_parm'], #list of solvable parameters
92 num_iter = 10, #stop after 10 iterations or after convergence
93 epsilon = 1e-4, #convergence limit, good default
94 last_update=True, #sends last update to parms after convergence
95 save_funklets=True #needed to save funklets in parmtable
96 )
97 # Make a bookmark of the result node, for easy viewing:
98 bm = record(name='result',page=
99 [record(viewer='Result Plotter',udi='/node/simple_parm', publish=True, pos=(0,0)),
100 record(viewer='Result Plotter',udi='/node/polc_parm', publish=True, pos=(1,0)),
101 record(viewer='Result Plotter',udi='/node/functional_parm', publish=True, pos=(0,1)),
102 record(viewer='Result Plotter',udi='/node/shape_parm', publish=True, pos=(1,1)),
103 record(viewer='Result Plotter',udi='/node/condeq_polc_shape', publish=True, pos=(1,2)),
104 record(viewer='Result Plotter',udi='/node/condeq_simple_functional', publish=True, pos=(0,2)),
105 record(viewer='Result Plotter',udi='/node/solver', publish=True, pos=(2,0))
106 ])
107 Settings.forest_state.bookmarks.append(bm)
108
109 # Finished:
110 return True
111
112
113
114 #********************************************************************************
115 # The function under the TDL Exec button:
116 #********************************************************************************
117
118 def _tdl_job_execute (mqs, parent):
119 """Execute the forest, starting at the named node"""
120 domain = meq.domain(1,10,1,10) # (f1,f2,t1,t2)
121 cells = meq.cells(domain, num_freq=10, num_time=11)
122 request = meq.request(cells, rqtype='ev')
123 result = mqs.meq('Node.Execute',record(name='solver', request=request))
124 return result
125
126 #********************************************************************************
127 #********************************************************************************
