<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _read_erd(erd_file, begsam, endsam):
 """Read the raw data and return a matrix, converted to microvolts. Parameters erd_file : str one of the .erd files to read begsam : int index of the first sample to read endsam : int index of the last sample (excluded, per python convention) Returns ------- numpy.ndarray 2d matrix with the data, as read from the file Error ----- It checks whether the event byte (the first byte) is x00 as expected. It can also be x01, meaning that an event was generated by an external trigger. According to the manual, "a photic stimulator is the only supported device which generates an external trigger." If the eventbyte is something else, it throws an error. Notes ----- Each sample point consists of these parts: - Event Byte - Frequency byte (only if file_schema >= 8 and one chan has != freq) - Delta mask (only if file_schema >= 8) - Delta Information - Absolute Channel Values Event Byte: Bit 0 of the event byte indicates the presence of the external trigger during the sample period. It's very rare. Delta Mask: Bit-mask of a size int( number_of_channels / 8 + 0.5). Each 1 in the mask indicates that corresponding channel has 2*n bit delta, 0 means that corresponding channel has n bit delta. The rest of the byte of the delta mask is filled with "1". If file_schema <= 7, it generates a "fake" delta, where everything is 0. Some channels are shorted (i.e. not recorded), however they are stored in a non-intuitive way: deltamask takes them into account, but for the rest they are never used/recorded. So, we need to keep track both of all the channels (including the non-shorted) and of the actual channels only. When we save the data as memory-mapped, we only save the real channels. However, the data in the output have both shorted and non-shorted channels. Shorted channels have NaN's only. About the actual implementation, we always follow the python convention that the first sample is included and the last sample is not. """

    hdr = _read_hdr_file(erd_file)
    n_allchan = hdr['num_channels']
    shorted = hdr['shorted']  # does this exist for Schema 7 at all?
    n_shorted = sum(shorted)
    if n_shorted > 0:
        raise NotImplementedError('shorted channels not tested yet')

    if hdr['file_schema'] in (7,):
        abs_delta = b'\x80'  # one byte: 10000000
        raise NotImplementedError('schema 7 not tested yet')

    if hdr['file_schema'] in (8, 9):
        abs_delta = b'\xff\xff'

    n_smp = endsam - begsam
    data = empty((n_allchan, n_smp))
    data.fill(NaN)

    # it includes the sample in both cases
    etc = _read_etc(erd_file.with_suffix('.etc'))
    all_beg = etc['samplestamp']
    all_end = etc['samplestamp'] + etc['sample_span'] - 1

    try:
        begrec = where((all_end >= begsam))[0][0]
        endrec = where((all_beg < endsam))[0][-1]
    except IndexError:
        return data

    with erd_file.open('rb') as f:
        for rec in range(begrec, endrec + 1):

            # [begpos_rec, endpos_rec]
            begpos_rec = begsam - all_beg[rec]
            endpos_rec = endsam - all_beg[rec]

            begpos_rec = max(begpos_rec, 0)
            endpos_rec = min(endpos_rec, all_end[rec] - all_beg[rec] + 1)

            # [d1, d2)
            d1 = begpos_rec + all_beg[rec] - begsam
            d2 = endpos_rec + all_beg[rec] - begsam

            dat = _read_packet(f, etc['offset'][rec], endpos_rec, n_allchan,
                               abs_delta)
            data[:, d1:d2] = dat[:, begpos_rec:endpos_rec]


    # fill up the output data, put NaN for shorted channels
    if n_shorted > 0:
        full_channels = where(asarray([x == 0 for x in shorted]))[0]
        output = empty((n_allchan, n_smp))
        output.fill(NaN)
        output[full_channels, :] = data
    else:
        output = data

    factor = _calculate_conversion(hdr)
    return expand_dims(factor, 1) * output