def process_frame(run, frame, lm, cm):

    dm = DataMatrix(length=len(SUBJECTS))
    dm.frame = frame
    dm.sub = IntColumn
    dm.x = FloatColumn
    dm.y = FloatColumn
    dm.pupil = FloatColumn
    dm.luminance = FloatColumn
    dm.change = FloatColumn
    print('Run {}, frame {}'.format(run, frame))
    for row, sub in zip(dm, SUBJECTS):
        _dm = _get_subject_data(sub, run)
        _dm.pupil = ops.z(_dm.pupil)
        try:
            _row = (_dm.frame == frame)[0]
        except IndexError:
            continue
        row.sub = sub
        x = min(1279, max(0, _row.x))
        y = min(546, max(0, _row.y))
        if not x and not y:
            row.x = np.nan
            row.y = np.nan
            row.pupil = np.nan
            row.luminance = np.nan
            row.change = np.nan
        else:
            row.x = x
            row.y = y
            row.pupil = _row.pupil
            row.luminance = lm[int(y), int(x)]
            row.change = cm[int(y), int(x)]
    return dm
def merge_pupil(subject_run):

    subject, run = subject_run
    print(SRC_EYEGAZE.format(subject=subject, run=run))
    if '--clean' not in sys.argv and os.path.exists(
        DST.format(subject=subject, run=run)
    ):
        print('already done ...')
        return
    print('\treading ...')
    a = np.genfromtxt(
        SRC_EYEGAZE.format(subject=subject, run=run),
        delimiter='\t'
    )
    n_eyegaze = a.shape[0] // DOWNSAMPLE
    dm = DataMatrix(length=n_eyegaze)
    gazex = a[:, 0]
    gazey = a[:, 1]
    pupil = a[:, 2]
    print('\treconstructing blinks ...')
    pupil = srs.blinkreconstruct(pupil)
    pupil[pupil == 0] = np.nan
    print('\tgetting average luminance ...')
    luminance, change = video_timeseries(
        subject=subject,
        run=run,
        frames=a[:, 3]
    )
    print('\tdownsampling ...')
    frame = a[:, 3]
    dm.pupil_size = srs.downsample(pupil, DOWNSAMPLE, fnc=np.nanmedian)
    dm.luminance = srs.downsample(luminance, DOWNSAMPLE, fnc=np.nanmedian)
    dm.change = srs.downsample(change, DOWNSAMPLE, fnc=np.nanmedian)
    dm.sdgazex = srs.downsample(gazey, DOWNSAMPLE, fnc=np.nanstd)
    dm.sdgazey = srs.downsample(gazex, DOWNSAMPLE, fnc=np.nanstd)
    dm.start_frame = srs.downsample(frame, DOWNSAMPLE, fnc=np.nanmin)
    dm.end_frame = srs.downsample(frame, DOWNSAMPLE, fnc=np.nanmax)
    print('\twriting {}'.format(DST.format(subject=subject, run=run)))
    io.writetxt(dm, DST.format(subject=subject, run=run))