Cannot connect to Net Station 4.4.2 with egi_pynetstation

I’m using PsychoPy 2022.2.4 and Mac OS 11.6.4. (I have also received this error when trying to run this experiment on Mac OS X 10.11 and Mac OS 10.13.)

I’m trying to use pynetstation to connect to my lab’s EGI NetStation computer. That computer is running Net Station 4.4.2 on Mac OS X 10.6. It is connected to a Net Amps 300 amplifier.

I am attempting to implement the same code from the PsychoPy documentation on pynetstation (https://psychopy.org/hardware/egiNetStation.html). When I run the PsychoPy experiment, it times out, and I receive the following messages in the log:

308.0067     INFO     Loaded monitor calibration from ['2021_07_08 12:22']
2022-11-15 11:27:52.025 python[1952:22787] ApplePersistenceIgnoreState: Existing state will not be touched. New state will be written to /var/folders/51/mhhhd0r95wd3k994jbk1mwpc0000gp/T/org.opensciencetools.psychopy.savedState
Traceback (most recent call last):
  File "ntplib.pyc", line 318, in request
socket.timeout: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/mbv0/Desktop/Research/flanker_eeg/testing_netstation/test1_lastrun.py", line 126, in <module>
    eci_client.begin_rec()
  File "/Applications/PsychoPy_v2022-2-4.app/Contents/Resources/lib/python3.8/egi_pynetstation/NetStation.py", line 103, in wrapper
    func(*args, **kwargs)
  File "/Applications/PsychoPy_v2022-2-4.app/Contents/Resources/lib/python3.8/egi_pynetstation/NetStation.py", line 198, in begin_rec
    self.ntpsync()
  File "/Applications/PsychoPy_v2022-2-4.app/Contents/Resources/lib/python3.8/egi_pynetstation/NetStation.py", line 103, in wrapper
    func(*args, **kwargs)
  File "/Applications/PsychoPy_v2022-2-4.app/Contents/Resources/lib/python3.8/egi_pynetstation/NetStation.py", line 153, in ntpsync
    response = c.request(self._ntp_ip, version=3)
  File "ntplib.pyc", line 323, in request
ntplib.NTPException: No response received from 10.10.10.42.
################# Experiment ended with exit code 1 [pid:1952] #################

I also am monitoring the TCP/IP Port log on the Net Station computer. It seems that the connection is established, but something about the NTP lines won’t work. Here is the log from the Net Station computer:

Query: NTEL
Identify: 
Attention
OK
Attention
OK
Timeout waiting for response from Attention command.

I’ve tried using some code on an older experiment machine (as I mentioned above), running a much older version of PsychoPy that uses egi.simple (as in this post), and I can establish a connection with Net Station that way, but I am concerned about precise timestamping, since millisecond precision is required for my planned experiments.

My specific questions are:

  1. Is there a fix for the error I’m receiving when I use egi_pynetstation and PsychoPy 2022.2.4?
  2. If this version of pynetstation is simply incompatible with Net Station 4.4.2, and I must use older versions of the library/PsychoPy, are there any timing problems I should be on the lookout for?

Thank you very much!

Hello,

When we wrote the new version for NTP of egi_pynetstation, we didn’t test it on versions of Net Station before 5.x. On the plus side, we do know that the package works with 300 series amplifiers.

My initial thought is that your NTP server may not be running on the Net Station Mac. There’s a script that you can run distributed by EGI/MagStim, but you’ll need to reach out to them directly: support@magstimegi.com

Can you post your code for connecting and starting to record?

Have you attempted to connect to the amplifier with either E-PRIME 2.x/3.x or PsychToolbox using NTP? That might help us track down the issue a bit more if you want to use the NTP method.

As for using the older “polling” mechanism in the PsychoPy2 package - the major things are to do an ns.sync() before events and to checkout this thread by expert Joshua Zosky

-Peter

Hi Peter,

Thanks so much for this information! I have reached out to Joshua and to EGI/MagStim for assistance.

Here is the code I’m using to connect and start recording. I have double checked that the IP address and port are correct:

#Import Netstation library
from egi_pynetstation.NetStation import NetStation

#IP address of NetStation Mac
IP_ns = '10.10.10.42'

#IP address of amplifier (if using 300
#series, this is the same as the IP address of
#NetStation. If using newer series, the amplifier
#has its own IP address)
IP_amp = '10.10.10.42'

#Port configured for ECI in NetStation
port_ns = 55513

#Start recording and send trigger to show this
eci_client = NetStation(IP_ns, port_ns)
eci_client.connect(ntp_ip = IP_amp)
eci_client.begin_rec()
eci_client.send_event(event_type = 'STRT', start = 0.0)

We have used PsychToolbox to connect to the amplifier before, but I don’t think that we did so using NTP. Here is an example of the code we used in a previous PsychToolbox-3 experiment from 2019:

% ========== EEG command start ========== %
% Establish connection w/ NetStation
[connect, messageConnect] = NetStation('Connect', '10.10.10.42'); % Connect to EEG computer 
[sync, messageSync] = NetStation('Synchronize'); % Synchronize computers
[record, messageRecord] = NetStation('StartRecording'); % Start EEG recording
% ========== EEG command end ========== %

Looking at the PsychToolbox documentation, I think [sync, messageSync] = NetStation('Synchronize'); is similar to the “polling” mechanism in the PsychoPy2 package, right?

Thanks again for your help!

Mercedes

Hi Mercedes-

Yes that code in PsychToolbox is for the polling style of communicating with Net Station. The PsychToolbox code for using NTP has a:
NetStation( ‘GetNTPSynchronize’, ntpserver ).

The PsychoPy/Python code looks correct for communicating with a 300 series amplifier (same IP for Net Station and Amp). And given that you have a Net Station log of the connection, suggests strongly that the IP is correct! That timeout message you’re getting is related to the NTP server not responding.

The EGI team will have to walk you through or send you the script for enabling the NTP server on your Net Station computer so that you can use our NTP code. Mark on the support team has helped a few other 300-series users get their setup working with our code so far.

Most importantly is to use your photocell timing kit to ensure that your setup is getting accurate and stable timing once you have your experiment coded up.

In the meantime if you do use the polling technique you should read over this thread. There is also a GitHub page that updated the old egi package for Python3. I continue to recommend getting the NTP setup working, we specifically chose to implement NTP timing as it is more accurate with less drift.

-Peter

Hello, I am running into the same error in the original post where “No response received from 10.10.10.42”. Should I reach out directly to EGI/MagStim for assistance? Also, following up on the comment above, should I be using GitHub - gstothart/EGI-Psychopy-Python3: EGI Psychopy library - Python 3 compatibility update or GitHub - nimh-sfim/egi-pynetstation: Python package to enable the use of a Python-based API for EGI's NetStation EEG amplifier interface.? It looks like the latter has been updated for python 3? Thank you.

Hmm that’s interesting. You should be using the NIMH-SFIM one (GitHub - nimh-sfim/egi-pynetstation: Python package to enable the use of a Python-based API for EGI's NetStation EEG amplifier interface.).

Can you post the webpage that loads when you turn on the amplifier and NetStation computer? Also post the code that you’re using to connect and send messages?

You can also clone this repo for an example script that should work out of the box assuming that everything is configured correctly: GitHub - nimh-cmn/stroopEGI: Demo PsychoPy experiment with EGI EEG amplifier events for Stroop Experiment

Hi, thanks for getting back to me so quickly!

from egi_pynetstation.NetStation import NetStation
  
# Set an IP address for the computer running NetStation as an IPv4 string
IP_ns = '10.10.10.42'  
# Set a port that NetStation will be listening to as an integer
port_ns = 55513
ns = NetStation(IP_ns, port_ns)
# Set an NTP clock server (the amplifier) address as an IPv4 string
IP_amp = '10.10.10.42'
ns.connect(ntp_ip=IP_amp)
# Do whatever setup for your experiment here...
# Begin recording
ns.begin_rec()

I run into issues with the last line. Here’s a copy of the traceback:

Traceback (most recent call last):
  File "/Users/.../site-packages/ntplib.py", line 318, in request
    response_packet, src_addr = s.recvfrom(256)
  socket.timeout: timed out
  
During handling of the above exception, another exception occurred:
  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/.../site-packages/egi_pynetstation/NetStation.py", line 102, in wrapper
    func(*args, **kwargs)
  File "/Users/.../site-packages/egi_pynetstation/NetStation.py", line 192, in begin_rec
    self.ntpsync()
  File "/Users/.../site-packages/egi_pynetstation/NetStation.py", line 102, in wrapper
    func(*args, **kwargs)
  File "/Users/.../site-packages/egi_pynetstation/NetStation.py", line 152, in ntpsync
    response = c.request(self._ntp_ip, version=3)
  File "/Users/.../site-packages/ntplib.py", line 323, in request
    raise NTPException("No response received from %s." % host)
ntplib.NTPException: No response received from 10.10.10.42.
  • Thanks for sharing the stroopEGI demo. After changing the IP_amp in the code snippet to match that of NetStation, I have the same exception: “No response received from 10.10.10.42”. Is there something wrong with my configuration?

Which amplifier do you have? 300 or 400? Feel free to post a photo of your setup.

With the 400 series the NetStation laptop is usually configured to open a webpage in Firefox. In the 300 series that’s not the case.

I suspect if you have a 300 series amplifier (with FireWire cable) then you may need to active the NTP server on your net station computer. EGI support can help with this. But if you have a 400 series amplifier then we may need to do more debugging.

Yes, I have the 300 series amplifier. I’ll have to check it’s with a FireWire cable. Thanks for all your help! I’ll reach out to EGI support and test your stroopEGI demo again.

Any chance someone here has the script for enabling an NTP server on a NetStation computer and can share it? I haven’t heard back from MagstimEGI yet and am hoping to confirm asap that I can integrate my task code with our EEG system using the egi-pynetstation SDK. Thanks in advance.

Can you run the following in your terminal?

sntp -d localhost

You might have to put in the IP address of your current computer in place of localhost. That’ll tell us if the NTP server is at least running.

Also the output of ifconfig on your NetStation computer would be useful.

It doesn’t look like an NTP server is running: sntp -d localhost or the IP address results in no UCST response after 5 seconds

Here is the output of ifconfig:

lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
inet 127.0.0.1 netmask 0xff000000
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
nd6 options=201<PERFORMNUD,DAD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
XHC20: flags=0<> mtu 0
XHC0: flags=0<> mtu 0
XHC1: flags=0<> mtu 0
XHC2: flags=0<> mtu 0
XHC3: flags=0<> mtu 0
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=10b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV>
ether 68:fe:f7:04:30:0e
nd6 options=201<PERFORMNUD,DAD>
media: autoselect (none)
status: inactive
en5: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=b<RXCSUM,TXCSUM,VLAN_HWTAGGING>
ether 00:50:b6:8c:a1:99
inet6 fe80::10d5:4edd:57:2b1b%en5 prefixlen 64 secured scopeid 0xa
inet 10.10.10.42 netmask 0xffffff00 broadcast 10.10.10.255
nd6 options=201<PERFORMNUD,DAD>
media: autoselect (1000baseT <full-duplex,flow-control,energy-efficient-ethernet>)
status: active
en1: flags=8823<UP,BROADCAST,SMART,SIMPLEX,MULTICAST> mtu 1500
ether 14:20:5e:15:46:96
nd6 options=201<PERFORMNUD,DAD>
media: autoselect (<unknown type>)
status: inactive
en2: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
options=60<TSO4,TSO6>
ether aa:00:d4:e8:f1:00
media: autoselect <full-duplex>
status: inactive
en3: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
options=60<TSO4,TSO6>
ether aa:00:d4:e8:f1:01
media: autoselect <full-duplex>
status: inactive
fw0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 4078
lladdr 00:50:b6:10:00:01:2a:ff
nd6 options=201<PERFORMNUD,DAD>
media: autoselect <full-duplex>
status: inactive
p2p0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 2304
ether 06:20:5e:15:46:96
media: autoselect
status: inactive
awdl0: flags=8902<BROADCAST,PROMISC,SIMPLEX,MULTICAST> mtu 1484
ether e2:be:fd:5e:0b:15
nd6 options=201<PERFORMNUD,DAD>
media: autoselect
status: inactive
bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=63<RXCSUM,TXCSUM,TSO4,TSO6>
ether aa:00:d4:e8:f1:00
Configuration:
id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
ipfilter disabled flags 0x2
member: en2 flags=3<LEARNING,DISCOVER>
        ifmaxaddr 0 port 12 priority 0 path cost 0
member: en3 flags=3<LEARNING,DISCOVER>
        ifmaxaddr 0 port 13 priority 0 path cost 0
nd6 options=201<PERFORMNUD,DAD>
media: <unknown type>
status: inactive
utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 2000
inet6 fe80::83cf:5c41:8f94:69%utun0 prefixlen 64 scopeid 0x12
nd6 options=201<PERFORMNUD,DAD>

I’ve now received a script from EGI to set up an NTP server – thanks for all of your help! Before I run it, I wanted to confirm a couple of things. My colleague has been using this package: GitHub - gstothart/EGI-Psychopy-Python3: EGI Psychopy library - Python 3 compatibility update, which is older than the NIMH one (and I’d prefer to use the latter). How do the two packages differ? Based on my limited understanding, setting up an NTP server using the EGI script should not interfere with my colleague’s setup; do you know whether this is indeed the case?

Setting up the NTP server shouldn’t interfere with using the “older” package. In the python 2 days (and thus psychopy 2.x) we used the older EGI package to communicate with the amp. It used a polling technique where you ask the amplifier before each event “what time is it?” And the amp returns a sync time. You then send your event relative to that. The package your colleague is using is a python 3 port of that code, which is very good but has limitations.

The NTP package that we made synchronizes the clocks of the stim computer with the amp/Mac (400 / 300 series systems) so you don’t have to ask every time and also keeps that timing stable for longer. It should be superior in general, but doing an occasional resync is a good idea. I could go into more technical details on why the new package is better, but suffice to say we wouldn’t have invested the time and released it if the results weren’t superior.

Thanks so much, Peter. I’m new to EEG, so all of this information is extremely helpful! I’ve convinced my colleague to use the egi-pynetstation SDK moving forward.
I’m now working on setting up the NTP server, so hopefully everything will go smoothly from here on out.

1 Like

Hi all. I’m running EGI-pynetstation on a windows 10 machine connecting to a NS 5.4.2 macbook pro connected to a 300 amp.

I’m connecting and sending events just fine, but I’ve got a drift of about 40ms over the course of an hour. The events start out with a 4ms offset that increases over time.

I’m testing this with a fullscreen chessboard reversal and a cedrus stimtracker photodiode. This drift persists even with eci.resync() calls every 500ms.

I’ve started to chase this down, but I’ve always used the old style synchronization and I really don’t know NTP in any detail. I’m wondering if you can suggest any obvious places to start e.g., making sure that the NTP server is running correctly on the macbook etc.

For reference, I think that the NTP script I have from EGI is from 2019 so I’m not sure if there have been meaningful advances since then.

Interesting! Can you upload or send me the experiment?

What do you see with no resync?

sure, but what do you mean ‘what do you see with resync’ does it return useful info? regarding timing, the drift is identical with or without the resync call. Should I pull any other information that I might not be thinking of?
Thanks!

Yes was looking to see if the drift was the same or different with the resync() added in. 500ms is a pretty quick resync, we’re doing them on the order of 5 seconds and preferably when not immediately asking to send an event.

Ok let me try to get more info:

  1. Can you post the timing test output for offsets for each trial?
  2. What version of macOS are you running?
  3. What’s your stimulus display screen resolution and refresh rate? What monitor do you have? What graphics card / graphics card software/drivers?
  4. Do you have E-PRIME handy that you can test against their reference implementation?
  5. Can you run this stroop experiment to see if you get drift?

awesome, thanks. should I run the experiment in builder or coder?

The stroop experiment happily runs from builder.