7 from types
import FunctionType
9 from orion.client
import build_experiment
10 from orion.storage.base
import get_storage
17 RootMaterialTrackReader,
18 RootMaterialTrackWriter,
28 SurfaceMaterialMapper,
33 MaterialMapJsonConverter,
36 from common
import getOpenDataDetectorDirectory
38 from datetime
import datetime
46 mapName=
"material-map",
49 format=JsonFormat.Json,
50 readCachedSurfaceInformation=
False,
54 Implementation of the material mapping that doesn't write the material tracks.
55 Used to create the material map that will then be used to compute the material variance.
57 trackingGeometry : The tracking geometry
58 decorators : The decorators for the tracking geometry
59 outputDir : Output directory for the material map
60 inputDir : Input directory containing the Material track
61 mapName : Name of the material map
62 mapSurface : Is material being mapped onto surfaces ?
63 mapVolume : Is material being mapped onto volumes ?
64 format : Json format used to write the material map (json, cbor, ...)
65 readCachedSurfaceInformation : If set to true it will be assumed that the surface has already been associated with each material interaction in the input file.
68 s = s
or Sequencer(numThreads=1)
69 for decorator
in decorators:
70 s.addContextDecorator(decorator)
71 wb = WhiteBoard(acts.logging.INFO)
72 context = AlgorithmContext(0, 0, wb)
73 for decorator
in decorators:
74 assert decorator.decorate(context) == ProcessCode.SUCCESS
78 RootMaterialTrackReader(
79 level=acts.logging.INFO,
80 collection=
"material-tracks",
84 "optimised-material-map_tracks.root"
85 if readCachedSurfaceInformation
86 else "geant4_material_tracks.root",
89 readCachedSurfaceInformation=readCachedSurfaceInformation,
93 stepper = StraightLineStepper()
94 mmAlgCfg = MaterialMapping.Config(context.geoContext, context.magFieldContext)
95 mmAlgCfg.trackingGeometry = trackingGeometry
96 mmAlgCfg.collection =
"material-tracks"
99 navigator = Navigator(
100 trackingGeometry=trackingGeometry,
101 resolveSensitive=
True,
102 resolveMaterial=
True,
106 mapper = SurfaceMaterialMapper(level=acts.logging.INFO, propagator=propagator)
107 mmAlgCfg.materialSurfaceMapper = mapper
110 navigator = Navigator(
111 trackingGeometry=trackingGeometry,
114 mapper = VolumeMaterialMapper(
115 level=acts.logging.INFO, propagator=propagator, mappingStep=999
117 mmAlgCfg.materialVolumeMapper = mapper
119 jmConverterCfg = MaterialMapJsonConverter.Config(
120 processSensitives=
True,
121 processApproaches=
True,
122 processRepresenting=
True,
123 processBoundaries=
True,
125 context=context.geoContext,
128 jmw = JsonMaterialWriter(
129 level=acts.logging.VERBOSE,
130 converterCfg=jmConverterCfg,
131 fileName=os.path.join(outputDir, mapName),
135 mmAlgCfg.materialWriters = [jmw]
137 s.addAlgorithm(MaterialMapping(level=acts.logging.INFO, config=mmAlgCfg))
149 readCachedSurfaceInformation=
False,
152 Run the material mapping and compute the variance for each bin of each surface
153 Return a dict with the GeometryId value of the surface as a key that stores
154 a list of pairs corresponding to the variance and number of tracks associated with each bin of the surface
156 binMap : Map containing the binning for each surface
157 events : Number of event to use in the mapping
159 inputPath : Directory containing the input geantino track and the json geometry
160 pathExp : Material mapping optimisation path
161 pipeResult : Pipe to send back the score to the main python instance
162 readCachedSurfaceInformation : Are surface information stored in the material track. Switch to true if the mapping was already performed to improve the speed.
165 datetime.now().strftime(
"%H:%M:%S") +
" Start mapping for job " +
str(job),
168 mapName =
"material-map-" +
str(job)
173 matDeco = acts.IMaterialDecorator.fromFile(
174 str(os.path.join(inputPath,
"geometry-map.json"))
179 matMapDeco = acts.MappingMaterialDecorator(
180 tGeometry=trackingGeometryTemp, level=acts.logging.ERROR
183 matMapDeco.setBinningMap(binMap)
186 del trackingGeometryTemp
196 events=events, numThreads=1, logLevel=acts.logging.INFO
206 format=JsonFormat.Cbor,
208 readCachedSurfaceInformation=readCachedSurfaceInformation,
219 datetime.now().strftime(
"%H:%M:%S")
222 +
": second pass to compute the variance",
226 cborMap = os.path.join(pathExp, (mapName +
".cbor"))
227 matDecoVar = acts.IMaterialDecorator.fromFile(cborMap)
232 for decorator
in decoratorsVar:
233 s.addContextDecorator(decorator)
234 wb = WhiteBoard(acts.logging.ERROR)
235 context = AlgorithmContext(0, 0, wb)
236 for decorator
in decoratorsVar:
237 assert decorator.decorate(context) == ProcessCode.SUCCESS
240 reader = RootMaterialTrackReader(
241 level=acts.logging.ERROR,
242 collection=
"material-tracks",
246 "optimised-material-map_tracks.root"
247 if readCachedSurfaceInformation
248 else "geant4_material_tracks.root",
251 readCachedSurfaceInformation=readCachedSurfaceInformation,
254 stepper = StraightLineStepper()
255 mmAlgCfg = MaterialMapping.Config(context.geoContext, context.magFieldContext)
256 mmAlgCfg.trackingGeometry = trackingGeometryVar
257 mmAlgCfg.collection =
"material-tracks"
260 navigator = Navigator(
261 trackingGeometry=trackingGeometryVar,
262 resolveSensitive=
True,
263 resolveMaterial=
True,
267 surfaceCfg = SurfaceMaterialMapper.Config(
270 mapper = SurfaceMaterialMapper(
271 config=surfaceCfg, level=acts.logging.ERROR, propagator=propagator
273 mmAlgCfg.materialSurfaceMapper = mapper
276 navigator = Navigator(
277 trackingGeometry=trackingGeometryVar,
280 mapper = VolumeMaterialMapper(
281 level=acts.logging.ERROR, propagator=propagator, mappingStep=999
283 mmAlgCfg.materialVolumeMapper = mapper
285 mapping = MaterialMapping(level=acts.logging.ERROR, config=mmAlgCfg)
286 s.addAlgorithm(mapping)
294 binParameters = mapping.scoringParameters(key)
297 for parameters
in binParameters:
298 if parameters[1] != 0:
299 objective += parameters[0] * (1.0 + 1.0 / parameters[1])
302 objective = objective / nonZero
303 score[key] = [dict(name=
"surface_score", type=
"objective", value=objective)]
305 datetime.now().strftime(
"%H:%M:%S")
306 +
" Mapping over for job "
308 +
" : now sending score",
311 pipeResult.send(score)
316 del trackingGeometryVar
323 This function create an experiment for a given single surface
324 Due to how Orion is implemented only one DB can exist per job, this thus need to be call using pythons multiprocessing to circumvent the issue.
326 key : Id of the surface corresponding to this experiment
327 nbJobs : Total number of jobs to be executed simultaneously
328 pathDB : Path to the databases
329 pathResult : Path to write the result of the optimisation
330 pipeBin : Pipe use to send the experiment binning to the main python instance
331 pipeResult : Pipe to receive the result of the optimisation
332 doPloting : true if we want to plot the result of the optimisation and obtain the optimal material map
337 "name":
"database_" +
str(key),
339 "host": os.path.join(pathDB,
"database_" +
str(key) +
".pkl"),
347 "x":
"uniform(1, 240, discrete=True)",
348 "y":
"uniform(1, 240, discrete=True)",
351 experiments = build_experiment(
360 store = get_storage()
361 store.delete_trials(uid=experiments.id, where={
"status": {
"$ne":
"completed"}})
362 store.release_algorithm_lock(uid=experiments.id)
367 for job
in range(nbJobs):
368 trials[job] = experiments.suggest()
369 binMap[job] = (trials[job].params[
"x"], trials[job].params[
"y"])
371 datetime.now().strftime(
"%H:%M:%S")
372 +
" Binning for job "
376 +
" has been selected",
379 pipeBin.send(binMap[job])
381 datetime.now().strftime(
"%H:%M:%S")
382 +
" All binning for surface "
388 for job
in range(nbJobs):
389 score = pipeResult.recv()
391 datetime.now().strftime(
"%H:%M:%S")
392 +
" Received score for job "
398 experiments.observe(trials[job], score)
400 datetime.now().strftime(
"%H:%M:%S")
405 +
" has been written",
412 datetime.now().strftime(
"%H:%M:%S")
413 +
" All the jobs are over. Now creating the optimisation plots",
417 pathExpSurface = os.path.join(pathResult,
"b_" +
str(key))
418 if not os.path.isdir(pathExpSurface):
419 os.makedirs(pathExpSurface)
421 regret = experiments.plot.regret()
422 regret.write_html(pathExpSurface +
"/regret.html")
424 parallel_coordinates = experiments.plot.parallel_coordinates()
425 parallel_coordinates.write_html(pathExpSurface +
"/parallel_coordinates.html")
427 lpi = experiments.plot.lpi()
428 lpi.write_html(pathExpSurface +
"/lpi.html")
430 partial_dependencies = experiments.plot.partial_dependencies()
431 partial_dependencies.write_html(pathExpSurface +
"/partial_dependencies.html")
434 df = experiments.to_pandas()
435 best = df.iloc[df.objective.idxmin()]
437 datetime.now().strftime(
"%H:%M:%S")
438 +
" Best score for surface "
444 resultBinMap = (best.x, best.y)
445 pipeBin.send(resultBinMap)
448 if "__main__" == __name__:
450 print(datetime.now().strftime(
"%H:%M:%S") +
" Starting")
452 parser = argparse.ArgumentParser()
454 "--numberOfJobs", nargs=
"?", default=2, type=int
457 "--topNumberOfEvents", nargs=
"?", default=100, type=int
460 "--inputPath", nargs=
"?", default=os.getcwd(), type=str
463 "--outputPath", nargs=
"?", default=
"", type=str
466 "--doPloting", action=
"store_true"
469 "--readCachedSurfaceInformation", action=
"store_true"
471 parser.set_defaults(doPloting=
False)
472 parser.set_defaults(readCachedSurfaceInformation=
False)
473 args = parser.parse_args()
476 pathExp = os.path.join(args.outputPath,
"Mapping")
477 pathDB = os.path.join(pathExp,
"Database")
478 pathResult = os.path.join(pathExp,
"Result")
479 if not os.path.isdir(pathExp):
481 if not os.path.isdir(pathDB):
483 if not os.path.isdir(pathResult):
484 os.makedirs(pathResult)
487 matDeco = acts.IMaterialDecorator.fromFile(
488 str(os.path.join(args.inputPath,
"geometry-map.json"))
495 matMapDeco = acts.MappingMaterialDecorator(
496 tGeometry=trackingGeometry, level=acts.logging.WARNING
498 binDict = matMapDeco.binningMap()
499 del detector, decorators
502 from multiprocessing
import Process, Pipe
504 binPipes_child = dict()
505 resultPipes_child = dict()
506 scorePipes_child = dict()
508 binPipes_parent = dict()
509 resultPipes_parent = dict()
510 scorePipes_parent = dict()
519 binPipes_parent[key], binPipes_child[key] =
Pipe()
520 scorePipes_parent[key], scorePipes_child[key] =
Pipe()
521 expJob[key] = Process(
522 target=surfaceExperiment,
529 scorePipes_child[key],
536 for job
in range(args.numberOfJobs):
537 resultPipes_parent[job], resultPipes_child[job] =
Pipe()
541 binMap[key] = binPipes_parent[key].recv()
543 datetime.now().strftime(
"%H:%M:%S")
544 +
" Binning for job "
546 +
" have been selected, now running the mapping",
550 OptiJob[job] = Process(
551 target=runMaterialMappingVariance,
554 args.topNumberOfEvents,
558 resultPipes_child[job],
559 args.readCachedSurfaceInformation,
565 for job
in range(args.numberOfJobs):
566 scores = resultPipes_parent[job].recv()
568 datetime.now().strftime(
"%H:%M:%S")
569 +
" Retried score for job "
575 scorePipes_parent[key].send(score)
577 datetime.now().strftime(
"%H:%M:%S")
588 datetime.now().strftime(
"%H:%M:%S")
589 +
" Running the material mapping to obtain the optimised material map",
592 resultBinMap = dict()
594 resultBinMap[key] = binPipes_parent[key].recv()
595 matMapDeco.setBinningMap(resultBinMap)
604 events=args.topNumberOfEvents, numThreads=1, logLevel=acts.logging.INFO
608 from material_mapping
import runMaterialMapping
611 resultTrackingGeometry,
613 outputDir=args.outputPath,
614 inputDir=args.inputPath,
615 mapName=
"optimised-material-map",
616 format=JsonFormat.Json,
622 del resultDetector, resultTrackingGeometry, resultDecorators
624 datetime.now().strftime(
"%H:%M:%S")
625 +
" Waiting for all the score to have been stored",
630 deadline = time.time() + 600
633 timeout = max(deadline - time.time(), 0)
634 expJob[key].
join(timeout=timeout)
635 expJob[key].terminate()
637 datetime.now().strftime(
"%H:%M:%S")
638 +
" Experiment for surface "