[docs]defcheck(self):ifnothasattr(self.model,"agents"):Warning("Recorder: model expected to have a 'agents' attribute.")ifnothasattr(self.model,"patches"):Warning("Recorder: model expected to have a 'patches' attribute.")return
def__call__(self,model,tick:int)->None:# write the current state of the model to an HDF5 file if it is the last tick of the simulationiftick==(model.params.nticks-1):# To get output must a) specify hdf5_output = true in the params file and b) specify properties to returnwrite_output=(("hdf5_output"inmodel.params)andmodel.params.hdf5_outputand("return"inmodel.params)andmodel.params["return"])ifwrite_output:root=Path(model.params.outdir)if"outdir"inmodel.paramsandmodel.params.outdirelsePath.cwd()root.mkdir(parents=True,exist_ok=True)filename=root/f"{datetime.now().strftime('%Y%m%d%H%M%S')}.h5"# noqa: DTZ005if("compress"inmodel.params)andmodel.params.compress:filename=save_compressed_hdf5_parameters(model,filename)else:filename=save_hdf5_parameters(model,filename)logger.info(f"Recorder: model state saved to {filename}")else:logger.info("Recorder: model state not saved to HDF5 file.")logger.info(f"\t'hdf5_output' {'is'if'hdf5_output'inmodel.paramselse'is not'} in the params file."+(f" hdf5_output = {model.params.hdf5_output}"if"hdf5_output"inmodel.paramselse""))logger.info(f"\t'return' {'is'if'return'inmodel.paramselse'is not'} in the params file."+(f" return = {model.params['return']}"if"return"inmodel.paramselse""))return
[docs]defsave_hdf5_parameters(model,filename:Union[str,Path])->Path:# Step 1: Write HDF5 content to the filewithh5.File(filename,"w")ash5file:save_hdf5(h5file,model)returnfilename# Unmodified
[docs]defsave_compressed_hdf5_parameters(model,filename:Union[str,Path])->Path:# Step 1: Create an in-memory buffer for HDF5hdf5_buffer=io.BytesIO()# Step 2: Write HDF5 content to the bufferwithh5.File(hdf5_buffer,"w")ash5file:save_hdf5(h5file,model)# Step 3: Compress and save to diskfilename=filename.with_name(filename.name+".gz")withgzip.open(filename,"wb")asgz_file:gz_file.write(hdf5_buffer.getvalue())returnfilename# With .gz extension
[docs]defsave_hdf5(h5file:h5.File,model)->None:forframein["agents","patches"]:ifnothasattr(model,frame):raiseAttributeError(f"Recorder: model needs to have a '{frame}' attribute.")lf=getattr(model,frame)properties=dir(lf)# TODO - automagically write all properties if a subset is not specifiedproperties=[pforpinpropertiesifnotp.startswith("_")]properties=[pforpinpropertiesifnotisinstance(getattr(lf,p),(MethodType))]# TODO - if a subset is specified, don't bother with the filtering aboveproperties=[pforpinpropertiesifpinmodel.params["return"]]group=h5file.create_group(frame)forpropinproperties:logger.info(f"Recorder: saving {frame}.{prop} ...")group.create_dataset(prop,data=getattr(lf,prop))return