Giter Site home page Giter Site logo

Comments (12)

armwal avatar armwal commented on August 12, 2024 1

I have to say that I can't guarantee that the following is correct and it might be better to wait for Peter's answer next week who is the expert on interacting with the stimulator. If you want to use different stimulation patterns on different electrodes, to the best of my knowledge it works like this:

The MEA2100 has 3 independent stimulus generators (Stg1, Stg2, Stg3) and you can configure stimulation patterns (amplitude arrays and duration arrays) for each of them. You can then assign all electrodes that should get the first pattern to Stg1 via the SetElectrodeDacMux call, electrodes that should get the second pattern to Stg2, and so on. Then, you can call

PrepareAndSendData(UInt32(0), amplitude[0], duration[0], STG_DestinationEnumNet.channeldata_voltage) # pattern for Stg1
PrepareAndSendData(UInt32(1), amplitude[1], duration[1], STG_DestinationEnumNet.channeldata_voltage) # pattern for Stg2
PrepareAndSendData(UInt32(2), amplitude[2], duration[2], STG_DestinationEnumNet.channeldata_voltage) # pattern for Stg3

If you call PrepareAndSendData multiple times for the same channel (the first parameter), the stimulation pattern defined for this channel gets overwritten.

Then, you also need make sure that all Stgs get started, via the SetupTrigger call. Currently, you've defined it that only Stg1 gets started and the pattern is repeated 10 times. In order to start all Stgs, you'll need to:

Edit: Removed, because code had errors

from mcsusbnet_examples.

armwal avatar armwal commented on August 12, 2024

Hi,
thanks for notifying us! Our colleague who did most of the scripting for stimulation is on vacation this week but will get back to you next week. In the meantime, could you attach an example Python script where SetElectrodeMode crashes? This makes it easier for us to replicate the issue. Which Python version are you using?

Regarding the stimulation code that doesn't produce artifacts: Are you referring to the Python code (Stimulation.py) or to the Matlab or C# examples?

Best,
Armin

from mcsusbnet_examples.

satabios avatar satabios commented on August 12, 2024

My task was to replicate the MATLAB stimulation script provided in the repository into Python. In MATLAB I was trying to stimulate a set of electrodes with a set of train pulses. Here I use "SetElectrodeMode" method to select and enable them for stimulation. I also use "SetBlankingEnable" for blanking the electrodes. This code worked expected by stimulating the corresponding electrodes as soon as "device.SendStart(1)" command was sent.

MATLAB SCRIPT

   assembly = NET.addAssembly( 'C:\Users\45c\Downloads\McsUsbNet-5.1.6\McsUsbNet-5.1.6\x64\McsUsbNet.dll');
   device = Mcs.Usb.CStg200xDownloadNet();



   deviceList = Mcs.Usb.CMcsUsbListNet(Mcs.Usb.DeviceEnumNet.MCS_STG_DEVICE);
      fprintf('Found %d STGs\n', deviceList.GetNumberOfDevices());

for i=1:deviceList.GetNumberOfDevices()
   SerialNumber = char(deviceList.GetUsbListEntry(i-1).SerialNumber);
   fprintf('Serial Number: %s\n', SerialNumber);
end

% Connect to the first STG object
status = device.Connect(deviceList.GetUsbListEntry(0));

if status == 0
    % Register cleanup function. This ensures that the device
    % disconnects when the run_stim function terminates
    cleanupObj = onCleanup(@()cleanup_stim(device));
    electrode = uint32(85);

    
    % ElectrodeMode: emManual: electrode is permanently selected for stimulation
    device.SetElectrodeMode(electrode, Mcs.Usb.ElectrodeModeEnumNet.emManual);

    % ElectrodeDacMux: DAC to use for Stimulation
    device.SetElectrodeDacMux(electrode, 0, Mcs.Usb.ElectrodeDacMuxEnumNet.Stg1);

    % ElectrodeEnable: enable electrode for stimulation
    device.SetElectrodeEnable(electrode, 0, true);

    % BlankingEnable: false: do not blank the ADC signal while stimulation is running
    device.SetBlankingEnable(electrode, false);

    % AmplifierProtectionSwitch: false: Keep ADC connected to electrode even while stimulation is running
    device.SetEnableAmplifierProtectionSwitch(electrode, false);

    % array of amplitudes and duration
    amplitude_array = int32([+200000 -200000]);  % Amplitude in uV
    duration_array = uint64([1000000 1000000]);  % Duration in us


    % use voltage stimulation
    device.SetVoltageMode();

    % send stimulus data to device
    device.PrepareAndSendData(uint32(0), NET.convertArray(amplitude_array, 'System.Int32'), NET.convertArray(duration_array, 'System.UInt64'), Mcs.Usb.STG_DestinationEnumNet.channeldata_voltage);

    % connect all stimulation channels to the first trigger and repeat the
    % pulse 3 times
    
    device.SetupTrigger(uint32(0), NET.convertArray(255, 'System.UInt32'), NET.convertArray(255, 'System.UInt32'), NET.convertArray(1, 'System.UInt32'));

    % start the first trigger
    device.SendStart(1);`

To replicate the same functionality in the Python. I used the same script provided at https://github.com/multichannelsystems/McsUsbNet_Examples/blob/master/Examples/Python/Stimulation.py to enable the "SetElectrodeMode" at https://github.com/multichannelsystems/McsUsbNet_Examples/blob/master/Examples/Python/Stimulation.py#L40. To my dismay it threw up an error stating that "No method matches given arguments for SetElectrodeMode", even though the object contained the in bound function in its attributes I was unable to access it. Could you suggest me how to use "SetElectrodeMode" in Python? If not how should I go about the same. The python script looked something like below.

PYTHON SCRIPT

       `import time
        import clr
        
        from System import Action
        from System import *
        
        clr.AddReference('C:\\Users\\45c\\Downloads\\McsUsbNet-5.1.6\\McsUsbNet-5.1.6\\x64\\McsUsbNet.dll')
        from Mcs.Usb import CMcsUsbListNet
        from Mcs.Usb import DeviceEnumNet
        
        from Mcs.Usb import CStg200xDownloadNet
        from Mcs.Usb import McsBusTypeEnumNet
        from Mcs.Usb import STG_DestinationEnumNet
        from Mcs.Usb import ElectrodeModeEnumNet
        from Mcs.Usb import ElectrodeDacMuxEnumNet
        from Mcs.Usb import *
        
        def PollHandler(status, stgStatusNet, index_list):
            print('%x %s' % (status, str(stgStatusNet.TiggerStatus[0])))
        
        deviceList = CMcsUsbListNet(DeviceEnumNet.MCS_DEVICE_USB)
        
        print("found %d devices" % (deviceList.Count))
        
        for i in range(deviceList.Count):
            listEntry = deviceList.GetUsbListEntry(i)
            print("Device: %s   Serial: %s" % (listEntry.DeviceName,listEntry.SerialNumber))
        
        
        device = CStg200xDownloadNet();
        
        device.Stg200xPollStatusEvent += PollHandler;
        
        device.Connect(deviceList.GetUsbListEntry(0))
        
        voltageRange = device.GetVoltageRangeInMicroVolt(0);
        voltageResulution = device.GetVoltageResolutionInMicroVolt(0);
        currentRange = device.GetCurrentRangeInNanoAmp(0);
        currentResolution = device.GetCurrentResolutionInNanoAmp(0);
        
        print('Voltage Mode:  Range: %d mV  Resolution: %1.2f mV' % (voltageRange/1000, voltageResulution/1000.0))
        print('Current Mode:  Range: %d uA  Resolution: %1.2f uA' % (currentRange/1000, currentResolution/1000.0))
        
        channelmap = Array[UInt32]([85,0,0,0])
        syncoutmap = Array[UInt32]([85,0,0,0])
        repeat = Array[UInt32]([10,0,0,0])
        
        amplitude = Array[Int32]([-10000,10000]);
        duration = Array[UInt64]([10000,10000]);
        
        electrode =  UInt32(85)
        
        device.SetElectrodeMode(electrode, ElectrodeModeEnumNet.emManual);
        device.SetElectrodeDacMux(electrode, 0, ElectrodeDacMuxEnumNet.Stg1);
        device.SetElectrodeEnable(electrode, 0, True);
        device.SetBlankingEnable(electrode, False);
        # AmplifierProtectionSwitch: false: Keep ADC connected to electrode even while stimulation is running
        device.SetEnableAmplifierProtectionSwitch(electrode, False);
        
        device.SetupTrigger(0, channelmap, syncoutmap, repeat)
        device.SetVoltageMode();
        device.PrepareAndSendData(0, amplitude, duration, STG_DestinationEnumNet.channeldata_voltage)
        device.SendStart(1)
        time.sleep(10)
        
        device.Disconnect()`

The python version currently in use is 3.7. Regarding the stimulation code that doesn't produce artifacts: I used the python original Stimulation script provided in the repository https://github.com/multichannelsystems/McsUsbNet_Examples/blob/master/Examples/Python/Stimulation.py

from mcsusbnet_examples.

armwal avatar armwal commented on August 12, 2024

Thank you very much for the detailed explanation! There are two minor issues with the Python code, but they probably weren't present in your original script:

  • The line electrode = uint32(101); should probably be electrode = UInt32(101);
  • You'll need to import the ElectrodeModeEnumNet before using it:
# at the start of your script
from Mcs.Usb import ElectrodeModeEnumNet
# then change your device.SetElectrodeMode line to
device.SetElectrodeMode(electrode, ElectrodeModeEnumNet.emManual);

Beyond that I can't do more checks right now as I don't have a MEA2100 available at the moment... I'll refer you to my colleague Peter who will be back next week.

from mcsusbnet_examples.

satabios avatar satabios commented on August 12, 2024

Thank you for your prompt reply. I have updated the code for your perusal. By using
from Mcs.Usb import ElectrodeModeEnumNet I'm able to use the function device.SetElectrodeMode(electrode, ElectrodeModeEnumNet.emManual);.
However, when I try to import from Mcs.Usb import ElectrodeDacMuxEnumNet for device.SetElectrodeDacMux(electrode, 0, ElectrodeDacMuxEnumNet.Stg1); it prompts the same error.
Also event after importing from Mcs.Usb import ElectrodeModeEnumNet I'm unable to run the line device.SetElectrodeEnable(electrode, 0, True); whereas device.SetElectrodeMode(electrode, ElectrodeModeEnumNet.emManual); works as mentioned above.
Am I importing it the wrong way? Please guide me regarding the same.

from mcsusbnet_examples.

armwal avatar armwal commented on August 12, 2024

Hi,
these errors are due to the 0 in the SetElectrodeDacMux and SetElectrodeEnable. Because you are calling a .NET Dll, it is necessary to use the correct data types for function parameters. Both of these functions expect unsigned integers, so the correct way to call them would be:

device.SetElectrodeDacMux(electrode, UInt32(0), ElectrodeDacMuxEnumNet.Stg1)
device.SetElectrodeEnable(electrode, UInt32(0), True)

The same is true for other functions in your script, e.g. SetupTrigger, PrepareAndSendData and SendStart. Please check the documentation (https://github.com/multichannelsystems/McsUsbNet/blob/master/docu/McsUsbNet.pdf) for the correct data types for the respective functions.

from mcsusbnet_examples.

satabios avatar satabios commented on August 12, 2024

Thanks that resolved the issues. Now the script is able to stimulate the electrode. One more quick question how to stimulate multiple electrodes at the same time? I extrapolated the above example and have attached the code below, Can you verify if I have implemented it the correct way?

  import time
  import clr
  
  from System import Action
  from System import *
  
  clr.AddReference('C:\\Users\\45c\\Downloads\\McsUsbNet-5.1.6\\McsUsbNet-5.1.6\\x64\\McsUsbNet.dll')
  from Mcs.Usb import CMcsUsbListNet
  from Mcs.Usb import DeviceEnumNet
  
  from Mcs.Usb import CStg200xDownloadNet
  from Mcs.Usb import McsBusTypeEnumNet
  from Mcs.Usb import STG_DestinationEnumNet
  from Mcs.Usb import ElectrodeModeEnumNet
  from Mcs.Usb import ElectrodeDacMuxEnumNet
  
  
  def PollHandler(status, stgStatusNet, index_list):
      print('%x %s' % (status, str(stgStatusNet.TiggerStatus[0])))
  
  deviceList = CMcsUsbListNet(DeviceEnumNet.MCS_DEVICE_USB)
  
  print("found %d devices" % (deviceList.Count))
  
  for i in range(deviceList.Count):
      listEntry = deviceList.GetUsbListEntry(i)
      print("Device: %s   Serial: %s" % (listEntry.DeviceName,listEntry.SerialNumber))
  
  
  device = CStg200xDownloadNet();
  
  device.Stg200xPollStatusEvent += PollHandler;
  
  device.Connect(deviceList.GetUsbListEntry(0))
  
  voltageRange = device.GetVoltageRangeInMicroVolt(0);
  voltageResulution = device.GetVoltageResolutionInMicroVolt(0);
  currentRange = device.GetCurrentRangeInNanoAmp(0);
  currentResolution = device.GetCurrentResolutionInNanoAmp(0);
  
  print('Voltage Mode:  Range: %d mV  Resolution: %1.2f mV' % (voltageRange/1000, voltageResulution/1000.0))
  print('Current Mode:  Range: %d uA  Resolution: %1.2f uA' % (currentRange/1000, currentResolution/1000.0))
  
  channelmap = Array[UInt32]([1,0,0,0])
  syncoutmap = Array[UInt32]([1,0,0,0])
  repeat = Array[UInt32]([10,0,0,0])
  
  amplitude = [Array[Int32]([-10000,10000]),Array[Int32]([-10000,10000]),Array[Int32]([-10000,10000])]
  duration = [Array[UInt64]([10000,10000]),Array[UInt64]([10000,10000]),Array[UInt64]([10000,10000])]
  
  electrode = [3,1,52]  #Some list of electrodes I desire to stimulate
  
  for elec in range(len(electrode)):
  
      device.SetElectrodeMode(UInt32(electrode[elec]), ElectrodeModeEnumNet.emManual)
      device.SetElectrodeDacMux(UInt32(electrode[elec]),  UInt32(0), ElectrodeDacMuxEnumNet.Stg1)
      device.SetElectrodeEnable(UInt32(electrode[elec]),  UInt32(0), True);
      device.SetBlankingEnable(UInt32(electrode[elec]), False);
      # AmplifierProtectionSwitch: false: Keep ADC connected to electrode even while stimulation is running
      device.SetEnableAmplifierProtectionSwitch(UInt32(electrode[elec]), False);
      device.PrepareAndSendData(0, amplitude[elec], duration[elec], STG_DestinationEnumNet.channeldata_voltage)
  
  device.SetupTrigger(0, channelmap, syncoutmap, repeat)
  device.SetVoltageMode();
  
  device.SendStart(1)
  time.sleep(10)
  
  device.Disconnect()

from mcsusbnet_examples.

armwal avatar armwal commented on August 12, 2024

Glad to hear that it worked! I don't have a way to test your script with hardware at the moment, so I can't run a full test. The only issue with the code I can see is that you are calling PrepareAndSendData inside the loop. This is not necessary: sending the stimulation data to the device just once is enough. You can move the PrepareAndSendData call outside of the loop, directly before the SetupTrigger call.

from mcsusbnet_examples.

satabios avatar satabios commented on August 12, 2024

Since I was trying to stimulate multiple electrodes I was sending each array of stimulation corresponding to that particular array, that is the reason I put PrepareAndSendData under the loop. Holistically am I stimulating the electrodes in the correct fashion?

from mcsusbnet_examples.

armwal avatar armwal commented on August 12, 2024

Ah, sorry, I overlooked the parameters for the PrepareAndSendData call: Essentially, what you have configured is that all of your electrodes will receive stimulation from the same stimulus generator (Stg1, due to the device.SetElectrodeDacMux(UInt32(electrode[elec]), UInt32(0), ElectrodeDacMuxEnumNet.Stg1) call). Typically, you can only have a single stimulation pattern per stimulus generator, so all your electrodes will receive the same stimulation pattern. Because of this, having

amplitude = Array[Int32]([-10000,10000])
duration = Array[UInt64]([10000,10000])

and then calling device.PrepareAndSendData(0, amplitude, duration, STG_DestinationEnumNet.channeldata_voltage) sends this pattern to all 3 electrodes.

from mcsusbnet_examples.

satabios avatar satabios commented on August 12, 2024

Just to clarify, even if I change the amplitude with varying patterns, the stimulus generator would only pick one type of stimulus?
(i.e..) say if I set amplitude = [Array[Int32]([-10000,0,10000]),Array[Int32]([-300,300]),Array[Int32]([-700,700])] with the corresponding duration intervals. Even then the stimulus would only generate the last pattern?

from mcsusbnet_examples.

armwal avatar armwal commented on August 12, 2024

Sorry, the last code block had some errors, here is the corrected version:

To start all Stgs, you can either assign all of them to the same trigger so they are started together:

channelmap = Array[UInt32]([7,0,0,0])
syncoutmap = Array[UInt32]([7,0,0,0])
repeat = Array[UInt32]([10,0,0,0])
device.SetupTrigger(0, channelmap, syncoutmap, repeat)
device.SendStart(1)

The 7 in channelmap and syncoutmap has to be interpreted as binary 111, meaning all 3 Stgs are assigned to the first trigger, represented as the first entry in the channelmap, syncoutmap and repeat arrays. Then, device.SendStart(1) starts the first trigger.

Another option would be to assign each Stg to its own trigger, so you could start them independently from each other:

channelmap = Array[UInt32]([1,2,4,0])
syncoutmap = Array[UInt32]([1,2,4,0])
repeat = Array[UInt32]([10,10,10,0])
device.SetupTrigger(0, channelmap, syncoutmap, repeat)
device.SendStart(7)

Here, 1, 2 and 4 need to be interpreted as binary 001, 010 and 100, meaning Stg1, Stg2 and Stg3 are assigned to their own triggers. Each trigger is configured with 10 repeats, and device.SendStart(7) means that all 3 triggers are started at the same time.

I'll close this ticket for now, please reopen it if you experience further issues

from mcsusbnet_examples.

Related Issues (13)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.