Check whether a single field is valid in its basic form. Does
        not check compatibility with other fields.

        Parameters
        ----------
        field : str
            The field name
        required_channels : list, optional
            Used for signal specification fields. All channels are
            checked for their integrity if present, but channels that do
            not lie in this field may be None.

        Notes
        -----
        This function is called from wrheader to check fields before
        writing. It is also supposed to be usable at any point to
        check a specific field.

def check_field(self, field, required_channels='all'):
        """
        Check whether a single field is valid in its basic form. Does
        not check compatibility with other fields.

        Parameters
        ----------
        field : str
            The field name
        required_channels : list, optional
            Used for signal specification fields. All channels are
            checked for their integrity if present, but channels that do
            not lie in this field may be None.

        Notes
        -----
        This function is called from wrheader to check fields before
        writing. It is also supposed to be usable at any point to
        check a specific field.

        """
        item = getattr(self, field)
        if item is None:
            raise Exception('Missing field required: %s' % field)

        # We should have a list specifying these automatically.

        # Whether the item should be a list. Watch out for required_channels for `segments`
        expect_list = True if field in LIST_FIELDS else False

        # Check the type of the field (and of its elements if it should
        # be a list)
        _check_item_type(item, field_name=field,
                        allowed_types=ALLOWED_TYPES[field],
                        expect_list=expect_list,
                        required_channels=required_channels)

        # Individual specific field checks

        if field in ['d_signal', 'p_signal']:
            check_np_array(item=item, field_name=field, ndim=2,
                           parent_class=(lambda f: np.integer if f == 'd_signal' else np.floating)(field))
        elif field in ['e_d_signal', 'e_p_signal']:
            for ch in range(len(item)):
                check_np_array(item=item[ch], field_name=field,
                               ndim=1, parent_class=(lambda f: np.integer if f == 'e_d_signal' else np.floating)(field),
                               channel_num=ch)

        # Record specification fields

        elif field == 'record_name':
            # Allow letters, digits, hyphens, and underscores.
            accepted_string = re.match('[-\w]+', self.record_name)
            if not accepted_string or accepted_string.string != self.record_name:
                raise ValueError('record_name must only comprise of letters, digits, hyphens, and underscores.')
        elif field == 'n_seg':
            if self.n_seg <= 0:
                raise ValueError('n_seg must be a positive integer')
        elif field == 'n_sig':
            if self.n_sig <= 0:
                raise ValueError('n_sig must be a positive integer')
        elif field == 'fs':
            if self.fs <= 0:
                raise ValueError('fs must be a positive number')
        elif field == 'counter_freq':
            if self.counter_freq <= 0:
                raise ValueError('counter_freq must be a positive number')
        elif field == 'base_counter':
            if self.base_counter <= 0:
                raise ValueError('base_counter must be a positive number')
        elif field == 'sig_len':
            if self.sig_len < 0:
                raise ValueError('sig_len must be a non-negative integer')

        # Signal specification fields
        elif field in _header.SIGNAL_SPECS.index:
            if required_channels == 'all':
                required_channels = range(len(item))

            for ch in range(len(item)):
                # If the element is allowed to be None
                if ch not in required_channels:
                    if item[ch] is None:
                        continue

                if field == 'file_name':
                    # Check for file_name characters
                    accepted_string = re.match('[-\w]+\.?[\w]+', item[ch])
                    if not accepted_string or accepted_string.string != item[ch]:
                        raise ValueError('File names should only contain alphanumerics, hyphens, and an extension. eg. record-100.dat')
                    # Check that dat files are grouped together
                    if not is_monotonic(self.file_name):
                        raise ValueError('Signals in a record that share a given file must be consecutive.')
                elif field == 'fmt':
                    if item[ch] not in _signal.DAT_FMTS:
                        raise ValueError('File formats must be valid WFDB dat formats:', _signal.DAT_FMTS)
                elif field == 'samps_per_frame':
                    if item[ch] < 1:
                        raise ValueError('samps_per_frame values must be positive integers')
                elif field == 'skew':
                    if item[ch] < 0:
                        raise ValueError('skew values must be non-negative integers')
                elif field == 'byte_offset':
                    if item[ch] < 0:
                        raise ValueError('byte_offset values must be non-negative integers')
                elif field == 'adc_gain':
                    if item[ch] <= 0:
                        raise ValueError('adc_gain values must be positive')
                elif field == 'baseline':
                    # Original WFDB library 10.5.24 only has 4 bytes for
                    # baseline.
                    if item[ch] < -2147483648 or item[ch] > 2147483648:
                        raise ValueError('baseline values must be between -2147483648 (-2^31) and 2147483647 (2^31 -1)')
                elif field == 'units':
                    if re.search('\s', item[ch]):
                        raise ValueError('units strings may not contain whitespaces.')
                elif field == 'adc_res':
                    if item[ch] < 0:
                        raise ValueError('adc_res values must be non-negative integers')
                elif field == 'block_size':
                    if item[ch] < 0:
                        raise ValueError('block_size values must be non-negative integers')
                elif field == 'sig_name':
                    if re.search('\s', item[ch]):
                        raise ValueError('sig_name strings may not contain whitespaces.')
                    if len(set(item)) != len(item):
                        raise ValueError('sig_name strings must be unique.')

        # Segment specification fields and comments
        elif field in _header.SEGMENT_SPECS.index:
            for ch in range(len(item)):
                if field == 'seg_name':
                    # Segment names must be alphanumerics or just a
                    # single '~'
                    if item[ch] == '~':
                        continue
                    accepted_string = re.match('[-\w]+', item[ch])
                    if not accepted_string or accepted_string.string != item[ch]:
                        raise ValueError("Non-null segment names may only contain alphanumerics and dashes. Null segment names must be set to '~'")
                elif field == 'seg_len':
                    # For records with more than 1 segment, the first
                    # segment may be the layout specification segment
                    # with a length of 0
                    min_len = 0 if ch == 0 else 1
                    if item[ch] < min_len:
                        raise ValueError('seg_len values must be positive integers. Only seg_len[0] may be 0 to indicate a layout segment')
                # Comment field
                elif field == 'comments':
                    if item[ch].startswith('#'):
                        print("Note: comment strings do not need to begin with '#'. This library adds them automatically.")
                    if re.search('[\t\n\r\f\v]', item[ch]):
                        raise ValueError('comments may not contain tabs or newlines (they may contain spaces and underscores).')