Repository: mne-tools/mne-python

Issue:
[fNIRS] Misleading error message when the raw_data path does not exist
#### Describe the bug

When the path provided by the user does not exist (i.e. when the directory does not exist), the error message raised by the **RAWNirx** `__init__` function is 
```
RuntimeError: Expect one evt file, got 0
```

I think it should be something like 
```
RuntimeError: The path you specified does not exist
```
since the error is not about the existence of a file, but rather about the directory's

#### Steps to reproduce
Create a **RAWNirx** instance by reading the data of a non-existent directory :
```
fnirs_raw_dir = 'a/path/that/doesnt/exist'

raw_intensity = mne.io.read_raw_nirx(fnirs_raw_dir,
                                         verbose=True).load_data()
```

#### Expected results
The error message tells the user the path to the specified directory does not exist.


#### Actual results
The error message tells the user the specified directory lacks an `*.evt` file (since it is the first file extension that is checked) but not that the directory does not exist: the existence of the directory is not checked, which is misleading the user.


#### Additional information
Platform:        Windows-10-10.0.18362-SP0
Python:          3.8.3 (default, May 19 2020, 06:50:17) [MSC v.1916 64 bit (AMD64)]
Executable:     C:\Users\juliend\Anaconda3\envs\mne_dev\python.exe
CPU:              Intel64 Family 6 Model 58 Stepping 9, GenuineIntel: 8 cores
Memory:        15.6 GB

mne:              0.21.dev0
numpy:          1.18.1 {blas=mkl_rt, lapack=mkl_rt}
scipy:             1.4.1
matplotlib:     3.1.3 {backend=Qt5Agg}

sklearn:         0.22.1
numba:         0.49.1
nibabel:         3.1.0
cupy:             Not found
pandas:         1.0.3
dipy:             1.1.1
mayavi:        4.7.2.dev0
pyvista:        0.25.3
vtk:              9.0.0
PyQt5:         5.9.2

\-\-

Please note that adding
```
if not op.exists(fname):
    raise RuntimeError('The path you specified does not exist.')
```
or
```
if not op.isdir(fname):
    raise RuntimeError('The path you specified does not exist.')
```
at the start of `__init` function of **RAWNirx** does ~~not~~ [EDIT: see [this](https://github.com/mne-tools/mne-python/issues/7913#issuecomment-647976330) comment] lead to raising the error, if *fname* is a non-existent path; ~~there must be a "good" reason for that~~. I'm in to correct the behaviour if you think it should be fixed.




Discussion:

Resolving patch:
diff --git a/mne/io/nirx/nirx.py b/mne/io/nirx/nirx.py
--- a/mne/io/nirx/nirx.py
+++ b/mne/io/nirx/nirx.py
@@ -22,6 +22,8 @@
 def read_raw_nirx(fname, preload=False, verbose=None):
     """Reader for a NIRX fNIRS recording.
 
+    This function has only been tested with NIRScout devices.
+
     Parameters
     ----------
     fname : str
@@ -70,6 +72,9 @@ def __init__(self, fname, preload=False, verbose=None):
         if fname.endswith('.hdr'):
             fname = op.dirname(op.abspath(fname))
 
+        if not op.isdir(fname):
+            raise RuntimeError('The path you specified does not exist.')
+
         # Check if required files exist and store names for later use
         files = dict()
         keys = ('evt', 'hdr', 'inf', 'set', 'tpl', 'wl1', 'wl2',
@@ -92,35 +97,6 @@ def __init__(self, fname, preload=False, verbose=None):
             for line in fid:
                 last_sample += 1
 
-        # Read participant information file
-        inf = ConfigParser(allow_no_value=True)
-        inf.read(files['inf'])
-        inf = inf._sections['Subject Demographics']
-
-        # Store subject information from inf file in mne format
-        # Note: NIRX also records "Study Type", "Experiment History",
-        #       "Additional Notes", "Contact Information" and this information
-        #       is currently discarded
-        subject_info = {}
-        names = inf['name'].split()
-        if len(names) > 0:
-            subject_info['first_name'] = \
-                inf['name'].split()[0].replace("\"", "")
-        if len(names) > 1:
-            subject_info['last_name'] = \
-                inf['name'].split()[-1].replace("\"", "")
-        if len(names) > 2:
-            subject_info['middle_name'] = \
-                inf['name'].split()[-2].replace("\"", "")
-        # subject_info['birthday'] = inf['age']  # TODO: not formatted properly
-        subject_info['sex'] = inf['gender'].replace("\"", "")
-        # Recode values
-        if subject_info['sex'] in {'M', 'Male', '1'}:
-            subject_info['sex'] = FIFF.FIFFV_SUBJ_SEX_MALE
-        elif subject_info['sex'] in {'F', 'Female', '2'}:
-            subject_info['sex'] = FIFF.FIFFV_SUBJ_SEX_FEMALE
-        # NIRStar does not record an id, or handedness by default
-
         # Read header file
         # The header file isn't compliant with the configparser. So all the
         # text between comments must be removed before passing to parser
@@ -135,6 +111,10 @@ def __init__(self, fname, preload=False, verbose=None):
                    ["\"15.0\"", "\"15.2\""]):
             raise RuntimeError('MNE does not support this NIRStar version'
                                ' (%s)' % (hdr['GeneralInfo']['NIRStar'],))
+        if "NIRScout" not in hdr['GeneralInfo']['Device']:
+            warn("Only import of data from NIRScout devices have been "
+                 "thoroughly tested. You are using a %s device. " %
+                 hdr['GeneralInfo']['Device'])
 
         # Parse required header fields
 
@@ -161,6 +141,35 @@ def __init__(self, fname, preload=False, verbose=None):
         # Extract sampling rate
         samplingrate = float(hdr['ImagingParameters']['SamplingRate'])
 
+        # Read participant information file
+        inf = ConfigParser(allow_no_value=True)
+        inf.read(files['inf'])
+        inf = inf._sections['Subject Demographics']
+
+        # Store subject information from inf file in mne format
+        # Note: NIRX also records "Study Type", "Experiment History",
+        #       "Additional Notes", "Contact Information" and this information
+        #       is currently discarded
+        subject_info = {}
+        names = inf['name'].split()
+        if len(names) > 0:
+            subject_info['first_name'] = \
+                inf['name'].split()[0].replace("\"", "")
+        if len(names) > 1:
+            subject_info['last_name'] = \
+                inf['name'].split()[-1].replace("\"", "")
+        if len(names) > 2:
+            subject_info['middle_name'] = \
+                inf['name'].split()[-2].replace("\"", "")
+        # subject_info['birthday'] = inf['age']  # TODO: not formatted properly
+        subject_info['sex'] = inf['gender'].replace("\"", "")
+        # Recode values
+        if subject_info['sex'] in {'M', 'Male', '1'}:
+            subject_info['sex'] = FIFF.FIFFV_SUBJ_SEX_MALE
+        elif subject_info['sex'] in {'F', 'Female', '2'}:
+            subject_info['sex'] = FIFF.FIFFV_SUBJ_SEX_FEMALE
+        # NIRStar does not record an id, or handedness by default
+
         # Read information about probe/montage/optodes
         # A word on terminology used here:
         #   Sources produce light


Test patch:
diff --git a/mne/io/nirx/tests/test_nirx.py b/mne/io/nirx/tests/test_nirx.py
--- a/mne/io/nirx/tests/test_nirx.py
+++ b/mne/io/nirx/tests/test_nirx.py
@@ -37,6 +37,13 @@ def test_nirx_hdr_load():
     assert raw.info['sfreq'] == 12.5
 
 
+@requires_testing_data
+def test_nirx_missing_warn():
+    """Test reading NIRX files when missing data."""
+    with pytest.raises(RuntimeError, match='The path you'):
+        read_raw_nirx(fname_nirx_15_2_short + "1", preload=True)
+
+
 @requires_testing_data
 def test_nirx_dat_warn(tmpdir):
     """Test reading NIRX files when missing data."""