<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def timecalMs1DataMedian(msrunContainer, specfile, calibrationData, minDataPoints=50, deviationKey='relDev'):
 """Generates a calibration value for each MS1 scan by calculating the median deviation :param msrunContainer: intance of :class:`maspy.core.MsrunContainer` :param specfile: filename of an ms-run file, used to generate an calibration value for each MS1 spectrum item. :param calibrationData: a dictionary of ``numpy.arrays`` containing calibration data, as returned by :func:`aquireMs1CalibrationData()` :param minDataPoints: The minimal number of data points necessary to calculate the calibration value, default value is "50". The calibration value for each scan is calulated as the median of all calibration data points present for this scan. However, if the number of data points is less then specified by ``minDataPoints` the data points of the preceeding and subsequent scans are added until the minimal number of data points is reached. :param deviationKey: the ``calibrationData`` key which contains the calibration data that should be used. :returns: a dictionary containing the calibration values for each MS1 ``Si``. ``{si.id: {'calibValue': float, 'n': int, 'data': list}`` """

    corrData = dict()
    _posDict = dict()
    pos = 0
    for si in msrunContainer.getItems(specfiles=specfile, sort='rt',
                                      selector=lambda si: si.msLevel==1
                                      ):
        corrData[si.id] =  {'calibValue': float(), 'n': int(), 'data': list()}
        _posDict[pos] = si.id
        pos += 1

    for siId, deviation in zip(calibrationData['siId'],
                               calibrationData[deviationKey]):
        corrData[siId]['data'].append(deviation)
        corrData[siId]['n'] += 1

    for pos in range(len(corrData)):
        entry = corrData[_posDict[pos]]

        _data = [entry['data']]
        _n = entry['n']
        expansion = 0
        while _n < minDataPoints:
            expansion += 1
            try:
                expData = corrData[_posDict[pos+expansion]]['data']
                _data.append(expData)
                _n += corrData[_posDict[pos+expansion]]['n']
            except KeyError:
                pass
            try:
                expData = corrData[_posDict[pos-expansion]]['data']
                _data.append(expData)
                _n += corrData[_posDict[pos-expansion]]['n']
            except KeyError:
                pass

        if len(entry['data']) > 0:
            median = numpy.median(entry['data'])
            factor = 1
        else:
            median = float()
            factor = 0

        for expData in _data[1:]:
            if len(expData) > 0:
                median += numpy.median(expData) * 0.5
                factor += 0.5
        median = median / factor
        entry['calibValue'] = median
    return corrData