1 """ Interface between signals and figures
3 Class Oscopy: Commands callables from oscopy commandline
7 Create empty lists of figures, readers and signals
10 Create a new figure, and assign signals if provided
16 Select the figure and the graph to become the current ones
19 set_ the layout of the current figure
22 Print a list of figures
28 Read signals from file fn
30 write(fn, fmt, sns, opts)
31 Write signals sns to file fn using format sns and options opts
34 Reread all signals from files
37 Add a graph to the current figure
40 Delete a graph from the current figure
43 Set the mode of the current graph
46 Set the axis scale of the current graph e.g. log or lin
49 Set the axis range of the current graph
52 Set the unit of current graph from current figure
55 Add signals to the current graph of the current figure
58 Remove signals from the current graph of the current figure
61 Set the freeze flag of signals
64 Unset_ the freeze flag of signals
70 Create a signal from a mathematical expression
73 Return a list of the signal names from the arguments provided by the user
74 Should not be called from the command line
86 import matplotlib
.pyplot
as plt
87 from Readers
.DetectReader
import DetectReader
88 from Writers
.DetectWriter
import DetectWriter
89 from Readers
.Reader
import ReadError
90 from Writers
.Writer
import WriteError
91 from Figure
import Figure
94 """ Class Oscopy -- Interface between signals and figures
96 This object is the interface between the signals and the figures,
97 e.g. it handle operations on figures, signals, readers and writers.
98 It maintain a list of figures, a dict of reader and a dict of signals.
100 The keys for the signal dict are the signal name, as presented to the user
101 The keys for the reader dict are the file name.
105 """ Create the instance variables
114 def create(self
, sigs
):
115 """ Create a new figure and set_ it as current
116 Can be either called from commandline or a function.
117 When called from commandline, call signames_to_sigs to retrieve
119 When called from a function, if the argument is not a list
121 After those tests, the figure is created with the signal list.
123 if isinstance(sigs
, list):
124 # Called from commandline,
125 # Get the signal list from args
127 sigs
= self
.signames_to_sigs(sigs
)
129 # No signal list provided
131 elif not isinstance(sigs
, dict):
133 # toplot is now a list
138 def destroy(self
, num
):
140 User must provide the figure number.
141 If the number is out of range, then return
142 Act as a "pop" with self.curfig
144 if num
> len(self
.figs
) or num
< 1:
146 if self
.curfig
== self
.figs
[num
- 1]:
147 if len(self
.figs
) == 1:
148 # Only one element remaining in the list
150 elif num
== len(self
.figs
):
151 # Last element, go to the previous
152 self
.curfig
= self
.figs
[num
- 2]
155 self
.curfig
= self
.figs
[num
]
156 del self
.figs
[num
- 1]
157 if self
.curfig
is not None:
158 print "Curfig : ", self
.figs
.index(self
.curfig
) + 1
162 def select(self
, num
, gn
= 0):
163 """ Select the current figure
165 if num
> len(self
.figs
) or num
< 1:
167 self
.curfig
= self
.figs
[num
- 1]
169 self
.curfig
.select(gn
)
172 """ Define the layout of the current figure
174 if self
.curfig
is not None:
175 self
.curfig
.set_layout(l
)
178 """ Print the list of figures
180 for i
, f
in enumerate(self
.figs
):
185 print "Figure", i
+ 1, ":", f
.layout
189 """ Plot the figures, and enter in the matplotlib main loop
193 for i
, f
in enumerate(self
.figs
):
194 fig
= plt
.figure(i
+ 1)
199 """ Read signals from file.
200 Duplicate signal names overwrite the previous one.
201 For new only gnucap files are supported.
202 Do not load the same file twice.
204 # File already loaded ?
205 if fn
in self
.readers
.keys():
206 print "File already loaded"
211 print "File format unknown"
215 # Insert signals into the dict
216 for sn
in sigs
.keys():
217 self
.sigs
[sn
] = sigs
[sn
]
220 for s
in sigs
.itervalues():
224 def write(self
, fn
, fmt
, sns
, opts
):
225 """ Write signals to file
228 sigs
= self
.signames_to_sigs(sns
)
232 w
= DetectWriter(fmt
, fn
, True)
233 except WriteError
, e
:
234 print "Write error:", e
238 w
.write(fn
, sigs
, opts
)
239 except WriteError
, e
:
240 print "Write error:", e
242 def update(self
, r
=None, upn
=-1):
243 """ Reread signal from files.
244 For each file, reread it, and for updated, new and deleted signal,
245 update the signal dict accordingly.
249 # Normal call create the new list etc etc
251 for reader
in self
.readers
.itervalues():
252 print "Updating signals from", reader
253 n
.update(self
.update(reader
, self
.upn
))
255 # First look at its dependencies
256 if hasattr(r
, "get_depends") and callable(r
.get_depends
):
257 for sn
in r
.get_depends():
258 print " Updating signals from", self
.sn_to_r
[sn
]
259 n
.update(self
.update(self
.sn_to_r
[sn
], self
.upn
))
260 # TODO: Update depencies: what happens to vo when
261 # vout is deleted ? It seems it is not deleted: it should!
263 n
.update(r
.update(self
.upn
, keep
=False))
266 # Find deleted signals
268 for sn
, s
in self
.sigs
.iteritems():
269 #n.update(s.update(self.upn, False))
274 # Delete signals: first from figure and after from dict
277 f
.remove({sn
:self
.sigs
[sn
]}, "all")
281 """ Add a graph to the current figure
282 The signal list is a coma separated list of signal names
283 If no figure exist, create a new one.
288 sigs
= self
.signames_to_sigs(sns
)
289 self
.curfig
.add(sigs
)
291 def delete(self
, gn
):
292 """ Delete a graph from the current figure
294 if self
.curfig
is not None:
295 self
.curfig
.delete(gn
)
297 def mode(self
, mode
):
298 """ Set the mode of the current graph of the current figure
300 if self
.curfig
is not None:
301 self
.curfig
.set_mode(mode
)
304 """ Set the axis scale of the current graph of the current figure
306 if self
.curfig
is not None:
307 self
.curfig
.set_scale(sc
)
309 def range(self
, a1
= "reset", a2
= None, a3
= None, a4
= None):
310 """ Set the axis range of the current graph of the current figure
312 if self
.curfig
is not None:
313 self
.curfig
.set_range(a1
, a2
, a3
, a4
)
315 def unit(self
, xu
, yu
= ""):
316 """ Set the units of current graph of current figure
318 if self
.curfig
is not None:
319 self
.curfig
.set_unit(xu
, yu
)
321 def insert(self
, sns
):
322 """ Insert a list of signals into the current graph
323 of the current figure
328 if self
.curfig
is not None:
329 sigs
= self
.signames_to_sigs(sns
)
330 self
.curfig
.insert(sigs
)
332 def remove(self
, sns
):
333 """ Remove a list of signals from the current graph
334 of the current figure
339 if self
.curfig
is not None:
340 sigs
= self
.signames_to_sigs(sns
)
341 self
.curfig
.remove(sigs
)
343 def freeze(self
, sns
):
344 """ Set the freeze flag of signals
346 sigs
= self
.signames_to_sigs(sns
)
347 for s
in sigs
.itervalues():
350 def unfreeze(self
, sns
):
351 """ Unset the freeze flag of signals
353 sigs
= self
.signames_to_sigs(sns
)
354 for s
in sigs
.itervalues():
358 """ List loaded signals
360 for s
in self
.sigs
.itervalues():
364 """ Create a signal from mathematical expression
368 # Create the expression
369 r
= DetectReader(inp
)
372 # Failed to read file
373 # If reader provide a missing() and set_origsigs() functions
374 # and if signal names are found pass them to reader
375 if hasattr(r
, "missing") and callable(r
.missing
):
377 if hasattr(r
, "set_origsigs") and callable(r
.set_origsigs
):
379 if self
.sigs
.has_key(sn
):
380 sigs
[sn
] = self
.sigs
[sn
]
386 print "Signal not generated"
387 for sn
, s
in ss
.iteritems():
389 self
.sn_to_r
[sn
] = inp
390 self
.readers
[inp
] = r
392 def signames_to_sigs(self
, sns
):
393 """ Return a signal dict from the signal names list provided
394 If no signals are found, return {}
399 # Are there signals ?
401 print "No signal loaded"
404 # Prepare the signal list
406 if sn
in self
.sigs
.keys():
407 sigs
[sn
] = self
.sigs
[sn
]
409 print sn
+ ": Not here"
413 print "No signals found"