<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def get_params_from_func(func: Callable, signature: Signature=None) -> Params: """Gets all parameters from a function signature. :param func: The function to inspect. :param signature: An inspect.Signature instance. :returns: A named tuple containing information about all, optional, required and logic function parameters. """

    if signature is None:
        # Check if the function already parsed the signature
        signature = getattr(func, '_doctor_signature', None)
        # Otherwise parse the signature
        if signature is None:
            signature = inspect.signature(func)

    # Check if a `req_obj_type` was provided for the function.  If so we should
    # derrive the parameters from that defined type instead of the signature.
    if getattr(func, '_doctor_req_obj_type', None):
        annotation = func._doctor_req_obj_type
        all_params = list(annotation.properties.keys())
        required = annotation.required
        optional = list(set(all_params) - set(required))
    else:
        # Required is a positional argument with no defualt value and it's
        # annotation must sub class SuperType.  This is so we don't try to
        # require parameters passed to a logic function by a decorator that are
        # not part of a request.
        required = [key for key, p in signature.parameters.items()
                    if p.default == p.empty and
                    issubclass(p.annotation, SuperType)]
        optional = [key for key, p in signature.parameters.items()
                    if p.default != p.empty]
        all_params = [key for key in signature.parameters.keys()]

    # Logic params are all parameters that are part of the logic signature.
    logic_params = copy(all_params)
    return Params(all_params, required, optional, logic_params)