/src/python/WMCore/HTTPFrontEnd/PlotFairy/Plots/Plot.py

https://github.com/PerilousApricot/WMCore-OLDOLD · Python · 133 lines · 114 code · 8 blank · 11 comment · 38 complexity · d1d0485a00bfede6faf31f8d0f0e29b9 MD5 · raw file

  1. #!/usr/bin/env python
  2. import re
  3. import matplotlib
  4. import sys
  5. import traceback
  6. '''
  7. The Plot class is a base class for PlotFairy plots to inherit from. Authors of
  8. new plots should override the plot(self, data) method. Plots should be
  9. instantiated via a factory, and be stateless.
  10. '''
  11. import matplotlib.pyplot
  12. from Utils import Props,elem
  13. class null(object):
  14. def null(self):
  15. pass
  16. instancemethod = type(null.null)
  17. class Plot(type):
  18. def __new__(cls, name, bases, attrs):
  19. #print 'Plot::__new__',cls,name,bases
  20. def _validate(self,input):
  21. for v in self.validators:
  22. if not v.validate(input):
  23. return 'validation-failed: %s'%v.element_name
  24. return True
  25. #return super(self.__class__,self).validate(input) and self.validate(input)
  26. attrs['_validate']=_validate
  27. def _extract(self,input):
  28. for v in self.validators:
  29. if hasattr(self.props,v.element_name):
  30. val = v.extract(input)
  31. if isinstance(val,dict):
  32. getattr(self.props,v.element_name).update(val)
  33. else:
  34. setattr(self.props,v.element_name,val)
  35. else:
  36. setattr(self.props,v.element_name,v.extract(input))
  37. #super(self.__class__,self).extract(input)
  38. for method in self.__class__._extract_calls:
  39. method(self,input)
  40. #self.extract(input)
  41. attrs['_extract']=_extract
  42. def __call__(self,input):
  43. self.figure = None
  44. try:
  45. validate_result = self._validate(input)
  46. if not validate_result==True:
  47. return self._error(validate_result)
  48. for method in self.__class__._validate_calls:
  49. validate_result = method(self,input)
  50. if not validate_result==True:
  51. return self._error(validate_result)
  52. self._extract(input)
  53. for method in self.__class__._extract_calls:
  54. method(self,input)
  55. for method in self.__class__._build_calls:
  56. method(self)
  57. return self.figure
  58. except Exception as e:
  59. traceback.print_exc(file=sys.stderr)
  60. return self._error(str(e))
  61. #return self._error(traceback.format_exc())
  62. attrs['__call__']=__call__
  63. def __init__(self,*args,**kwargs):
  64. self.props = Props()
  65. self.validators = []
  66. self.figure = None
  67. super(self.__class__,self).__init__(*args,**kwargs)
  68. if not '__init__' in attrs:
  69. attrs['__init__']=__init__
  70. def _error(self,msg):
  71. height = self.props.get('height',600)
  72. width = self.props.get('width',800)
  73. dpi = self.props.get('dpi',100)
  74. if self.figure and isinstance(self.figure,matplotlib.figure.Figure):
  75. try:
  76. matplotlib.pyplot.close(self.figure)
  77. except:
  78. pass
  79. self.figure = matplotlib.pyplot.figure(figsize=(height/dpi,width/dpi),dpi=dpi)
  80. self.figure.text(0.5,0.5,'Error!\n%s'%msg,ha='center',va='center',weight='bold',color='r')
  81. return self.figure
  82. if not '_error' in attrs:
  83. attrs['_error']=_error
  84. def __del__(self):
  85. if self.figure and isinstance(self.figure,matplotlib.figure.Figure):
  86. try:
  87. matplotlib.pyplot.close(self.figure)
  88. except:
  89. pass
  90. if not '__del__' in attrs:
  91. attrs['__del__']=__del__
  92. _validate_calls = []
  93. _extract_calls = []
  94. _build_calls = []
  95. def doc(self):
  96. head = elem('head',elem('title','Plotfairy::Documentation::%s'%self.__class__.__name__))
  97. header = elem('div',elem('h1','Documentation for Plotfairy::%s'%self.__class__.__name__))
  98. docstr = elem('div',elem('h2','Synopsis')) \
  99. +elem('div',elem('pre',self.__doc__))
  100. validators = elem('div',elem('h2','Options')) \
  101. +elem('div',elem('ul','\n'.join([v.doc() for v in self.validators])))
  102. mixins = elem('div',elem('h2','Mixins')) \
  103. +elem('div','Uses'+elem('ul','\n'.join([elem('li',k.__name__) for k in self.__class__.__bases__]))) \
  104. +elem('div','Method order'+elem('ul','\n'.join([elem('li','%s::%s'%(f.im_class.__name__ if hasattr(f,'im_class') else self.__class__.__name__,f.__name__)) for f in self._validate_calls+self._extract_calls+self._build_calls])))
  105. return elem('html',head+elem('body',header+docstr+validators+mixins))
  106. attrs['doc']=doc
  107. for klass in bases:
  108. if hasattr(klass,'validate'):
  109. _validate_calls.append(getattr(klass,'validate'))
  110. if hasattr(klass,'extract'):
  111. _extract_calls.append(getattr(klass,'extract'))
  112. if 'validate' in attrs:
  113. _validate_calls.append(attrs['validate'])
  114. if 'extract' in attrs:
  115. _extract_calls.append(attrs['extract'])
  116. for step in ('construct','predata','data','postdata','finalise'):
  117. for klass in bases:
  118. if hasattr(klass,step):
  119. _build_calls.append(getattr(klass,step))
  120. if step in attrs:
  121. _build_calls.append(attrs[step])
  122. attrs['_validate_calls']=_validate_calls
  123. attrs['_extract_calls']=_extract_calls
  124. attrs['_build_calls']=_build_calls
  125. return super(Plot,cls).__new__(cls, name, bases, attrs)