BCI2000Tools 1.0.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,48 @@
1
+ __all__ = [
2
+ 'ForgetBCI2000Tools',
3
+ ]
4
+ import os
5
+ import sys
6
+ import glob
7
+
8
+ thisSubmoduleName = os.path.splitext( os.path.basename( __file__ ) )[ 0 ]
9
+ parentDir = os.path.realpath( os.path.dirname( __file__ ) )
10
+ parentModuleName = os.path.basename( parentDir )
11
+ submodulePaths = sorted( glob.glob( os.path.join( parentDir, '*.py' ) ) )
12
+ iskosher = lambda x: x.replace( '/', '' ).replace( '\\', '' ).replace( '_', '' ).replace( '.', '' ).isalnum()
13
+ submodulePaths = [ submodulePath for submodulePath in submodulePaths if iskosher( submodulePath[ len( parentDir ): ] ) ]
14
+ sub = None
15
+ allItems = {}
16
+ provenance = {}
17
+ print( '# The path to %s is %s' % ( parentModuleName, parentDir.replace( '\\', '/' ) ) )
18
+ from . import Bootstrapping; from .Bootstrapping import bci2000path, bci2000_exe_extension
19
+ for submodulePath in submodulePaths:
20
+ submoduleName = os.path.splitext( os.path.basename( submodulePath ) )[ 0 ] # NB: this assumes no sub-sub-modules (flat structure inside BCI2000Tools directory)
21
+ if submoduleName in ( '__init__', '__main__', thisSubmoduleName ): continue
22
+ msg = 'from %s.%s import *' % ( parentModuleName, submoduleName )
23
+ canaries = []
24
+ if submoduleName in [ 'Remote' ]:
25
+ canaries.append( 'prog/BCI2000Remote.py' )
26
+ if submoduleName in [ 'Chain' ]:
27
+ exeExtension = bci2000_exe_extension('tools/cmdline')
28
+ canaries.append( 'tools/cmdline/bci_dat2stream' + exeExtension )
29
+ canaries.append( 'tools/cmdline/bci_stream2hybrid' + exeExtension )
30
+ deadCanaries = [ canary for canary in canaries if not os.path.exists( bci2000path( canary ) ) ]
31
+ if deadCanaries:
32
+ print( '#%s # skipped (no %s)' % ( msg, deadCanaries[ 0 ] ) )
33
+ continue
34
+ print( msg )
35
+ exec( 'import %s.%s as sub' % ( parentModuleName, submoduleName ) )
36
+ for name in sub.__all__:
37
+ item = getattr( sub, name )
38
+ if item is not allItems.get( name, item ): print( '# WARNING: %s from %s.%s overwrites %s from %s.%s' % ( name, parentModuleName, submoduleName, name, parentModuleName, provenance[ name ] ) )
39
+ allItems[ name ] = item
40
+ provenance[ name ] = submoduleName
41
+
42
+ __all__ += allItems.keys()
43
+ locals().update( allItems )
44
+
45
+ def ForgetBCI2000Tools():
46
+ for k in list( sys.modules ):
47
+ if k.startswith( parentModuleName + '.' ): del sys.modules[ k ]
48
+
@@ -0,0 +1,145 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # ///////////////////////////////////////////////////////////////////////////
4
+ # $Id: Bootstrapping.py 9000 2025-08-05 18:07:32Z jhill $
5
+ # Author: jeremy.hill@neurotechcenter.org
6
+ # Description: infer/specify/use the location of the BCI2000 distribution
7
+ #
8
+ # $BEGIN_BCI2000_LICENSE$
9
+ #
10
+ # This file is part of BCI2000, a platform for real-time bio-signal research.
11
+ # [ Copyright (C) 2000-2022: BCI2000 team and many external contributors ]
12
+ #
13
+ # BCI2000 is free software: you can redistribute it and/or modify it under the
14
+ # terms of the GNU General Public License as published by the Free Software
15
+ # Foundation, either version 3 of the License, or (at your option) any later
16
+ # version.
17
+ #
18
+ # BCI2000 is distributed in the hope that it will be useful, but
19
+ # WITHOUT ANY WARRANTY
20
+ # - without even the implied warranty of MERCHANTABILITY or FITNESS FOR
21
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
22
+ #
23
+ # You should have received a copy of the GNU General Public License along with
24
+ # this program. If not, see <http://www.gnu.org/licenses/>.
25
+ #
26
+ # $END_BCI2000_LICENSE$
27
+ # ///////////////////////////////////////////////////////////////////////////
28
+ """
29
+ Use `bci2000root()` to set the path to the root directory of the BCI2000
30
+ distribution you want to use. It will be stored as a global variable in the
31
+ module and remembered for the rest of the session.
32
+
33
+ Use `bci2000path()` to resolve partial paths relative to the currently
34
+ configured `bci2000root()` setting.
35
+
36
+ By default, when you first import this submodule, it attempts to set
37
+ `bci2000root()` based on the assumption that the module itself is installed
38
+ within the `tools/python` subtree of the relevant BCI2000 distribution
39
+ (perhaps using `pip install -e`, as recommended in our `setup.py` file). If
40
+ this fails, `bci2000root()` will be left as `None`.
41
+ """
42
+
43
+ __all__ = [
44
+ 'bci2000root', 'bci2000path',
45
+ 'bci2000_exe_extension',
46
+ ]
47
+
48
+ import os
49
+ import sys
50
+ import inspect
51
+
52
+ if sys.version < '3': bytes = str
53
+ else: unicode = str; basestring = ( unicode, bytes )
54
+
55
+ BCI2000_ROOT_DIR = None
56
+
57
+ def bci2000root( set=None ):
58
+ """
59
+ Specify, or query, the absolute path to the root directory of the BCI2000
60
+ distribution (the parent directory of `batch`, `parms`, `prog` and `tools`).
61
+
62
+ If this has been set, `bci2000chain()` will look for command-line binaries
63
+ in the `tools/cmdline` subdirectory of the root, by default.
64
+ """
65
+ global BCI2000_ROOT_DIR
66
+ if set is not None: BCI2000_ROOT_DIR = os.path.realpath( os.path.expanduser( set ) )
67
+ return BCI2000_ROOT_DIR
68
+
69
+ def bci2000path( partial_path ):
70
+ """
71
+ If `bci2000root()` has been set, and the specified `partial_path` exists
72
+ relative to it, join them together and return the resulting absolute path.
73
+
74
+ If not, just return the result of `os.path.realpath(partial_path)`.
75
+ """
76
+ if isinstance( partial_path, basestring ) and isinstance( BCI2000_ROOT_DIR, basestring ) and not os.path.exists( partial_path ) and os.path.exists( os.path.join( BCI2000_ROOT_DIR, partial_path ) ):
77
+ return os.path.realpath( os.path.join( BCI2000_ROOT_DIR, partial_path ) )
78
+ return os.path.realpath( partial_path )
79
+
80
+
81
+ # Now let's automatically try to fill in a default for BCI2000_ROOT_DIR based
82
+ # on the location of this Python module itself.
83
+
84
+ class NoParentDirectory( ValueError ): pass
85
+
86
+ def WhereAmI( nFileSystemLevelsUp=1, nStackLevelsBack=0 ):
87
+ """
88
+ `WhereAmI( 0 )` is equivalent to `__file__`
89
+
90
+ `WhereAmI()` or `WhereAmI(1)` gives you the current source file's
91
+ parent directory.
92
+ """
93
+ my_getfile = inspect.getfile
94
+ if getattr( sys, 'frozen', False ) and hasattr( sys, '_MEIPASS' ):
95
+ # sys._MEIPASS indicates that we're in PyInstaller which, in a surprise reversal
96
+ # of the old py2exe situation, supports `__file__` but NOT `inspect.getfile()`.
97
+ # The following workaround is adapted from
98
+ # http://lists.swapbytes.de/archives/obspy-users/2017-April/002395.html
99
+ def my_getfile( object ):
100
+ if inspect.isframe( object ):
101
+ try: return object.f_globals[ '__file__' ]
102
+ except: pass
103
+ return inspect.getfile( object )
104
+
105
+ try:
106
+ frame = inspect.currentframe()
107
+ for i in range( abs( nStackLevelsBack ) + 1 ):
108
+ frame = frame.f_back
109
+ file = my_getfile( frame )
110
+ finally:
111
+ del frame # https://docs.python.org/3/library/inspect.html#the-interpreter-stack
112
+ result = file = os.path.realpath( file )
113
+ nFileSystemLevelsUp = abs( nFileSystemLevelsUp )
114
+ for i in range( nFileSystemLevelsUp ):
115
+ pardir = os.path.dirname( result )
116
+ if pardir == result: raise NoParentDirectory( 'cannot go %d file-system levels up from %s (maximum is %d)' % ( nFileSystemLevelsUp, file, i ) )
117
+ result = pardir
118
+ return result
119
+
120
+ try: candidate = WhereAmI( 4 ) # assume we are in $BCI2000_ROOT_DIR/tools/python/BCI2000Tools/Bootstrapping.py ...
121
+ except NoParentDirectory: pass
122
+ else:
123
+ for partial in [ 'tools/python' ]: # but if we go up 4 levels and don't find all the partial paths in this list beneath us, cancel that assumption
124
+ if not os.path.isdir( os.path.join( candidate, *partial.split( '/' ) ) ): break
125
+ else: # if no break has occurred
126
+ BCI2000_ROOT_DIR = candidate
127
+
128
+ def bci2000_exe_extension(where=None):
129
+ if where is None:
130
+ where = 'tools/cmdline' if os.path.isdir( bci2000path( 'tools/cmdline' ) ) else 'prog'
131
+ if sys.platform.lower().startswith( 'win' ):
132
+ return '.exe'
133
+ elif sys.platform.lower().startswith( 'darwin' ):
134
+ if where == 'tools/cmdline':
135
+ what = os.path.join( bci2000path( where ), 'bci_dat2stream' )
136
+ if os.path.exists( what + '.app' ) and not os.path.isfile( what ): return '.app'
137
+ else: return ''
138
+ elif where == 'prog':
139
+ what = os.path.join( bci2000path( where ), 'Operator' )
140
+ if os.path.isfile( what ) and not os.path.exists( what + '.app' ): return ''
141
+ else: return '.app'
142
+ else:
143
+ raise ValueError( 'unsupported test location %r' % where )
144
+ else:
145
+ return ''