• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NeuralEnsemble / PyNN / 4092881168

pending completion
4092881168

push

github

GitHub
Merge pull request #775 from apdavison/spring-clean

642 of 746 new or added lines in 66 files covered. (86.06%)

328 existing lines in 17 files now uncovered.

7631 of 10662 relevant lines covered (71.57%)

2.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.67
/pyNN/utility/script_tools.py
1
"""
2
A collection of functions to help writing simualtion scripts.
3

4
:copyright: Copyright 2006-2023 by the PyNN team, see AUTHORS.
5
:license: CeCILL, see LICENSE for details.
6
"""
7

8
from datetime import datetime
4✔
9
import os
4✔
10
import sys
4✔
11
from importlib import import_module
4✔
12
import logging
4✔
13

14
# If there is a settings.py file on the path, defaults will be
15
# taken from there.
16
try:
4✔
17
    from settings import SMTPHOST, EMAIL
4✔
18
except ImportError:
4✔
19
    SMTPHOST = None
4✔
20
    EMAIL = None
4✔
21

22

23
def get_script_args(n_args, usage=''):
4✔
24
    """
25
    Get command line arguments.
26

27
    This works by finding the name of the main script and assuming any
28
    arguments after this in sys.argv are arguments to the script.
29
    It would be nicer to use optparse, but this doesn't seem to work too well
30
    with nrniv or mpirun.
31
    """
32
    calling_frame = sys._getframe(1)
4✔
33
    if '__file__' in calling_frame.f_locals:
4✔
NEW
34
        script = calling_frame.f_locals['__file__']
×
NEW
35
        try:
×
NEW
36
            script_index = sys.argv.index(script)
×
NEW
37
        except ValueError:
×
NEW
38
            try:
×
NEW
39
                script_index = sys.argv.index(os.path.abspath(script))
×
NEW
40
            except ValueError:
×
NEW
41
                script_index = 0
×
42
    else:
43
        script_index = 0
4✔
44
    args = sys.argv[script_index + 1:script_index + 1 + n_args]
4✔
45
    if len(args) != n_args:
4✔
NEW
46
        usage = usage or "Script requires %d arguments, you supplied %d" % (n_args, len(args))
×
NEW
47
        raise Exception(usage)
×
48
    return args
4✔
49

50

51
def get_simulator(*arguments):
4✔
52
    """
53
    Import and return a PyNN simulator backend module based on command-line
54
    arguments.
55

56
    The simulator name should be the first positional argument. If your script
57
    needs additional arguments, you can specify them as (name, help_text) tuples.
58
    If you need more complex argument handling, you should use argparse
59
    directly.
60

61
    Returns (simulator, command-line arguments)
62
    """
NEW
63
    import argparse
×
NEW
64
    parser = argparse.ArgumentParser()
×
NEW
65
    parser.add_argument("simulator",
×
66
                        help="neuron, nest, brian or another backend simulator")
NEW
67
    for argument in arguments:
×
NEW
68
        arg_name, help_text = argument[:2]
×
NEW
69
        extra_args = {}
×
NEW
70
        if len(argument) > 2:
×
NEW
71
            extra_args = argument[2]
×
NEW
72
        parser.add_argument(arg_name, help=help_text, **extra_args)
×
NEW
73
    args = parser.parse_args()
×
NEW
74
    sim = import_module("pyNN.%s" % args.simulator)
×
NEW
75
    return sim, args
×
76

77

78
def init_logging(logfile, debug=False, num_processes=1, rank=0, level=None):
4✔
79
    """
80
    Simple configuration of logging.
81
    """
82
    # allow logfile == None
83
    # which implies output to stderr
84
    # num_processes and rank should be obtained using mpi4py, rather than having them as arguments
85
    if logfile:
4✔
NEW
86
        if num_processes > 1:
×
NEW
87
            logfile += '.%d' % rank
×
NEW
88
        logfile = os.path.abspath(logfile)
×
89

90
    # prefix log messages with mpi rank
91
    mpi_prefix = ""
4✔
92
    if num_processes > 1:
4✔
NEW
93
        mpi_prefix = 'Rank %d of %d: ' % (rank, num_processes)
×
94

95
    if debug:
4✔
96
        log_level = logging.DEBUG
4✔
97
    else:
NEW
98
        log_level = logging.INFO
×
99

100
    # allow user to override exact log_level
101
    if level:
4✔
NEW
102
        log_level = level
×
103

104
    logging.basicConfig(
4✔
105
        level=log_level,
106
        format=mpi_prefix + '%(asctime)s %(levelname)-8s [%(name)s] %(message)s (%(pathname)s[%(lineno)d]:%(funcName)s)',  # noqa: E501
107
        filename=logfile,
108
        filemode='w')
109
    return logging.getLogger("PyNN")
4✔
110

111

112
def normalized_filename(root, basename, extension, simulator,
4✔
113
                        num_processes=None, use_iso8601=False):
114
    """
115
    Generate a file path containing a timestamp and information about the
116
    simulator used and the number of MPI processes.
117

118
    The date is used as a sub-directory name, the date & time are included in the
119
    filename.
120
    If use_iso8601 is True, follow https://en.wikipedia.org/wiki/ISO_8601
121
    """
122
    timestamp = datetime.now()
2✔
123
    if use_iso8601:
2✔
NEW
124
        date = timestamp.strftime("%Y-%m-%d")
×
NEW
125
        date_time = timestamp.strftime("%Y-%m-%dT%H:%M:%S")
×
126
    else:
127
        date = timestamp.strftime("%Y%m%d")
2✔
128
        date_time = timestamp.strftime("%Y%m%d-%H%M%S")
2✔
129

130
    if num_processes:
2✔
NEW
131
        np = "_np%d" % num_processes
×
132
    else:
133
        np = ""
2✔
134
    return os.path.join(root,
2✔
135
                        date,
136
                        "%s_%s%s_%s.%s" % (basename,
137
                                           simulator,
138
                                           np,
139
                                           date_time,
140
                                           extension))
141

142

143
def notify(
4✔
144
    msg="Simulation finished.",
145
    subject="Simulation finished.",
146
    smtphost=SMTPHOST,
147
    address=EMAIL,
148
):
149
    """Send an e-mail stating that the simulation has finished."""
150
    if not (smtphost and address):
4✔
151
        print(
4✔
152
            "SMTP host and/or e-mail address not specified.\n"
153
            "Unable to send notification message."
154
        )
155
    else:
NEW
156
        import smtplib
×
157

NEW
158
        msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n") % (
×
159
            address,
160
            address,
161
            subject,
162
        ) + msg
NEW
163
        msg += "\nTimestamp: %s" % datetime.now().strftime("%H:%M:%S, %F")
×
NEW
164
        server = smtplib.SMTP(smtphost)
×
NEW
165
        server.sendmail(address, address, msg)
×
NEW
166
        server.quit()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc