def build_group_id(ad, desc_list, prettify=(), force_list=(), additional=None):
    """
    Builds a Group ID from information found in the descriptors. It takes a number
    of descriptor names, invokes and then concatenates their result (converted to string)
    to from a group ID.  Additional parameters can be passed to modify the result.

    Parameters
    ----------
    ad: AstroData
              An instance of `AstroData` derivative that the descriptors will be

    desc_list: list of str
              A list of descriptor names (order matters) which will be used to
              build the Group ID

    prettify: sequence/set of str
              Names of descriptors that need to be invoked with `pretty=True`

    force_list: sequence/set of str
              The descriptors named in this list will have their results coerced
              into a list, if they returned something else.

    additional: str
              Additional information that will be added verbatim at the end of
              the Group ID

    Returns
    -------
    A string with the group id
    """
    desc_object_string_list = []
    for descriptor in desc_list:
        desc_method = getattr(ad, descriptor)
        if descriptor in prettify or 'section' in descriptor:
            desc_object = desc_method(pretty=True)
        else:
            desc_object = desc_method()

        # Ensure we get a list, even if only looking at one extension
        if (descriptor in force_list and
                not isinstance(desc_object, list)):
            desc_object = [desc_object]

        # Convert descriptor to a string and store
        desc_object_string_list.append(str(desc_object))

    # Add in any none descriptor related information
    if additional is not None:
        desc_object_string_list.append(additional)

    # Create and return the final group_id string
    return '_'.join(desc_object_string_list)