<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def from_agent_proto(agent_info_list, brain_params):
 """ Converts list of agent infos to BrainInfo. """

        vis_obs = []
        for i in range(brain_params.number_visual_observations):
            obs = [BrainInfo.process_pixels(x.visual_observations[i],
                                            brain_params.camera_resolutions[i]['blackAndWhite'])
                   for x in agent_info_list]
            vis_obs += [obs]
        if len(agent_info_list) == 0:
            memory_size = 0
        else:
            memory_size = max([len(x.memories) for x in agent_info_list])
        if memory_size == 0:
            memory = np.zeros((0, 0))
        else:
            [x.memories.extend([0] * (memory_size - len(x.memories))) for x in agent_info_list]
            memory = np.array([list(x.memories) for x in agent_info_list])
        total_num_actions = sum(brain_params.vector_action_space_size)
        mask_actions = np.ones((len(agent_info_list), total_num_actions))
        for agent_index, agent_info in enumerate(agent_info_list):
            if agent_info.action_mask is not None:
                if len(agent_info.action_mask) == total_num_actions:
                    mask_actions[agent_index, :] = [
                        0 if agent_info.action_mask[k] else 1 for k in range(total_num_actions)]
        if any([np.isnan(x.reward) for x in agent_info_list]):
            logger.warning("An agent had a NaN reward for brain " + brain_params.brain_name)
        if any([np.isnan(x.stacked_vector_observation).any() for x in agent_info_list]):
            logger.warning("An agent had a NaN observation for brain " + brain_params.brain_name)

        if len(agent_info_list) == 0:
            vector_obs = np.zeros(
                (0, brain_params.vector_observation_space_size * brain_params.num_stacked_vector_observations)
            )
        else:
            vector_obs = np.nan_to_num(
                np.array([x.stacked_vector_observation for x in agent_info_list])
            )
        brain_info = BrainInfo(
            visual_observation=vis_obs,
            vector_observation=vector_obs,
            text_observations=[x.text_observation for x in agent_info_list],
            memory=memory,
            reward=[x.reward if not np.isnan(x.reward) else 0 for x in agent_info_list],
            agents=[x.id for x in agent_info_list],
            local_done=[x.done for x in agent_info_list],
            vector_action=np.array([x.stored_vector_actions for x in agent_info_list]),
            text_action=[list(x.stored_text_actions) for x in agent_info_list],
            max_reached=[x.max_step_reached for x in agent_info_list],
            custom_observations=[x.custom_observation for x in agent_info_list],
            action_mask=mask_actions
        )
        return brain_info