34 flags = AthConfigFlags()
36 flags.addFlag(
'Trigger.doLVL1',
lambda prevFlags: prevFlags.Input.isMC,
37 help=
'enable L1 simulation')
39 flags.addFlag(
'Trigger.doHLT',
False,
40 help=
'run HLT selection algorithms')
42 flags.addFlag(
"Trigger.forceEnableAllChains",
lambda prevFlags: prevFlags.GeoModel.Run >= LHCPeriod.Run4,
43 help=
'always enable all configured chains (for testing). Currently enabled by default for Run 4.')
45 flags.addFlag(
"Trigger.disableL1ConsistencyChecker",
False,
46 help=
'force disabling the L1 ConsistencyChecker')
48 flags.addFlag(
'Trigger.enableL0Muon',
49 lambda prevFlags: prevFlags.GeoModel.Run >= LHCPeriod.Run4,
50 help=
'enable Run-4+ L0 Muon simulation or decoding')
52 flags.addFlag(
'Trigger.enableL1MuonPhase1',
lambda prevFlags:
53 (
not prevFlags.Trigger.enableL0Muon)
and
54 prevFlags.Trigger.EDMVersion >= 3
or prevFlags.Detector.EnableMM
or prevFlags.Detector.EnablesTGC,
55 help=
'enable Run-3 LVL1 muon decoding')
57 flags.addFlag(
'Trigger.enableL1CaloPhase1',
lambda prevFlags:
58 prevFlags.Trigger.EDMVersion >= 3
or prevFlags.GeoModel.Run >= LHCPeriod.Run3,
59 help=
'enable Phase-1 LVL1 calo simulation and/or decoding for Run-3+')
61 flags.addFlag(
'Trigger.enableL1TopoDump',
False,
62 help=
'enable L1Topo simulation to write inputs to txt file')
64 flags.addFlag(
'Trigger.enableL1TopoBWSimulation',
True,
65 help=
'enable bitwise L1Topo simulation')
67 flags.addFlag(
'Trigger.enableL1CaloLegacy',
lambda prevFlags:
68 not (
not prevFlags.Input.isMC
and prevFlags.Trigger.doHLT),
69 help=
'enable Run-2 L1Calo simulation and/or decoding')
72 flags.addFlag(
'Trigger.L0MuonSim.doEmulation',
73 lambda prevFlags: prevFlags.Trigger.enableL0Muon
and
74 prevFlags.Input.isMC
and
75 'TruthParticleContainer' in prevFlags.Input.Collections,
76 help=
'Emulate the L0Muon trigger TOBs from smeared truth muon particles')
79 flags.addFlag(
'Trigger.L1MuonSim.EmulateNSW',
False,
80 help=
'enable emulation tool for NSW-TGC coincidence')
82 flags.addFlag(
'Trigger.L1MuonSim.doMMTrigger',
True,
83 help=
'enable NSW MM trigger')
85 flags.addFlag(
'Trigger.L1MuonSim.doPadTrigger',
True,
86 help=
'enable NSW sTGC pad trigger')
88 flags.addFlag(
'Trigger.L1MuonSim.doStripTrigger',
False,
89 help=
'enable NSW sTGC strip trigger')
91 flags.addFlag(
'Trigger.L1MuonSim.WriteNSWDebugNtuple',
False,
92 help=
'enable Storing NSW debug Ntuple')
94 flags.addFlag(
'Trigger.L1MuonSim.WriteMMBranches',
False,
95 help=
'enable storing of Micromega branches in NSW debug Ntuple')
97 flags.addFlag(
'Trigger.L1MuonSim.WritesTGCBranches',
False,
98 help=
'enable storing of TGC branches in NSW debug Ntuple')
100 flags.addFlag(
'Trigger.L1MuonSim.NSWVetoMode',
True,
101 help=
'enable the veto mode of the NSW-TGC coincidence')
103 flags.addFlag(
'Trigger.L1MuonSim.doBIS78',
True,
104 help=
'enable TGC-RPC BIS78 coincidence')
106 flags.addFlag(
'Trigger.L1MuonSim.CondDBOffline',
'OFLCOND-MC16-SDR-RUN2-04',
107 help=
'offline CondDB tag for RPC/TGC coincidence window in rerunLVL1 on data')
109 flags.addFlag(
'Trigger.L1MuonSim.RPCNBX',
lambda prevFlags:
110 8
if prevFlags.Input.isMC
else 4,
111 help=
'Number of bunch crossings in RPC readout')
113 flags.addFlag(
'Trigger.L1MuonSim.RPCNBCZ',
lambda prevFlags:
114 3
if prevFlags.Input.isMC
else 1,
115 help=
'Nominal BC for RPC readout')
119 flags.addFlag(
'Trigger.doID',
True,
120 help=
'enable Inner Detector')
122 flags.addFlag(
'Trigger.doMuon',
True,
123 help=
'enable muon systems')
125 flags.addFlag(
'Trigger.doCalo',
True,
126 help=
'enable calorimeters')
128 flags.addFlag(
'Trigger.doZDC',
False,
129 help=
'enable ZDC system')
131 flags.addFlag(
'Trigger.ZdcLUT',
'TrigT1ZDC/zdcRun3T1LUT_v2_08_08_2023.json',
132 help=
'path to Run3 ZDC LUT')
135 flags.addFlag(
'Trigger.doTRT',
False)
138 flags.addFlag(
'Trigger.TRT.TTCMultiplicity', 4)
141 flags.addFlag(
'Trigger.TRT.maskedChipsFile',
'TrigT1TRT/fastORmaskedChips.json')
144 flags.addFlag(
'Trigger.doValidationMonitoring',
False,
145 help=
'enable additional validation histograms')
147 flags.addFlag(
'Trigger.doRuntimeNaviVal',
False,
148 help=(
'Check validity of each Decision objects in the entire decision tree (CPU expensive). '
149 'Also enable per-step decision printouts.'))
151 flags.addFlag(
'Trigger.ROBPrefetchingOptions',
152 [ROBPrefetching.InitialRoI, ROBPrefetching.StepRoI, ROBPrefetching.TauCoreLargeRoI],
153 help=
'select ROB prefetching types, empty list disables prefetching')
155 def EDMVersion(flags):
156 """Determine Trigger EDM version based on the input file."""
157 _log = logging.getLogger(
'TriggerConfigFlags.EDMVersion')
161 if flags.Input.Format
is Format.BS:
162 _log.debug(
"Input format is ByteStream")
164 if not any(flags.Input.Files)
and flags.Common.isOnline:
165 _log.info(
"Online reconstruction, no input file. Return default EDMVersion=%d", default_version)
166 return default_version
168 from TrigEDMConfig.Utils
import getEDMVersionFromBS
170 log.error(
"Failed to import TrigEDMConfig, analysing ByteStream files is not possible in this release!")
174 version = getEDMVersionFromBS(flags.Input.Files[0])
176 return version
if version
is not None else default_version
180 _log.debug(
"Input format is POOL -- determine from input file collections")
181 collections = flags.Input.Collections
182 if "HLTResult_EF" in collections:
183 _log.info(
"Determined EDMVersion to be 1, because HLTResult_EF found in POOL file")
185 elif "TrigNavigation" in collections:
186 _log.info(
"Determined EDMVersion to be 2, because TrigNavigation found in POOL file")
188 elif flags.Trigger.doHLT:
189 if flags.GeoModel.Run >= LHCPeriod.Run4:
190 _log.info(
"Determined EDMVersion to be 4, because we're now running the trigger and GeoModel.Run >= 4")
193 _log.info(
"Determined EDMVersion to be 3, because we're now running the trigger")
195 elif any(
"HLTNav_Summary" in s
for s
in collections):
196 if flags.GeoModel.Run >= LHCPeriod.Run4:
197 _log.info(
"Determined EDMVersion to be 4, because HLTNav_Summary.* found in POOL file and GeoModel.Run >= 4")
200 _log.info(
"Determined EDMVersion to be 3, because HLTNav_Summary.* found in POOL file")
202 elif not flags.Input.Collections:
205 _log.warning(
"All input files seem to be empty, cannot determine EDM version. Guessing EDMVersion=3")
208 _log.info(
"Could not determine EDM version from the input file. Return default EDMVersion=%d",
210 return default_version
212 flags.addFlag(
'Trigger.EDMVersion',
lambda prevFlags: EDMVersion(prevFlags),
213 help=
'Trigger EDM version (determined by input file or set to the version to be produced)')
215 flags.addFlag(
'Trigger.doEDMVersionConversion',
False,
216 help=
'convert Run-1&2 EDM to Run-3 EDM')
218 flags.addFlag(
'Trigger.doxAODConversion',
True,
219 help=(
'convert Run-1 EDM to xAOD'))
221 flags.addFlag(
'Trigger.doOnlineNavigationCompactification',
True,
222 help=
'enable trigger Navigation compactification into a single collection')
224 flags.addFlag(
'Trigger.doNavigationSlimming',
True,
225 help=
'enable Navigation slimming for RAWtoXYZ or AODtoDAOD transforms')
227 flags.addFlag(
'Trigger.derivationsExtraChains', [],
228 help=
'list of chains which should be considered for trigger-matching in addition to those from the TriggerAPI when running derivations')
231 flags.addFlag(
'Trigger.CostMonitoring.doCostMonitoring',
True,
232 help=
'enable cost monitoring')
234 flags.addFlag(
'Trigger.CostMonitoring.chain',
'HLT_noalg_CostMonDS_L1All',
235 help=
'Cost monitoring chain name')
237 flags.addFlag(
'Trigger.CostMonitoring.outputCollection',
'HLT_TrigCostContainer',
238 help=
'Cost monitoring output collection name')
240 flags.addFlag(
'Trigger.CostMonitoring.monitorAllEvents',
False,
241 help=
'enable Cost monitoring for all events')
243 flags.addFlag(
'Trigger.CostMonitoring.monitorROBs',
True,
244 help=
'enable Cost monitoring of ROB accesses')
247 flags.addFlag(
'Trigger.L1.doMuon',
True,
248 help=
'enable L1Muon ByteStream conversion/simulation')
250 flags.addFlag(
'Trigger.L1.doMuonTopoInputs',
True,
251 help=
'enable ByteStream conversion/simulation of MUCTPI Topo TOBs')
253 flags.addFlag(
'Trigger.L1.doCalo',
True,
254 help=
'enable L1Calo ByteStream conversion/simulation')
256 flags.addFlag(
'Trigger.L1.doCaloInputs',
lambda prevFlags:
257 prevFlags.Trigger.L1.doCalo
and prevFlags.Trigger.enableL1CaloPhase1
and not prevFlags.Trigger.doHLT,
258 help=
'enable L1Calo Input ([ejg]Towers) ByteStream conversion/simulation')
260 flags.addFlag(
'Trigger.L1.doeFex',
lambda prevFlags:
261 prevFlags.Trigger.L1.doCalo
and prevFlags.Trigger.enableL1CaloPhase1,
262 help=
'enable eFEX ByteStream conversion/simulation')
264 flags.addFlag(
'Trigger.L1.Menu.doeFexBDTTau',
True,
265 help=
'set BDT tau algorithm as the active one for eFEX when constructing L1 menus')
267 flags.addFlag(
'Trigger.L1.dojFex',
lambda prevFlags:
268 prevFlags.Trigger.L1.doCalo
and prevFlags.Trigger.enableL1CaloPhase1,
269 help=
'enable jFEX ByteStream conversion/simulation')
271 flags.addFlag(
'Trigger.L1.dogFex',
lambda prevFlags:
272 prevFlags.Trigger.L1.doCalo
and prevFlags.Trigger.enableL1CaloPhase1,
273 help=
'enable gFEX ByteStream conversion/simulation')
275 flags.addFlag(
'Trigger.L1.L1CaloSuperCellContainerName',
lambda prevFlags:
276 "EmulatedSCell" if prevFlags.GeoModel.Run
is LHCPeriod.Run2
else "SCell",
277 help=
'name of SuperCell container')
279 flags.addFlag(
'Trigger.L1.doTopo',
True,
280 help=
'enable L1Topo ByteStream conversion/simulation (steering both legacy and phase-1 Topo)')
282 flags.addFlag(
'Trigger.L1.doTopoPhase1',
lambda prevFlags:
283 prevFlags.Trigger.L1.doTopo
and prevFlags.Trigger.enableL1CaloPhase1,
284 help=
'control Phase-I L1Topo simulation even if L1.doTopo is True')
286 flags.addFlag(
'Trigger.L1.doGlobal',
lambda prevFlags: prevFlags.GeoModel.Run >= LHCPeriod.Run4,
287 help=
'enable L0Global ByteStream conversion/simulation')
289 flags.addFlag(
'Trigger.L1.doCTP',
True,
290 help=
'enable CTP ByteStream conversion/simulation')
292 flags.addFlag(
'Trigger.L1.Menu.doHeavyIonTobThresholds',
lambda prevFlags:
293 'HI' in prevFlags.Trigger.triggerMenuSetup,
294 help=
'modify min-pt-to-Topo threshold for TOBs to HI values')
296 flags.addFlag(
'Trigger.L1.errorOnMissingTOB',
True,
297 help=
'Set to true to enable strict-mode which will generate an ERROR on missing (non-overflow) TOB events in HLT-seeding from L1')
300 flags.addFlag(
'Trigger.Online.partitionName', os.getenv(
'TDAQ_PARTITION')
or '',
301 help=
'partition name used to determine online vs offline BS result writing')
303 flags.addFlag(
'Trigger.Online.isPartition',
lambda prevFlags: len(prevFlags.Trigger.Online.partitionName)>0,
304 help=
'check if job is running in a partition (i.e. partition name is not empty)')
306 flags.addFlag(
'Trigger.Online.useOnlineTHistSvc',
False,
307 help=
'use online THistSvc')
309 flags.addFlag(
'Trigger.Online.useOnlineWebdaqHistSvc',
False,
310 help=
'use online Webdaq HistSvc')
312 flags.addFlag(
'Trigger.Online.BFieldAutoConfig',
True,
313 help=
'auto-configure magnetic field from currents in IS')
315 flags.addFlag(
'Trigger.writeBS',
False,
316 help=
'enable bytestream writing of trigger information')
318 flags.addFlag(
'Trigger.doTransientByteStream',
lambda prevFlags:
319 True if prevFlags.Input.Format
is Format.POOL
and prevFlags.Trigger.doCalo
else False,
320 help=
'create transient BS (for running on MC RDO with clients that require BS inputs)')
322 flags.addFlag(
'Trigger.AODEDMSet',
lambda flags:
'AODSLIM' if flags.Input.isMC
else 'AODFULL',
323 help=
'list of EDM objects to be written to AOD')
325 flags.addFlag(
'Trigger.ESDEDMSet',
'ESD',
326 help=
'list of EDM objects to be written to ESD')
328 flags.addFlag(
'Trigger.ExtraEDMList', [],
329 help=
'list of extra EDM objects to be stored (for testing). Supported features: Add new items. Add extra decorations to existing Aux. Add additional output targets.')
331 def __availableRecoMetadata(flags):
332 systems = [
'L1',
'HLT']
334 if not any(flags.Input.Files)
and flags.Common.isOnline:
337 elif flags.Trigger.doHLT:
338 raise RuntimeError(
'Trigger.availableRecoMetadata is ill-defined if Trigger.doHLT==True')
340 elif flags.Input.Format
is Format.BS:
341 from TrigConfigSvc.TriggerConfigAccess
import getKeysFromConditions
342 keys = getKeysFromConditions(flags.Input.RunNumbers[0], lbNr = 1, flags = flags)
343 return ( ([
'L1']
if 'LVL1PSK' in keys
else []) +
344 ([
'HLT']
if 'HLTPSK' in keys
else []) )
347 return systems
if flags.Trigger.triggerConfig ==
'INFILE' else []
349 flags.addFlag(
'Trigger.availableRecoMetadata',
lambda flags: __availableRecoMetadata(flags),
350 help=
"list of enabled trigger sub-systems in reconstruction: ['L1,'HLT']")
352 flags.addFlag(
"Trigger.decodeHLT",
True,
353 help=
'enable decoding of HLT trigger decision/result in reconstruction')
355 flags.addFlag(
"Trigger.DecisionMakerValidation.Execute",
True,
356 help=
'run trigger decision validation algorithm in reconstruction')
358 flags.addFlag(
"Trigger.DecisionMakerValidation.ErrorMode",
True,
359 help=
'emit an ERROR (or WARNING) in case of trigger decision validation failure')
362 def __triggerConfig(flags):
363 _log = logging.getLogger(
'TriggerConfigFlags.triggerConfig')
364 if flags.Common.isOnline
and not flags.Trigger.doHLT:
366 _log.debug(
"Autoconfigured default value for running reconstruction inside Point 1: 'DB'")
368 elif flags.Input.Format
is Format.BS:
369 from glob
import glob
370 hasLocal =
True if (glob(
"HLTMenu*.json")
and glob(
"L1Menu*.json")
and glob(
"HLTPrescales*.json")
and glob(
"L1Prescales*.json")
and glob(
"HLTMonitoring*.json")
and glob(
"BunchGroupSet*.json"))
else False
371 if flags.Trigger.doHLT:
373 _log.debug(
"Autoconfigured default value for running the trigger on data: 'FILE'")
379 _log.debug(
"Autoconfigured default value for running reconstruction with a pre-supplied set of trigger configuration JSON files: 'FILE'")
381 elif flags.GeoModel.Run >= LHCPeriod.Run3:
383 _log.debug(
"Autoconfigured default value for reconstruction of Run 3 data: 'DB'")
387 _log.debug(
"Autoconfigured default value for reconstruction of Run 1 or Run 2 data: 'FILE'")
390 from AthenaConfiguration.AutoConfigFlags
import GetFileMD
391 md = GetFileMD(flags.Input.Files)
394 hasTrigMeta = (
"metadata_items" in md
and any((
'TriggerMenu' in key)
for key
in md[
"metadata_items"].keys()))
397 _log.debug(
"Autoconfigured default value to read trigger configuration data from the input file: 'INFILE'")
401 _log.debug(
"Autoconfigured default value to read trigger configuration data from disk for MC production: 'FILE'")
404 flags.addFlag(
'Trigger.triggerConfig',
lambda flags: __triggerConfig(flags),
405 help=
'Trigger configuration source (https://twiki.cern.ch/twiki/bin/view/Atlas/TriggerConfigFlag)')
407 flags.addFlag(
'Trigger.useCrest',
lambda prevFlags: prevFlags.IOVDb.UseCREST,
408 help=
'Flag enables trigger configuration database access through CREST')
410 flags.addFlag(
'Trigger.crestServer',
lambda prevFlags: prevFlags.IOVDb.CrestServer,
411 help=
'CREST server to access trigger configuration')
413 flags.addFlag(
'Trigger.triggerMenuSetup',
lambda flags:
'MC_pp_run3_v1_BulkMCProd_prescale' if flags.GeoModel.Run
is LHCPeriod.Run3
else 'MC_pp_run4_v1_BulkMCProd_prescale',
414 help=
'name of the trigger menu')
416 flags.addFlag(
'Trigger.generateMenuDiagnostics',
False,
417 help=
'print debug output from control flow generation')
419 flags.addFlag(
'Trigger.fastMenuGeneration',
True,
420 help=
'avoid re-merging CAs that were already seen once')
422 flags.addFlag(
'Trigger.disableCPS',
False,
423 help=
'disable coherent prescale sets (for testing with small menu)')
425 flags.addFlag(
'Trigger.enableEndOfEventProcessing',
True,
426 help=
'enable execution of extra algorithms for accepted events')
428 flags.addFlag(
'Trigger.doCFEmulationTest',
False,
429 help=
'enable run Control Flow Emulation test')
434 if doTriggerRecoFlags:
438 flags.Trigger.disableCPS =
lambda prevFlags: prevFlags.Trigger.selectChains
or len(prevFlags.Trigger.enabledSignatures)==1
444 flags = AthConfigFlags()
447 def _allSignatures (prevFlags):
448 from TriggerMenuMT.HLT.Config.GenerateMenuMT
import allSignatures
449 l = list(allSignatures())
452 flags.addFlag(
"Trigger.enabledSignatures", _allSignatures, help=
'list of enabled trigger signatures')
453 flags.addFlag(
"Trigger.disabledSignatures", [], help=
'list of disabled trigger signatures')
454 flags.addFlag(
"Trigger.selectChains", [], help=
'list of enabled chains')
455 flags.addFlag(
"Trigger.disableChains", [], help=
'list of disabled chains')
458 from TriggerMenuMT.HLT.Egamma.TrigEgammaConfigFlags
import createTrigEgammaConfigFlags
459 return createTrigEgammaConfigFlags()
460 flags.addFlagsCategory(
'Trigger.egamma', __egamma )
464 from MuonConfig.MuonConfigFlags
import createMuonConfigFlags
465 muonflags = createMuonConfigFlags()
466 muonflags.Muon.useTGCPriorNextBC=
True
467 muonflags.Muon.MuonTrigger=
True
468 muonflags.Muon.SAMuonTrigger=
True
469 muonflags.Muon.runCommissioningChain=
False
470 muonflags.Muon.enableErrorTuning=
False
472 flags.addFlagsCategory(
'Trigger.Offline.SA', __muonSA, prefix=
True)
475 from MuonConfig.MuonConfigFlags
import createMuonConfigFlags
476 muonflags = createMuonConfigFlags()
477 muonflags.Muon.useTGCPriorNextBC=
True
478 muonflags.Muon.MuonTrigger=
True
479 muonflags.Muon.enableErrorTuning=
False
481 flags.addFlagsCategory(
'Trigger.Offline', __muon, prefix=
True)
483 def __muonCombined():
484 from MuonCombinedConfig.MuonCombinedConfigFlags
import createMuonCombinedConfigFlags
485 muonflags = createMuonCombinedConfigFlags()
486 muonflags.MuonCombined.doCaloTrkMuId =
False
487 muonflags.MuonCombined.doSiAssocForwardMuons =
False
488 muonflags.MuonCombined.doStatisticalCombination =
False
489 muonflags.MuonCombined.doMuGirl =
False
490 muonflags.MuonCombined.doCombinedFit =
True
492 flags.addFlagsCategory(
'Trigger.Offline.Combined', __muonCombined, prefix=
True)
495 from TrigTauRec.TrigTauConfigFlags
import createTrigTauConfigFlags
496 return createTrigTauConfigFlags()
497 flags.addFlagsCategory(
'Trigger.Offline.Tau', __tau )
500 from TrigInDetConfig.TrigTrackingPassFlags
import createTrigTrackingPassFlags
501 return createTrigTrackingPassFlags()
502 flags.addFlagsCategory(
'Trigger.InDetTracking', __idTrk )
505 from TrigInDetConfig.TrigTrackingPassFlags
import createTrigTrackingPassFlags
506 return createTrigTrackingPassFlags(mode=
'ITk')
507 flags.addFlagsCategory(
'Trigger.ITkTracking', __idITk )
510 from TrigInDetConfig.TrigTrackingPassFlags
import createTrigTrackingPassFlags
511 return createTrigTrackingPassFlags(mode=
'Acts')
512 flags.addFlagsCategory(
'Trigger.ActsTracking', _idActs )
514 flags.addFlag(
'Trigger.useActsTracking',
False, help=
'use ACTS for ITk tracking')
515 flags.addFlag(
'Trigger.EFTrackPipeline',
"", help=
'string to specify EFTrack pipeline')
518 from TrigCaloRec.TrigCaloConfigFlags
import createTrigCaloConfigFlags
519 return createTrigCaloConfigFlags()
520 flags.addFlagsCategory(
'Trigger.Calo', __trigCalo )
523 from TrigT1MuctpiPhase1.TrigMUCTPIConfigFlags
import createTrigMUCTPIConfigFlags
524 return createTrigMUCTPIConfigFlags()
525 flags.addFlagsCategory(
'Trigger.MUCTPI', __muctpiFlags )
528 from TrigT1CTP.CTPSimulationConfigFlags
import createTrigCTPConfigFlags
529 return createTrigCTPConfigFlags()
530 flags.addFlagsCategory(
'Trigger.CTP', __ctpFlags )
532 def __fpgatracksimFlags():
533 """Additional function delays import"""
534 from FPGATrackSimConfTools.FPGATrackSimConfigFlags
import createFPGATrackSimConfigFlags
535 return createFPGATrackSimConfigFlags()
536 flags.addFlagsCategory(
"Trigger.FPGATrackSim", __fpgatracksimFlags, prefix=
True )
539 from TriggerMenuMT.HLT.Jet.TrigJetConfigFlags
import createTrigJetConfigFlags
540 return createTrigJetConfigFlags()
541 flags.addFlagsCategory(
'Trigger.Jet', __jet )
544 from TriggerMenuMT.HLT.Jet.TrigJetConfigFlags
import createTrigFSHadConfigFlags
545 return createTrigFSHadConfigFlags()
546 flags.addFlagsCategory(
'Trigger.FSHad', __fshad )