def create_page_and_grid(self, page): self.ops.append((document.OperationWidgetAdd(self.doc.basewidget, 'page', name=page))) self.apply_ops(descr='MakeDefaultPlot: Page ' + page) wg = self.doc.basewidget.getChild(page) if self.fields.get('grid', False): self.ops.append( document.OperationWidgetAdd(wg, 'grid', name='grid')) self.apply_ops(descr='MakeDefaultPlot: Grid') wg = wg.getChild('grid') self.toset(wg, 'topMargin', '16pt') return wg
def initCurve(self, name='Curve', xData='xD', yData='yD', yAxis='y', axisLabel='Curve', graph='/page/graph'): """Configure a new curve (appearance, axes positions, data labels""" logging.debug('initCurve', name, xData, yData) doc = self.doc gobj = doc.resolveFullWidgetPath(graph) preop = [] preop.append(document.OperationWidgetAdd(gobj, 'xy', name=name)) create = True for obj in gobj.children: if obj.name == yAxis: create = False break if create: preop.append( document.OperationWidgetAdd(gobj, 'axis-function', name=yAxis, direction='vertical')) # Create graph and axis (if needed) logging.debug('applying operations', preop) doc.applyOperation( document.OperationMultiple(preop, descr='PlotDataset:Create')) obj = gobj.getChild(name) n = len(doc.data[yData].data) thin = int(max(1, n / 100)) if n > 10: self.toset(obj, 'marker', u'none') else: self.toset(obj, 'marker', u'circle') self.toset(obj, 'markerSize', u'2pt') self.toset(obj, 'thinfactor', thin) self.toset(obj, 'yData', yData) self.toset(obj, 'xData', xData) self.toset(obj, 'key', name.replace('_', '\\_')) self.toset(obj, 'yAxis', yAxis) yax = gobj.getChild(yAxis) self.toset(yax, 'label', axisLabel.replace('_', '\\_').replace('/', '.')) self.apply_ops('PlotDataset:Associate') return True
def create_page_temperature(self, page): wg = self.create_page_and_grid(page) self.ops.append(document.OperationWidgetAdd(wg, 'graph', name='temp')) self.apply_ops(descr='MakeDefaultPlot: Graph Temperature') title = self.fields.get('title', False) or 'By Temperature' self.make_title(wg, title) graph = wg.getChild('temp') self.adjust_graph(graph, u'Temperature (°C)')
def add_label_to(curve, message, label_name, doc, toset): if not curve.hasChild(label_name): doc.applyOperation( document.OperationWidgetAdd(curve, 'curvelabel', name=label_name)) label = curve.getChild(label_name) toset(label, 'label', message) toset(label, 'xPos', 0.1) toset(label, 'yPos', 0.9)
def make_title(self, page_wg, title): if self.fields.get('grid', False): page_wg = page_wg.parent self.ops.append((document.OperationWidgetAdd(page_wg, 'label', name='title'))) self.apply_ops(descr='MakeDefaultPlot: Title') props = {'xPos': 0.1, 'yPos': 1, 'label': title, 'alignVert': 'top'} label = page_wg.getChild('title') self.dict_toset(label, props) self.dict_toset(page_wg, {'notes': title}) self.ops.append( document.OperationWidgetMove(label.path, page_wg.path, 0)) return True
def label(self): """Draw label""" cur = self.fld.get('currentwidget') g = self.doc.resolveFullWidgetPath(cur) g = utils.searchFirstOccurrence(g, ['graph', 'page']) if g is None or g.typename not in ['graph', 'page']: raise plugins.ToolsPluginException( 'Impossible to draw the label. Select a page or a graph.') name = 'lbl_' + self.fld['d'].replace('summary/', '').replace('/', '_') if not g.getChild(name): self.ops.append(document.OperationWidgetAdd(g, 'label', name=name)) self.apply_ops(self.name + ':CreateLabel') lbl = g.getChild(name) self.toset(lbl, 'label', self.msg.replace('\n', '\\\\'))
def makeWidget(self, widgettype, autoadd=True, name=None): """Called when an add widget button is clicked. widgettype is the type of widget autoadd specifies whether to add default children if name is set this name is used if possible (ie no other children have it) """ # if no widget selected, bomb out if not self.selwidgets: return parent = document.getSuitableParent(widgettype, self.selwidgets[0]) assert parent is not None if name in parent.childnames: name = None # make the new widget and update the document w = self.document.applyOperation( document.OperationWidgetAdd(parent, widgettype, autoadd=autoadd, name=name) ) # select the widget self.selectWidget(w)
def intercept_xy(self, obj): """Intercept obj xy for all line length""" doc = self.document self.doc = doc # Translate end points coords xax = self.parent.getChild(obj.settings.xAxis) ox, ox2 = translateCoord(xax, [self.x, self.x2]) yax = self.parent.getChild(obj.settings.yAxis) oy, oy2 = translateCoord(yax, [self.y, self.y2]) logging.debug('limits', ox, oy2, ox2, oy2) # Get the data from the plot obj vx = doc.data[obj.settings.xData].data vy = doc.data[obj.settings.yData].data # Line angle ang = np.arctan((oy2 - oy) / (ox2 - ox)) logging.debug('Angle', ang * 180 / np.pi) # Rotation matrix rot = np.matrix([[np.cos(ang), np.sin(ang)], [-np.sin(ang), np.cos(ang)]]) # Rotate the data r = np.asarray(rot * np.array([vx, vy])) # Rotate the points rp = np.asarray(rot * np.array([[ox], [oy]])) rox = rp[0][0] roy = rp[1][0] # Find where the rotated array crosses the x axis crossing = np.diff(np.sign(r[1] - roy)) # print 'Diff sign',crossing,np.abs(crossing).sum() crossings = np.where(crossing != 0)[0] logging.debug('Crossings', crossings) # Find valid crossing cx = [] found = {obj: {}} for c in crossings: if not (min(ox, ox2) < vx[c] < max(ox, ox2) or min(oy, oy2) < vy[c] < max(oy, oy2)): logging.debug('ignoring crossing', c, vx[c], vy[c]) continue # Avoid very similar entries if c + 1 in cx or c - 1 in cx: logging.debug('Ignoring too near crossing', c, vx[c], vy[c]) continue cx.append(c) # Must create a new DataPoint widget for this crossing name = 'intercept_%s_%s_%i' % (self.name, obj.name, c) dpset = { 'name': name, 'xy': obj.name, 'xAxis': obj.settings.xAxis, 'yAxis': obj.settings.yAxis, 'xPos': float(vx[c]), 'yPos': float(vy[c]), 'coordLabel': '', 'showLabel': False } if self.settings.showLabels == True: lblname = 'lbl_' + name dpset['showLabel'] = True dpset['coordLabel'] = lblname self.ops.append( document.OperationWidgetAdd(self.parent, 'label', name=lblname)) self.ops.append( document.OperationWidgetAdd(self.parent, 'datapoint', **dpset)) found[obj][c] = (name, vx[c], vy[c]) # Update crossings dictionary self.crossings.update(found) return True
def dependencies(self): """Create/destroy dependent widgets""" s = self.settings # Tangent tg = s.get('tangentLine').findWidget() if tg is None: logging.debug('No tangent line specified') if s.showTangent: name = 'tg_' + self.name self.ops.append( document.OperationWidgetAdd(self, 'datapointline', name=name)) self.toset(self, 'tangentLine', name) # Destroy if not needed elif not s.showTangent: self.ops.append(document.OperationWidgetDelete(tg)) # Perpendicular tg = s.get('perpendicularLine').findWidget() if tg is None: logging.debug('No pp line specified') if s.showTangent: name = 'pp_' + self.name self.ops.append( document.OperationWidgetAdd(self, 'datapointline', name=name)) self.toset(self, 'perpendicularLine', name) # Destroy if not needed elif not s.showPerpendicular: self.ops.append(document.OperationWidgetDelete(tg)) # PT2PT tg = s.get('pt2ptLine').findWidget() p2 = s.get('secondPoint').findWidget() if tg is None: logging.debug('No p2p line specified') if p2 is not None: name = 'p2p_%s_%s' % (self.name, p2.name) self.ops.append( document.OperationWidgetAdd(self, 'datapointline', name=name)) self.toset(self, 'pt2ptLine', name) # Destroy if not needed elif p2 is None: self.ops.append(document.OperationWidgetDelete(tg)) # Label has_label = len(self.children) > 0 if not has_label and s.showLabel: name = 'lbl_' + self.name self.ops.append( document.OperationWidgetAdd(self, 'datapointlabel', name=name)) self.toset(self, 'coordLabel', name) if not s.showLabel: for label in self.children: self.ops.append(document.OperationWidgetDelete(label)) self.apply_ops('Datapoint: Dependencies')
def actionUp(self): logging.debug('SYNC LINE UP') self.ops = [] doc = self.document ref = None # Reference curve is the first child xref = [] yref = [] # Fractional position on x axis apos = self.settings.otherPosition # Translation mode trmode = self.settings.trans # Maximum translations up_ext = 0 down_ext = 0 axmap = {} objmap = {} # Search for all curves in parent graph for i in range(self.ncurves): u = 'curve' + str(i) uc = getattr(self.settings, u) obj = self.parent.getChild(uc) if obj is None: if i == 0: logging.debug('No reference curve defined') return break xax = self.parent.getChild(obj.settings.xAxis) # Get the y axis yax = self.parent.getChild(obj.settings.yAxis) if None in [xax, yax]: continue # Obtain real position relative to xax pos = apos * \ (xax.plottedrange[1] - xax.plottedrange[0]) + \ xax.plottedrange[0] # Set reference values if ref is None: ref = obj xref = doc.data[ref.settings.xData].data yref = doc.data[ref.settings.yData].data yaxref = yax # Reference ranges ymin_ref, ymax_ref = yaxref.plottedrange # Search the nearest X value on ref X-array dst = np.abs(xref - pos) i = np.where(dst == dst.min())[0][0] # Get the corresponding Y value on the ref Y-array yval_ref = yref[i] axmap[yax.name] = obj objmap[obj] = (yax, 0) continue # Getting curve data xtr = doc.data[obj.settings.xData].data yds_name = obj.settings.yData yds = doc.data[yds_name] ytr = yds.data # Search the nearest X value on trans X-array dst = np.abs(xtr - pos) i = np.where(dst == dst.min())[0][0] # Delta d = ytr[i] - yval_ref objmap[obj] = (yax, d) # Create axes - only for axis translation if trmode == 'Values': new = yds.data - d # Create a copy of the dataset ydsn = copy.copy(yds) # Change copy's values ydsn.data = new # Set original dataset to copied one op = document.OperationDatasetSet(yds_name, ydsn) self.ops.append(op) # Remember translation if not self.trcum.has_key(obj.path): self.trcum[obj.path] = 0 self.trcum[obj.path] += d continue # Remember for future translation if ytr.min() < ymin_ref: ymin_ref = ytr.min() if ytr.max() > ymax_ref: ymax_ref = ytr.max() # Each Y axis MUST be unique. # Create new one if current obj happens to share its axis with a # previous one if axmap.has_key(yax.name): axname = 'ax_%s_%s' % (obj.name, self.name) axset = { 'name': axname, 'direction': 'vertical', 'label': 'Trans:' + yax.settings.label, 'hide': False } # will be True! don't want to see all that axes self.ops.append( document.OperationWidgetAdd(self.parent, 'axis', **axset)) self.toset(obj, 'yAxis', axname) axmap[axname] = obj self.axmap[obj.path] = (axname, yax.name, (yax.settings.min, yax.settings.max)) # else: # self.axmap[obj.path]=(yax.name,yax.name,(yax.settings.min,yax.settings.max)) if trmode == 'Values': # Remove dissociated objects ucs = set([obj.path for obj in objmap.keys()]) for uc in set(self.trcum.keys()) - ucs: del self.trcum[uc] self.apply_ops('SynAxis: Translation') return # Remove unused restore info ucs = set([obj.path for obj in objmap.keys()]) for uc in set(self.axmap.keys()) - ucs: del self.axmap[uc] self.trcum = {} # Apply axis creation self.apply_ops('SynAxis: Create') # Extend axes and apply translations self.toset(yaxref, 'max', float(ymax_ref)) self.toset(yaxref, 'min', float(ymin_ref)) for obj, (yax, d) in objmap.iteritems(): self.toset(yax, 'max', float(ymax_ref + d)) self.toset(yax, 'min', float(ymin_ref + d)) self.apply_ops('SynAxis: Update')
def apply(self, cmd, fields): """Do the work of the plugin. cmd: veusz command line interface object (exporting commands) fields: dict mapping field names to values """ self.ops = [] self.doc = cmd.document cur = fields['currentwidget'] g = self.doc.resolveFullWidgetPath(cur) g = utils.searchFirstOccurrence(g, 'graph') if g is None or g.typename != 'graph': raise plugins.ToolsPluginException( 'You should run this tool on a graph') axn = fields['axis'] val = fields['val'] text = fields['text'] targetds = fields['target'] doc = cmd.document hor = axn == 'X' datapoint_paths = [] logging.debug( 'targets', targetds) for datapoint_parent in g.children: if not isinstance(datapoint_parent, veusz.widgets.point.PointPlotter): continue if datapoint_parent.settings.hide: logging.debug('Skipping hidden object', datapoint_parent.path) continue if datapoint_parent.settings.yData not in targetds and len(targetds) > 0: logging.debug('Skipping non-targeted object', datapoint_parent.path, datapoint_parent.settings.yData) continue # Search the nearest point x = datapoint_parent.settings.get('xData').getFloatArray(doc) y = datapoint_parent.settings.get('yData').getFloatArray(doc) dst = abs(x - val) if hor else abs(y - val) i = np.where(dst == dst.min())[0] if len(i) == 0: raise plugins.ToolsPluginException( 'Impossible to find required value: %E' % val) i = i[0] # Add the datapoint cmd.To(g.path) name = datapoint_parent.createUniqueName('datapoint') lblname = name + '_lbl' # Create the datapoint datapoint_settings = {'name': name, 'xAxis': datapoint_parent.settings.xAxis, 'yAxis': datapoint_parent.settings.yAxis, 'xPos': float(x[i]), 'yPos': float(y[i]), 'coordLabel': lblname, 'labelText': text, 'search': fields['search'], 'searchRange': fields['searchRange']} if fields.has_key('critical_x'): datapoint_settings['critical_x'] = fields['critical_x'] self.ops.append(document.OperationWidgetAdd(datapoint_parent, 'datapoint', **datapoint_settings)) datapoint_paths.append(datapoint_parent.path + '/' + name) logging.debug('Intercepting', self.ops) self.apply_ops('Intercept') for path in datapoint_paths: cmd.To(path) cmd.Action('up')