Skip to content

Commit 1d71cb5

Browse files
Merge pull request #7 from VH-Lab/port-ndi-fun-15436069323376111980
Port ndi.fun from Matlab to Python
2 parents dd08d0a + 5d0fe1b commit 1d71cb5

70 files changed

Lines changed: 1835 additions & 97 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

comparison_table.md

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -353,59 +353,59 @@
353353
| ndi.file.pfilemirror | No | No |
354354
| ndi.file.temp_fid | No | No |
355355
| ndi.file.temp_name | No | No |
356-
| ndi.fun.calc.stimulus_tuningcurve_log | No | No |
357-
| ndi.fun.data.mat2ngrid | No | No |
358-
| ndi.fun.data.readImageStack | No | No |
359-
| ndi.fun.data.readngrid | No | No |
360-
| ndi.fun.data.writengrid | No | No |
361-
| ndi.fun.dataset.diff | No | No |
362-
| ndi.fun.doc.probe.probeLocations4probes | No | No |
363-
| ndi.fun.doc.subject.makeSpeciesStrainSex | No | No |
364-
| ndi.fun.doc.allTypes | No | No |
365-
| ndi.fun.doc.diff | No | No |
366-
| ndi.fun.doc.findFuid | No | No |
367-
| ndi.fun.doc.getDocTypes | No | No |
368-
| ndi.fun.doc.ontologyTableRowDoc2Table | No | No |
369-
| ndi.fun.doc.ontologyTableRowVars | No | No |
370-
| ndi.fun.doc.t0_t1cell2array | No | No |
371-
| ndi.fun.docTable.docCellArray2Table | No | No |
372-
| ndi.fun.docTable.element | No | No |
373-
| ndi.fun.docTable.epoch | No | No |
374-
| ndi.fun.docTable.openminds | No | No |
375-
| ndi.fun.docTable.probe | No | No |
376-
| ndi.fun.docTable.subject | No | No |
377-
| ndi.fun.docTable.treatment | No | No |
378-
| ndi.fun.epoch.epochid2element | No | No |
379-
| ndi.fun.epoch.filename2epochid | No | No |
380-
| ndi.fun.file.MD5 | No | No |
381-
| ndi.fun.file.dateCreated | No | No |
382-
| ndi.fun.file.dateUpdated | No | No |
383-
| ndi.fun.plot.bar3 | No | No |
384-
| ndi.fun.plot.multichan | No | No |
385-
| ndi.fun.probe.location | No | No |
386-
| ndi.fun.session.diff | No | No |
387-
| ndi.fun.stimulus.f0_f1_responses | No | No |
388-
| ndi.fun.stimulus.findMixtureName | No | No |
389-
| ndi.fun.stimulus.tuning_curve_to_response_type | No | No |
390-
| ndi.fun.table.identifyMatchingRows | No | No |
391-
| ndi.fun.table.identifyValidRows | No | No |
392-
| ndi.fun.table.join | No | No |
393-
| ndi.fun.table.moveColumnsLeft | No | No |
394-
| ndi.fun.table.vstack | No | No |
356+
| ndi.fun.calc.stimulus_tuningcurve_log | Yes | Yes |
357+
| ndi.fun.data.mat2ngrid | Yes | Yes |
358+
| ndi.fun.data.readImageStack | Yes | Yes |
359+
| ndi.fun.data.readngrid | Yes | Yes |
360+
| ndi.fun.data.writengrid | Yes | Yes |
361+
| ndi.fun.dataset.diff | Yes | Yes |
362+
| ndi.fun.doc.probe.probeLocations4probes | Yes | Yes |
363+
| ndi.fun.doc.subject.makeSpeciesStrainSex | Yes | Yes |
364+
| ndi.fun.doc.allTypes | Yes | Yes |
365+
| ndi.fun.doc.diff | Yes | Yes |
366+
| ndi.fun.doc.findFuid | Yes | Yes |
367+
| ndi.fun.doc.getDocTypes | Yes | Yes |
368+
| ndi.fun.doc.ontologyTableRowDoc2Table | Yes | Yes |
369+
| ndi.fun.doc.ontologyTableRowVars | Yes | Yes |
370+
| ndi.fun.doc.t0_t1cell2array | Yes | Yes |
371+
| ndi.fun.docTable.docCellArray2Table | Yes | Yes |
372+
| ndi.fun.docTable.element | Yes | Yes |
373+
| ndi.fun.docTable.epoch | Yes | Yes |
374+
| ndi.fun.docTable.openminds | Yes | Yes |
375+
| ndi.fun.docTable.probe | Yes | Yes |
376+
| ndi.fun.docTable.subject | Yes | Yes |
377+
| ndi.fun.docTable.treatment | Yes | Yes |
378+
| ndi.fun.epoch.epochid2element | Yes | Yes |
379+
| ndi.fun.epoch.filename2epochid | Yes | Yes |
380+
| ndi.fun.file.MD5 | Yes | Yes |
381+
| ndi.fun.file.dateCreated | Yes | Yes |
382+
| ndi.fun.file.dateUpdated | Yes | Yes |
383+
| ndi.fun.plot.bar3 | Yes | Yes |
384+
| ndi.fun.plot.multichan | Yes | Yes |
385+
| ndi.fun.probe.location | Yes | Yes |
386+
| ndi.fun.session.diff | Yes | Yes |
387+
| ndi.fun.stimulus.f0_f1_responses | Yes | Yes |
388+
| ndi.fun.stimulus.findMixtureName | Yes | Yes |
389+
| ndi.fun.stimulus.tuning_curve_to_response_type | Yes | Yes |
390+
| ndi.fun.table.identifyMatchingRows | Yes | Yes |
391+
| ndi.fun.table.identifyValidRows | Yes | Yes |
392+
| ndi.fun.table.join | Yes | Yes |
393+
| ndi.fun.table.moveColumnsLeft | Yes | Yes |
394+
| ndi.fun.table.vstack | Yes | Yes |
395395
| ndi.fun.assertAddonOnPath | No | No |
396-
| ndi.fun.channelname2prefixnumber | No | No |
396+
| ndi.fun.channelname2prefixnumber | Yes | Yes |
397397
| ndi.fun.check_Matlab_toolboxes | No | No |
398-
| ndi.fun.console | No | No |
398+
| ndi.fun.console | Yes | Yes |
399399
| ndi.fun.convertoldnsd2ndi | No | No |
400-
| ndi.fun.debuglog | No | No |
401-
| ndi.fun.errlog | No | No |
402-
| ndi.fun.find_calc_directories | No | No |
403-
| ndi.fun.name2variableName | No | No |
400+
| ndi.fun.debuglog | Yes | Yes |
401+
| ndi.fun.errlog | Yes | Yes |
402+
| ndi.fun.find_calc_directories | Yes | Yes |
403+
| ndi.fun.name2variableName | Yes | Yes |
404404
| ndi.fun.plot_extracellular_spikeshapes | No | No |
405-
| ndi.fun.pseudorandomint | No | No |
405+
| ndi.fun.pseudorandomint | Yes | Yes |
406406
| ndi.fun.run_Linux_checks | No | No |
407-
| ndi.fun.stimulustemporalfrequency | No | No |
408-
| ndi.fun.syslog | No | No |
407+
| ndi.fun.stimulustemporalfrequency | Yes | Yes |
408+
| ndi.fun.syslog | Yes | Yes |
409409
| ndi.fun.timestamp | Yes | Yes |
410410
| ndi.gui.component.abstract.ProgressMonitor | No | No |
411411
| ndi.gui.component.internal.event.MessageUpdatedEventData | No | No |

src/ndi/common/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .path_constants import PathConstants

src/ndi/common/path_constants.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import os
2+
3+
class PathConstants:
4+
@staticmethod
5+
def root_folder():
6+
"""
7+
Returns the root folder of the NDI distribution.
8+
"""
9+
# Assuming this file is in src/ndi/common/path_constants.py
10+
# Root is src/ndi/
11+
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
12+
13+
@staticmethod
14+
def common_folder():
15+
"""
16+
Returns the path to the package ndi_common resources.
17+
"""
18+
return os.path.join(PathConstants.root_folder(), 'resources', 'ndi_common')

src/ndi/document.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from did.document import Document
22
from .ido import Ido
3-
import ndi.fun.timestamp
3+
import ndi.fun
44
from .util.vlt import data as vlt_data
55
import json
66
import os
@@ -15,7 +15,7 @@ def __init__(self, document_type, **kwargs):
1515
self.document_properties = self.read_blank_definition(document_type)
1616
ido = Ido()
1717
self.document_properties['base']['id'] = ido.id()
18-
self.document_properties['base']['datestamp'] = ndi.fun.timestamp.timestamp()
18+
self.document_properties['base']['datestamp'] = ndi.fun.timestamp()
1919

2020
for key, value in kwargs.items():
2121
keys = key.split('.')

src/ndi/fun/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from .channel_name_to_prefix_number import channel_name_to_prefix_number
2+
from .name_to_variable_name import name_to_variable_name
3+
from .timestamp import timestamp
4+
from .pseudorandomint import pseudorandomint
5+
from .stimulus_temporal_frequency import stimulus_temporal_frequency
6+
from .find_calc_directories import find_calc_directories
7+
from .console import console
8+
from .debug_log import debug_log
9+
from .err_log import err_log
10+
from .sys_log import sys_log

src/ndi/fun/calc/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .stimulus_tuning_curve_log import stimulus_tuning_curve_log
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from did.query import Query
2+
3+
def stimulus_tuning_curve_log(S, doc):
4+
"""
5+
Retrieve stimulus_tuningcurve log string from dependent document.
6+
7+
Args:
8+
S: ndi.session object.
9+
doc: ndi.document object.
10+
11+
Returns:
12+
str: The log string.
13+
"""
14+
log_str = ''
15+
16+
try:
17+
stim_tune_doc_id = doc.dependency_value('stimulus_tuningcurve_id')
18+
except Exception:
19+
# If dependency not found
20+
return log_str
21+
22+
q1 = Query('base.id', 'exact_string', stim_tune_doc_id)
23+
q2 = Query('', 'isa', 'tuningcurve_calc')
24+
25+
stim_tune_doc = S.database_search(q1 & q2)
26+
27+
if stim_tune_doc:
28+
props = stim_tune_doc[0].document_properties.get('tuningcurve_calc', {})
29+
log_str = props.get('log', '')
30+
31+
return log_str

src/ndi/fun/console.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import sys
2+
import platform
3+
import os
4+
import subprocess
5+
import tempfile
6+
7+
def console(filename):
8+
"""
9+
Pops up an external terminal window that displays a log file.
10+
11+
CONSOLE(FILENAME)
12+
13+
Pops up a console window that displays a log file.
14+
Right now, only MacOS is supported.
15+
"""
16+
17+
system = platform.system()
18+
19+
if system == 'Darwin': # MacOS
20+
# Create temporary applescript file
21+
with tempfile.NamedTemporaryFile(mode='w', suffix='.scpt', delete=False) as f:
22+
script_content = f"""tell application "Terminal"
23+
activate
24+
do script "tail -f {filename}"
25+
end tell"""
26+
f.write(script_content)
27+
temp_filename = f.name
28+
29+
try:
30+
subprocess.run(['osascript', temp_filename], check=True)
31+
finally:
32+
os.remove(temp_filename)
33+
34+
elif system == 'Linux':
35+
# Try some common terminal emulators
36+
terminals = ['gnome-terminal', 'xterm', 'konsole']
37+
launched = False
38+
for term in terminals:
39+
try:
40+
# This is a very basic attempt and might need adjustment for specific terminals
41+
if term == 'gnome-terminal':
42+
subprocess.run([term, '--', 'tail', '-f', filename])
43+
elif term == 'xterm':
44+
subprocess.run([term, '-e', f'tail -f {filename}'])
45+
elif term == 'konsole':
46+
subprocess.run([term, '-e', 'tail', '-f', filename])
47+
launched = True
48+
break
49+
except FileNotFoundError:
50+
continue
51+
52+
if not launched:
53+
raise NotImplementedError("Linux terminal launch not fully supported yet.")
54+
55+
elif system == 'Windows':
56+
raise NotImplementedError("Windows not supported yet.")
57+
else:
58+
raise NotImplementedError(f"{system} not supported yet.")

src/ndi/fun/data/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .read_ngrid import read_ngrid
2+
from .write_ngrid import write_ngrid
3+
from .read_image_stack import read_image_stack
4+
from .mat_to_ngrid import mat_to_ngrid

src/ndi/fun/data/mat_to_ngrid.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def mat_to_ngrid():
2+
raise NotImplementedError("Not yet ported.")

0 commit comments

Comments
 (0)