audeering / audinterface

Generic interfaces for signal processing
https://audeering.github.io/audinterface/
Other
4 stars 0 forks source link

Suggested feature: `process_func_args` in `process_index()`etc. #156

Closed maxschmitt closed 4 months ago

maxschmitt commented 5 months ago
import audb
import audinterface
import numpy as np

def compute_stat(signal, sampling_rate, functional=np.mean):
    return functional(signal)

media = [
    'wav/03a01Fa.wav',
    'wav/03a01Nc.wav',
    'wav/16b10Wb.wav',
]
db = audb.load(
    'emodb',
    version='1.4.1',
    media=media,
)

for f in [np.mean, np.std]:
    interface = audinterface.Process(process_func=compute_stat,
                                     process_func_args={'functional': f})
    result = interface.process_index(db['emotion'].index)
    print(result)

If the behavior of the processing function can be controlled by arguments, it would be favorable to have an argument process_func_args also in .process_index(), .process_folder() etc.

The advantage might not become clear with this simple example, but consider a case where different processing functions are defined and corresponding audinterface objects are passed to other functions, where different indexes are processed with different process_func_args.

@hagenw

hagenw commented 5 months ago

Looks like this should be easy to implement. Basically, interface.process_index(..., process_func_args={...}) could temporarily overwrite the arguments provided when initializing the interface.

maxschmitt commented 5 months ago

Sounds good and would help to reduce code lines or global variables in some scripts.

hagenw commented 5 months ago

Would you expect that interface.process_index(..., process_func_args={...}) overwrites interafce.process_func_args and in following calls to the method it will use the new args, or should it only temporarily change them, and when calling the method again with process_func_args=None it uses the ones set when instantiating the interface object?

hagenw commented 5 months ago

BTW, as a workaround you can already overwrite interface.process_func_args before calling interface.process_*(). But this is not completely error free as under the hood we need to handle the special arguments idx, root, file if those are part of process_func(). So it seems we indeed should add a process_func_args argument to all the process_*() methods.

maxschmitt commented 5 months ago

Would you expect that interface.process_index(..., process_func_args={...}) overwrites interafce.process_func_args and in following calls to the method it will use the new args, or should it only temporarily change them, and when calling the method again with process_func_args=None it uses the ones set when instantiating the interface object?

The latter, this should be only a temporary overwrite.

BTW, as a workaround you can already overwrite interface.process_func_args before calling interface.process_*(). But this is not completely error free as under the hood we need to handle the special arguments idx, root, file if those are part of process_func(). So it seems we indeed should add a process_func_args argument to all the process_*() methods.

Yes, from my layman's perspective, this is the better solution, I think.

Changing temporarily in process_() might become an issue when calling it in parallel on different indexes, but this might be prevented by, e.g., blocking so that no other process_() can be run.