From fc0c707c71a923e9c426e31e7d2d2834b20242b4 Mon Sep 17 00:00:00 2001
From: Tomasz Bold <tomasz.bold@gmail.com>
Date: Thu, 24 Aug 2017 18:34:39 +0000
Subject: [PATCH] Testing of Lvl1Converter as preparation for OR seeding fix

---
 Trigger/TrigFake/CMakeLists.txt               |   9 +-
 Trigger/TrigFake/src/FakeRoIB.cxx             | 101 ++++++++++++++++++
 Trigger/TrigFake/src/FakeRoIB.h               |  43 ++++++++
 .../src/components/TrigFake_entries.cxx       |   6 +-
 Trigger/TrigFake/test/FakeRoIB_test.cxx       |  30 ++++++
 Trigger/TrigSteer/TrigSteering/CMakeLists.txt |   9 ++
 .../share/pureSteering_jobOptions.py          |  40 ++++++-
 .../share/pureSteering_l1Seeding_menu.py      |  80 ++++++++++++++
 .../TrigSteering/share/pureSteering_l1menu.py |   2 +
 .../TrigSteering/test/SteeringChain_test.cxx  | 101 ++++++++++++++++++
 10 files changed, 416 insertions(+), 5 deletions(-)
 create mode 100644 Trigger/TrigFake/src/FakeRoIB.cxx
 create mode 100644 Trigger/TrigFake/src/FakeRoIB.h
 create mode 100644 Trigger/TrigFake/test/FakeRoIB_test.cxx
 create mode 100644 Trigger/TrigSteer/TrigSteering/share/pureSteering_l1Seeding_menu.py
 create mode 100644 Trigger/TrigSteer/TrigSteering/test/SteeringChain_test.cxx

diff --git a/Trigger/TrigFake/CMakeLists.txt b/Trigger/TrigFake/CMakeLists.txt
index 75cd78001fa9..758a63a80c67 100644
--- a/Trigger/TrigFake/CMakeLists.txt
+++ b/Trigger/TrigFake/CMakeLists.txt
@@ -13,6 +13,7 @@ atlas_depends_on_subdirs( PUBLIC
                           Trigger/TrigEvent/TrigSteeringEvent
                           Trigger/TrigSteer/TrigSteering
                           PRIVATE
+                          AtlasTest/TestTools
                           Control/StoreGate
                           Generators/GeneratorObjects
                           Trigger/TrigConfiguration/TrigConfHLTData
@@ -31,14 +32,18 @@ atlas_add_library( TrigFakeLib
                    PUBLIC_HEADERS TrigFake
                    PRIVATE_INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
                    PRIVATE_DEFINITIONS ${CLHEP_DEFINITIONS}
-                   LINK_LIBRARIES AthenaBaseComps GaudiKernel TrigInDetEvent TrigSteeringEvent TrigSteeringLib StoreGateLib SGtests TrigNavigationLib TrigInterfacesLib
-                   PRIVATE_LINK_LIBRARIES ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} GeneratorObjects TrigConfHLTData TrigT1Interfaces TrigT1Result )
+                   LINK_LIBRARIES AthenaBaseComps GaudiKernel TrigInDetEvent TrigSteeringEvent TrigSteeringLib StoreGateLib SGtests TrigNavigationLib TrigInterfacesLib 
+                   PRIVATE_LINK_LIBRARIES ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} GeneratorObjects TrigConfHLTData TrigT1Interfaces TrigT1Result  )
 
 atlas_add_component( TrigFake
                      src/components/*.cxx
                      INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
                      LINK_LIBRARIES ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps GaudiKernel TrigInDetEvent TrigSteeringEvent TrigSteeringLib StoreGateLib SGtests GeneratorObjects TrigConfHLTData TrigNavigationLib TrigInterfacesLib TrigT1Interfaces TrigT1Result TrigFakeLib )
 
+atlas_add_test( FakeRoIB_test
+		SOURCES test/FakeRoIB_test.cxx
+		LINK_LIBRARIES TrigFakeLib TrigT1Result )
+
 # Install files from the package:
 atlas_install_joboptions( share/jobOfragment_TrigFake.* )
 
diff --git a/Trigger/TrigFake/src/FakeRoIB.cxx b/Trigger/TrigFake/src/FakeRoIB.cxx
new file mode 100644
index 000000000000..8220b5bae690
--- /dev/null
+++ b/Trigger/TrigFake/src/FakeRoIB.cxx
@@ -0,0 +1,101 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <iostream>
+#include <fstream>
+#include "TrigT1Result/RoIBResult.h"
+#include "eformat/SourceIdentifier.h"
+#include "FakeRoIB.h"
+using namespace ROIB;
+
+FakeRoIB::FakeRoIB( const std::string& name, ISvcLocator* pSvcLocator ):                                
+  AthAlgorithm( name, pSvcLocator ), 
+  m_eventCounter( 0 ) {
+  declareProperty( "InputFile", m_inputFile, "File wiht fake input" );
+}
+
+StatusCode FakeRoIB::initialize() {
+  std::ifstream inputFile( m_inputFile );
+  if ( not inputFile.good() ) {
+    ATH_MSG_DEBUG( "Input file is wrong: " << m_inputFile );
+    return StatusCode::FAILURE;
+  }
+  auto checkBitChar = [&]( char c ){ return ( ( c == '1' or c == '0' ) ?  StatusCode::SUCCESS : StatusCode::FAILURE );  };
+  auto isChar   = [&]( char c, const char req ) { return ( ( c == req ) ?  StatusCode::SUCCESS : StatusCode::FAILURE ); };
+
+  auto setBit   = [&]( std::vector<uint32_t>& v, size_t position ) {
+    size_t word = position / 32;
+    uint32_t bitMask  = 1<< ( position % 32 );
+    v[word] = v[word] | bitMask;
+  };
+
+  std::string line;
+  while ( std::getline( inputFile, line ) ) {
+    std::istringstream items( line );
+    std::vector<uint32_t>  TBP( 16 ); // 16  x 32 =  512 bits, number of CTP item bits
+    std::vector<uint32_t>  TAV( 16 );
+
+    while ( items )  {
+      int itemID( 0 );
+      items >> itemID;
+      char colon;
+      items >> colon;
+      CHECK( isChar( colon, ':' ) );
+      // now we will read pttern like 1,0 which TBP and TAV
+      char TBPBit, TAVBit, coma;
+
+      items >> TBPBit >> coma >> TAVBit;
+      CHECK( checkBitChar( TBPBit ) );
+      CHECK( checkBitChar( TAVBit ) );
+
+      CHECK( isChar( coma, ',' ) );
+      
+      if ( TBPBit == '1' ) setBit( TBP, itemID );
+      if ( TAVBit == '1' ) setBit( TAV, itemID );
+    }
+    m_data.push_back( CTPRecord( TBP, TAV ) );
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FakeRoIB::execute() {
+  const size_t index = m_eventCounter % m_data.size(); 
+  ATH_MSG_DEBUG( "Inserting event: " << index );
+  
+  CTPResult ctp = FakeRoIBHelper::buildCTPFragment( m_data[index].TBP, m_data[index].TAV, index );
+  ATH_MSG_DEBUG( "CTP words: " << ctp.print() );
+  if ( not ctp.isComplete() )  {
+    ATH_MSG_ERROR( "Cant't construct compte CTP fragment" );
+    return StatusCode::FAILURE;
+  }
+    
+  RoIBResult *result = new RoIBResult ( ctp );
+
+  CHECK( evtStore()->record( result, "RoIBResult" ) );
+
+  m_eventCounter ++;
+  return StatusCode::SUCCESS;
+}
+
+
+
+
+namespace FakeRoIBHelper {
+  CTPResult buildCTPFragment( const std::vector<uint32_t>& tbp, const std::vector<uint32_t>& tav,  uint32_t index ) {
+    const uint32_t eformatVersion = 5;
+    const uint32_t subdetID = 0x770001;
+    Header h( subdetID, index, eformatVersion );
+
+    std::vector<uint32_t> in( 2 ); // unused timing words
+    in[0] = 0x00;
+    in[1] = 0x00;
+    in.insert( in.end(), tbp.begin(), tbp.end() );
+    in.insert( in.end(), tav.begin(), tav.end() );
+    Trailer t( in.size() ); 
+    CTPResult ctp( eformatVersion, h, t, in );
+    return ctp;
+  }
+
+}
diff --git a/Trigger/TrigFake/src/FakeRoIB.h b/Trigger/TrigFake/src/FakeRoIB.h
new file mode 100644
index 000000000000..c4a9eabb6773
--- /dev/null
+++ b/Trigger/TrigFake/src/FakeRoIB.h
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TrigFake_FakeRoIB_h
+#define TrigFake_FakeRoIB_h
+#include "TrigT1Result/CTPResult.h"
+#include "AthenaBaseComps/AthAlgorithm.h"
+
+
+class FakeRoIB : public AthAlgorithm {
+ public:
+  FakeRoIB( const std::string& name, ISvcLocator* pSvcLocator );
+  /**
+   * @brief this function reads the input file formatted as follows:
+   * item:TBP,TAP,TAV item:TBP,TAP,TAV ... e.g. 12:1,0,0 13:1,1,1 ....
+   **/
+  StatusCode initialize() override;
+  StatusCode execute() override;
+  
+ private:
+
+  
+  struct CTPRecord {
+    CTPRecord( const std::vector<uint32_t>& tbp, const std::vector<uint32_t>& tav ) 
+    :  TBP(tbp), TAV(tav) {}
+    std::vector<uint32_t> TBP;
+    std::vector<uint32_t> TAV;
+
+  };
+  
+  std::vector<CTPRecord> m_data;
+  size_t m_eventCounter;
+  std::string m_inputFile;
+};
+
+namespace FakeRoIBHelper {
+  ROIB::CTPResult buildCTPFragment( const std::vector<uint32_t>& tbp, const std::vector<uint32_t>& tav, uint32_t index );
+
+}
+
+
+#endif 
diff --git a/Trigger/TrigFake/src/components/TrigFake_entries.cxx b/Trigger/TrigFake/src/components/TrigFake_entries.cxx
index d0892344b80e..0870b0d59382 100755
--- a/Trigger/TrigFake/src/components/TrigFake_entries.cxx
+++ b/Trigger/TrigFake/src/components/TrigFake_entries.cxx
@@ -1,16 +1,17 @@
+#include "GaudiKernel/DeclareFactoryEntries.h"
 #include "TrigFake/FakeLvl1RoIatFixedEtaPhi.h"
 #include "TrigFake/FakeLvl1MultipleRoIsatFixedEtaPhi.h"
 //#include "TrigFake/FakeLvl1ConversionTestBeam.h"
 #include "TrigFake/FakeLvl1RoIfromKine.h"
 #include "TrigFake/ZVertexFromKine.h"
-#include "GaudiKernel/DeclareFactoryEntries.h"
-
+#include "../FakeRoIB.h"
 
 DECLARE_TOOL_FACTORY( FakeLvl1RoIfromKine )
   //DECLARE_ALGORITHM_FACTORY( FakeLvl1ConversionTestBeam )
 DECLARE_TOOL_FACTORY( FakeLvl1RoIatFixedEtaPhi )
 DECLARE_TOOL_FACTORY( FakeLvl1MultipleRoIsatFixedEtaPhi )
 DECLARE_ALGORITHM_FACTORY( ZVertexFromKine )
+DECLARE_ALGORITHM_FACTORY( FakeRoIB )
 
 DECLARE_FACTORY_ENTRIES(TrigFake) {
     DECLARE_TOOL( FakeLvl1RoIfromKine )
@@ -18,4 +19,5 @@ DECLARE_FACTORY_ENTRIES(TrigFake) {
     DECLARE_TOOL( FakeLvl1RoIatFixedEtaPhi )
     DECLARE_TOOL( FakeLvl1MultipleRoIsatFixedEtaPhi )
     DECLARE_ALGORITHM( ZVertexFromKine )
+    DECLARE_ALGORITHM( FakeRoIB )
 }
diff --git a/Trigger/TrigFake/test/FakeRoIB_test.cxx b/Trigger/TrigFake/test/FakeRoIB_test.cxx
new file mode 100644
index 000000000000..efacc9933683
--- /dev/null
+++ b/Trigger/TrigFake/test/FakeRoIB_test.cxx
@@ -0,0 +1,30 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+#include "CTPfragment/CTPdataformatVersion.h"
+#include "../src/FakeRoIB.h"
+using namespace ROIB;
+int main() {
+
+  std::vector<uint32_t> tbp(16);
+  tbp[0] = 0x11; // just not to be all 0 in TBP
+  std::vector<uint32_t> tav(16);
+  tav[0] = 0x11; // just not to be all 0 in TAV
+  CTPdataformatVersion format(5); // we will use version 5 
+  CTPResult r = FakeRoIBHelper::buildCTPFragment( tbp, tav, 0x55 ); // 0x55 is event number 
+  std::cout << "time words: " << format.getNumberTimeWords() << " RoIB words per bunch " << format.getRoIBwordsPerBunch() << " " << format.getDAQwordsPerBunch() << std::endl;
+  std::cout << " header size " << r.header().size() << " trailer size " << r.trailer().size()  <<  " CTP RoI " << r.roIVec().size() << std::endl;
+
+
+  std::cout << std::endl;
+  std::cout << r.print(true);
+  std::cout << std::endl;
+  
+  
+  if ( not r.isComplete() ) {
+    std::cout << "CTP Result is not complete \n" ;
+    return 1;    
+  }
+
+  return 0;
+}
diff --git a/Trigger/TrigSteer/TrigSteering/CMakeLists.txt b/Trigger/TrigSteer/TrigSteering/CMakeLists.txt
index e164edf04274..b78c2db28075 100644
--- a/Trigger/TrigSteer/TrigSteering/CMakeLists.txt
+++ b/Trigger/TrigSteer/TrigSteering/CMakeLists.txt
@@ -79,6 +79,15 @@ atlas_add_test( Signature_test
                 LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${TDAQ-COMMON_LIBRARIES} ${CLHEP_LIBRARIES} AthenaBaseComps AthenaKernel AthenaMonitoringLib DataModel StoreGateLib SGtests EventInfo xAODEventInfo GaudiKernel TrigConfBase TrigConfHLTData TrigROBDataProviderSvcLib TrigSteeringEvent L1TopoAlgorithms L1TopoCoreSim L1TopoEvent L1TopoSimulationLib TrigT1CaloEventLib TrigT1CaloToolInterfaces TrigT1Result TrigTimeAlgsLib TestTools ByteStreamCnvSvcBaseLib xAODTrigger TrigConfL1Data TrigSerializeResultLib TrigNavigationLib TrigStorageDefinitions TrigMonitorBaseLib TrigInterfacesLib L1TopoCommon L1TopoConfig TrigT1Interfaces TrigSteeringLib
                 EXTRA_PATTERNS ".*" )
 
+
+atlas_add_test( SteeringChain_test
+                SOURCES
+                test/SteeringChain_test.cxx
+                INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${TDAQ-COMMON_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
+                LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${TDAQ-COMMON_LIBRARIES} ${CLHEP_LIBRARIES} AthenaBaseComps AthenaKernel AthenaMonitoringLib DataModel StoreGateLib SGtests EventInfo xAODEventInfo GaudiKernel TrigConfBase TrigConfHLTData TrigROBDataProviderSvcLib TrigSteeringEvent L1TopoAlgorithms L1TopoCoreSim L1TopoEvent L1TopoSimulationLib TrigT1CaloEventLib TrigT1CaloToolInterfaces TrigT1Result TrigTimeAlgsLib TestTools ByteStreamCnvSvcBaseLib xAODTrigger TrigConfL1Data TrigSerializeResultLib TrigNavigationLib TrigStorageDefinitions TrigMonitorBaseLib TrigInterfacesLib L1TopoCommon L1TopoConfig TrigT1Interfaces TrigSteeringLib
+                EXTRA_PATTERNS ".*" )
+
+
 # Install files from the package:
 atlas_install_python_modules( python/*.py )
 atlas_install_joboptions( share/*.py share/Lvl1Results.txt )
diff --git a/Trigger/TrigSteer/TrigSteering/share/pureSteering_jobOptions.py b/Trigger/TrigSteer/TrigSteering/share/pureSteering_jobOptions.py
index 24909eb88870..bce8d5970376 100755
--- a/Trigger/TrigSteer/TrigSteering/share/pureSteering_jobOptions.py
+++ b/Trigger/TrigSteer/TrigSteering/share/pureSteering_jobOptions.py
@@ -2,7 +2,7 @@ from AthenaCommon.Logging import logging
 log = logging.getLogger( 'PureSteeringJob' )
 
 svcMgr.MessageSvc.Format = "% F%52W%S%7W%R%T %0W%M"
-svcMgr.MessageSvc.OutputLevel = DEBUG
+svcMgr.MessageSvc.OutputLevel = WARNING
 svcMgr.MessageSvc.defaultLimit = 0
 svcMgr.StoreGateSvc.Dump = True  #true will dump data store contents
 
@@ -31,6 +31,7 @@ if not "usePrescaleMenu" in dir(): usePrescaleMenu = False
 if not "useMultiSeedingMenu" in dir(): useMultiSeedingMenu = False
 if not "useMenuWithAcceptInput" in dir(): useMenuWithAcceptInput = False
 if not "useBusyEventSetup" in dir(): useBusyEventSetup = False
+if not "l1SeedingTest" in dir(): l1SeedingTest = False
 
 # Default L1 RoIs if not set otherwise below
 
@@ -103,6 +104,24 @@ EM15i,EM25i
 EM15i,EM25i
 """
 
+elif l1SeedingTest:
+    include("TrigSteering/pureSteering_l1Seeding_menu.py")
+    RoIs = "MU6, MU20\n"*7
+    # see for info about 
+    # 106 is ctp ID of L1_MU06 120 is for L1_MU20 and 121 for L1_MU21
+    #
+    ctpbits = "106:1,0 120:1,1\n" 
+    ctpbits += "106:1,1 120:0,0 121:1,1\n" # L1_MU21 active
+    ctpbits += "106:1,0 120:1,1 121:0,0\n"  # L1_MU20 acts ( the other is inactive )
+    ctpbits += "106:1,1 120:1,1 121:0,0\n"
+    ctpbits += "106:1,1 120:1,1 121:0,0\n"
+    ctpbits += "106:1,1 120:1,1 121:0,0\n"
+    ctpbits += "106:1,1 120:1,0 121:0,0\n" # L1_MU20 activated but prescaled
+
+    ctpfile=open("Lvl1CTPResults.txt", "w")
+    ctpfile.write(ctpbits)
+    ctpfile.close()
+
 else:
     include("TrigSteering/pureSteering_menu.py")
 
@@ -122,6 +141,9 @@ roifile.write("\n")
 roifile.close()
 
 
+
+
+
 ###    Setup  TrigConfigSvc      ###
 ####################################
 from TrigConfigSvc.TrigConfigSvcConfig import SetupTrigConfigSvc
@@ -173,8 +195,24 @@ if runMergedSteering:
         hltSteer.ResultBuilder.ErrorStreamTags = ["ABORT_CHAIN ALGO_ERROR GAUDI_EXCEPTION: hltexceptions physics", "ABORT_EVENT ALGO_ERROR TIMEOUT: hlttimeout debug"]
         hltSteer.softEventTimeout = 1 * Units.s
 
+    if l1SeedingTest:
+        from TrigSteering.TestingTrigSteeringConfig import TestingLvl1Converter
+        lvl1Converter = TestingLvl1Converter()
+        hltSteer += lvl1Converter        
+        hltSteer.LvlConverterTool = lvl1Converter
+        hltSteer.LvlConverterTool.useL1Calo = False
+        hltSteer.LvlConverterTool.useL1Muon = False
+        hltSteer.LvlConverterTool.useL1JetEnergy = False
+        hltSteer.LvlConverterTool.OutputLevel = DEBUG
+        from TrigFake.TrigFakeConf import FakeRoIB
+        fakeRoIB = FakeRoIB()
+        fakeRoIB.OutputLevel = DEBUG
+        fakeRoIB.InputFile="Lvl1CTPResults.txt"
+        job += fakeRoIB
+
     job += hltSteer
 
+
 else:
     ### L2 TopAlgorithm from configurable ###
     #########################################
diff --git a/Trigger/TrigSteer/TrigSteering/share/pureSteering_l1Seeding_menu.py b/Trigger/TrigSteer/TrigSteering/share/pureSteering_l1Seeding_menu.py
new file mode 100644
index 000000000000..f589db98ead5
--- /dev/null
+++ b/Trigger/TrigSteer/TrigSteering/share/pureSteering_l1Seeding_menu.py
@@ -0,0 +1,80 @@
+from TriggerMenu.TriggerConfigLVL1 import TriggerConfigLVL1            
+from TriggerMenu.l1.Lvl1Flags import Lvl1Flags
+from TriggerMenu.l1.Lvl1MenuItems import LVL1MenuItem
+from TriggerMenu.l1.TriggerTypeDef import TT
+from TriggerMenu.l1.Lvl1Condition import ThrCondition, Lvl1InternalTrigger
+from TriggerMenu.l1.Logic import Logic
+
+#
+# L1
+#
+l1menu = TriggerConfigLVL1(outputFile = 'l1menu.xml', menuName = 'menutest', topoMenu = None)
+LVL1MenuItem.l1configForRegistration = l1menu
+
+Lvl1Flags.thresholds = [ 'MU06', 'MU20' ]
+Lvl1Flags.items = [ 'L1_MU06', 'L1_MU20', 'L1_MU21' ]
+
+bgrp = Logic(Lvl1InternalTrigger('BGRP0')) & Logic(Lvl1InternalTrigger('BGRP1'))
+
+thr = l1menu.registerThr('MU06','MUON').addThrValue(6)
+LVL1MenuItem('L1_MU06').setLogic( ThrCondition(thr) & bgrp ).setTriggerType( TT.muon )
+
+thr = l1menu.registerThr('MU20','MUON').addThrValue(20)
+LVL1MenuItem('L1_MU20').setLogic( ThrCondition(thr) & bgrp ).setTriggerType( TT.muon )
+LVL1MenuItem('L1_MU21').setLogic( ThrCondition(thr) & bgrp ).setTriggerType( TT.muon )
+
+
+# fix CTP IDs
+l1menu.registeredItems['L1_MU06'].setCtpid( 106 )
+l1menu.registeredItems['L1_MU20'].setCtpid( 120 )
+l1menu.registeredItems['L1_MU21'].setCtpid( 121 )
+
+# overwrite menu
+l1menu.generateMenu()        
+l1menu.writeXML()
+
+
+
+
+
+from TriggerMenu.menu.TriggerPythonConfig import TriggerPythonConfig
+from TriggerMenu.menu.HLTObjects import HLTChain
+menu = TriggerPythonConfig('pureSteering_menu.xml')
+
+# HLT
+# chain1 = HLTChain( chain_name='HLT_e25', chain_counter='1', lower_chain_name='L1_EM25i', level='HLT', prescale='1', pass_through='1')
+# chain1.addHLTSignature( 'em25i' ).addHLTSignature( 'em25i'' )
+# chain1.addTriggerTypeBit('4')
+# chain1.addStreamTag('electrons', prescale='1')
+# chain1.addStreamTag('IDCalibration', prescale='1', type='calibration')
+# chain1.addGroup('electrons')
+# menu.addHLTChain(chain1)
+
+chain = HLTChain( chain_name='HLT_mu6', chain_counter='1', lower_chain_name='L1_MU06', level='HLT', prescale='2', pass_through='0')
+chain.addTriggerTypeBit('4')
+chain.addStreamTag('muons', prescale='1')
+chain.addGroup('muons')
+menu.addHLTChain(chain)
+
+chain = HLTChain( chain_name='HLT_mu20', chain_counter='2', lower_chain_name='L1_MU20', level='HLT', prescale='2', pass_through='0')
+chain.addTriggerTypeBit('4')
+chain.addStreamTag('muons', prescale='1')
+chain.addGroup('muons')
+menu.addHLTChain(chain)
+
+chain = HLTChain( chain_name='HLT_mu21', chain_counter='3', lower_chain_name='L1_MU21', level='HLT', prescale='2', pass_through='0')
+chain.addTriggerTypeBit('4')
+chain.addStreamTag('muons', prescale='1')
+chain.addGroup('muons')
+menu.addHLTChain(chain)
+
+chain = HLTChain( chain_name='HLT_mu20_21', chain_counter='4', lower_chain_name='L1_MU20 L1_MU21', level='HLT', prescale='2', pass_through='0')
+chain.addTriggerTypeBit('4')
+chain.addStreamTag('muons', prescale='1')
+chain.addGroup('muons')
+menu.addHLTChain(chain)
+
+
+menu.writeConfigFiles();
+menu.dot(algs=True)
+
diff --git a/Trigger/TrigSteer/TrigSteering/share/pureSteering_l1menu.py b/Trigger/TrigSteer/TrigSteering/share/pureSteering_l1menu.py
index 9b6b0acbe903..6d4feeda025d 100644
--- a/Trigger/TrigSteer/TrigSteering/share/pureSteering_l1menu.py
+++ b/Trigger/TrigSteer/TrigSteering/share/pureSteering_l1menu.py
@@ -33,6 +33,8 @@ LVL1MenuItem('L1_2MU06').setLogic( ThrCondition(thr).x(2) & bgrp ).setTriggerTyp
 thr = l1menu.registerThr('MU20','MUON').addThrValue(20)
 LVL1MenuItem('L1_MU20').setLogic( ThrCondition(thr) & bgrp ).setTriggerType( TT.muon )
 
+
+
 thr = l1menu.registerThr('J200','JET').addThrValue(200)
 LVL1MenuItem('L1_J200').setLogic( ThrCondition(thr) & bgrp ).setTriggerType( TT.calo )
 
diff --git a/Trigger/TrigSteer/TrigSteering/test/SteeringChain_test.cxx b/Trigger/TrigSteer/TrigSteering/test/SteeringChain_test.cxx
new file mode 100644
index 000000000000..08b6113d95bd
--- /dev/null
+++ b/Trigger/TrigSteer/TrigSteering/test/SteeringChain_test.cxx
@@ -0,0 +1,101 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <cassert>
+#include <iostream>
+
+#include "TrigSteering/Signature.h"
+#include "TrigSteering/Sequence.h"
+#include "TrigSteering/SteeringChain.h"
+#include "TrigSteering/PeriodicScaler.h"
+#include "TrigSteering/ISequenceProvider.h"
+#include "TrigSteering/IScalerSvc.h"
+#include "TrigInterfaces/AlgoConfig.h"
+
+#include "TestTools/initGaudi.h"
+#include "GaudiKernel/MsgStream.h"
+#include "AthenaKernel/getMessageSvc.h"
+
+
+using namespace HLT;
+class TestSequenceProvider : public ISequenceProvider {
+public:
+  HLT::Sequence* findSeqForOutputTeType( const unsigned int ) override {
+    return 0;
+  }
+};
+
+class TestScalerSvc : public IScalerSvc, public AthService {
+public:
+  TestScalerSvc( ISvcLocator* pSvc ) : AthService( "TestScalerSvc", pSvc ) {}
+  IScaler* get( const std::string& ) const {
+    return new PeriodicScaler;
+  } 
+private:
+};
+
+int main()
+{
+
+  // get Gaudi MsgService:
+  ISvcLocator* pSvcLoc;
+  if ( !Athena_test::initGaudi( pSvcLoc ) ) {
+    std::cerr << "problem loading Athena_test::initGaudi !!" << std::endl;
+    return 0;
+  }
+  assert( pSvcLoc );
+
+  MsgStream* log = new MsgStream( Athena::getMessageSvc(), "getMessageSvc_test" );
+  int logLvl = log->level();
+
+  // Create & set the config object, holding all common variables
+  HLT::AlgoConfig* config = new HLT::AlgoConfig();
+  config->setMsgStream( log );
+  config->setMsgLvl( logLvl );
+  const std::vector<TrigConf::HLTSignature*> noSteps;
+  TrigConf::HLTChain chainConf( "HLT_multiSeeded", 1, 0, "HLT", "L1_A L1_B", 0, noSteps );
+  chainConf.set_prescale( 10 );
+  chainConf.addStream( new TrigConf::HLTStreamTag("Main", "physics", true, 1.) );
+  chainConf.addStream( new TrigConf::HLTStreamTag("express", "express", true, 1.) );
+  chainConf.set_groupList( std::set<std::string>( {"grA", "grB"} ) );
+
+
+  TestSequenceProvider seqProvider;
+  TestScalerSvc scalerSvc( pSvcLoc );
+  HLT::SteeringChain steeringChain( &chainConf, &seqProvider, config, &scalerSvc );
+  std::cout << "After creation" << std::endl;
+  steeringChain.print(std::cout);
+  std::cout << std::endl;
+
+  std::cout << "reset:" << std::endl;
+  for ( int i = 0; i < 20; ++i ) {
+    steeringChain.reset();
+    steeringChain.setActive();
+
+    steeringChain.setPrescaleState();
+    steeringChain.print(std::cout);
+    std::cout << std::endl;  
+  }
+
+  std::cout << "reseetChain:" << std::endl;
+  for ( int i = 0; i < 20; ++i ) {
+    steeringChain.resetChain();
+    steeringChain.setActive();
+
+    steeringChain.setPrescaleState();
+    steeringChain.print(std::cout);
+    std::cout << std::endl;  
+  }
+
+  
+
+  
+  
+  delete log;
+  delete config;
+
+
+
+  return 0;
+}
-- 
GitLab