Repository: mne-tools/mne-bids

Issue:
Problems with conversion of BTI datasets
### Description of the problem

There are two problems with the conversion of BTI/4D data to BIDS format. The first is that if there is no headshape data, mne_bids.write_raw_bids will fail (in function copyfile_bti_mod). 

The second issue is both an MNE bids and an MNE issue - not sure if I should replicate this issue there? When reading in a 4D dataset, raw.__init_kwargs is correctly populated with the full path for the dataset, i.e.

raw._init_kwargs['pdf_fname'] = '/path_to_file/4D/c,rfDC'

but the field for the config file

raw._init_kwargs['config_fname'] = 'config'

Without the full path to the config file, copyfile_bti_mod will fail. 

### Steps to reproduce

```Python
#requires definition of the 'meg_fname' filepath and 'topdir' filepath

raw=mne.io.read_raw_bti(meg_fname, head_shape_fname=None, convert=False)
bids_path = BIDSPath(subject=subjid, session='1', task='rest',
                    run='01', root=topdir, suffix='meg')
write_raw_bids(raw, bids_path, overwrite=True)
```


### Expected results

I expect it to copy the files to the BIDS directory rather than erroring out

### Actual results

### Error because full path for config file is not specified:

Traceback (most recent call last):

  Cell In[7], line 48
    write_raw_bids(raw, bids_path, overwrite=True)

  File <decorator-gen-640>:12 in write_raw_bids

  File ~/mambaforge/envs/enigma_meg/lib/python3.11/site-packages/mne_bids/write.py:1979 in write_raw_bids
    copyfile_bti(raw_orig, raw_dir)

  File ~/mambaforge/envs/enigma_meg/lib/python3.11/site-packages/mne_bids/copyfiles.py:600 in copyfile_bti
    sh.copyfile(raw._init_kwargs['config_fname'],

  File ~/mambaforge/envs/enigma_meg/lib/python3.11/shutil.py:256 in copyfile
    with open(src, 'rb') as fsrc:

FileNotFoundError: [Errno 2] No such file or directory: 'config'

### Additional information

Using mne version 1.4.2 and mne-bids 0.12


Discussion:
Hello! 👋 Thanks for opening your first issue here! ❤️ We will try to get back to you soon. 🚴🏽‍♂️

Hi, thanks for the report!

> The second issue is both an MNE bids and an MNE issue - not sure if I should replicate this issue there? When reading in a 4D dataset, raw.__init_kwargs is correctly populated with the full path for the dataset, i.e.

please open an MNE-Python issue on the MNE-Python repository 👍 

> The first is that if there is no headshape data, mne_bids.write_raw_bids will fail (in function copyfile_bti_mod).

why do you not have a headshape file for your data? Have you had a look at the mne-bids codebase to identify the potential problem?
This is HCP data that I'm trying to get into a format resembling BIDS. Since the HCP did not distribute the data with the headshape or the locations of the fiducial points, I'm limited to organizing the data more-or-less in BIDS format with the -trans.fif file for coregistration. It will make it easier for me to modify software designed to work on BIDS format data if I have the HCP data in something close to BIDS. 
Oh - and in response to the suggestion of identifying the source of the problem in the mne-bids codebase, it's just that copyfile_bti fails on line 602 of copyfiles.py:

```python
sh.copyfile(raw._init_kwargs['head_shape_fname'],
                    op.join(dest, 'hs_file'))
```

It returns an error that sh.copyfile cannot accept an argument of type None. 

Resolving patch:
diff --git a/mne_bids/copyfiles.py b/mne_bids/copyfiles.py
--- a/mne_bids/copyfiles.py
+++ b/mne_bids/copyfiles.py
@@ -22,7 +22,6 @@
 
 from scipy.io import loadmat, savemat
 
-import mne
 from mne.io import read_raw_brainvision, read_raw_edf, read_raw_bdf, anonymize_info
 from mne.utils import logger, verbose
 
@@ -539,9 +538,6 @@ def copyfile_eeglab(src, dest):
     copyfile_kit
 
     """
-    if not mne.utils.check_version("scipy", "1.5.0"):  # pragma: no cover
-        raise ImportError("SciPy >=1.5.0 is required handling EEGLAB data.")
-
     # Get extension of the EEGLAB file
     _, ext_src = _parse_ext(src)
     fname_dest, ext_dest = _parse_ext(dest)
@@ -625,4 +621,8 @@ def copyfile_bti(raw, dest):
         pdf_fname = "c,rf%0.1fHz" % raw.info["highpass"]
     sh.copyfile(raw._init_kwargs["pdf_fname"], op.join(dest, pdf_fname))
     sh.copyfile(raw._init_kwargs["config_fname"], op.join(dest, "config"))
-    sh.copyfile(raw._init_kwargs["head_shape_fname"], op.join(dest, "hs_file"))
+
+    # If no headshape file present, cannot copy it
+    hs_file = raw._init_kwargs.get("head_shape_fname")
+    if hs_file is not None:  # pragma: no cover
+        sh.copyfile(hs_file, op.join(dest, "hs_file"))
diff --git a/mne_bids/inspect.py b/mne_bids/inspect.py
--- a/mne_bids/inspect.py
+++ b/mne_bids/inspect.py
@@ -11,17 +11,8 @@
 import mne
 
 from mne.utils import logger, verbose
-from mne.fixes import _compare_version
 from mne.viz import use_browser_backend
-
-if _compare_version(mne.__version__, "<", "1.0.dev0"):  # pragma: no cover
-    from mne.preprocessing import annotate_flat
-
-    _annotate_flat_func = annotate_flat
-else:
-    from mne.preprocessing import annotate_amplitude
-
-    _annotate_flat_func = annotate_amplitude
+from mne.preprocessing import annotate_amplitude
 
 from mne_bids import read_raw_bids, mark_channels
 from mne_bids.read import _from_tsv, _read_events
@@ -151,12 +142,9 @@ def _inspect_raw(*, bids_path, l_freq, h_freq, find_flat, show_annotations):
 
     if find_flat:
         raw.load_data()  # Speeds up processing dramatically
-        if _annotate_flat_func.__name__ == "annotate_amplitude":
-            flat_annot, flat_chans = annotate_amplitude(
-                raw=raw, flat=0, min_duration=0.05, bad_percent=5
-            )
-        else:  # pragma: no cover
-            flat_annot, flat_chans = annotate_flat(raw=raw, min_duration=0.05)
+        flat_annot, flat_chans = annotate_amplitude(
+            raw=raw, flat=0, min_duration=0.05, bad_percent=5
+        )
         new_annot = raw.annotations + flat_annot
         raw.set_annotations(new_annot)
         raw.info["bads"] = list(set(raw.info["bads"] + flat_chans))


Test patch: