class_docstr: RawMff class.
docstr: Read a chunk of data.
docstr_tok: ["Read","a","chunk","of","data","."]
code: def _read_segment_file(self, data, idx, fi, start, stop, cals, mult):
      """Read a chunk of data."""
      logger.debug(f"Reading MFF {start:6d} ... {stop:6d} ...")
      dtype = "<f4"  # Data read in four byte floats.
  
      egi_info = self._raw_extras[fi]
      one = np.zeros((egi_info["kind_bounds"][-1], stop - start))
  
      # info about the binary file structure
      n_channels = egi_info["n_channels"]
      samples_block = egi_info["samples_block"]
  
      # Check how many channels to read are from each type
      bounds = egi_info["kind_bounds"]
      if isinstance(idx, slice):
          idx = np.arange(idx.start, idx.stop)
      eeg_out = np.where(idx < bounds[1])[0]
      eeg_one = idx[eeg_out, np.newaxis]
      eeg_in = idx[eeg_out]
      stim_out = np.where((idx >= bounds[1]) & (idx < bounds[2]))[0]
      stim_one = idx[stim_out]
      stim_in = idx[stim_out] - bounds[1]
      pns_out = np.where((idx >= bounds[2]) & (idx < bounds[3]))[0]
      pns_in = idx[pns_out] - bounds[2]
      pns_one = idx[pns_out, np.newaxis]
      del eeg_out, stim_out, pns_out
  
      # take into account events (already extended to correct size)
      one[stim_one, :] = egi_info["egi_events"][stim_in, start:stop]
  
      # Convert start and stop to limits in terms of the data
      # actually on disk, plus an indexer (disk_use_idx) that populates
      # the potentially larger `data` with it, taking skips into account
      disk_samps = egi_info["disk_samps"][start:stop]
      disk_use_idx = np.where(disk_samps > -1)[0]
      # short circuit in case we don't need any samples
      if not len(disk_use_idx):
          _mult_cal_one(data, one, idx, cals, mult)
          return
  
      start = disk_samps[disk_use_idx[0]]
      stop = disk_samps[disk_use_idx[-1]] + 1
      assert len(disk_use_idx) == stop - start
  
      # Get starting/stopping block/samples
      block_samples_offset = np.cumsum(samples_block)
      offset_blocks = np.sum(block_samples_offset <= start)
      offset_samples = start - (
          block_samples_offset[offset_blocks - 1]
          if offset_blocks > 0
          else 0
      )
  
      # TODO: Refactor this reading with the PNS reading in a single function
      # (DRY)
      samples_to_read = stop - start
      with open(self._filenames[fi], "rb", buffering=0) as fid:
          # Go to starting block
          current_block = 0
          current_block_info = None
          current_data_sample = 0
          while current_block < offset_blocks:
              this_block_info = _block_r(fid)
              if this_block_info is not None:
                  current_block_info = this_block_info
              fid.seek(current_block_info["block_size"], 1)
              current_block += 1
  
          # Start reading samples
          while samples_to_read > 0:
              logger.debug(f"    Reading from block {current_block}")
              this_block_info = _block_r(fid)
              current_block += 1
              if this_block_info is not None:
                  current_block_info = this_block_info
  
              to_read = (
                  current_block_info["nsamples"]
                  * current_block_info["nc"]
              )
              block_data = np.fromfile(fid, dtype, to_read)
              block_data = block_data.reshape(n_channels, -1, order="C")
  
              # Compute indexes
              samples_read = block_data.shape[1]
              logger.debug(f"        Read   {samples_read} samples")
              logger.debug(f"        Offset {offset_samples} samples")
              if offset_samples > 0:
                  # First block read, skip to the offset:
                  block_data = block_data[:, offset_samples:]
                  samples_read = samples_read - offset_samples
                  offset_samples = 0
              if samples_to_read < samples_read:
                  # Last block to read, skip the last samples
                  block_data = block_data[:, :samples_to_read]
                  samples_read = samples_to_read
              logger.debug(f"        Keep   {samples_read} samples")
  
              s_start = current_data_sample
              s_end = s_start + samples_read
  
              one[eeg_one, disk_use_idx[s_start:s_end]] = block_data[
                  eeg_in
              ]
              samples_to_read = samples_to_read - samples_read
              current_data_sample = current_data_sample + samples_read
  
      if len(pns_one) > 0:
          # PNS Data is present and should be read:
          pns_filepath = egi_info["pns_filepath"]
          pns_info = egi_info["pns_sample_blocks"]
          n_channels = pns_info["n_channels"]
          samples_block = pns_info["samples_block"]
  
          # Get starting/stopping block/samples
          block_samples_offset = np.cumsum(samples_block)
          offset_blocks = np.sum(block_samples_offset < start)
          offset_samples = start - (
              block_samples_offset[offset_blocks - 1]
              if offset_blocks > 0
              else 0
          )
  
          samples_to_read = stop - start
          with open(pns_filepath, "rb", buffering=0) as fid:
              # Check file size
              fid.seek(0, 2)
              file_size = fid.tell()
              fid.seek(0)
              # Go to starting block
              current_block = 0
              current_block_info = None
              current_data_sample = 0
              while current_block < offset_blocks:
                  this_block_info = _block_r(fid)
                  if this_block_info is not None:
                      current_block_info = this_block_info
                  fid.seek(current_block_info["block_size"], 1)
                  current_block += 1
  
              # Start reading samples
              while samples_to_read > 0:
                  if samples_to_read == 1 and fid.tell() == file_size:
                      # We are in the presence of the EEG bug
                      # fill with zeros and break the loop
                      one[pns_one, -1] = 0
                      break
  
                  this_block_info = _block_r(fid)
                  if this_block_info is not None:
                      current_block_info = this_block_info
  
                  to_read = (
                      current_block_info["nsamples"]
                      * current_block_info["nc"]
                  )
                  block_data = np.fromfile(fid, dtype, to_read)
                  block_data = block_data.reshape(
                      n_channels, -1, order="C"
                  )
  
                  # Compute indexes
                  samples_read = block_data.shape[1]
                  if offset_samples > 0:
                      # First block read, skip to the offset:
                      block_data = block_data[:, offset_samples:]
                      samples_read = samples_read - offset_samples
                      offset_samples = 0
  
                  if samples_to_read < samples_read:
                      # Last block to read, skip the last samples
                      block_data = block_data[:, :samples_to_read]
                      samples_read = samples_to_read
  
                  s_start = current_data_sample
                  s_end = s_start + samples_read
  
                  one[
                      pns_one, disk_use_idx[s_start:s_end]
                  ] = block_data[pns_in]
                  samples_to_read = samples_to_read - samples_read
                  current_data_sample = (
                      current_data_sample + samples_read
                  )
  
      # do the calibration
      _mult_cal_one(data, one, idx, cals, mult)
  
imports: import datetime
  import math
  import os.path
  import re
  from collections import OrderedDict
  from pathlib import Path
  import numpy
  from ..._fiff.constants import FIFF
  from ..._fiff.meas_info import _empty_info, _ensure_meas_date_none_or_dt, create_info
  from ..._fiff.proj import setup_proj
  from ..._fiff.utils import _create_chs, _mult_cal_one
  from ...annotations import Annotations
  from ...channels.montage import make_dig_montage
  from ...evoked import EvokedArray
  from ...utils import _check_fname, _check_option, _soft_import, logger, verbose, warn
  from ..base import BaseRaw
  from .events import _combine_triggers, _read_events
  from .general import _block_r, _extract, _get_blocks, _get_ep_info, _get_gains, _get_signalfname
label_desc: Use image node_id 2 for calling the RawMff obj's underlying member method code with example usage: obj._read_segment_file(data, idx, fi, start, stop, cals, mult) without return types