# How to read the Nihon Kohden EEG files comments (Content of the Comment)

**URL:** <https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680>\
**Category:** Support & Discussions\
**Tags:** eeg, annotations\
**Created:** [February 2, 2026, 6:48am UTC](https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680 "2026-02-02T06:48:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![eulerleibniz](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/eulerleibniz/32/3858_2.png) [@eulerleibniz](https://mne.discourse.group/u/eulerleibniz)\
**Post date:** [February 2, 2026, 6:48am UTC](https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680/1 "2026-02-02T06:48:35Z")

</div>

**Hello**  
I am trying to read some EEG files using MNE and so far I can read almost all of the data and annotations, but can’t read the content of the comments. Unfortunately I can not share the EEG file but here is the complete description of the problem. I appreciate any input on this and thanks in advance:  
\*\*  
CODE:\*\*

```python
import mne 
print(mne. __version__ )
raw = mne.io.read_raw_nihon("FJ00231Z.EEG", preload=False) # OR preload=True
for ann in raw.annotations:
    print(ann)

```

This will output the annotations as expected, but it does not read the comments content. Here is a sample output of the code:  
```

```python
1.11.0 # MNE version
Loading FJ00231Z.EEG
Found 21E file, reading channel names.
Reading header from Path\To\File\EEG2100\FJ00231Z.EEG # EEG 2100 Device
Found PNT file, reading metadata.
Found LOG file, reading events.

OrderedDict({'onset': np.float64(11768.0), 'duration': np.float64(0.0), 'description': np.str_('eye close'), 'orig_time': datetime.datetime(2025, 12, 27, 9, 49, 31, tzinfo=datetime.timezone.utc), 'extras': {}})

OrderedDict({'onset': np.float64(13307.568), 'duration': np.float64(0.0), 'description': np.str_('P_COMMENT'), 'orig_time': datetime.datetime(2025, 12, 27, 9, 49, 31, tzinfo=datetime.timezone.utc), 'extras': {}})

```

The problem is that those annotations with `'description': np.str_('P_COMMENT')` contain comments such as this image and I have no idea on how to read those:

 ![image](https://global.discourse-cdn.com/free1/uploads/mne/original/2X/0/0bc7fb41e28d3914251575a219d9ccd3a7844d0e.png)

**Environment:**

- MNE version: 1.11.0
- operating system: Tested on Windows 11 / Ubuntu 24.04
- Nihon Kohden Software Compatible with data: EEG-1200 Review application (version 08.10), also identified as Neurofax QP-112AK.
- EEG Device: EEG 2100

---

<div class="post-metadata">

**Author:** ![wmvanvliet](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/wmvanvliet/32/100_2.png) [@wmvanvliet](https://mne.discourse.group/u/wmvanvliet)\
**Post date:** [February 2, 2026, 9:20am UTC](https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680/2 "2026-02-02T09:20:18Z")

</div>

It seems we don’t support it (yet). [The documentation](https://mne.tools/0.21/auto_tutorials/io/plot_20_reading_eeg_data.html#nihon-kohden-eeg-data-eeg-21e-pnt-log) says:

> Reading `.11D`, `.CMT`, `.CN2`, and `.EDF` files is currently not supported.

I assume `.CMT` stands for “comment”? Searching the [open issues for “nihon”](https://github.com/mne-tools/mne-python/issues?q=is%3Aissue%20state%3Aopen%20nihon) reveals some other lacking functionality.

Is this a format used in a hospital? I’m not familiar with it myself and perhaps none of the regular developers of MNE-Python even have access to a collection of nihon files to implement these features. MNE-Python is a community project mostly consisting of unpaid volunteers. If you can program a little Python and are interested in adding support for this yourself, we would very much welcome you opening an issue stating your intent of adding this, followed by a pull request that adds the functionality to MNE-Python. We would gladly help you by answering questions about the codebase and the various procedures involved in this.

---

<div class="post-metadata">

**Author:** ![eulerleibniz](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/eulerleibniz/32/3858_2.png) [@eulerleibniz](https://mne.discourse.group/u/eulerleibniz)\
**Post date:** [February 2, 2026, 7:18pm UTC](https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680/3 "2026-02-02T19:18:42Z")

</div>

@wmvanvliet Thanks for your quick reply. And i found the notes I was looking for in that `.CMT` files, thanks for pointing out. I will try writing some code to read it and hopefully i will do a pull request to add this feature.

Regarding your question: “Is this a format used in a hospital?”  
It is used in many hospitals in Iran where I live. We use some outdated devices, software, and formats though (due to USA sanctions). The latest update of this software I used for opening files dates back to 2015. The devices are much older. And we have a massive dataset here all with this file format (at least 2000 long term monitoring recordings - each ~48 hour EEG).

Thanks again.

---

<div class="post-metadata">

**Author:** ![eulerleibniz](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/eulerleibniz/32/3858_2.png) [@eulerleibniz](https://mne.discourse.group/u/eulerleibniz)\
**Post date:** [February 3, 2026, 3:09am UTC](https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680/4 "2026-02-03T03:09:20Z")

</div>

Here is the code to read the comments (Tested only on EEG 2100 devices). I will do my best to do a pull request soon, i think i need to open an issue first.

```python
import re
import string
from dataclasses import dataclass

@dataclass
class Comment:
    timestamp: int
    text: str

TS_RE = re.compile(rb"(\d{20})")

PRINTABLE = set(bytes(string.printable, "ascii"))

def clean_bytes(b: bytes) -> str:
    # keep printable ASCII, including space and newline
    cleaned_byte = bytes(c if c in PRINTABLE else ord(" ") for c in b)
    cleaned_str = cleaned_byte.decode("ascii", errors="ignore").strip()
    cleaned_str = cleaned_str[10:].lstrip().lstrip("\t\n\x0b\r\x0c")
    return cleaned_str

def parse_cmt(path: str):
    data = open(path, "rb").read()
    matches = list(TS_RE.finditer(data))
    records = []
    for i, m in enumerate(matches):
        ts = int(m.group(1).decode("ascii"))
        start = m.end()
        end = matches[i + 1].start() if i + 1 < len(matches) else len(data)

        raw_text = data[start:end]
        text = clean_bytes(raw_text)

        if text:
            records.append(Comment(timestamp=ts, text=text))

    return records

records = parse_cmt("ROOT_PATH/NKT/EEG2100/FJ00231Z.CMT")
for r in records:
    print("📝")
    print(r.timestamp)
    print(r.text)

```

---

<div class="post-metadata">

**Author:** ![wmvanvliet](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/wmvanvliet/32/100_2.png) [@wmvanvliet](https://mne.discourse.group/u/wmvanvliet)\
**Post date:** [February 3, 2026, 7:32am UTC](https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680/5 "2026-02-03T07:32:36Z")

</div>

Glad to read that you figured out how to load the comments yourself. Even even happier to hear you would be willing to contribute this to MNE-Python!

Yes, first submit a “feature request” issue in which you describe the problem and how you propose it could be addressed (you can re-use the explanation you give in this forum topic). The idea is that we can discuss the overall approach before actual work starts, so you don’t end up doing a lot of work just for us to say “actually, this way is better” and having to start all over. In your case, the feature is quite straightforward, as you show in your initial implementation above. Although I would ask about text encoding: your implementation forces plain ASCII, while the MNE-Python nihon reader takes the encoding (defaults to utf-8) as a parameter for the user to specify.

This makes for a perfect first contribution I think. The style doesn’t quite match the rest of the MNE-Python codebase yet, but we can go back and forth on that in the actual PR.

---

<div class="post-metadata">

**Author:** ![eulerleibniz](https://yyz2.discourse-cdn.com/free1/user_avatar/mne.discourse.group/eulerleibniz/32/3858_2.png) [@eulerleibniz](https://mne.discourse.group/u/eulerleibniz)\
**Post date:** [February 4, 2026, 1:02am UTC](https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680/6 "2026-02-04T01:02:47Z")

</div>

Just opened an issue here:

> <https://github.com/mne-tools/mne-python/issues/13633>
>
> \### Describe the new feature or enhancement
> 
> \## Description
> 
> Nihon Kohden EEG fi…les contain \*\*comments/annotations with textual and image content\*\*, but currently this information is not accessible when reading the data with MNE.
> 
> I previously raised this question on the MNE Discourse forum, where the limitation was discussed:
> \[https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680\](https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680)
> 
> At the moment, MNE can detect the presence/timing of comments but does \*\*not expose the actual text content\*\* of those comments to the user.
> 
> \## Why this matters
> 
> The comment text in Nihon Kohden recordings often contains \*\*clinically and experimentally relevant metadata\*\*, such as:
> 
> \* Seizure/Event types and full descriptions added by experts
> \* Manual annotations added during recording added by nurses
> 
> Losing this information during import makes downstream analysis specially in case of machine learning incomplete and requires users to rely on external vendor software.
> 
> \## Current behavior
> 
> Given a code like this:
> \`\`\`python
> import mne 
> print(mne.\_\_version\_\_)
> raw = mne.io.read\_raw\_nihon("FJ00231Z.EEG", preload=False) # OR preload=True
> for ann in raw.annotations:
> print(ann)
> \`\`\`
> This will output the annotations as expected, but it does not read the comments content. Here is a sample output of the code:
> \`\`\`python
> 1.11.0 # MNE version
> Loading FJ00231Z.EEG
> Found 21E file, reading channel names.
> Reading header from Path\\To\\File\\EEG2100\\FJ00231Z.EEG # EEG 2100 Device
> Found PNT file, reading metadata.
> Found LOG file, reading events.
> 
> OrderedDict({'onset': np.float64(11768.0), 'duration': np.float64(0.0), 'description': np.str\_('eye close'), 'orig\_time': datetime.datetime(2025, 12, 27, 9, 49, 31, tzinfo=datetime.timezone.utc), 'extras': {}})
> 
> OrderedDict({'onset': np.float64(13307.568), 'duration': np.float64(0.0), 'description': np.str\_('P\_COMMENT'), 'orig\_time': datetime.datetime(2025, 12, 27, 9, 49, 31, tzinfo=datetime.timezone.utc), 'extras': {}})
> \`\`\`
> Those annotations with 'description': np.str\_('P\_COMMENT') contain comments such as this image and are not currently readable:
> 
> \<img width="1444" height="860" alt="Image" src="https://github.com/user-attachments/assets/1bdcb254-a32c-46f3-8c1c-aaefb4a6ef24" /\>
> 
> \* Nihon Kohden EEG files can be read
> \* Annotations can be read
> \* Comments timing are available
> \* \*\*Comments are all shown as \`P\_COMMENT\` and the text/content is not accessible\*\*
> 
> \## Expected behavior
> 
> At least the Comment text should be parsed and exposed, ideally as:
> 
> \* \`Annotations.description\`, or
> \* In the extra field of the annotation ideally as a dict
> 
> \### Describe your proposed implementation
> 
> \## Basic code snippet
> 
> Here is the code i use currently to read the comments from a given \`.CMT\` file. It should be integrated into \`mne.io.read\_raw\_nihon\` code but the code is not complete so it can wait.
> \`\`\`python
> import re
> import string
> from dataclasses import dataclass
> 
> 
> @dataclass
> class Comment:
> timestamp: int
> text: str
> 
> 
> TS\_RE = re.compile(rb"(\\d{20})") # The timing of each annotation which is 20 digit long
> 
> PRINTABLE = set(bytes(string.printable, "ascii")) # The .CMT file contains many NULL and control characters
> 
> 
> def clean\_bytes(b: bytes) -\> str:
> # keep printable ASCII, including space and newline - NOT TESTED WITH COMMENTS INCLUDING IMAGE LINKS
> cleaned\_byte = bytes(c if c in PRINTABLE else ord(" ") for c in b)
> cleaned\_str = cleaned\_byte.decode("ascii", errors="ignore").strip()
> cleaned\_str = cleaned\_str\[10:\].lstrip().lstrip("\\t\\n\\x0b\\r\\x0c") # at least 10 control characters are included before the text
> return cleaned\_str
> 
> 
> def parse\_cmt(path: str):
> data = open(path, "rb").read()
> matches = list(TS\_RE.finditer(data))
> records = \[\]
> for i, m in enumerate(matches):
> ts = int(m.group(1).decode("ascii"))
> start = m.end()
> end = matches\[i + 1\].start() if i + 1 \< len(matches) else len(data)
> 
> raw\_text = data\[start:end\]
> text = clean\_bytes(raw\_text)
> 
> if text:
> records.append(Comment(timestamp=ts, text=text))
> 
> return records
> 
> 
> records = parse\_cmt("ROOT\_PATH/NKT/EEG2100/FJ00231Z.CMT")
> for r in records:
> print("📝")
> print(r.timestamp)
> print(r.text)
> \`\`\`
> \## Limitations:
> \- Tested only on EEG 2100 devices
> \- Its just a workaround for starter
> \- Nihon Kohden Comments can containt color code, background transparency, and even a reference image. None of these are read here as i've never seen experts really use them.
> 
> \### Describe possible alternatives
> 
> No alternatives currently
> 
> \### Additional context
> 
> \_No response\_

I will wait for the response and see what happens.  
Also i just noticed that Nihon Kohden comments can actually contain image links. I didn’t cover that aspect in my code snippet.

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/free1/uploads/mne/original/1X/85cc6bd2b69cb698a166dc6d880fb550510d0144.jpeg) [@system](https://mne.discourse.group/u/system)\
**Post date:** [February 11, 2026, 1:03am UTC](https://mne.discourse.group/t/how-to-read-the-nihon-kohden-eeg-files-comments-content-of-the-comment/11680/7 "2026-02-11T01:03:02Z")

</div>

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.
