def METHOD_NAME(num, period, filename):
    """
    num (int or None): if None, will never stop, unless interrupted
    """
    # Find components by their role
    ccd = model.getComponent(role="ccd")
    ebeam = model.getComponent(role="e-beam")
    sed = model.getComponent(role="se-detector")
    light = model.getComponent(role="light")
    light_filter = model.getComponent(role="filter")
    stage = model.getComponent(role="stage")
    focus = model.getComponent(role="focus")
    # Prepare the streams and acquisition manager
    # The settings of the emissions and excitation are based on the current
    # hardware settings.
    stfm = stream.FluoStream("Fluorescence image", ccd, ccd.data, light, light_filter)
    # Force the excitation light using that command:
    # stfm.excitation.value = (4.72e-07, 4.79e-07, 4.85e-07, 4.91e-07, 4.97e-07)
    stem = stream.SEMStream("Secondary electrons", sed, sed.data, ebeam)
    # Special stream that will run the overlay and update the metadata based on this
    # Note: if more complex overlay is needed (eg, with background subtraction,
    # or with saving the CCD image), we'd need to directly call FindOverlay())
    stovl = stream.OverlayStream("Overlay", ccd, ebeam, sed)
    stovl.dwellTime.value = OVERLAY_DT
    acq_streams = [stem, stfm, stovl]
    # Prepare to save each acquisition in a separate file
    exporter = dataio.find_fittest_converter(filename)
    basename, ext = os.path.splitext(filename)
    fn_pattern = basename + "%04d" + ext
    fn_pos = basename + "pos.csv"
    fpos = open(fn_pos, "a")
    fpos.write("time\tX\tY\tZ\n")
    # Run acquisition every period
    try:
        i = 1
        while True:
            logging.info("Acquiring image %d", i)
            start = time.time()
            # Acquire all the images
            f = acqmng.acquire(acq_streams)
            data, e = f.result()
            if e:
                logging.error("Acquisition failed with %s", e)
                # It can partially fail, so still allow to save the data successfully acquired
            # Note: the actual time of the position is the one when the position was read
            # by the pigcs driver.
            spos = stage.position.value
            fpos.write("%.20g\t%g\t%g\t%g\n" %
                       (time.time(), spos["x"], spos["y"], focus.position.value["z"]))
            # Save the file
            if data:
                exporter.export(fn_pattern % (i,), data)
            # TODO: run autofocus from time to time?
            left = period - (time.time() - start)
            if left < 0:
                logging.warning("Acquisition took longer than the period (%g s overdue)", -left)
            else:
                logging.info("Sleeping for another %g s", left)
                time.sleep(left)
            if i == num:  # will never be True if num is None
                break
            i += 1
    except KeyboardInterrupt:
        logging.info("Closing after only %d images acquired", i)
    except Exception:
        logging.exception("Failed to acquire all the images.")
        raise
    fpos.close()