Gradient of the log likelihood function at y, given link(f) w.r.t link(f)

        .. math::

        :param link_f: latent variables (f)
        :type link_f: Nx1 array
        :param y: data
        :type y: Nx1 array
        :param Y_metadata: includes censoring information in dictionary key 'censored'
        :returns: gradient of likelihood evaluated at points
        :rtype: Nx1 array

def dlogpdf_dlink(self, link_f, y, Y_metadata=None):
        """
        Gradient of the log likelihood function at y, given link(f) w.r.t link(f)

        .. math::

        :param link_f: latent variables (f)
        :type link_f: Nx1 array
        :param y: data
        :type y: Nx1 array
        :param Y_metadata: includes censoring information in dictionary key 'censored'
        :returns: gradient of likelihood evaluated at points
        :rtype: Nx1 array

        """
        # c = Y_metadata['censored']
        # for debugging
        # c = np.zeros((y.shape[0],))
        c = np.zeros_like(link_f)

        if Y_metadata is not None and 'censored' in Y_metadata.keys():
            c = Y_metadata['censored']

        #y_link_f = y/link_f
        #y_link_f_r = y_link_f**self.r
        y_link_f_r = np.clip(y**self.r, 1e-150, 1e200) / np.clip(link_f**self.r, 1e-150, 1e200)

        #In terms of link_f
        # uncensored = (1-c)*( (2*self.r*y**r)/(link_f**self.r + y**self.r) - link_f*self.r)
        uncensored = (1-c)*self.r*(y_link_f_r - 1)/(link_f*(1 + y_link_f_r))
        censored = c*(self.r*y_link_f_r/(link_f*y_link_f_r + link_f))
        return uncensored + censored