ehpor / hcipy

A framework for performing optical propagation simulations, meant for high contrast imaging, in Python.
https://hcipy.org
MIT License
93 stars 31 forks source link

The random function in the deformable mirror is not functioning properly #203

Open Oswald522 opened 1 year ago

Oswald522 commented 1 year ago

When using dm.random(rms), it does not return a consistent surface with the specified RMS value. The source code is located in deformable_mirror.py and needs the following modifications:

# deformable_mirror.py
 def random(self, rms):
        '''Set the dm actuators with random white noise of a certain rms.

        Parameters
        ----------
        rms : scalar
            The dm surface rms.
        '''
        self._actuators = np.random.randn(self._actuators.size) 
     # add this line
        self._actuators *= (rms)/np.std(self.surface))
    # or this line
        self._actuators *= (rms)/np.sqrt(np.mean(self.surface**2))
ehpor commented 1 year ago

While the code does exactly what we intended it to do, I agree that your version is way more useful and I'm totally for changing this. I think the way to do is, is to use a different name for the new function and leave the old function as is (or even deprecate it?). I want to add a few more features to the new function.

We can also add the second and third points to the existing function, which would be a reason to not deprecate it. So the new function signatures would be:

def random(self, rms, seed=None):
    '''Set the DM actuators with random white noise of a certain RMS.

    Parameters
    -----------
    rms : scalar or ndarray
        The RMS per actuator. If this is a scalar, the same RMS will be used for all actuators.
    seed : None, int, ndarray of ints, SeedSequence, BitGenerator or Generator
        A seed to use for the random noise. If this is a noise generator, this will be used as the source of the noise.
    '''

def random_surface(self, surface_rms, rms_distribution=None, std_weights=None, seed=None):
    '''Set the DM to a random surface with a certain RMS.

    Parameters
    -----------
    surface_rms : scalar
        The requested RMS of the DM surface.
    rms_distribution : ndarray or None

    std_weights : Field or None
        The weights to use for the surface RMS. If this is None (default), then the surface will be weighted equally.
    seed : None, int, ndarray of ints, SeedSequence, BitGenerator or Generator
        A seed to use for the random noise. If this is a noise generator, this will be used as the source of the noise.
    '''

BTW, I don't like normalizing the surface after the fact. This results in a surface that is always exactly the requested RMS, but that wouldn't happen naturally. Naturally, there is a bit of variation in the RMS. So you'd have to precompute the normalization factor in advance, and not post-facto.

ehpor commented 1 year ago

@Oswald522 Do you want to take a first stab at this? You can create a PR and put me as reviewer.