From 068b621ff2a6f2e953e0807946bf642be014a873 Mon Sep 17 00:00:00 2001 From: Markus Rosenstihl Date: Fri, 9 Jan 2015 11:58:43 +0100 Subject: [PATCH] Fixes Issue #2: preliminary support for xmgrace file creation --- {bds_io => fileio}/__init__.py | 0 {bds_io => fileio}/bds_file_reader.py | 0 {bds_io => fileio}/gracedriver.py | 81 ++++++++++++++++++++++----- gui/container_widgets.py | 4 +- qds.py | 30 +++++++--- 5 files changed, 92 insertions(+), 23 deletions(-) rename {bds_io => fileio}/__init__.py (100%) rename {bds_io => fileio}/bds_file_reader.py (100%) rename {bds_io => fileio}/gracedriver.py (52%) diff --git a/bds_io/__init__.py b/fileio/__init__.py similarity index 100% rename from bds_io/__init__.py rename to fileio/__init__.py diff --git a/bds_io/bds_file_reader.py b/fileio/bds_file_reader.py similarity index 100% rename from bds_io/bds_file_reader.py rename to fileio/bds_file_reader.py diff --git a/bds_io/gracedriver.py b/fileio/gracedriver.py similarity index 52% rename from bds_io/gracedriver.py rename to fileio/gracedriver.py index 7a22093..62dd6b8 100644 --- a/bds_io/gracedriver.py +++ b/fileio/gracedriver.py @@ -1,21 +1,27 @@ +import re +import PyQt4.QtGui + __author__ = 'markusro' import tempfile,os import numpy as np -class grace: + +class GracePlot(object): def __init__(self): self.ls_map = {"None":0, "-":1, ":":2, "--":3, "-.":4 } # Symbols: 0:None 1:Circle 2:Square 3:Diamond 4:Triangle 5:up 6:left 7:down 8:right, 9:PLus 10:X 11:Star - self.sym_map = {"None":0, "o":1, "s":2, + self.sym_map = {None:0, "None":0, "o":1, "s":2, "d":3, "D":4, "2":5, "v":6, "3":6, "4":7,"1":8, "+":8,"x":9,"*":10 } self.tmpfiles = [] self.cmds = [] + self.color_map = {} # color map will pbe prepended to the final agr file self.data_counter = 0 + self.color_counter = 8 # keep first 8 colors already defined? def __del__(self): # take care of tmp files: @@ -23,18 +29,20 @@ class grace: os.remove(f) def plot(self, x, y, **kwds): + # save data to temporary file tmp_fd, tmp_name = tempfile.mkstemp() self.tmpfiles.append(tmp_name) np.savetxt(tmp_name, np.array([x, y]).T) #tmp_fd.close() + # read data in xmgrace self.cmds.append('READ NXY "%s"\n'%tmp_name) self.cmds.append('S%i SYMBOL SIZE 0.7\n'%(self.data_counter)) - self.cmds.append('S%i SYMBOL COLOR 1\n'%(self.data_counter)) + #self.cmds.append('S%i SYMBOL FILL COLOR %i\n'%(self.data_counter, self.data_counter)) self.cmds.append('S%i SYMBOL FILL PATTERN 1\n'%(self.data_counter)) self.cmds.append('S%i SYMBOL 1\n'%(self.data_counter)) # No line - #self.cmds.append('S%i LINE COLOR %i\n'%(self.data_counter, self.data_counter)) + if "label" in kwds.keys(): label = kwds["label"] self.cmds.append('S%i LEGEND "%s"\n'%(self.data_counter, label)) @@ -50,17 +58,50 @@ class grace: self.cmds.append('S%i SYMBOL %i\n'%(self.data_counter, self.sym_map[sym])) if sym in ['+', 'x', '*']: self.cmds.append('S%i SYMBOL COLOR %i\n'%(self.data_counter, self.data_counter)) + else: + self.cmds.append('S%i SYMBOL COLOR %i\n' % (self.data_counter, 1)) # vlack symbol outline + else: print "Symbol not known: %s"%sym + if "color" in kwds.keys(): + color = str(PyQt4.QtGui.QColor(kwds["color"]).getRgb()[:3]) + if color in self.color_map.keys(): + color_id = self.color_map[color][0] + else: + self.color_map[color] = [ + self.color_counter, + "@MAP COLOR %i TO %s, \"qds%i\" \n"% (self.color_counter, color, self.color_counter) + ] + color_id = self.color_counter + self.color_counter += 1 - - # if "label" in kwds.keys(): - # label = kwds["label"] - # self.cmds.append('S%i LEGEND "%s"\n'%(self.data_counter, label)) + self.cmds.append('S%i SYMBOL FILL COLOR %i\n' % (self.data_counter, color_id)) + self.cmds.append('S%i LINE COLOR %i\n' % (self.data_counter, color_id)) self.data_counter += 1 - pass + + + def loglog(self, x,y, **kwds): + self.cmds.append('YAXES SCALE LOGARITHMIC\n') + self.cmds.append("YAXIS TICKLABEL FORMAT POWER\n") + self.cmds.append("YAXIS TICKLABEL PREC 0\n") + self.cmds.append('XAXES SCALE LOGARITHMIC\n') + self.cmds.append("XAXIS TICKLABEL FORMAT POWER\n") + self.cmds.append("XAXIS TICKLABEL PREC 0\n") + self.plot(x, y, **kwds) + + def semilogx(self, x, y, **kwds): + self.cmds.append('XAXES SCALE LOGARITHMIC\n') + self.cmds.append("xAXIS TICKLABEL FORMAT POWER\n") + self.cmds.append("xAXIS TICKLABEL PREC 0\n") + self.plot(x, y, **kwds) + + def semilogy(self, x, y, **kwds): + self.cmds.append('YAXES SCALE LOGARITHMIC\n') + self.cmds.append("YAXIS TICKLABEL FORMAT POWER\n") + self.cmds.append("YAXIS TICKLABEL PREC 0\n") + self.plot(x, y, **kwds) def xlabel(self, label ): @@ -81,6 +122,7 @@ class grace: def save(self, fname): + self.cmds.append('AUTOSCALE\n') self.cmds.append('SAVEALL "%s"\n'%fname) # write cmds to tmpfile tmp_fd, tmp_name = tempfile.mkstemp() @@ -88,21 +130,34 @@ class grace: tmp_file = open(tmp_name, 'w') tmp_file.writelines(self.cmds) tmp_file.close() - # excecute tmpfile + # excecute tempraray xmgrace file to create final agr os.system("xmgrace -batch %s -hardcopy -nosafe -printfile tmp.tmp"%tmp_name) os.remove("tmp.tmp") + # prepend color map to the new file + with file(fname, 'r') as original_agr: data = original_agr.readlines() + # get the last "@map color ..." line + last_color_lineno = 0 + for i,line in enumerate(data): + if line.lower().startswith("@map color"): + last_color_lineno = i+1 + with file(fname, 'w') as new_agr: + new_agr.writelines(data[:last_color_lineno]) + for color in self.color_map: + new_agr.write(self.color_map[color][1]) + new_agr.writelines(data[last_color_lineno:]) if __name__ == "__main__": print "Testing Grace driver" np.random.seed(1337) # make it reproducible nums = 30 - gr = grace() + gr = GracePlot() t = np.linspace(0,1,nums) for i in xrange(30): - gr.plot(t, i + np.sin(2*np.pi * 3 * t + i*0.33 ) + 0.3*np.random.random(nums), + gr.loglog(t, i + np.sin(2*np.pi * 3 * t + i*0.33 ) + 0.3*np.random.random(nums), label="label %i"%i, ls=gr.ls_map.keys()[i%(len(gr.ls_map))], sym=gr.sym_map.keys()[i%(len(gr.sym_map))], + color="red" ) gr.xlabel(r"xlabel / \xm\sl\N\0") gr.ylabel(r"ylabel / \xt\sS\N\0") @@ -110,4 +165,4 @@ if __name__ == "__main__": print "created test.agr" os.system("xmgrace test.agr") print "deleting test.agr" - os.remove("test.agr") \ No newline at end of file + #os.remove("test.agr") \ No newline at end of file diff --git a/gui/container_widgets.py b/gui/container_widgets.py index 464d222..a85e766 100644 --- a/gui/container_widgets.py +++ b/gui/container_widgets.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- from ui import ConductivityGroupBox, PeakGroupBox, StaticGroupBox, PowerLawGroupBox, YAFFparameters, YAFFConfig -__author__ = 'markusro' +__author__ = 'Markus Rosenstihl ' from PyQt4.QtGui import * from PyQt4.QtCore import QRegExp, pyqtSignal,pyqtSlot @@ -114,7 +114,6 @@ class BaseWidget(QGroupBox): self.errors[i].setStyleSheet(sd_style) self.errors[i].setText(sd) self.blockSignals(False) - #self.update() def replaceDoubleSpinBox(self, layout, widget): ndx = layout.indexOf(widget) @@ -124,7 +123,6 @@ class BaseWidget(QGroupBox): layout.addWidget(widget, row,column) - class PeakWidget(BaseWidget,QGroupBox): def __init__(self, parent=None): QGroupBox.__init__(self) diff --git a/qds.py b/qds.py index 214793b..0643917 100755 --- a/qds.py +++ b/qds.py @@ -1,5 +1,6 @@ #!/usr/bin/env python # -*- encoding: utf-8 -*- +import fileio.gracedriver _author_ = "Markus Rosenstihl" @@ -30,7 +31,7 @@ from libmath.BDSlib import FunctionRegister, FitRoutine from data.experimental import Data from gui import ExtraDifferentialWidget -from bds_io import bds_file_reader +from fileio import bds_file_reader class AppWindow(QMainWindow): @@ -265,7 +266,7 @@ class AppWindow(QMainWindow): pre_header += "# Time: {time}\n# SessionID={id}\n".format(time=time.strftime("%H:%M:%S"), id=self.session_id) pars = [] base_filename, file_ext = os.path.splitext(self.filepath) - header = "{n1:13}{n2:13}".format(n1="# 0:T", n2="1:invT") + header = "{n1:13}{n2:13}".format(n1="# 0:T", n2="1:1000/T") varnum = 2 # T, invT are the first two columns for i_fcn, fcn in enumerate(self.function_registry.get_registered_functions()): @@ -312,7 +313,7 @@ class AppWindow(QMainWindow): pass pars.insert(0, self.data.meta["T"]) - pars.insert(1, 1e3/self.data.meta["1000/T"]) + pars.insert(1, 1e3/self.data.meta["invT"]) pars.append(self.data.fit_limits[0]) pars.append(self.data.fit_limits[1]) pars = np.array([pars]) @@ -347,12 +348,27 @@ class AppWindow(QMainWindow): pyplot.savefig(os.path.splitext(self.filepath)[0]+".pdf") fig.clear() del (fig) + self._saveFitFigureGrace() - def _saveFitFigureGrace( self ): - #agrtemplate = open('template.agr').read() - agrtemplate = """ + def _saveFitFigureGrace(self): + grace_plot = fileio.gracedriver.GracePlot() + grace_plot.loglog(self.data.frequency, self.data.epsilon.imag, sym='o', ls="-", label="Data") + grace_plot.loglog(self.data.frequency_fit, self.data.epsilon_fit.imag, sym=None, ls="-", label="Fit") + + # loop over functions and add data to plot + for fcn in self.function_registry.get_registered_functions(): + f, eps = fcn.get_data() + label = fcn.id_label + color = hex2color(str(fcn.color.name())) + grace_plot.loglog(f, eps[1], ls=":", color=color, sym=None, label=label) + # vertical lines (fit limits) + #for i in (0, 1): pyplot.axvline(x=self.data.fit_limits[i], color='b', ls="-", lw=0.5) + grace_plot.legend(True) + grace_plot.xlabel("f / Hz") + grace_plot.ylabel("eps") + print grace_plot.cmds + grace_plot.save(os.path.splitext(self.filepath)[0] + ".agr") - """ def addContainer(self, selected_container, pos): _cont = selected_container(plt_real=self.ui.pgPlotWidget_real,