@@ -64,6 +64,8 @@ def default(self, obj):
6464 return {"__dataframe__" : True , "content" : obj .to_dict (orient = "list" )}
6565 if isinstance (obj , pd .Series ):
6666 return {"__series__" : True , "content" : obj .to_dict ()}
67+ if isinstance (obj , np .random .Generator ):
68+ return encode_numpy_random_generator (obj )
6769 if inspect .isfunction (obj ):
6870 return {
6971 "__function__" : True ,
@@ -133,6 +135,30 @@ def encode_astropy_unit(obj):
133135 return obj
134136
135137
138+ def encode_numpy_random_generator (generator ):
139+ """Encode a numpy random generator to a dictionary.
140+
141+ Adds the key :code:`__numpy_random_generator__` to the dictionary to indicate
142+ that the object is a numpy random generator.
143+
144+ The :code:`bit_generator_state` key contains the state of the bit generator
145+ including its name.
146+
147+ .. versionadded:: 2.5.0
148+ """
149+ state = generator .bit_generator .state
150+ # The state and inc integers are converted to strings to avoid issues with
151+ # arbitrary precision integers when encoding to HDF5.
152+ # We list them explicitly to avoid issues that may arise if the numpy
153+ # random generator changes its state representation.
154+ state ["state" ]["state" ] = str (state ["state" ]["state" ])
155+ state ["state" ]["inc" ] = str (state ["state" ]["inc" ])
156+ return {
157+ "__numpy_random_generator__" : True ,
158+ "bit_generator_state" : state ,
159+ }
160+
161+
136162def decode_astropy_cosmology (dct ):
137163 """Decode an astropy cosmology from a dictionary.
138164
@@ -217,6 +243,30 @@ def decode_astropy_unit(dct):
217243 return dct
218244
219245
246+ def decode_numpy_random_generator (dct ):
247+ """Decode a numpy random generator from a dictionary.
248+
249+ .. versionadded:: 2.5.0
250+ """
251+ try :
252+ bit_generator = getattr (np .random , dct ["bit_generator_state" ]["bit_generator" ])
253+ except AttributeError as e :
254+ raise ValueError (
255+ f"Unknown numpy bit generator { dct ['bit_generator_state' ]['bit_generator' ]} . "
256+ "The bit generator must be a numpy.random.Generator."
257+ f"Original error: { e } "
258+ ) from e
259+ # Convert the state and inc integers back to integers
260+ dct ["bit_generator_state" ]["state" ]["state" ] = \
261+ int (dct ["bit_generator_state" ]["state" ]["state" ])
262+ dct ["bit_generator_state" ]["state" ]["inc" ] = \
263+ int (dct ["bit_generator_state" ]["state" ]["inc" ])
264+
265+ generator = np .random .Generator (bit_generator ())
266+ generator .bit_generator .state = dct ["bit_generator_state" ]
267+ return generator
268+
269+
220270def load_json (filename , gzip ):
221271 if gzip or os .path .splitext (filename )[1 ].lstrip ("." ) == "gz" :
222272 import gzip
@@ -252,6 +302,8 @@ def decode_bilby_json(dct):
252302 cls = Prior
253303 obj = cls (** dct ["kwargs" ])
254304 return obj
305+ if dct .get ("__numpy_random_generator__" , False ):
306+ return decode_numpy_random_generator (dct )
255307 if dct .get ("__cosmology__" , False ):
256308 return decode_astropy_cosmology (dct )
257309 if dct .get ("__astropy_quantity__" , False ):
@@ -372,6 +424,8 @@ def encode_for_hdf5(key, item):
372424 item = np .array (item , dtype = 'S' )
373425 if isinstance (item , (np .ndarray , int , float , complex , str , bytes )):
374426 output = item
427+ elif isinstance (item , np .random .Generator ):
428+ output = encode_numpy_random_generator (item )
375429 elif item is None :
376430 output = "__none__"
377431 elif isinstance (item , list ):
@@ -434,6 +488,8 @@ def decode_hdf5_dict(output):
434488 output = decode_astropy_quantity (output )
435489 elif "__astropy_unit__" in output :
436490 output = decode_astropy_unit (output )
491+ elif "__numpy_random_generator__" in output :
492+ output = decode_numpy_random_generator (output )
437493 return output
438494
439495
0 commit comments