This PR adds the ability to recast a galsim.BaseDeviate object as a numpy.Generator. I allow this via rng.as_numpy_generator(), for people who prefer verbose methods for this kind of thing. And a quick and dirty rng.np property for people who prefer an abbreviated syntax. I think I'll prefer the latter, but they do the same thing, so to each their own.
This took me a while to figure out, since the documentation for making your own numpy.random.BitGenerator is pretty spare. And the primary source for all this is done in cython, which I didn't want to deal with on our end.
But it turns out not to be that hard once I figured out how everything works. You basically just let the numpy base class make all the initial stuff. Then you overwrite the elements of the capsule's bitgen_t struct with the functions you actually want to use. And there are only three functions returning uint32_t, uint64_t and double. So those are pretty easy. I was almost surprised when it actually worked for me. (To be fair, this was attempt number 30 or so, so I'd gotten used to failing by that point.)
I also updated a few places in the code to use the new numpy syntax, where I thought the numpy syntax was clearly superior. (Including the recent PR's of @jmeyers314 which prompted this effort.)
This PR adds the ability to recast a
galsim.BaseDeviate
object as anumpy.Generator
. I allow this viarng.as_numpy_generator()
, for people who prefer verbose methods for this kind of thing. And a quick and dirtyrng.np
property for people who prefer an abbreviated syntax. I think I'll prefer the latter, but they do the same thing, so to each their own.This took me a while to figure out, since the documentation for making your own numpy.random.BitGenerator is pretty spare. And the primary source for all this is done in cython, which I didn't want to deal with on our end.
But it turns out not to be that hard once I figured out how everything works. You basically just let the numpy base class make all the initial stuff. Then you overwrite the elements of the
capsule
'sbitgen_t
struct with the functions you actually want to use. And there are only three functions returninguint32_t
,uint64_t
anddouble
. So those are pretty easy. I was almost surprised when it actually worked for me. (To be fair, this was attempt number 30 or so, so I'd gotten used to failing by that point.)I also updated a few places in the code to use the new numpy syntax, where I thought the numpy syntax was clearly superior. (Including the recent PR's of @jmeyers314 which prompted this effort.)