CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
getPayloadData.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 
4 from __future__ import print_function
5 import shutil
6 import glob
7 import json
8 import yaml
9 import sys
10 import sys
11 import os
12 
13 from importlib import import_module
14 from argparse import ArgumentParser, RawTextHelpFormatter
15 
16 
17 import pluginCondDBV2PyInterface
18 pluginCondDBV2PyInterface.CMSSWInit()
19 
20 
21 
22 def supress_output( f ):
23  '''
24  Temporarily disables stdout and stderr so that printouts from the plot
25  plugin does not compromise the purity of our ssh stream if
26  args.suppress_output is true
27  '''
28  def decorated( *fargs, **fkwargs ):
29 
30  suppress = args.suppress_output
31  if suppress:
32 
33  # Get rid of what is already there ( should be nothing for this script )
34  sys.stdout.flush()
35 
36  # Save file descriptors so it can be reactivated later
37  saved_stdout = os.dup( 1 )
38  saved_stderr = os.dup( 2 )
39 
40  # /dev/null is used just to discard what is being printed
41  devnull = os.open( '/dev/null', os.O_WRONLY )
42 
43  # Duplicate the file descriptor for /dev/null
44  # and overwrite the value for stdout (file descriptor 1)
45  os.dup2( devnull, 1 )
46  os.dup2( devnull, 2 )
47 
48  result = f( *fargs, **fkwargs )
49 
50  if suppress:
51 
52  # Close devnull after duplication (no longer needed)
53  os.close( devnull )
54 
55  # Reenable stdout and stderr
56  os.dup2( saved_stdout, 1 )
57  os.dup2( saved_stderr, 2 )
58 
59  return result
60 
61  return decorated
62 
63 
64 @supress_output
65 def deserialize_iovs(db, plugin_name, plot_name, tags, time_type, input_params):
66  ''' Deserializes given iovs data and returns plot coordinates '''
67 
68  output('Starting to deserialize iovs: ', '')
69  output('db: ', db)
70  output('plugin name: ', plugin_name)
71  output('plot name: ', plot_name)
72  output('tags: ', tags)
73  output('tag time type: ', time_type)
74 
75  plugin_base = import_module('pluginModule_PayloadInspector')
76  output('PI plugin base: ', plugin_base)
77 
78  plugin_obj = import_module(plugin_name)
79  output('PI plugin object: ', plugin_obj)
80 
81  # get plot method and execute it with given iovs
82  plot = getattr(plugin_obj, plot_name)()
83  output('plot object: ', plot)
84 
85  if db == "Prod":
86  db_name = 'frontier://FrontierProd/CMS_CONDITIONS'
87  elif db == 'Prep' :
88  db_name = 'frontier://FrontierPrep/CMS_CONDITIONS'
89  else:
90  db_name = db
91 
92  output('full DB name: ', db_name)
93 
94  if input_params is not None:
95  plot.setInputParamValues( input_params )
96 
97  modv = getattr(plugin_base,'ModuleVersion')
98 
99  success = False
100  if modv.label == '1.0':
101  if len(tags)==1:
102  success = plot.process(db_name, tags[0][0], time_type, int(tags[0][1]), int(tags[0][2]) )
103  elif len(tags)==2:
104  success = plot.processTwoTags(db_name, tags[0][0], tags[1][0], int(tags[0][1]),int(tags[1][1]) )
105  elif modv.label == '2.0':
106  success = plot.process(db_name, tags)
107 
108  output('plot processed data successfully: ', success)
109  if not success:
110  return False
111 
112  result = plot.data()
113  output('deserialized data: ', result)
114  return result
115 
117  ''' Returns a list of Payload Inspector plugin names
118  Example:
119  ['pluginBasicPayload_PayloadInspector', 'pluginBeamSpot_PayloadInspector', 'pluginSiStrip_PayloadInspector']
120  '''
121  architecture = os.environ.get('SCRAM_ARCH', None)
122  output('architecture: ', architecture)
123 
124  plugins = []
125  releases = [
126  os.environ.get('CMSSW_BASE', None),
127  os.environ.get('CMSSW_RELEASE_BASE', None),
128  os.environ.get('CMSSW_FULL_RELEASE_BASE', None)
129  ]
130 
131  for r in releases:
132  if not r: continue # skip if release base is not specified
133  output('* release: ', r)
134 
135  path = os.path.join(r, 'lib', architecture)
136  output('* full release path: ', path)
137 
138  plugins += glob.glob(path + '/plugin*_PayloadInspector.so' )
139  output('found plugins: ', plugins)
140 
141  # If no plugins are found in the local release,
142  # go find them in the release base (or full release base, in case of patches)
143  if(len(plugins)==0):
144  output('# plugins found:',len(plugins))
145  else:
146  if r: break # break loop if CMSSW_BASE is specified
147 
148  # extracts the object name from plugin path:
149  # /afs/cern.ch/cms/slc6_amd64_gcc493/cms/cmssw/CMSSW_8_0_6/lib/slc6_amd64_gcc493/pluginBasicPayload_PayloadInspector.so
150  # becomes pluginBasicPayload_PayloadInspector
151  result = []
152  for p in plugins:
153  result.append(p.split('/')[-1].replace('.so', ''))
154 
155  output('discovered plugins: ', result)
156  return result
157 
158 def discover():
159  ''' Discovers object types and plots for a given cmssw release
160  Example:
161  {
162  "BasicPayload": [
163  {"plot": "plot_BeamSpot_x", "plot_type": "History",
164  "single_iov": false, "plugin_name": "pluginBeamSpot_PayloadInspector",
165  "title": "x vs run number"},
166  ...
167  ],
168  ...
169  }
170  '''
171  plugin_base = import_module('pluginModule_PayloadInspector')
172  modv = getattr(plugin_base,'ModuleVersion')
173  result = {}
174  for plugin_name in discover_plugins():
175  output(' - plugin name: ', plugin_name)
176  plugin_obj = import_module(plugin_name)
177  output('*** PI plugin object: ', plugin_obj)
178  for plot in dir(plugin_obj):
179  if 'plot_' not in plot: continue # skip if method doesn't start with 'plot_' prefix
180  output(' - plot name: ', plot)
181  plot_method= getattr(plugin_obj, plot)()
182  output(' - plot object: ', plot_method)
183  payload_type = plot_method.payloadType()
184  output(' - payload type: ', payload_type)
185  plot_title = plot_method.title()
186  output(' - plot title: ', plot_title)
187  plot_type = plot_method.type()
188  output(' - plot type: ', plot_type)
189  single_iov = plot_method.isSingleIov()
190  output(' - is single iov: ', single_iov)
191  two_tags = plot_method.isTwoTags()
192  output(' - is Two Tags: ', two_tags)
193  plot_dict = { 'plot': plot, 'plugin_name': plugin_name, 'title': plot_title, 'plot_type': plot_type, 'single_iov': single_iov, 'two_tags': two_tags }
194  if modv.label == '2.0':
195  input_params = plot_method.inputParams()
196  output(' - input params: ', len(input_params))
197  plot_dict[ 'input_params'] = input_params
198  result.setdefault(payload_type, []).append( plot_dict )
199  output('currently discovered info: ', result)
200  output('*** final output:', '')
201  return json.dumps(result)
202 
203 def output(description, param):
204  if args.verbose:
205  print('')
206  print(description, param)
207 
208 if __name__ == '__main__':
209 
210  description = '''
211  Payload Inspector - data visualisation tool which is integrated into the cmsDbBrowser.
212  It allows to display plots and monitor the calibration and alignment data.
213 
214  You can access Payload Inspector with a link below:
215  https://cms-conddb.cern.ch/cmsDbBrowser/payload_inspector/Prod
216 
217  This script is a part of the Payload Inspector service and is responsible for:
218  a) discovering PI objects that are available in a given cmssw release
219  b) deserializing payload data which is later used as plot coordinates
220  c) testing new PI objects which are under development
221 
222  To test new PI objects please do the following:
223  a) run ./getPayloadData.py --discover
224  to check if your newly created object is found by the script.
225  Please note that we strongly rely on naming conventions so if you don't
226  see your object listed you probably misnamed it in objectType() method.
227  Also all plot methods should start with "plot_" prefix.
228 
229  b) second step is to test if it returns data correctly:
230  run ./getPayloadData.py --plugin YourPIPluginName --plot YourObjectPlot --tag tagName --time_type Run --iovs '{"start_iov": "201", "end_iov": "801"}' --db Prod --test
231 
232  Here is an example for BasicPayload object:
233  run ./getPayloadData.py --plugin pluginBasicPayload_PayloadInspector --plot plot_BasicPayload_data0 --tag BasicPayload_v2 --time_type Run --iovs '{"start_iov": "201", "end_iov": "801"}' --db Prod --test
234 
235  c) if it works correctly please make a pull request and once it's accepted
236  go to cmsDbBrowser and wait for the next IB to test it.
237  '''
238 
239  parser = ArgumentParser(description=description, formatter_class=RawTextHelpFormatter)
240  parser.add_argument("-d", "--discover", help="discovers object types and plots \nfor a given cmssw release", action="store_true")
241  parser.add_argument("-i", "--iovs", help="deserializes given iovs data encoded in base64 and returns plot coordinates also encoded in base64")
242  parser.add_argument("-i2", "--iovstwo", help="deserializes given iovs data encoded in base64 and returns plot coordinates also encoded in base64")
243  parser.add_argument("-o", "--plugin", help="Payload Inspector plugin name needed for iovs deserialization")
244  parser.add_argument("-p", "--plot", help="plot name needed for iovs deserialization")
245  parser.add_argument("-t", "--tag", help="tag name needed for iovs deserialization")
246  parser.add_argument("-t2", "--tagtwo", help="tag name needed for iovs deserialization")
247  parser.add_argument("-tt", "--time_type", help="tag time type name needed for iovs deserialization")
248  parser.add_argument("-b", "--db", help="db (Prod or Prep) needed for iovs deserialization")
249  parser.add_argument("-test", "--test", help="add this flag if you want to test the deserialization function and want to see a readable output", action="store_true")
250  parser.add_argument("-v", "--verbose", help="verbose mode. Shows more information", action="store_true")
251  parser.add_argument("-ip","--image_plot", help="Switch telling the script that this plot type is of type Image", action="store_true")
252  parser.add_argument("-s", "--suppress-output", help="Supresses output from so that stdout and stderr can be kept pure for the ssh transmission", action="store_true")
253  parser.add_argument("-is", "--input_params", help="Plot input parameters ( dictionary, JSON serialized into string )" )
254 
255  # shows help if no arguments are provided
256  if len(sys.argv) == 1:
257  parser.print_help()
258  sys.exit(1)
259 
260  args = parser.parse_args()
261 
262  # Return discover of plot if requested
263  if args.discover:
264  os.write( 1, str.encode(discover()) )
265 
266  input_params = None
267  if args.input_params is not None:
268  input_params = yaml.safe_load(args.input_params)
269 
270  tags = []
271  if args.tag:
272  iovDict = yaml.safe_load( args.iovs )
273  tags.append( (args.tag, iovDict['start_iov'], iovDict['end_iov'] ) )
274  if args.tagtwo:
275  iovDict = yaml.safe_load( args.iovstwo )
276  tags.append( (args.tagtwo, iovDict['start_iov'], iovDict['end_iov'] ) )
277 
278  result = deserialize_iovs(args.db, args.plugin, args.plot, tags, args.time_type, input_params)
279 
280  # If test -> output the result as formatted json
281  if args.test:
282  os.write( 2, str.encode(json.dumps( json.loads( result ), indent=4 )))
283 
284  # If image plot -> get image file from result, open it and output bytes
285  elif args.image_plot:
286 
287  filename = None
288 
289  try:
290  filename = json.loads( result )['file']
291  #print 'File name',filename
292  except ValueError as e:
293  os.write( 2, 'Value error when getting image name: %s\n' % str( e ))
294  except KeyError as e:
295  os.write( 2, 'Key error when getting image name: %s\n' % str( e ))
296 
297  if not filename or not os.path.isfile( filename ):
298  os.write( 2, str.encode('Error: Generated image file (%s) not found\n' % filename ))
299 
300  try:
301  with open( filename, 'rb' ) as f:
302  shutil.copyfileobj( f, sys.stdout.buffer )
303  except IOError as e:
304  os.write( 2, str.encode('IO error when streaming image: %s' % str( e )))
305  finally:
306  os.remove( filename )
307 
308 
309  # Else -> output result json string with base 64 encoding
310  else:
311  import base64
312  os.write( 1, base64.b64encode(bytes(result, 'utf-8')))
boost::dynamic_bitset append(const boost::dynamic_bitset<> &bs1, const boost::dynamic_bitset<> &bs2)
this method takes two bitsets bs1 and bs2 and returns result of bs2 appended to the end of bs1 ...
if(conf_.getParameter< bool >("UseStripCablingDB"))
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
#define str(s)