Commit 19fad86f authored by Yori Fournier's avatar Yori Fournier
Browse files

Merge branch '49-make-myaxes-client' of gitlab.aip.de:yfournier/myplotlib into...

Merge branch '49-make-myaxes-client' of gitlab.aip.de:yfournier/myplotlib into 49-make-myaxes-client
parents f4bdcba0 91f99163
......@@ -96,10 +96,12 @@ if D_HIERARCHY in ('CLIENT', 'client', 'LOCAL', 'local'):
if D_HIERARCHY in ('CLIENT', 'client'):
# MyAxes: Overlay on matplotlib.Axes class
from .myAxes import MyAxes_client as MyAxes
from .myAxes_client import MyAxes_client as MyAxes
# MyFig: Overlay on matplotlib.Figure class
from .myFig import MyFig_client as MyFig
from .myFig_client import MyFig_client as MyFig
from .serverInterface import ServerInterface
elif(D_HIERARCHY in ('SERVER', 'server')):
......@@ -159,8 +161,9 @@ if D_HIERARCHY in ('CLIENT', 'client', 'LOCAL', 'local'):
if D_HIERARCHY in ('CLIENT', 'client', 'LOCAL', 'local'):
from .test import myTest
from .test import testList
# from .test import myTest
# from .test import testList
from .test import FigTest
# for testing purpose
from .test import readStupidData
......@@ -50,7 +50,7 @@ from . import rcParams
# Class MyAxes Overwriting Matplotlib.figure.Axes
class MyAxes(Axes):
class MyAxes_client(Axes):
# CONSTRUCTOR --------------------------------------------------------
def __init__(self, fig, ratio, frameRect, *args, **kwargs):
......
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# ================= FILE HEADER ========================================
#
# myplotlib v3.0.1,
#
# @file myFig.py
# @author Yori 'AGy' Fournier
# @licence CC-BY-SA
#
# MyFig class: Overlay of matplotlib Figure class
# It is done such that the user can concentrate on
# the important aspect of the figure and not the
# technical part.
#
# @Class MyFig
#
# @Constructor
#
# fignum: number of the Figure.
# reformat: flag for reComputing plotted data
# from rawData.
# debug: flag for debugging, more verbatile.
# (kw)args: user defined arguments and keywords.
#
# @section Functions
#
# - printDebug: print some debug information.
#
# - plot: overlay of Figure.plot() function,
# should be overwrited by the user.
# Consists of
# - creating axes,
# - formating the data,
# - adding the axis to the figure
# - plotting the axis
#
# - update: update the parameters in the
# keywords dictionary.
#
# @section History
#
# v 0.1.1 - MyFig class for the myplotlib module.
#
# v 1.0.0 - Changed rawdata with inputarg to allows any type
# of rawdata, can be an array.
#
# replace the attribute format (reserved word) with
# formatted.
#
# v 1.0.1 - Suppress the explicit definitions of the keywords.
# by the introduction of the keywords dictionary.
# All parameters in this dictionary are automatically
# updated.
#
# suppress the default value of fignum and hardcode it
# to be -1.
#
# add the attribute boundedToWin required for the
# interactive mode of myplotlib.
#
# v 2.2.3 - Allow the possibility of giving a unique rawdata format
# all axes. /!\ self.rawdata is a generator. /!\
#
# ======================================================================
#
#
# IMPORT ---------------------------------------------------------------
from . import os
from . import D_FIGSIZE, D_INPUTARG, D_DEBUG, D_REFORMAT, D_FORMATTED
from . import D_OFORMAT, D_OPATH
from . import DBUG, SEVR, INFO, SPCE, WARN
from . import MyData
from . import MyAxes
from . import Figure
# Class MyFig Overwriting Matplotlib.figure.Figure
class MyFig_client(Figure):
# Set the size of the Figure in inch
# (private variable can not be updated)
FIGSIZE = D_FIGSIZE
# CONSTRUCTOR --------------------------------------------------------
def __init__(self, rawdata, *args, **kwargs):
# for the update function
self._attributesToUpdateKeys = ['fignum', 'reformat', 'debug', 'formatted', 'aliases']
# initialise the attribute default values and remove them from kwargs
self.fignum = kwargs.pop('fignum', -1) # need to be hard coded for interactive mode
self.reformat = kwargs.pop('reformat', D_REFORMAT)
self.debug = kwargs.pop('debug', D_DEBUG)
self.formatted = kwargs.pop('formatted', D_FORMATTED)
self.aliases = {}
self.FIGSIZE = kwargs.pop('figsize', self.FIGSIZE)
# parent constructor
Figure.__init__(self, figsize=self.FIGSIZE)
# This is required for the interactive mode
# it ensures that a figure can not be bounded
# to several windows and prevent the loss of canvas.
self.boundedToWin = False
# initialise
self._initialize(*args, **kwargs)
# INITIALIZE -------------------------------------------------------
def _initialize(self, *args, **kwargs):
# add the axes
self.addAxes()
# declare the aliases
self.declareAliases()
# update the attributes and keywords
self.update(**kwargs)
# UPDATE ----------------------------------------------------------
def update(self, **kwargs):
# check attributes in keywords
for keyword in kwargs.keys():
# if it is an attribute
if keyword in self._attributesToUpdateKeys:
# update value
setattr(self, keyword, kwargs[keyword])
# For each axes update the keywords
for ax in self.get_axes():
forax = {}
for keyword in kwargs.keys():
# ignore figure attributes
if keyword in self._attributesToUpdateKeys :
pass
# Check if a key of kwargs has an alias for this axes
elif keyword in self.aliases.keys():
alax, alkey = self.aliases[keyword]
# If an alias is found then update axkwargs
if ax == alax:
forax.update(**{alkey: kwargs[keyword]})
# use keyword as it is for the axes
else :
forax.update(**{keyword : kwargs[keyword]})
# Then eventually all collected Keywords are updated in one go
if (forax) :
if self.debug:
print (DBUG+' fig.update ', ax, 'keywords: ', forax)
ax.update(**forax)
return(True)
# DECLARE ALIASES -------------------------------------------------
def declareAliases(self):
pass
# ADD AXES ---------------------------------------------------------
def addAxes(self, *arg, **kwargs):
pass
# This overwrites MPL add_axes. It gives a name to the axis added so that it is easier to refer to
def add_axes(self, ax, name) :
# if isinstance(name, str) and issubclass(ax.__class__, MyAxes): # This lead to an error is ax is not in the same namespace
ax.name = name
# else:
# print(SEVR + " there is an error with the input type of add_axes()")
# return False
# test if an axes with that name is already present
for pax in self.get_axes() :
if pax.name == name :
print(SEVR + " an axes with that name is already present")
return False
Figure.add_axes(self, ax)
return True
# GET AXES BY NAME -------------------------------------------------
def getAxesByName(self, name):
for ax in self.get_axes() :
if ax.name == name :
return ax
#if the name is correct we should never get here.
print(SEVR + "The axes name ", name, " was not found")
return None
# FORMAT RAW DATA --------------------------------------------------
def formatRawData(self):
# HEre comes a function that send a signal to the server
# and tells him to execute the format rawdata of the
# synchronized figure (server-side)
pass
# PLOT -------------------------------------------------------------
def plot(self):
status = True
if(self.debug):
print(DBUG + "currently formatting the data...")
if((self.reformat) or (not self.formatted)):
status = self.formatRawData()
if(not status): return(False)
if(self.debug):
print(DBUG + "currently plotting the axes...")
# For all axes in the figure reformat if needed and plot
for ax in self.get_axes():
# clean the axes
ax.cla()
# plot
plottingStatus = ax.plotting()
status = status and plottingStatus
return(status)
# RESET ------------------------------------------------------------
def reset(self, *args, **kwargs):
self.clf()
self._initialize(*args, **kwargs)
self.plot()
# DEBUG --------------------------------------------------------------
def printDebug(self):
className = str(self.__class__.__name__)
print('\n' + DBUG + " {0} PARAMETERS: ".format(className))
print(SPCE + " ID the figure: " + str(self.fignum))
print(SPCE + "Size of the figure: " + str(self.FIGSIZE) + ' [inch] \n')
# PRINT 2 FILE -------------------------------------------------------
def print2file(self, filename, *args, **kwargs):
# get the keywords
debug = kwargs.get('debug', D_DEBUG)
oformat = kwargs.get('oformat', D_OFORMAT)
opath = kwargs.get('opath', D_OPATH)
as_seen = kwargs.get('as_seen', False)
# set the dpi
if(oformat == 'png'):
dpi = 300.
addMetaData = True # NOT YET IMPLEENTED
else:
dpi = 100.
addMetaData = False # NOT YET IMPLEMENTED
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
# if the figure is boundedToWin
# save to canvas in a local variable and restore after saving to file.
if self.boundedToWin:
winCanvas = self.canvas
else:
winCanvas = None
canvas = FigureCanvas(self) # the canvas of the figure changed
# Plot the figure
if not as_seen:
status = self.plot()
if not status:
print(SEVR + 'Can not plot the figure. sorry --> EXIT')
return(False)
# draw the figure on the new canvas
canvas.draw() # not really needed (savefig does that)
# check if the extention is in the name
if '.png' in str(filename):
oformat = 'png'
filename = filename[:-4]
elif '.eps' in str(filename):
oformat = 'eps'
filename = filename[:-4]
# check if the path is in the name
if '/' in str(filename):
if(debug):
print(WARN + "I detect that the path is in the name of the file, will ignore D_OPATH.")
arg = filename
filename = os.path.basename(arg)
opath = os.path.dirname(arg)
# take care of the . in the extention
if oformat[0] == '.':
oformat = oformat[1:]
# clean the output path
if str(opath)[-1] == '/':
opath = str(opath)[:-1]
else:
opath = str(opath)
# print into a file
try:
self.savefig(str(opath) + '/' + str(filename) + '.' + str(oformat), dpi=dpi) # ! this not the save from plt but from fig
except IOError:
print(SEVR + 'the path to the file does not exists:')
print(SPCE + str(opath) + '/' + str(filename) + '.' + str(oformat) + ' --> EXIT')
return(False)
except:
print(SEVR + 'Can not save file. sorry --> EXIT')
return(False)
# restore the former canvas
if winCanvas is not None:
self.canvas = winCanvas
return(True)
......@@ -32,7 +32,15 @@ class ServerInterface(object):
def newSyncFigure(self, figClass, symbolicRawdata, **kwargs):
syncFigure = figClass(symbolicRawdata, **kwargs)
# syncFigure = figClass(symbolicRawdata, **kwargs)
content = "['"+str(figClass.__name__)+"', \""+str(symbolicRawdata)+"\", '"+str(kwargs)+"']"
signal = "("+"'newSyncFigure'"+", "+str(content)+")"
sock = self.sendSignal(signal)
answer = self.waitForAnswer(sock)
header, content, errmsg = eval(answer)
# create a socket
# connect to ip:port
......@@ -41,12 +49,21 @@ class ServerInterface(object):
# response is [ID, errormsg]
# ID = -1 no figure were created
# maybe error msg?
ID = 1
ID = content
# if ok then create syncFigure.
if ID is not None:
syncFigure = figClass(symbolicRawdata, **kwargs)
syncFigure.syncID = ID
else:
print(WARN + 'The server could not create the figure')
print(errmsg)
syncFigure = None
# add the identifier of the server-side figure
syncFigure.syncID = ID
#syncFigure.syncID = ID
# return the syncFigure
# return(True)
return(syncFigure)
def sendSignal(self, signal):
......
......@@ -4,9 +4,10 @@ from .myIOs import readStupidData, readStupidData2
if D_HIERARCHY in ('CLIENT', 'client'):
from .axTestClient import AxTestClient
# from .figTestClient import FigTestClient
from .figTestClient import FigTestClient as FigTest
# from .tests_client import myTest
# from .tests_client import test100
# from .tests import myTest
# testList = [test100,
# ]
......
# IMPORT ---------------------------------------------------------------
from .. import D_HIERARCHY
from .. import SEVR, DBUG, INFO
if D_HIERARCHY in ('Client', 'CLIENT', 'client'):
print(INFO+"Testing the client.")
else:
print(SEVR+"This is atest for the client, the imports are not correct.")
raise ImportError
from .. import MyFig
from . import AxTestClient
class FigTestClient(MyFig):
FIGSIZE = (8., 6.)
def addAxes(self):
ratio = 6. / 8. # height/width of the axes (in inch)
frame1 = [0.1, 0.1, 0.8, 0.8] # part of the fig that is available
self.add_axes(AxTestClient(self, ratio, frame1), "p1")
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment