import importlib


def my_loss_fct(opts):
    """Selects and instantiates loss object according to parsed options.

    Selects function from the module optimization.loss_fcts with name
    opts.opts2loss_fct to instantiate loss object.

    Args:
        opts (obj): Namespace object with options. Required attribute is
            attribute opts.opts2loss_fct.
    
    Returns:
        my_loss (obj): Instantiated loss object.

    Raises:
        NotImplementedError: When no function with name opts.opts2loss_fct
            exists in module optimization.loss_fcts.
    """

       
    loss_fcts_import = 'optimization.loss_fcts'
    loss_fcts_lib = importlib.import_module(loss_fcts_import)
    
    #Pick loss function wrapper out of optimization.loss_fcts
    my_loss = None
    for name, fct in loss_fcts_lib.__dict__.items():
        if name == opts.opts2loss_fct:
            my_loss = fct(opts)

    if my_loss==None:
        raise NotImplementedError(
                """In {loss_fcts_import} is no function with name 
                {opts2loss_fct} implemented.""".format(
                    loss_fcts_import=loss_fcts_import, 
                    opts2loss_fct=opts.opts2loss_fct
                    )
                )

    print("""Loss object instantiated via function with name
            {opts2loss_fct} from module {loss_fcts_import}.""".format(
                opts2loss_fct=opts.opts2loss_fct,
                loss_fcts_import=loss_fcts_import
                )
            )
     

    return my_loss