{"action":"created","comment":{"url":"https://api.github.com/repos/cms-sw/cmssw/pulls/comments/78190855","id":78190855,"diff_hunk":"@@ -0,0 +1,817 @@\n+#!/usr/bin/env python\n+\n+'''Script that submits CMS Tracker Alignment Primary Vertex Validation workflows\n+'''\n+\n+__author__ = 'Marco Musich'\n+__copyright__ = 'Copyright 2015, CERN CMS'\n+__credits__ = ['Ernesto Migliore', 'Salvatore Di Guida', 'Javier Duarte']\n+__license__ = 'Unknown'\n+__maintainer__ = 'Marco Musich'\n+__email__ = 'marco.musich@cern.ch'\n+__version__ = 1\n+\n+import datetime,time\n+import os,sys\n+import copy\n+import string, re\n+import ConfigParser, json\n+from optparse import OptionParser\n+from subprocess import Popen, PIPE\n+\n+CopyRights  = '####################################\\n'\n+CopyRights += '#        submitAllJobs Script      #\\n'\n+CopyRights += '#     marco.musich@cern.ch         #\\n'\n+CopyRights += '#            December 2015         #\\n'\n+CopyRights += '####################################\\n'\n+\n+##############################################\n+def drawProgressBar(percent, barLen=40):\n+##############################################\n+    sys.stdout.write(\"\\r\")\n+    progress = \"\"\n+    for i in range(barLen):\n+        if i < int(barLen * percent):\n+            progress += \"=\"\n+        else:\n+            progress += \" \"\n+    sys.stdout.write(\"[ %s ] %.2f%%\" % (progress, percent * 100))\n+    sys.stdout.flush()\n+\n+##############################################\n+def getCommandOutput(command):\n+##############################################\n+    \"\"\"This function executes `command` and returns it output.\n+    Arguments:\n+    - `command`: Shell command to be invoked by this function.\n+    \"\"\"\n+    child = os.popen(command)\n+    data = child.read()\n+    err = child.close()\n+    if err:\n+        print '%s failed w/ exit code %d' % (command, err)\n+    return data\n+\n+##############################################\n+def to_bool(value):\n+##############################################\n+    \"\"\"\n+       Converts 'something' to boolean. Raises exception for invalid formats\n+           Possible True  values: 1, True, \"1\", \"TRue\", \"yes\", \"y\", \"t\"\n+           Possible False values: 0, False, None, [], {}, \"\", \"0\", \"faLse\", \"no\", \"n\", \"f\", 0.0, ...\n+    \"\"\"\n+    if str(value).lower() in (\"yes\", \"y\", \"true\",  \"t\", \"1\"): return True\n+    if str(value).lower() in (\"no\",  \"n\", \"false\", \"f\", \"0\", \"0.0\", \"\", \"none\", \"[]\", \"{}\"): return False\n+    raise Exception('Invalid value for boolean conversion: ' + str(value))\n+\n+####################--- Classes ---############################\n+class BetterConfigParser(ConfigParser.ConfigParser):\n+\n+    ##############################################\n+    def optionxform(self, optionstr):\n+        return optionstr\n+\n+    ##############################################\n+    def exists( self, section, option):\n+         try:\n+             items = self.items(section) \n+         except ConfigParser.NoSectionError:\n+             return False\n+         for item in items:\n+             if item[0] == option:\n+                 return True\n+         return False\n+\n+    ##############################################\n+    def __updateDict( self, dictionary, section ):\n+        result = dictionary\n+        try:\n+            for option in self.options( section ):\n+                result[option] = self.get( section, option )\n+            if \"local\"+section.title() in self.sections():\n+                for option in self.options( \"local\"+section.title() ):\n+                    result[option] = self.get( \"local\"+section.title(),option )\n+        except ConfigParser.NoSectionError, section:\n+            msg = (\"%s in configuration files. This section is mandatory.\"\n+                   %(str(section).replace(\":\", \"\", 1)))\n+            #raise AllInOneError(msg)\n+        return result     \n+\n+    ##############################################\n+    def getResultingSection( self, section, defaultDict = {}, demandPars = [] ):\n+        result = copy.deepcopy(defaultDict)\n+        for option in demandPars:\n+            try:\n+                result[option] = self.get( section, option )\n+            except ConfigParser.NoOptionError, globalSectionError:\n+                globalSection = str( globalSectionError ).split( \"'\" )[-2]\n+                splittedSectionName = section.split( \":\" )\n+                if len( splittedSectionName ) > 1:\n+                    localSection = (\"local\"+section.split( \":\" )[0].title()+\":\"\n+                                    +section.split(\":\")[1])\n+                else:\n+                    localSection = (\"local\"+section.split( \":\" )[0].title())\n+                if self.has_section( localSection ):\n+                    try:\n+                        result[option] = self.get( localSection, option )\n+                    except ConfigParser.NoOptionError, option:\n+                        msg = (\"%s. This option is mandatory.\"\n+                               %(str(option).replace(\":\", \"\", 1).replace(\n+                                   \"section\",\n+                                   \"section '\"+globalSection+\"' or\", 1)))\n+                        #raise AllInOneError(msg)\n+                else:\n+                    msg = (\"%s. This option is mandatory.\"\n+                           %(str(globalSectionError).replace(\":\", \"\", 1)))\n+                    #raise AllInOneError(msg)\n+        result = self.__updateDict( result, section )\n+        #print result\n+        return result\n+\n+##### method to parse the input file ################################\n+def ConfigSectionMap(config, section):\n+    the_dict = {}\n+    options = config.options(section)\n+    for option in options:\n+        try:\n+            the_dict[option] = config.get(section, option)\n+            if the_dict[option] == -1:\n+                DebugPrint(\"skip: %s\" % option)\n+        except:\n+            print(\"exception on %s!\" % option)\n+            the_dict[option] = None\n+    return the_dict\n+\n+###### method to create recursively directories on EOS #############\n+def mkdir_eos(out_path):\n+    newpath='/'\n+    for dir in out_path.split('/'):\n+        newpath=os.path.join(newpath,dir)\n+        # do not issue mkdir from very top of the tree\n+        if newpath.find('test_out') > 0:\n+            p = subprocess.Popen([\"cmsMkdir\",newpath], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n+            (out, err) = p.communicate()\n+            p.wait()\n+\n+    # now check that the directory exists\n+    p = subprocess.Popen([\"cmsLs\",out_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n+    (out, err) = p.communicate()\n+    p.wait()\n+    if p.returncode !=0:\n+        print out\n+\n+def split(sequence, size):\n+##########################    \n+# aux generator function to split lists\n+# based on http://sandrotosi.blogspot.com/2011/04/python-group-list-in-sub-lists-of-n.html\n+# about generators see also http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained\n+##########################\n+    for i in xrange(0, len(sequence), size):\n+        yield sequence[i:i+size] \n+\n+#############\n+class Job:\n+#############\n+\n+    def __init__(self, job_id, job_name, isDA, isMC, applyBOWS, applyEXTRACOND, extraconditions, runboundary, lumilist, maxevents, gt, allFromGT, alignmentDB, alignmentTAG, apeDB, apeTAG, bowDB, bowTAG, vertextype, tracktype, applyruncontrol, ptcut, CMSSW_dir ,the_dir):\n+###############################\n+        self.job_id=job_id    \n+        self.batch_job_id = None \n+        self.job_name=job_name\n+        \n+        self.isDA              = isDA             \n+        self.isMC              = isMC             \n+        self.applyBOWS         = applyBOWS\n+        self.applyEXTRACOND    = applyEXTRACOND\n+        self.extraCondVect     = extraconditions\n+        self.runboundary       = runboundary         \n+        self.lumilist          = lumilist         \n+        self.maxevents         = maxevents\n+        self.gt                = gt\n+        self.allFromGT         = allFromGT\n+        self.alignmentDB       = alignmentDB      \n+        self.alignmentTAG      = alignmentTAG     \n+        self.apeDB             = apeDB            \n+        self.apeTAG            = apeTAG           \n+        self.bowDB             = bowDB            \n+        self.bowTAG            = bowTAG           \n+        self.vertextype        = vertextype       \n+        self.tracktype         = tracktype        \n+        self.applyruncontrol   = applyruncontrol  \n+        self.ptcut             = ptcut            \n+\n+        self.the_dir=the_dir\n+        self.CMSSW_dir=CMSSW_dir\n+\n+        self.output_full_name=self.getOutputBaseName()+\"_\"+str(self.job_id)\n+\n+        self.cfg_dir=None\n+        self.outputCfgName=None\n+        \n+        # LSF variables        \n+        self.LSF_dir=None\n+        self.output_LSF_name=None\n+\n+        self.lfn_list=list()      \n+\n+        #self.OUTDIR = \"\" # TODO: write a setter method\n+        #self.OUTDIR = self.createEOSout()\n+\n+    def __del__(self):\n+###############################\n+        del self.lfn_list\n+\n+    def setEOSout(self,theEOSdir):    \n+###############################\n+        self.OUTDIR = theEOSdir\n+          \n+    def getOutputBaseName(self):\n+########################    \n+        return \"PVValidation_\"+self.job_name\n+        \n+    def createTheCfgFile(self,lfn):\n+###############################\n+\n+        global CopyRights\n+\n+        # write the cfg file \n+        self.cfg_dir = os.path.join(self.the_dir,\"cfg\")\n+        if not os.path.exists(self.cfg_dir):\n+            os.makedirs(self.cfg_dir)\n+\n+        self.outputCfgName=self.output_full_name+\"_cfg.py\"\n+        fout=open(os.path.join(self.cfg_dir,self.outputCfgName),'w+b')\n+\n+        # decide which template according to data/mc\n+        if self.isMC:\n+            template_cfg_file = os.path.join(self.the_dir,\"PVValidation_TEMPL_cfg.py\")\n+        else:\n+            template_cfg_file = os.path.join(self.the_dir,\"PVValidation_TEMPL_cfg.py\")\n+\n+        fin = open(template_cfg_file)\n+\n+        config_txt = '\\n\\n' + CopyRights + '\\n\\n'\n+        config_txt += fin.read()\n+\n+        config_txt=config_txt.replace(\"ISDATEMPLATE\",self.isDA)                 \n+        config_txt=config_txt.replace(\"ISMCTEMPLATE\",self.isMC)                  \n+        config_txt=config_txt.replace(\"APPLYBOWSTEMPLATE\",self.applyBOWS)       \n+        config_txt=config_txt.replace(\"EXTRACONDTEMPLATE\",self.applyEXTRACOND)                  \n+        config_txt=config_txt.replace(\"USEFILELISTTEMPLATE\",\"True\")             \n+        config_txt=config_txt.replace(\"RUNBOUNDARYTEMPLATE\",self.runboundary)   \n+        config_txt=config_txt.replace(\"LUMILISTTEMPLATE\",self.lumilist)         \n+        config_txt=config_txt.replace(\"MAXEVENTSTEMPLATE\",self.maxevents)       \n+        config_txt=config_txt.replace(\"GLOBALTAGTEMPLATE\",self.gt)              \n+        config_txt=config_txt.replace(\"ALLFROMGTTEMPLATE\",self.allFromGT)       \n+        config_txt=config_txt.replace(\"ALIGNOBJTEMPLATE\",self.alignmentDB)      \n+        config_txt=config_txt.replace(\"GEOMTAGTEMPLATE\",self.alignmentTAG)      \n+        config_txt=config_txt.replace(\"APEOBJTEMPLATE\",self.apeDB)              \n+        config_txt=config_txt.replace(\"ERRORTAGTEMPLATE\",self.apeTAG)           \n+        config_txt=config_txt.replace(\"BOWSOBJECTTEMPLATE\",self.bowDB)          \n+        config_txt=config_txt.replace(\"BOWSTAGTEMPLATE\",self.bowTAG)            \n+        config_txt=config_txt.replace(\"VERTEXTYPETEMPLATE\",self.vertextype)     \n+        config_txt=config_txt.replace(\"TRACKTYPETEMPLATE\",self.tracktype)       \n+        config_txt=config_txt.replace(\"PTCUTTEMPLATE\",self.ptcut)               \n+        config_txt=config_txt.replace(\"RUNCONTROLTEMPLATE\",self.applyruncontrol)\n+        lfn_with_quotes = map(lambda x: \"\\'\"+x+\"\\'\",lfn)                           \n+        config_txt=config_txt.replace(\"FILESOURCETEMPLATE\",\"[\"+\",\".join(lfn_with_quotes)+\"]\")         \n+        config_txt=config_txt.replace(\"OUTFILETEMPLATE\",self.output_full_name+\".root\")         \n+\n+        fout.write(config_txt)\n+        \n+        for line in fin.readlines():\n+\n+            if 'END OF EXTRA CONDITIONS' in line:\n+                for element in self.extraCondVect :\n+                    if(\"Rcd\" in element):\n+                        params = self.extraCondVect[element].split(',')\n+\n+                        fout.write(\" \\n\")\n+                        fout.write(\"     process.conditionsIn\"+element+\"= CalibTracker.Configuration.Common.PoolDBESSource_cfi.poolDBESSource.clone( \\n\")\n+                        fout.write(\"          connect = cms.string('\"+params[0]+\"'), \\n\")\n+                        fout.write(\"          toGet = cms.VPSet(cms.PSet(record = cms.string('\"+element+\"'), \\n\")\n+                        fout.write(\"                                     tag = cms.string('\"+params[1]+\"'), \\n\")\n+                        if (len(params)>2):\n+                            fout.write(\"                                     label = cms.string('\"+params[2]+\"') \\n\")\n+                        fout.write(\"                                     ) \\n\")\n+                        fout.write(\"                            ) \\n\")\n+                        fout.write(\"          ) \\n\")\n+                        fout.write(\"     process.prefer_conditionsIn\"+element+\" = cms.ESPrefer(\\\"PoolDBESSource\\\", \\\"conditionsIn\"+element[0]+\"\\\") \\n \\n\") \n+                        \n+            # if self.isMC:\n+            #     if line.find(\"ISDATEMPLATE\")!=-1:\n+            #         line=line.replace(\"ISDATEMPLATE\",self.isDA)\n+            #     if line.find(\"ISMCTEMPLATE\")!=-1:\n+            #         line=line.replace(\"ISMCTEMPLATE\",self.isMC)\n+            #     if line.find(\"APPLYBOWSTEMPLATE\")!=-1:\n+            #         line=line.replace(\"APPLYBOWSTEMPLATE\",self.applyBOWS)\n+            #     if line.find(\"EXTRACONDTEMPLATE\")!=-1:\n+            #         line=line.replace(\"EXTRACONDTEMPLATE\",self.applyEXTRACOND)\n+            #     if line.find(\"USEFILELISTTEMPLATE\")!=-1:\n+            #         line=line.replace(\"USEFILELISTTEMPLATE\",\"True\")  \n+            #     if line.find(\"RUNBOUNDARYTEMPLATE\")!=-1:\n+            #         line=line.replace(\"RUNBOUNDARYTEMPLATE\",self.runboundary)  \n+            #     if line.find(\"LUMILISTTEMPLATE\")!=-1:\n+            #         line=line.replace(\"LUMILISTTEMPLATE\",self.lumilist)\n+            #     if line.find(\"MAXEVENTSTEMPLATE\")!=-1:\n+            #         line=line.replace(\"MAXEVENTSTEMPLATE\",self.maxevents)\n+            #     if line.find(\"GLOBALTAGTEMPLATE\")!=-1:\n+            #         line=line.replace(\"GLOBALTAGTEMPLATE\",self.gt)    \n+            #     if line.find(\"ALLFROMGTTEMPLATE\")!=-1:\n+            #         line=line.replace(\"ALLFROMGTTEMPLATE\",self.allFromGT)    \n+            #     if line.find(\"ALIGNOBJTEMPLATE\")!=-1:\n+            #         line=line.replace(\"ALIGNOBJTEMPLATE\",self.alignmentDB)\n+            #     if line.find(\"GEOMTAGTEMPLATE\")!=-1:\n+            #         line=line.replace(\"GEOMTAGTEMPLATE\",self.alignmentTAG)\n+            #     if line.find(\"APEOBJTEMPLATE\")!=-1:\n+            #         line=line.replace(\"APEOBJTEMPLATE\",self.apeDB)\n+            #     if line.find(\"ERRORTAGTEMPLATE\")!=-1:\n+            #         line=line.replace(\"ERRORTAGTEMPLATE\",self.apeTAG)\n+            #     if line.find(\"BOWSOBJECTTEMPLATE\")!=-1:\n+            #         line=line.replace(\"BOWSOBJECTTEMPLATE\",self.bowDB)  \n+            #     if line.find(\"BOWSTAGTEMPLATE\")!=-1:\n+            #         line=line.replace(\"BOWSTAGTEMPLATE\",self.bowTAG)\n+            #     if line.find(\"VERTEXTYPETEMPLATE\")!=-1:\n+            #         line=line.replace(\"VERTEXTYPETEMPLATE\",self.vertextype) \n+            #     if line.find(\"TRACKTYPETEMPLATE\")!=-1:\n+            #         line=line.replace(\"TRACKTYPETEMPLATE\",self.tracktype) \n+            #     if line.find(\"PTCUTTEMPLATE\")!=-1:\n+            #         line=line.replace(\"PTCUTTEMPLATE\",self.ptcut) \n+            #     if line.find(\"RUNCONTROLTEMPLATE\")!=-1:\n+            #         line=line.replace(\"RUNCONTROLTEMPLATE\",self.applyruncontrol) \n+            # else:                    \n+            #     if line.find(\"ISDATTEMPLATE\")!=-1:\n+            #         line=line.replace(\"ISDATEMPLATE\",self.isDA)\n+            #     if line.find(\"ISMCTEMPLATE\")!=-1:\n+            #         line=line.replace(\"ISMCTEMPLATE\",self.isMC)\n+            #     if line.find(\"APPLYBOWSTEMPLATE\")!=-1:\n+            #         line=line.replace(\"APPLYBOWSTEMPLATE\",self.applyBOWS)\n+            #     if line.find(\"EXTRACONDTEMPLATE\")!=-1:\n+            #         line=line.replace(\"EXTRACONDTEMPLATE\",self.applyEXTRACOND)\n+            #     if line.find(\"USEFILELISTTEMPLATE\")!=-1:\n+            #         line=line.replace(\"USEFILELISTTEMPLATE\",\"True\")  \n+            #     if line.find(\"RUNBOUNDARYTEMPLATE\")!=-1:\n+            #         line=line.replace(\"RUNBOUNDARYTEMPLATE\",self.runboundary)     \n+            #     if line.find(\"LUMILISTTEMPLATE\")!=-1:\n+            #         line=line.replace(\"LUMILISTTEMPLATE\",self.lumilist)\n+            #     if line.find(\"MAXEVENTSTEMPLATE\")!=-1:\n+            #         line=line.replace(\"MAXEVENTSTEMPLATE\",self.maxevents)\n+            #     if line.find(\"GLOBALTAGTEMPLATE\")!=-1:\n+            #         line=line.replace(\"GLOBALTAGTEMPLATE\",self.gt) \n+            #     if line.find(\"ALLFROMGTTEMPLATE\")!=-1:\n+            #         line=line.replace(\"ALLFROMGTTEMPLATE\",self.allFromGT)    \n+            #     if line.find(\"ALIGNOBJTEMPLATE\")!=-1:\n+            #         line=line.replace(\"ALIGNOBJTEMPLATE\",self.alignmentDB)\n+            #     if line.find(\"GEOMTAGTEMPLATE\")!=-1:\n+            #         line=line.replace(\"GEOMTAGTEMPLATE\",self.alignmentTAG)\n+            #     if line.find(\"APEOBJTEMPLATE\")!=-1:\n+            #         line=line.replace(\"APEOBJTEMPLATE\",self.apeDB)\n+            #     if line.find(\"ERRORTAGTEMPLATE\")!=-1:\n+            #         line=line.replace(\"ERRORTAGTEMPLATE\",self.apeTAG)\n+            #     if line.find(\"BOWSOBJECTTEMPLATE\")!=-1:\n+            #         line=line.replace(\"BOWSOBJECTTEMPLATE\",self.bowDB)  \n+            #     if line.find(\"BOWSTAGTEMPLATE\")!=-1:\n+            #         line=line.replace(\"BOWSTAGTEMPLATE\",self.bowTAG)\n+            #     if line.find(\"VERTEXTYPETEMPLATE\")!=-1:\n+            #         line=line.replace(\"VERTEXTYPETEMPLATE\",self.vertextype) \n+            #     if line.find(\"TRACKTYPETEMPLATE\")!=-1:\n+            #         line=line.replace(\"TRACKTYPETEMPLATE\",self.tracktype) \n+            #     if line.find(\"PTCUTTEMPLATE\")!=-1:\n+            #         line=line.replace(\"PTCUTTEMPLATE\",self.ptcut) \n+            #     if line.find(\"RUNCONTROLTEMPLATE\")!=-1:\n+            #         line=line.replace(\"RUNCONTROLTEMPLATE\",self.applyruncontrol) \n+                        \n+            # if line.find(\"FILESOURCETEMPLATE\")!=-1:\n+            #     lfn_with_quotes = map(lambda x: \"\\'\"+x+\"\\'\",lfn)                   \n+            #     #print \"[\"+\",\".join(lfn_with_quotes)+\"]\"\n+            #     line=line.replace(\"FILESOURCETEMPLATE\",\"[\"+\",\".join(lfn_with_quotes)+\"]\") \n+            # if line.find(\"OUTFILETEMPLATE\")!=-1:\n+            #     line=line.replace(\"OUTFILETEMPLATE\",self.output_full_name+\".root\")           \n+            fout.write(line)    \n+      \n+        fout.close()                \n+                          \n+    def createTheLSFFile(self):\n+###############################\n+\n+       # directory to store the LSF to be submitted\n+        self.LSF_dir = os.path.join(self.the_dir,\"LSF\")\n+        if not os.path.exists(self.LSF_dir):\n+            os.makedirs(self.LSF_dir)\n+\n+        self.output_LSF_name=self.output_full_name+\".lsf\"\n+        fout=open(os.path.join(self.LSF_dir,self.output_LSF_name),'w')\n+    \n+        job_name = self.output_full_name\n+\n+        log_dir = os.path.join(self.the_dir,\"log\")\n+        if not os.path.exists(log_dir):\n+            os.makedirs(log_dir)\n+\n+        fout.write(\"#!/bin/sh \\n\") \n+        fout.write(\"#BSUB -L /bin/sh\\n\")       \n+        fout.write(\"#BSUB -J \"+job_name+\"\\n\")\n+        fout.write(\"#BSUB -o \"+os.path.join(log_dir,job_name+\".log\")+\"\\n\")\n+        fout.write(\"#BSUB -q cmscaf1nd \\n\")\n+        fout.write(\"JobName=\"+job_name+\" \\n\")\n+        fout.write(\"OUT_DIR=\"+self.OUTDIR+\" \\n\")\n+        fout.write(\"LXBATCH_DIR=`pwd` \\n\") \n+        fout.write(\"cd \"+os.path.join(self.CMSSW_dir,\"src\")+\" \\n\")\n+        fout.write(\"eval `scram runtime -sh` \\n\")\n+        fout.write(\"cd $LXBATCH_DIR \\n\") \n+        fout.write(\"cmsRun \"+os.path.join(self.cfg_dir,self.outputCfgName)+\" \\n\")\n+        fout.write(\"ls -lh . \\n\")\n+        fout.write(\"for RootOutputFile in $(ls *root ); do cmsStage -f ${RootOutputFile}  ${OUT_DIR}/${RootOutputFile} ; done \\n\")\n+        fout.write(\"for TxtOutputFile in $(ls *txt ); do cmsStage -f ${TxtOutputFile}  ${OUT_DIR}/${TxtOutputFile} ; done \\n\")\n+\n+        fout.close()\n+\n+    def getOutputFileName(self):\n+############################################\n+        return os.path.join(self.OUTDIR,self.output_full_name+\".root\")\n+        \n+    def submit(self):\n+###############################        \n+        print \"submit job\", self.job_id\n+        job_name = self.output_full_name\n+        submitcommand1 = \"chmod u+x \" + os.path.join(self.LSF_dir,self.output_LSF_name)\n+        child1  = os.system(submitcommand1)\n+        #submitcommand2 = \"bsub < \"+os.path.join(self.LSF_dir,self.output_LSF_name)\n+        #child2  = os.system(submitcommand2)\n+        self.batch_job_id = getCommandOutput(\"bsub < \"+os.path.join(self.LSF_dir,self.output_LSF_name))\n+\n+    def getBatchjobId(self):    \n+############################################\n+       return self.batch_job_id.split(\"<\")[1].split(\">\")[0] \n+\n+##############################################\n+def main():\n+##############################################\n+\n+    global CopyRights\n+    print '\\n'+CopyRights\n+\n+    # CMSSW section\n+    input_CMSSW_BASE = os.environ.get('CMSSW_BASE')\n+    AnalysisStep_dir = os.path.join(input_CMSSW_BASE,\"src/Alignment/OfflineValidation/test\")\n+    sourceModule     = os.path.join(input_CMSSW_BASE,\"src/Alignment/OfflineValidation/test\",\"PVValidation_HLTPhysics2015B_TkAlMinBias_cff.py\")\n+    lib_path = os.path.abspath(AnalysisStep_dir)\n+    sys.path.append(lib_path)\n+\n+    ## N.B.: this is dediced here once and for all\n+    srcFiles        = []\n+\n+    desc=\"\"\"This is a description of %prog.\"\"\"\n+    parser = OptionParser(description=desc,version='%prog version 0.1')\n+    parser.add_option('-s','--submit',    help='job submitted',    dest='submit',     action='store_true',  default=False)\n+    parser.add_option('-j','--jobname',   help='task name',        dest='taskname',   action='store',       default='')\n+    parser.add_option('-D','--dataset',   help='selected dataset', dest='data',       action='store'      , default='')\n+    parser.add_option('-r','--doRunBased',help='selected dataset', dest='doRunBased', action='store_true' , default=False)\n+    parser.add_option('-i','--input',     help='set input configuration (overrides default)', dest='inputconfig',action='store',default=None)\n+   \n+    (opts, args) = parser.parse_args()\n+\n+    now = datetime.datetime.now()\n+    t = now.strftime(\"test_%Y_%m_%d_%H_%M_%S_DATA_\")\n+    t+=opts.taskname\n+    \n+    USER = os.environ.get('USER')\n+    eosdir=os.path.join(\"/store/caf/user\",USER,\"test_out\",t)\n+    #mkdir_eos(eosdir)\n+\n+    #### Initialize all the variables\n+\n+    jobName         = None\n+    isMC            = None\n+    isDA            = None\n+    doRunBased      = False\n+    maxevents       = None\n+\n+    gt              = None\n+    allFromGT       = None\n+    applyEXTRACOND  = None\n+    extraCondVect   = None      \n+    alignmentDB     = None\n+    alignmentTAG    = None\n+    apeDB           = None\n+    apeTAG          = None\n+    applyBOWS       = None\n+    bowDB           = None\n+    bowTAG          = None\n+\n+    vertextype      = None\n+    tracktype       = None\n+\n+    applyruncontrol = None\n+    ptcut           = None\n+    runboundary     = None\n+    lumilist        = None\n+      \n+    ConfigFile = opts.inputconfig\n+    \n+    if ConfigFile is not None:\n+\n+        print \"********************************************************\"\n+        print \"* Parsing from input file:\", ConfigFile,\" \"\n+        \n+        #config = ConfigParser.ConfigParser()\n+        #config.read(ConfigFile)\n+\n+        config = BetterConfigParser()\n+        config.read(ConfigFile)\n+\n+        #print  config.sections()\n+\n+        # please notice: since in principle one wants to run on several different samples simultaneously,\n+        # all these inputs are vectors\n+\n+        jobName          = [ConfigSectionMap(config,\"Job\")['jobname']]\n+        isDA             = [ConfigSectionMap(config,\"Job\")['isda']]\n+        isMC             = [ConfigSectionMap(config,\"Job\")['ismc']]\n+        doRunBased       = opts.doRunBased\n+        maxevents        = [ConfigSectionMap(config,\"Job\")['maxevents']]\n+\n+        gt               = [ConfigSectionMap(config,\"Conditions\")['gt']]\n+        allFromGT        = [ConfigSectionMap(config,\"Conditions\")['allFromGT']]\n+        applyEXTRACOND   = [ConfigSectionMap(config,\"Conditions\")['applyextracond']]\n+        conditions       = [config.getResultingSection(\"ExtraConditions\")]\n+\n+        alignmentDB      = [ConfigSectionMap(config,\"Conditions\")['alignmentdb']]\n+        alignmentTAG     = [ConfigSectionMap(config,\"Conditions\")['alignmenttag']]\n+        apeDB            = [ConfigSectionMap(config,\"Conditions\")['apedb']]\n+        apeTAG           = [ConfigSectionMap(config,\"Conditions\")['apetag']]\n+        applyBOWS        = [ConfigSectionMap(config,\"Conditions\")['applybows']]\n+        bowDB            = [ConfigSectionMap(config,\"Conditions\")['bowdb']]\n+        bowTAG           = [ConfigSectionMap(config,\"Conditions\")['bowtag']]\n+        \n+        vertextype       = [ConfigSectionMap(config,\"Type\")['vertextype']]      \n+        tracktype        = [ConfigSectionMap(config,\"Type\")['tracktype']]\n+    \n+        applyruncontrol  = [ConfigSectionMap(config,\"Selection\")['applyruncontrol']]\n+        ptcut            = [ConfigSectionMap(config,\"Selection\")['ptcut']]\n+        runboundary      = [ConfigSectionMap(config,\"Selection\")['runboundary']]\n+        lumilist         = [ConfigSectionMap(config,\"Selection\")['lumilist']]\n+                      \n+    else :\n+\n+        print \"********************************************************\"\n+        print \"* Parsing from command line                            *\"\n+        print \"********************************************************\"\n+          \n+        jobName         = ['MinBiasQCD_CSA14Ali_CSA14APE']\n+        isDA            = ['True']   \n+        isMC            = ['True']\n+        doRunBased      = opts.doRunBased\n+        maxevents       = ['10000']\n+        \n+        gt              = ['START53_V7A::All']       \n+        allFromGT       = ['False']\n+        applyEXTRACOND  = ['False']\n+        conditions      = [[('SiPixelTemplateDBObjectRcd','frontier://FrontierProd/CMS_COND_31X_PIXEL','SiPixelTemplates38T_2010_2011_mc'),\n+                            ('SiPixelQualityFromDBRcd','frontier://FrontierProd/CMS_COND_31X_PIXEL','SiPixelQuality_v20_mc')]]\n+        alignmentDB     = ['sqlite_file:/afs/cern.ch/cms/CAF/CMSALCA/ALCA_TRACKERALIGN/PayLoads/TkAl-14-02_CSA14/Alignments_CSA14_v1.db']\n+        alignmentTAG    = ['TrackerCSA14Scenario']  \n+        apeDB           = ['sqlite_file:/afs/cern.ch/cms/CAF/CMSALCA/ALCA_TRACKERALIGN/PayLoads/TkAl-14-02_CSA14/AlignmentErrors_CSA14_v1.db']  \n+        apeTAG          = ['TrackerCSA14ScenarioErrors']\n+        applyBOWS       = ['True']  \n+        bowDB           = ['frontier://FrontierProd/CMS_COND_310X_ALIGN']  \n+        bowTAG          = ['TrackerSurfaceDeformations_2011Realistic_v2_mc']  \n+        \n+        vertextype      = ['offlinePrimaryVertices']  \n+        tracktype       = ['ALCARECOTkAlMinBias']  \n+        \n+        applyruncontrol = ['False']  \n+        ptcut           = ['3'] \n+        runboundary     = ['1']  \n+        lumilist        = ['']  \n+ \n+    # start loop on samples\n+\n+    # print some of the configuration\n+    \n+    print \"********************************************************\"\n+    print \"* Configuration info *\"\n+    print \"********************************************************\"\n+    print \"- submitted   : \",opts.submit\n+    print \"- Jobname     : \",jobName           \n+    print \"- use DA      : \",isDA            \n+    print \"- is MC       : \",isMC            \n+    print \"- is run-based: \",doRunBased\n+    print \"- evts/job    : \",maxevents                    \n+    print \"- GlobatTag   : \",gt      \n+    print \"- allFromGT?  : \",allFromGT\n+    print \"- extraCond?  : \",applyEXTRACOND\n+    print \"- extraCond   : \",conditions                 \n+    print \"- Align db    : \",alignmentDB     \n+    print \"- Align tag   : \",alignmentTAG    \n+    print \"- APE db      : \",apeDB           \n+    print \"- APE tag     : \",apeTAG          \n+    print \"- use bows?   : \",applyBOWS       \n+    print \"- K&B db      : \",bowDB\n+    print \"- K&B tag     : \",bowTAG                        \n+    print \"- VertexColl  : \",vertextype      \n+    print \"- TrackColl   : \",tracktype                       \n+    print \"- RunControl? : \",applyruncontrol \n+    print \"- Pt>           \",ptcut           \n+    print \"- run=          \",runboundary     \n+    print \"- JSON        : \",lumilist        \n+    print \"********************************************************\"\n+\n+    sublogging_dir = os.path.join(AnalysisStep_dir,\"submissions\")\n+    if not os.path.exists(sublogging_dir):\n+        os.makedirs(sublogging_dir)\n+    submission_log_file = os.path.join(sublogging_dir,\"sub\"+t+\".log\")\n+    log_fout = open(submission_log_file,'w')\n+    for iConf in range(len(jobName)):\n+        log_fout.write(\"============================================================ \\n\")\n+        log_fout.write(\"- timestamp   : \"+t.strip(\"test_\")+\"\\n\")\n+        log_fout.write(\"- submitted   : \"+str(opts.submit)+\"\\n\")\n+        log_fout.write(\"- Jobname     : \"+jobName[iConf]+\"\\n\")           \n+        log_fout.write(\"- use DA      : \"+isDA[iConf]+\"\\n\")            \n+        log_fout.write(\"- is MC       : \"+isMC[iConf]+\"\\n\")            \n+        log_fout.write(\"- is run-based: \"+str(doRunBased)+\"\\n\")\n+        log_fout.write(\"- evts/job    : \"+maxevents[iConf]+\"\\n\")                    \n+        log_fout.write(\"- GlobatTag   : \"+gt[iConf]+\"\\n\")      \n+        log_fout.write(\"- allFromGT?  : \"+allFromGT[iConf]+\"\\n\")\n+        log_fout.write(\"- extraCond?  : \"+applyEXTRACOND[iConf]+\"\\n\")\n+        for x in conditions:\n+            for attribute,value in x.items():\n+                     log_fout.write('   - {} : {}'.format(attribute, value)+\"\\n\")\n+        log_fout.write(\"- Align db    : \"+alignmentDB[iConf]+\"\\n\")     \n+        log_fout.write(\"- Align tag   : \"+alignmentTAG[iConf]+\"\\n\")    \n+        log_fout.write(\"- APE db      : \"+apeDB[iConf]+\"\\n\")           \n+        log_fout.write(\"- APE tag     : \"+apeTAG[iConf]+\"\\n\")          \n+        log_fout.write(\"- use bows?   : \"+applyBOWS[iConf]+\"\\n\")       \n+        log_fout.write(\"- K&B db      : \"+bowDB[iConf]+\"\\n\")\n+        log_fout.write(\"- K&B tag     : \"+bowTAG[iConf]+\"\\n\")                        \n+        log_fout.write(\"- VertexColl  : \"+vertextype[iConf]+\"\\n\")      \n+        log_fout.write(\"- TrackColl   : \"+tracktype[iConf]+\"\\n\")                       \n+        log_fout.write(\"- RunControl? : \"+applyruncontrol[iConf]+\"\\n\") \n+        log_fout.write(\"- Pt>           \"+ptcut[iConf]+\"\\n\")           \n+        log_fout.write(\"- run=          \"+runboundary[iConf]+\"\\n\")     \n+        log_fout.write(\"- JSON        : \"+lumilist[iConf]+\"\\n\")\n+        log_fout.write(\"- output EOS  : \"+eosdir+\"\\n\")\n+\n+    print \"Will run on \",len(jobName),\"workflows\"\n+\n+    for iConf in range(len(jobName)):\n+        print \"Preparing\",iConf,\" configurtion to run\"\n+\n+        # for hadd script\n+        scripts_dir = os.path.join(AnalysisStep_dir,\"scripts\")\n+        if not os.path.exists(scripts_dir):\n+            os.makedirs(scripts_dir)\n+        hadd_script_file = os.path.join(scripts_dir,jobName[iConf]+\".sh\")\n+        fout = open(hadd_script_file,'w')\n+\n+        output_file_list1=list()      \n+        output_file_list2=list()\n+        output_file_list2.append(\"hadd \")\n+            \n+        inputFiles = []\n+        myRuns = []\n+        \n+        if (to_bool(isMC[iConf]) or (not to_bool(doRunBased))):\n+            if(to_bool(isMC[iConf])):\n+                print \"this is MC\"\n+                cmd = 'das_client.py --limit=0 --query \\'file dataset='+opts.data+'\\''\n+                s = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE)\n+                out,err = s.communicate()\n+                mylist = out.split('\\n')\n+                mylist.pop()\n+                #print mylist\n+           \n+                splitList = split(mylist,10)\n+                for files in splitList:\n+                    inputFiles.append(files)\n+                    myRuns.append(str(1))\n+            else:\n+                print \"this is DATA (not doing full run-based selection)\"\n+                cmd = 'das_client.py --limit=0 --query \\'file dataset='+opts.data+' run='+runboundary[iConf]+'\\''\n+                s = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE)\n+                out,err = s.communicate()\n+                mylist = out.split('\\n')\n+                mylist.pop()\n+                #print \"len(mylist):\",len(mylist)\n+                print \"mylist:\",mylist\n+                inputFiles.append(mylist)\n+                myRuns.append(str(runboundary[iConf]))\n+\n+        else:\n+            print \"this is Data\"\n+            print \"doing run based selection\"\n+            cmd = 'das_client.py --limit=0 --query \\'run dataset='+opts.data+'\\''\n+            p = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE)\n+            out, err = p.communicate()\n+            listOfRuns=out.split('\\n')\n+            listOfRuns.pop()\n+            listOfRuns.sort()\n+            myRuns = listOfRuns\n+            print \"Will run on \",len(listOfRuns), \" runs\"\n+            print listOfRuns\n+\n+            procs = []\n+\n+            for run in listOfRuns:\n+                #print \"preparing run\",run\n+                cmd2 = ' das_client.py --limit=0 --query \\'file run='+run+' dataset='+opts.data+'\\''\n+                q = Popen(cmd2 , shell=True, stdout=PIPE, stderr=PIPE)\n+                procs.append(q)\n+                #out2, err2 = q.communicate()\n+                #mylist = out2.split('\\n')\n+                #mylist.pop()\n+                #inputFiles.append(mylist)\n+                \n+            toolbar_width = len(listOfRuns)\n+            # setup toolbar\n+            print \"********************************************************\"\n+            print \" Retrieving run info\"\n+            #sys.stdout.write(\"[%s]\" % (\" \" * toolbar_width))\n+            #sys.stdout.flush()\n+            #sys.stdout.write(\"\\b\" * (toolbar_width+1)) # return to start of line, after '['\n+\n+            for i,p in enumerate(procs):\n+                out2,err2 = p.communicate()\n+                mylist = out2.split('\\n')\n+                mylist.pop()\n+                inputFiles.append(mylist)\n+                #sys.stdout.write(\"-\")\n+                #sys.stdout.flush()\n+                percent = float(i)/len(procs)\n+                #print percent\n+                drawProgressBar(percent)\n+\n+            sys.stdout.write(\"\\n\") \n+\n+        for jobN,theSrcFiles in enumerate(inputFiles):\n+            print jobN,\"run\",myRuns[jobN],theSrcFiles\n+            thejobIndex=None\n+            batchJobIds = []\n+\n+            #if(to_bool(isMC[iConf]) and (not to_bool(doRunBased))):\n+            if(to_bool(isMC[iConf])):\n+                thejobIndex=jobN\n+            else:\n+                thejobIndex=myRuns[jobN]\n+\n+            aJob = Job(thejobIndex,\n+                       jobName[iConf],isDA[iConf],isMC[iConf],\n+                       applyBOWS[iConf],applyEXTRACOND[iConf],conditions[iConf],\n+                       myRuns[jobN], lumilist[iConf], maxevents[iConf],\n+                       gt[iConf],allFromGT[iConf],\n+                       alignmentDB[iConf], alignmentTAG[iConf],\n+                       apeDB[iConf], apeTAG[iConf],\n+                       bowDB[iConf], bowTAG[iConf],\n+                       vertextype[iConf], tracktype[iConf],\n+                       applyruncontrol[iConf],\n+                       ptcut[iConf],input_CMSSW_BASE,AnalysisStep_dir)\n+            \n+            aJob.setEOSout(eosdir)\n+            aJob.createTheCfgFile(theSrcFiles)\n+            aJob.createTheLSFFile()\n+\n+            output_file_list1.append(\"cmsStage \"+aJob.getOutputFileName()+\" /tmp/$USER/\"+opts.taskname+\" \\n\")\n+            if jobN == 0:\n+                output_file_list2.append(\"/tmp/$USER/\"+opts.taskname+\"/\"+aJob.getOutputBaseName()+\".root \")\n+            output_file_list2.append(\"/tmp/$USER/\"+opts.taskname+\"/\"+os.path.split(aJob.getOutputFileName())[1]+\" \")    \n+   \n+            if opts.submit:\n+                aJob.submit()\n+                batchJobIds.append(ajob.getBatchjobId())\n+            del aJob\n+\n+        if opts.submit:\n+            print \"********************************************************\"\n+            for theBatchJobId in batchJobIds:\n+                print \"theBatchJobId is: \",theBatchJobId\n+\n+        fout.write(\"#!/bin/bash \\n\")\n+        fout.write(\"MAIL = $USER@mail.cern.ch \\n\")\n+        fout.write(\"OUT_DIR = \"+eosdir+ \"\\n\")\n+        fout.write(\"echo $HOST | mail -s \\\"Harvesting job started\\\" $USER@mail.cern.ch \\n\")\n+        fout.write(\"cd \"+os.path.join(input_CMSSW_BASE,\"src\")+\"\\n\")\n+        fout.write(\"eval `scram r -sh` \\n\")\n+        fout.write(\"mkdir -p /tmp/$USER/\"+opts.taskname+\" \\n\")\n+        fout.writelines(output_file_list1)\n+        fout.writelines(output_file_list2)\n+        fout.write(\"cmsStage -f $FILE $OUT_DIR \\n\")\n+        fout.write(\"echo \\\"Harvesting for complete; please find output at $OUT_DIR \\\" | mail -s \\\"Harvesting for\" +opts.taskname +\" compled\\\" $MAIL \\n\")\n+\n+        os.system(\"chmod u+x \"+hadd_script_file)\n+\n+        conditions = '\"' + \" && \".join([\"ended(\" + jobId + \")\" for jobId in batchJobIds]) + '\"'\n+        print conditions\n+        lastJobCommand = \"bsub -o harvester\"+opts.taskname+\".tmp -q 1nh -w \"+conditions+\" \"+hadd_script_file\n+        print lastJobCommand\n+        if opts.submit:\n+            lastJobOutput = getCommandOutput(lastJobCommand)\n+            print lastJobOutput\n+\n+        fout.close()\n+        del output_file_list1\n+        \n+if __name__ == \"__main__\":        \n+    main()\n+\n+\n+   ","path":"Alignment/OfflineValidation/test/submitAllJobs.py","position":817,"original_position":817,"commit_id":"83dde8082def7791d20ab45ee84e358e8db1c247","original_commit_id":"83dde8082def7791d20ab45ee84e358e8db1c247","user":{"login":"ghellwig","id":4136328,"avatar_url":"https://avatars.githubusercontent.com/u/4136328?v=3","gravatar_id":"","url":"https://api.github.com/users/ghellwig","html_url":"https://github.com/ghellwig","followers_url":"https://api.github.com/users/ghellwig/followers","following_url":"https://api.github.com/users/ghellwig/following{/other_user}","gists_url":"https://api.github.com/users/ghellwig/gists{/gist_id}","starred_url":"https://api.github.com/users/ghellwig/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ghellwig/subscriptions","organizations_url":"https://api.github.com/users/ghellwig/orgs","repos_url":"https://api.github.com/users/ghellwig/repos","events_url":"https://api.github.com/users/ghellwig/events{/privacy}","received_events_url":"https://api.github.com/users/ghellwig/received_events","type":"User","site_admin":false},"body":"@mmusich looks a bit like duplication of the all-in-one tool. is this meant to be used stand-alone?","created_at":"2016-09-09T14:36:28Z","updated_at":"2016-09-09T14:36:28Z","html_url":"https://github.com/cms-sw/cmssw/pull/15798#discussion_r78190855","pull_request_url":"https://api.github.com/repos/cms-sw/cmssw/pulls/15798","_links":{"self":{"href":"https://api.github.com/repos/cms-sw/cmssw/pulls/comments/78190855"},"html":{"href":"https://github.com/cms-sw/cmssw/pull/15798#discussion_r78190855"},"pull_request":{"href":"https://api.github.com/repos/cms-sw/cmssw/pulls/15798"}}},"pull_request":{"url":"https://api.github.com/repos/cms-sw/cmssw/pulls/15798","id":84645934,"html_url":"https://github.com/cms-sw/cmssw/pull/15798","diff_url":"https://github.com/cms-sw/cmssw/pull/15798.diff","patch_url":"https://github.com/cms-sw/cmssw/pull/15798.patch","issue_url":"https://api.github.com/repos/cms-sw/cmssw/issues/15798","number":15798,"state":"open","locked":false,"title":"81X- Tracker Alignment PV Validation in all-in-one tool ","user":{"login":"mmusich","id":5082376,"avatar_url":"https://avatars.githubusercontent.com/u/5082376?v=3","gravatar_id":"","url":"https://api.github.com/users/mmusich","html_url":"https://github.com/mmusich","followers_url":"https://api.github.com/users/mmusich/followers","following_url":"https://api.github.com/users/mmusich/following{/other_user}","gists_url":"https://api.github.com/users/mmusich/gists{/gist_id}","starred_url":"https://api.github.com/users/mmusich/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mmusich/subscriptions","organizations_url":"https://api.github.com/users/mmusich/orgs","repos_url":"https://api.github.com/users/mmusich/repos","events_url":"https://api.github.com/users/mmusich/events{/privacy}","received_events_url":"https://api.github.com/users/mmusich/received_events","type":"User","site_admin":false},"body":"The primary goal of this PR is to introduce within the framework of the `Alignment/OfflineValidation` package all-in-one meta-tool the [Alignment PV Validation](https://twiki.cern.ch/twiki/bin/view/CMSPublic/SWGuideTkAlignmentValidationPrimaryVertex) tool  that has been developed so far on standalone branches.\r\nFeature introduced:\r\n   * processing speed up via filtering of soft events\r\n   * integration in the all-in-one framework\r\n   * beautification of output plots\r\n   * added script for run-by-run configuration/submission of validation jobs at CAF  \r\n   * added tests for the plugin\r\n\r\n","created_at":"2016-09-09T12:55:50Z","updated_at":"2016-09-09T14:36:28Z","closed_at":null,"merged_at":null,"merge_commit_sha":"fc5ebd5b8f19f3571df338b572d689c96aad8c71","assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/cms-sw/cmssw/milestones/59","html_url":"https://github.com/cms-sw/cmssw/milestones/Next%20CMSSW_8_1_X","labels_url":"https://api.github.com/repos/cms-sw/cmssw/milestones/59/labels","id":1590252,"number":59,"title":"Next CMSSW_8_1_X","description":null,"creator":{"login":"smuzaffar","id":4115138,"avatar_url":"https://avatars.githubusercontent.com/u/4115138?v=3","gravatar_id":"","url":"https://api.github.com/users/smuzaffar","html_url":"https://github.com/smuzaffar","followers_url":"https://api.github.com/users/smuzaffar/followers","following_url":"https://api.github.com/users/smuzaffar/following{/other_user}","gists_url":"https://api.github.com/users/smuzaffar/gists{/gist_id}","starred_url":"https://api.github.com/users/smuzaffar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smuzaffar/subscriptions","organizations_url":"https://api.github.com/users/smuzaffar/orgs","repos_url":"https://api.github.com/users/smuzaffar/repos","events_url":"https://api.github.com/users/smuzaffar/events{/privacy}","received_events_url":"https://api.github.com/users/smuzaffar/received_events","type":"User","site_admin":false},"open_issues":69,"closed_issues":1395,"state":"open","created_at":"2016-02-18T09:12:12Z","updated_at":"2016-09-09T14:07:37Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/cms-sw/cmssw/pulls/15798/commits","review_comments_url":"https://api.github.com/repos/cms-sw/cmssw/pulls/15798/comments","review_comment_url":"https://api.github.com/repos/cms-sw/cmssw/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cms-sw/cmssw/issues/15798/comments","statuses_url":"https://api.github.com/repos/cms-sw/cmssw/statuses/83dde8082def7791d20ab45ee84e358e8db1c247","head":{"label":"mmusich:PVValidation_81X","ref":"PVValidation_81X","sha":"83dde8082def7791d20ab45ee84e358e8db1c247","user":{"login":"mmusich","id":5082376,"avatar_url":"https://avatars.githubusercontent.com/u/5082376?v=3","gravatar_id":"","url":"https://api.github.com/users/mmusich","html_url":"https://github.com/mmusich","followers_url":"https://api.github.com/users/mmusich/followers","following_url":"https://api.github.com/users/mmusich/following{/other_user}","gists_url":"https://api.github.com/users/mmusich/gists{/gist_id}","starred_url":"https://api.github.com/users/mmusich/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mmusich/subscriptions","organizations_url":"https://api.github.com/users/mmusich/orgs","repos_url":"https://api.github.com/users/mmusich/repos","events_url":"https://api.github.com/users/mmusich/events{/privacy}","received_events_url":"https://api.github.com/users/mmusich/received_events","type":"User","site_admin":false},"repo":{"id":16596507,"name":"cmssw","full_name":"mmusich/cmssw","owner":{"login":"mmusich","id":5082376,"avatar_url":"https://avatars.githubusercontent.com/u/5082376?v=3","gravatar_id":"","url":"https://api.github.com/users/mmusich","html_url":"https://github.com/mmusich","followers_url":"https://api.github.com/users/mmusich/followers","following_url":"https://api.github.com/users/mmusich/following{/other_user}","gists_url":"https://api.github.com/users/mmusich/gists{/gist_id}","starred_url":"https://api.github.com/users/mmusich/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mmusich/subscriptions","organizations_url":"https://api.github.com/users/mmusich/orgs","repos_url":"https://api.github.com/users/mmusich/repos","events_url":"https://api.github.com/users/mmusich/events{/privacy}","received_events_url":"https://api.github.com/users/mmusich/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mmusich/cmssw","description":"CMS Offline Software","fork":true,"url":"https://api.github.com/repos/mmusich/cmssw","forks_url":"https://api.github.com/repos/mmusich/cmssw/forks","keys_url":"https://api.github.com/repos/mmusich/cmssw/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mmusich/cmssw/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mmusich/cmssw/teams","hooks_url":"https://api.github.com/repos/mmusich/cmssw/hooks","issue_events_url":"https://api.github.com/repos/mmusich/cmssw/issues/events{/number}","events_url":"https://api.github.com/repos/mmusich/cmssw/events","assignees_url":"https://api.github.com/repos/mmusich/cmssw/assignees{/user}","branches_url":"https://api.github.com/repos/mmusich/cmssw/branches{/branch}","tags_url":"https://api.github.com/repos/mmusich/cmssw/tags","blobs_url":"https://api.github.com/repos/mmusich/cmssw/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mmusich/cmssw/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mmusich/cmssw/git/refs{/sha}","trees_url":"https://api.github.com/repos/mmusich/cmssw/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mmusich/cmssw/statuses/{sha}","languages_url":"https://api.github.com/repos/mmusich/cmssw/languages","stargazers_url":"https://api.github.com/repos/mmusich/cmssw/stargazers","contributors_url":"https://api.github.com/repos/mmusich/cmssw/contributors","subscribers_url":"https://api.github.com/repos/mmusich/cmssw/subscribers","subscription_url":"https://api.github.com/repos/mmusich/cmssw/subscription","commits_url":"https://api.github.com/repos/mmusich/cmssw/commits{/sha}","git_commits_url":"https://api.github.com/repos/mmusich/cmssw/git/commits{/sha}","comments_url":"https://api.github.com/repos/mmusich/cmssw/comments{/number}","issue_comment_url":"https://api.github.com/repos/mmusich/cmssw/issues/comments{/number}","contents_url":"https://api.github.com/repos/mmusich/cmssw/contents/{+path}","compare_url":"https://api.github.com/repos/mmusich/cmssw/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mmusich/cmssw/merges","archive_url":"https://api.github.com/repos/mmusich/cmssw/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mmusich/cmssw/downloads","issues_url":"https://api.github.com/repos/mmusich/cmssw/issues{/number}","pulls_url":"https://api.github.com/repos/mmusich/cmssw/pulls{/number}","milestones_url":"https://api.github.com/repos/mmusich/cmssw/milestones{/number}","notifications_url":"https://api.github.com/repos/mmusich/cmssw/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mmusich/cmssw/labels{/name}","releases_url":"https://api.github.com/repos/mmusich/cmssw/releases{/id}","deployments_url":"https://api.github.com/repos/mmusich/cmssw/deployments","created_at":"2014-02-06T22:36:08Z","updated_at":"2014-06-11T16:17:30Z","pushed_at":"2016-09-09T12:48:37Z","git_url":"git://github.com/mmusich/cmssw.git","ssh_url":"git@github.com:mmusich/cmssw.git","clone_url":"https://github.com/mmusich/cmssw.git","svn_url":"https://github.com/mmusich/cmssw","homepage":"cms-sw.github.io/cmssw","size":884132,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"CMSSW_7_1_X"}},"base":{"label":"cms-sw:CMSSW_8_1_X","ref":"CMSSW_8_1_X","sha":"3a3a77ebab6828753a2060c38a09f59e811967e1","user":{"login":"cms-sw","id":3863500,"avatar_url":"https://avatars.githubusercontent.com/u/3863500?v=3","gravatar_id":"","url":"https://api.github.com/users/cms-sw","html_url":"https://github.com/cms-sw","followers_url":"https://api.github.com/users/cms-sw/followers","following_url":"https://api.github.com/users/cms-sw/following{/other_user}","gists_url":"https://api.github.com/users/cms-sw/gists{/gist_id}","starred_url":"https://api.github.com/users/cms-sw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cms-sw/subscriptions","organizations_url":"https://api.github.com/users/cms-sw/orgs","repos_url":"https://api.github.com/users/cms-sw/repos","events_url":"https://api.github.com/users/cms-sw/events{/privacy}","received_events_url":"https://api.github.com/users/cms-sw/received_events","type":"Organization","site_admin":false},"repo":{"id":10969551,"name":"cmssw","full_name":"cms-sw/cmssw","owner":{"login":"cms-sw","id":3863500,"avatar_url":"https://avatars.githubusercontent.com/u/3863500?v=3","gravatar_id":"","url":"https://api.github.com/users/cms-sw","html_url":"https://github.com/cms-sw","followers_url":"https://api.github.com/users/cms-sw/followers","following_url":"https://api.github.com/users/cms-sw/following{/other_user}","gists_url":"https://api.github.com/users/cms-sw/gists{/gist_id}","starred_url":"https://api.github.com/users/cms-sw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cms-sw/subscriptions","organizations_url":"https://api.github.com/users/cms-sw/orgs","repos_url":"https://api.github.com/users/cms-sw/repos","events_url":"https://api.github.com/users/cms-sw/events{/privacy}","received_events_url":"https://api.github.com/users/cms-sw/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cms-sw/cmssw","description":"CMS Offline Software","fork":false,"url":"https://api.github.com/repos/cms-sw/cmssw","forks_url":"https://api.github.com/repos/cms-sw/cmssw/forks","keys_url":"https://api.github.com/repos/cms-sw/cmssw/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cms-sw/cmssw/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cms-sw/cmssw/teams","hooks_url":"https://api.github.com/repos/cms-sw/cmssw/hooks","issue_events_url":"https://api.github.com/repos/cms-sw/cmssw/issues/events{/number}","events_url":"https://api.github.com/repos/cms-sw/cmssw/events","assignees_url":"https://api.github.com/repos/cms-sw/cmssw/assignees{/user}","branches_url":"https://api.github.com/repos/cms-sw/cmssw/branches{/branch}","tags_url":"https://api.github.com/repos/cms-sw/cmssw/tags","blobs_url":"https://api.github.com/repos/cms-sw/cmssw/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cms-sw/cmssw/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cms-sw/cmssw/git/refs{/sha}","trees_url":"https://api.github.com/repos/cms-sw/cmssw/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cms-sw/cmssw/statuses/{sha}","languages_url":"https://api.github.com/repos/cms-sw/cmssw/languages","stargazers_url":"https://api.github.com/repos/cms-sw/cmssw/stargazers","contributors_url":"https://api.github.com/repos/cms-sw/cmssw/contributors","subscribers_url":"https://api.github.com/repos/cms-sw/cmssw/subscribers","subscription_url":"https://api.github.com/repos/cms-sw/cmssw/subscription","commits_url":"https://api.github.com/repos/cms-sw/cmssw/commits{/sha}","git_commits_url":"https://api.github.com/repos/cms-sw/cmssw/git/commits{/sha}","comments_url":"https://api.github.com/repos/cms-sw/cmssw/comments{/number}","issue_comment_url":"https://api.github.com/repos/cms-sw/cmssw/issues/comments{/number}","contents_url":"https://api.github.com/repos/cms-sw/cmssw/contents/{+path}","compare_url":"https://api.github.com/repos/cms-sw/cmssw/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cms-sw/cmssw/merges","archive_url":"https://api.github.com/repos/cms-sw/cmssw/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cms-sw/cmssw/downloads","issues_url":"https://api.github.com/repos/cms-sw/cmssw/issues{/number}","pulls_url":"https://api.github.com/repos/cms-sw/cmssw/pulls{/number}","milestones_url":"https://api.github.com/repos/cms-sw/cmssw/milestones{/number}","notifications_url":"https://api.github.com/repos/cms-sw/cmssw/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cms-sw/cmssw/labels{/name}","releases_url":"https://api.github.com/repos/cms-sw/cmssw/releases{/id}","deployments_url":"https://api.github.com/repos/cms-sw/cmssw/deployments","created_at":"2013-06-26T14:09:07Z","updated_at":"2016-09-09T04:03:00Z","pushed_at":"2016-09-09T14:07:18Z","git_url":"git://github.com/cms-sw/cmssw.git","ssh_url":"git@github.com:cms-sw/cmssw.git","clone_url":"https://github.com/cms-sw/cmssw.git","svn_url":"https://github.com/cms-sw/cmssw","homepage":"http://cms-sw.github.io/","size":1105985,"stargazers_count":340,"watchers_count":340,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1970,"mirror_url":null,"open_issues_count":356,"forks":1970,"open_issues":356,"watchers":340,"default_branch":"CMSSW_8_1_X"}},"_links":{"self":{"href":"https://api.github.com/repos/cms-sw/cmssw/pulls/15798"},"html":{"href":"https://github.com/cms-sw/cmssw/pull/15798"},"issue":{"href":"https://api.github.com/repos/cms-sw/cmssw/issues/15798"},"comments":{"href":"https://api.github.com/repos/cms-sw/cmssw/issues/15798/comments"},"review_comments":{"href":"https://api.github.com/repos/cms-sw/cmssw/pulls/15798/comments"},"review_comment":{"href":"https://api.github.com/repos/cms-sw/cmssw/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cms-sw/cmssw/pulls/15798/commits"},"statuses":{"href":"https://api.github.com/repos/cms-sw/cmssw/statuses/83dde8082def7791d20ab45ee84e358e8db1c247"}}}}
{"actor":{"display_login":"ghellwig"}}