Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support XOR operator in triggerExpression::Parser [12_5_X] #39378

Merged
merged 1 commit into from Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions HLTrigger/HLTcore/interface/TriggerExpressionParser.h
Expand Up @@ -28,6 +28,7 @@ namespace triggerExpression {
operand_not = qi::lexeme[qi::lit("NOT") >> delimiter];
operand_and = qi::lexeme[qi::lit("AND") >> delimiter];
operand_or = qi::lexeme[qi::lit("OR") >> delimiter];
operand_xor = qi::lexeme[qi::lit("XOR") >> delimiter];
operand_masking = qi::lexeme[qi::lit("MASKING") >> delimiter];

// "TRUE": keyword to accept all events
Expand All @@ -40,9 +41,9 @@ namespace triggerExpression {
token_l1algo %= qi::raw[qi::lexeme["L1_" >> +(qi::char_("a-zA-Z0-9_*?"))]];

// Decisions of Paths in the CMSSW configuration (e.g. high-level triggers):
// any alphanumeric pattern except for "TRUE", "FALSE", "NOT", "AND", "OR", and "MASKING"
// any alphanumeric pattern except for "TRUE", "FALSE", "NOT", "AND", "OR", "XOR" and "MASKING"
token_path %= qi::raw[qi::lexeme[+(qi::char_("a-zA-Z0-9_*?"))] - token_true - token_false - operand_not -
operand_and - operand_or - operand_masking];
operand_and - operand_or - operand_xor - operand_masking];

token = (token_true[qi::_val = new_<Constant>(true)] | token_false[qi::_val = new_<Constant>(false)] |
token_l1algo[qi::_val = new_<L1uGTReader>(qi::_1)] | token_path[qi::_val = new_<PathReader>(qi::_1)]);
Expand All @@ -68,6 +69,7 @@ namespace triggerExpression {
expression = unary[qi::_val = qi::_1] >>
*((operand_and >> unary)[qi::_val = new_<OperatorAnd>(qi::_val, qi::_1)] |
(operand_or >> unary)[qi::_val = new_<OperatorOr>(qi::_val, qi::_1)] |
(operand_xor >> unary)[qi::_val = new_<OperatorXor>(qi::_val, qi::_1)] |
(operand_masking >> argument_masking)[qi::_val = new_<OperatorMasking>(qi::_val, qi::_1)]);
}

Expand All @@ -82,6 +84,7 @@ namespace triggerExpression {
terminal_rule operand_not;
terminal_rule operand_and;
terminal_rule operand_or;
terminal_rule operand_xor;
terminal_rule operand_masking;

name_rule token_l1algo;
Expand Down
14 changes: 12 additions & 2 deletions HLTrigger/HLTcore/test/test_catch2_TriggerExpressionParser.cc
Expand Up @@ -52,6 +52,11 @@ TEST_CASE("Test TriggerExpressionParser", "[TriggerExpressionParser]") {
"((Uninitialised_Path_Expression AND TRUE) AND (NOT Uninitialised_L1_Expression))"));
REQUIRE(testExpression("NOT NOTThisHLTPath", //
"(NOT Uninitialised_Path_Expression)"));
REQUIRE(testExpression("XYZ XOR TRUE", //
"(Uninitialised_Path_Expression XOR TRUE)"));
REQUIRE(testExpression("XYZ XOR ABC AND L1_* OR DEF/10", //
"(((Uninitialised_Path_Expression XOR Uninitialised_Path_Expression) AND "
"Uninitialised_L1_Expression) OR (Uninitialised_Path_Expression / 10))"));
REQUIRE(testExpression("ThisHLTANDNOTThatORTheOther", //
"Uninitialised_Path_Expression"));
REQUIRE(testExpression("TRUEPath AND NOTPath", //
Expand Down Expand Up @@ -86,8 +91,8 @@ TEST_CASE("Test TriggerExpressionParser", "[TriggerExpressionParser]") {
"L1_*copy* MASKING L1_*copy MASKING ((L1_*copy2))", //
"((Uninitialised_L1_Expression MASKING Uninitialised_L1_Expression) MASKING Uninitialised_L1_Expression)"));
REQUIRE(testExpression(
"(A AND B OR C) MASKING D OR E", //
"((((Uninitialised_Path_Expression AND Uninitialised_Path_Expression) OR Uninitialised_Path_Expression)"
"(A AND B XOR C) MASKING D OR E", //
"((((Uninitialised_Path_Expression AND Uninitialised_Path_Expression) XOR Uninitialised_Path_Expression)"
" MASKING Uninitialised_Path_Expression) OR Uninitialised_Path_Expression)"));
REQUIRE(testExpression("EXPR_A MASKING FALSE", "(Uninitialised_Path_Expression MASKING FALSE)"));
}
Expand All @@ -96,6 +101,11 @@ TEST_CASE("Test TriggerExpressionParser", "[TriggerExpressionParser]") {
SECTION("IncorrectExpressions") {
REQUIRE(not testExpression("A | B"));
REQUIRE(not testExpression("A && B"));
REQUIRE(not testExpression("NOT"));
REQUIRE(not testExpression("AND"));
REQUIRE(not testExpression("OR"));
REQUIRE(not testExpression("XOR"));
REQUIRE(not testExpression("MASKING"));
REQUIRE(not testExpression("NOT L1_SEED1 ANDD L1_SEED2*"));
REQUIRE(not testExpression("NOT (NOTHLT_Path OR HLT_Path2))"));
REQUIRE(not testExpression("HLT_Path* NOT TRUE"));
Expand Down
42 changes: 27 additions & 15 deletions HLTrigger/HLTfilters/test/triggerResultsFilter_by_PathStatus.py
Expand Up @@ -123,6 +123,16 @@
triggerConditions = ( 'NOT(Path_1/15)AND(NOT Path_2/10)AND(NOT Path_3/6)', )
)

# accept if Path_1 and Path_2 have different results (XOR) without using XOR operator
process.filter_1xor2_withoutXOR = _triggerResultsFilter.clone(
triggerConditions = ( 'Path_1 AND NOT Path_2', 'NOT Path_1 AND Path_2', )
)

# accept if Path_1 and Path_2 have different results (XOR) using XOR operator
process.filter_1xor2_withXOR = _triggerResultsFilter.clone(
triggerConditions = ( 'Path_1 XOR Path_2', )
)

# accept if any path succeeds (wildcard, '*')
process.filter_any_star = _triggerResultsFilter.clone(
triggerConditions = ( 'Path_*', )
Expand Down Expand Up @@ -204,25 +214,27 @@
process.Check_Any_Or = cms.Path( process.filter_any_or )
process.Check_Any_Star = cms.Path( process.filter_any_star )

process.Check_1_Pre = cms.Path( process.filter_1_pre )
process.Check_1_Pre = cms.Path( process.filter_1_pre )
process.Check_1_Pre_With_Masks1 = cms.Path( process.filter_1_pre_with_masks1 )
process.Check_1_Pre_With_Masks2 = cms.Path( process.filter_1_pre_with_masks2 )
process.Check_NOT_1_Pre = cms.Path( process.filter_not_1_pre )
process.Check_2_Pre = cms.Path( process.filter_2_pre )
process.Check_Any_Pre = cms.Path( process.filter_any_pre )
process.Check_NOT_1_Pre = cms.Path( process.filter_not_1_pre )
process.Check_2_Pre = cms.Path( process.filter_2_pre )
process.Check_Any_Pre = cms.Path( process.filter_any_pre )
process.Check_Any_Pre_DoubleNOT = cms.Path( process.filter_any_pre_doubleNOT )
process.Check_Not_Any_Pre = cms.Path( process.filter_not_any_pre )

process.Check_Any_Question = cms.Path( process.filter_any_question )
process.Check_Any_StarQuestion = cms.Path( process.filter_any_starquestion )
process.Check_Wrong_Name = cms.Path( process.filter_wrong_name )
process.Check_Wrong_Pattern = cms.Path( process.filter_wrong_pattern )
process.Check_Not_Wrong_Pattern = cms.Path( ~ process.filter_wrong_pattern )
process.Check_Empty_Pattern = cms.Path( process.filter_empty_pattern )
process.Check_L1Path_Pattern = cms.Path( process.filter_l1path_pattern )
process.Check_Not_Any_Pre = cms.Path( process.filter_not_any_pre )
process.Check_1xor2_withoutXOR = cms.Path( process.filter_1xor2_withoutXOR )
process.Check_1xor2_withXOR = cms.Path( process.filter_1xor2_withXOR )

process.Check_Any_Question = cms.Path( process.filter_any_question )
process.Check_Any_StarQuestion = cms.Path( process.filter_any_starquestion )
process.Check_Wrong_Name = cms.Path( process.filter_wrong_name )
process.Check_Wrong_Pattern = cms.Path( process.filter_wrong_pattern )
process.Check_Not_Wrong_Pattern = cms.Path( ~ process.filter_wrong_pattern )
process.Check_Empty_Pattern = cms.Path( process.filter_empty_pattern )
process.Check_L1Path_Pattern = cms.Path( process.filter_l1path_pattern )
process.Check_L1Singlemuopen_Pattern = cms.Path( process.filter_l1singlemuopen_pattern )
process.Check_True_Pattern = cms.Path( process.filter_true_pattern )
process.Check_False_Pattern = cms.Path( process.filter_false_pattern )
process.Check_True_Pattern = cms.Path( process.filter_true_pattern )
process.Check_False_Pattern = cms.Path( process.filter_false_pattern )
process.Check_AlwaysNOTFalse_Pattern = cms.Path( process.filter_AlwaysNOTFalse_pattern )
process.Check_NOTAlwaysFALSE_Pattern = cms.Path( process.filter_NOTAlwaysFALSE_pattern )

Expand Down
26 changes: 14 additions & 12 deletions HLTrigger/HLTfilters/test/triggerResultsFilter_by_PathStatus.sh
Expand Up @@ -41,18 +41,20 @@ TrigReport 1 16 1000 33 967 0 Check_2_Pre
TrigReport 1 17 1000 99 901 0 Check_Any_Pre
TrigReport 1 18 1000 99 901 0 Check_Any_Pre_DoubleNOT
TrigReport 1 19 1000 901 99 0 Check_Not_Any_Pre
TrigReport 1 20 1000 733 267 0 Check_Any_Question
TrigReport 1 21 1000 733 267 0 Check_Any_StarQuestion
TrigReport 1 22 1000 0 1000 0 Check_Wrong_Name
TrigReport 1 23 1000 0 1000 0 Check_Wrong_Pattern
TrigReport 1 24 1000 1000 0 0 Check_Not_Wrong_Pattern
TrigReport 1 25 1000 0 1000 0 Check_Empty_Pattern
TrigReport 1 26 1000 0 1000 0 Check_L1Path_Pattern
TrigReport 1 27 1000 0 1000 0 Check_L1Singlemuopen_Pattern
TrigReport 1 28 1000 1000 0 0 Check_True_Pattern
TrigReport 1 29 1000 0 1000 0 Check_False_Pattern
TrigReport 1 30 1000 1000 0 0 Check_AlwaysNOTFalse_Pattern
TrigReport 1 31 1000 1000 0 0 Check_NOTAlwaysFALSE_Pattern
TrigReport 1 20 1000 499 501 0 Check_1xor2_withoutXOR
TrigReport 1 21 1000 499 501 0 Check_1xor2_withXOR
TrigReport 1 22 1000 733 267 0 Check_Any_Question
TrigReport 1 23 1000 733 267 0 Check_Any_StarQuestion
TrigReport 1 24 1000 0 1000 0 Check_Wrong_Name
TrigReport 1 25 1000 0 1000 0 Check_Wrong_Pattern
TrigReport 1 26 1000 1000 0 0 Check_Not_Wrong_Pattern
TrigReport 1 27 1000 0 1000 0 Check_Empty_Pattern
TrigReport 1 28 1000 0 1000 0 Check_L1Path_Pattern
TrigReport 1 29 1000 0 1000 0 Check_L1Singlemuopen_Pattern
TrigReport 1 30 1000 1000 0 0 Check_True_Pattern
TrigReport 1 31 1000 0 1000 0 Check_False_Pattern
TrigReport 1 32 1000 1000 0 0 Check_AlwaysNOTFalse_Pattern
TrigReport 1 33 1000 1000 0 0 Check_NOTAlwaysFALSE_Pattern
@EOF

# compare to expected output of test job
Expand Down
Expand Up @@ -84,6 +84,16 @@
triggerConditions = ( 'NOT(Path_1/15)AND(NOT Path_2/10)AND(NOT Path_3/6)', )
)

# accept if Path_1 and Path_2 have different results (XOR) without using XOR operator
process.filter_1xor2_withoutXOR = _triggerResultsFilter.clone(
triggerConditions = ( 'Path_1 AND NOT Path_2', 'NOT Path_1 AND Path_2', )
)

# accept if Path_1 and Path_2 have different results (XOR) using XOR operator
process.filter_1xor2_withXOR = _triggerResultsFilter.clone(
triggerConditions = ( 'Path_1 XOR Path_2', )
)

# accept if any path succeeds (wildcard, '*')
process.filter_any_star = _triggerResultsFilter.clone(
triggerConditions = ( '*', )
Expand Down Expand Up @@ -157,14 +167,16 @@
process.path_any_or = cms.Path( process.filter_any_or )
process.path_any_star = cms.Path( process.filter_any_star )

process.path_1_pre = cms.Path( process.filter_1_pre )
process.path_1_pre = cms.Path( process.filter_1_pre )
process.path_1_pre_with_masks1 = cms.Path( process.filter_1_pre_with_masks1 )
process.path_1_pre_with_masks2 = cms.Path( process.filter_1_pre_with_masks2 )
process.path_not_1_pre = cms.Path( process.filter_not_1_pre )
process.path_2_pre = cms.Path( process.filter_2_pre )
process.path_any_pre = cms.Path( process.filter_any_pre )
process.path_not_1_pre = cms.Path( process.filter_not_1_pre )
process.path_2_pre = cms.Path( process.filter_2_pre )
process.path_any_pre = cms.Path( process.filter_any_pre )
process.path_any_pre_doubleNOT = cms.Path( process.filter_any_pre_doubleNOT )
process.path_not_any_pre = cms.Path( process.filter_not_any_pre )
process.path_not_any_pre = cms.Path( process.filter_not_any_pre )
process.Check_1xor2_withoutXOR = cms.Path( process.filter_1xor2_withoutXOR )
process.Check_1xor2_withXOR = cms.Path( process.filter_1xor2_withXOR )

process.path_any_doublestar = cms.Path( process.filter_any_doublestar )
process.path_any_question = cms.Path( process.filter_any_question )
Expand Down
22 changes: 12 additions & 10 deletions HLTrigger/HLTfilters/test/triggerResultsFilter_by_TriggerResults.sh
Expand Up @@ -38,16 +38,18 @@ TrigReport 1 10 1000 33 967 0 path_2_pre
TrigReport 1 11 1000 99 901 0 path_any_pre
TrigReport 1 12 1000 99 901 0 path_any_pre_doubleNOT
TrigReport 1 13 1000 901 99 0 path_not_any_pre
TrigReport 1 14 1000 1000 0 0 path_any_doublestar
TrigReport 1 15 1000 733 267 0 path_any_question
TrigReport 1 16 1000 0 1000 0 path_wrong_name
TrigReport 1 17 1000 0 1000 0 path_wrong_pattern
TrigReport 1 18 1000 1000 0 0 path_not_wrong_pattern
TrigReport 1 19 1000 0 1000 0 path_empty_pattern
TrigReport 1 20 1000 0 1000 0 path_l1path_pattern
TrigReport 1 21 1000 0 1000 0 path_l1singlemuopen_pattern
TrigReport 1 22 1000 1000 0 0 path_true_pattern
TrigReport 1 23 1000 0 1000 0 path_false_pattern
TrigReport 1 14 1000 499 501 0 Check_1xor2_withoutXOR
TrigReport 1 15 1000 499 501 0 Check_1xor2_withXOR
TrigReport 1 16 1000 1000 0 0 path_any_doublestar
TrigReport 1 17 1000 733 267 0 path_any_question
TrigReport 1 18 1000 0 1000 0 path_wrong_name
TrigReport 1 19 1000 0 1000 0 path_wrong_pattern
TrigReport 1 20 1000 1000 0 0 path_not_wrong_pattern
TrigReport 1 21 1000 0 1000 0 path_empty_pattern
TrigReport 1 22 1000 0 1000 0 path_l1path_pattern
TrigReport 1 23 1000 0 1000 0 path_l1singlemuopen_pattern
TrigReport 1 24 1000 1000 0 0 path_true_pattern
TrigReport 1 25 1000 0 1000 0 path_false_pattern
@EOF

# compare to expected output of test job
Expand Down