示例#1
0
    def __init__(self):
        self.model_interpreter = NetPyNEModelInterpreter()

        # Geppetto model of a created network
        self.geppetto_model = None

        self.netParams = specs.NetParams()
        self.simConfig = specs.SimConfig()
        self.run_config = model.RunConfig()

        self.experiments = experiments

        model.register(metadata)

        synchronization.startSynchronization(self.__dict__)
        logging.debug("Initializing the original model")

        jupyter_geppetto.context = {'netpyne_geppetto': self}

        # Set running experiments without any subprocess to ERRROR
        experiments.get_experiments()
        running_exps = experiments.get_by_states([
            model.ExperimentState.PENDING, model.ExperimentState.SIMULATING,
            model.ExperimentState.INSTANTIATING
        ])
        if not simulations.local.is_running():
            [experiments.set_to_error(e) for e in running_exps]
示例#2
0
    def getGeppettoModel(self, netParams, simConfig):
        sim.create(netParams, simConfig, True)
        sim.gatherData()

        modelInterpreter = NetPyNEModelInterpreter()
        geppettoModel = modelInterpreter.getGeppettoModel(sim)
        sim.analyze()
示例#3
0
    def __init__(self):
        self.model_interpreter = NetPyNEModelInterpreter()

        self.netParams = specs.NetParams()
        self.simConfig = specs.SimConfig()
        synchronization.startSynchronization(self.__dict__)
        logging.debug("Initializing the original model")

        jupyter_geppetto.context = {'netpyne_geppetto': self}
示例#4
0
class NetPyNEGeppetto:
    def __init__(self):
        self.model_interpreter = NetPyNEModelInterpreter()

        self.netParams = specs.NetParams()
        self.simConfig = specs.SimConfig()
        synchronization.startSynchronization(self.__dict__)
        logging.debug("Initializing the original model")

        jupyter_geppetto.context = {'netpyne_geppetto': self}

    def getData(self):
        return {
            "metadata": metadata,
            "netParams": self.netParams.todict(),
            "simConfig": self.simConfig.todict(),
            "isDocker": os.path.isfile('/.dockerenv'),
            "currentFolder": os.getcwd(),
            "tuts": self.find_tutorials()
        }

    def find_tutorials(self):
        from os import listdir
        from os.path import isfile, join
        onlyfiles = [
            f for f in listdir(NETPYNE_WORKDIR_PATH)
            if isfile(join(NETPYNE_WORKDIR_PATH, f))
        ]

        def _filter(_file):
            return '.py' in _file and 'tut' in _file and 'gui' in _file

        return list(filter(_filter, onlyfiles))

    def instantiateNetPyNEModelInGeppetto(self, args):
        try:
            with redirect_stdout(sys.__stdout__):
                if not 'usePrevInst' in args or not args['usePrevInst']:
                    netpyne_model = self.instantiateNetPyNEModel()
                    self.geppetto_model = self.model_interpreter.getGeppettoModel(
                        netpyne_model)

                return json.loads(
                    GeppettoModelSerializer.serialize(self.geppetto_model))
        except:
            return utils.getJSONError(
                "Error while instantiating the NetPyNE model", sys.exc_info())

    def simulateNetPyNEModelInGeppetto(self, args):
        try:
            with redirect_stdout(sys.__stdout__):
                # TODO mpi is not finding  libmpi.dylib.. set LD_LIBRARY_PATH to openmpi bin folder, but nothing
                if args['parallelSimulation']:
                    logging.debug('Running parallel simulation')
                    if not 'usePrevInst' in args or not args['usePrevInst']:
                        self.netParams.save("netParams.json")
                        self.simConfig.saveJson = True
                        self.simConfig.save("simParams.json")
                        template = os.path.join(os.path.dirname(__file__),
                                                'template.py')
                    else:
                        sim.cfg.saveJson = True
                        oldName = sim.cfg.filename
                        sim.cfg.filename = 'model_output'
                        sim.saveData()
                        sim.cfg.filename = oldName
                        template = os.path.join(os.path.dirname(__file__),
                                                'template2.py')
                    copyfile(template, './init.py')

                    cp = subprocess.run([
                        "mpiexec", "-n", args['cores'], "nrniv", "-mpi",
                        "-python", "init.py"
                    ],
                                        capture_output=True)
                    print(cp.stdout.decode() + cp.stderr.decode())
                    if cp.returncode != 0:
                        return utils.getJSONError(
                            "Error while simulating the NetPyNE model",
                            cp.stderr.decode())
                    sim.load('model_output.json')
                    self.geppetto_model = self.model_interpreter.getGeppettoModel(
                        sim)
                    netpyne_model = sim

                else:
                    logging.info("Starting simulation")

                    if not args.get('usePrevInst', False):
                        logging.debug('Instantiating single thread simulation')
                        netpyne_model = self.instantiateNetPyNEModel()
                        self.geppetto_model = self.model_interpreter.getGeppettoModel(
                            netpyne_model)

                    logging.debug('Running single thread simulation')
                    netpyne_model = self.simulateNetPyNEModel()

                return json.loads(
                    GeppettoModelSerializer.serialize(self.geppetto_model))
        except:
            return utils.getJSONError(
                "Error while simulating the NetPyNE model", sys.exc_info())

    def loadModel(self, args):
        """ Imports a model stored as file in json format.

        :param args:
        :return:
        """
        def remove(dictionary):
            # remove reserved keys such as __dict__, __Method__, etc
            # they appear when we do sim.loadAll(json_file)
            if isinstance(dictionary, dict):
                for key, value in list(dictionary.items()):
                    if key.startswith('__'):
                        dictionary.pop(key)
                    else:
                        remove(value)

        if not any([
                args[option] for option in
            ['loadNetParams', 'loadSimCfg', 'loadSimData', 'loadNet']
        ]):
            return utils.getJSONError(
                "Error while loading data",
                'You have to select at least one option')

        try:
            owd = os.getcwd()
            compileModMechFiles(args['compileMod'], args['modFolder'])
        except:
            return utils.getJSONError("Error while importing/compiling mods",
                                      sys.exc_info())
        finally:
            os.chdir(owd)

        try:
            with redirect_stdout(sys.__stdout__):
                sim.initialize()
                wake_up_geppetto = False
                if all([
                        args[option] for option in
                    ['loadNetParams', 'loadSimCfg', 'loadSimData', 'loadNet']
                ]):
                    wake_up_geppetto = True
                    if self.doIhaveInstOrSimData()['haveInstance']:
                        sim.clearAll()
                    sim.initialize()
                    sim.loadAll(args['jsonModelFolder'])
                    self.netParams = sim.net.params
                    self.simConfig = sim.cfg
                    remove(self.netParams.todict())
                    remove(self.simConfig.todict())
                else:
                    if args['loadNet']:
                        wake_up_geppetto = True
                        if self.doIhaveInstOrSimData()['haveInstance']:
                            sim.clearAll()
                        sim.initialize()
                        sim.loadNet(args['jsonModelFolder'])

                    if args['loadSimData']:  # TODO (https://github.com/Neurosim-lab/netpyne/issues/360)
                        wake_up_geppetto = True
                        if not self.doIhaveInstOrSimData()['haveInstance']:
                            sim.create(specs.NetParams(), specs.SimConfig())
                            sim.net.defineCellShapes()
                            sim.gatherData(gatherLFP=False)
                        sim.loadSimData(args['jsonModelFolder'])

                    if args['loadSimCfg']:
                        sim.loadSimCfg(args['jsonModelFolder'])
                        self.simConfig = sim.cfg
                        remove(self.simConfig.todict())

                    if args['loadNetParams']:
                        if self.doIhaveInstOrSimData()['haveInstance']:
                            sim.clearAll()
                        sim.loadNetParams(args['jsonModelFolder'])
                        self.netParams = sim.net.params
                        remove(self.netParams.todict())

                if wake_up_geppetto:
                    if len(sim.net.cells) > 0:
                        section = list(sim.net.cells[0].secs.keys())[0]
                        if 'pt3d' not in list(
                                sim.net.cells[0].secs[section].geom.keys()):
                            sim.net.defineCellShapes()
                            sim.gatherData()
                            sim.loadSimData(args['jsonModelFolder'])

                    sim.gatherData()
                    self.geppetto_model = self.model_interpreter.getGeppettoModel(
                        sim)
                    return json.loads(
                        GeppettoModelSerializer.serialize(self.geppetto_model))
                else:
                    return utils.getJSONReply()
        except:
            return utils.getJSONError("Error while loading the NetPyNE model",
                                      sys.exc_info())

    def importModel(self, modelParameters):
        """ Imports a model stored in form of Python files.

        :param modelParameters:
        :return:
        """
        if self.doIhaveInstOrSimData()['haveInstance']:
            # TODO: this must be integrated into the general lifecycle of "model change -> simulate"
            #   Shouldn't be specific to Import
            sim.clearAll()

        try:
            # Get Current dir
            owd = os.getcwd()

            compileModMechFiles(modelParameters['compileMod'],
                                modelParameters['modFolder'])

            with redirect_stdout(sys.__stdout__):
                # NetParams
                net_params_path = str(modelParameters["netParamsPath"])
                sys.path.append(net_params_path)
                os.chdir(net_params_path)
                # Import Module
                net_params_module_name = importlib.import_module(
                    str(modelParameters["netParamsModuleName"]))
                # Import Model attributes
                self.netParams = getattr(
                    net_params_module_name,
                    str(modelParameters["netParamsVariable"]))

                for key, value in self.netParams.cellParams.items():
                    if hasattr(value, 'todict'):
                        self.netParams.cellParams[key] = value.todict()

                # SimConfig
                sim_config_path = str(modelParameters["simConfigPath"])
                sys.path.append(sim_config_path)
                os.chdir(sim_config_path)
                # Import Module
                sim_config_module_name = importlib.import_module(
                    str(modelParameters["simConfigModuleName"]))
                # Import Model attributes
                self.simConfig = getattr(
                    sim_config_module_name,
                    str(modelParameters["simConfigVariable"]))

                # TODO: when should sim.initialize be called?
                #   Only on import or better before every simulation or network instantiation?
                sim.initialize()
            return utils.getJSONReply()
        except:
            return utils.getJSONError(
                "Error while importing the NetPyNE model", sys.exc_info())
        finally:
            os.chdir(owd)

    def importCellTemplate(self, modelParameters):
        try:
            with redirect_stdout(sys.__stdout__):
                rule = modelParameters["label"]
                # Get Current dir
                owd = os.getcwd()

                conds = {} if rule not in self.netParams.cellParams else self.netParams.cellParams[
                    rule]['conds']

                compileModMechFiles(modelParameters["compileMod"],
                                    modelParameters["modFolder"])

                del modelParameters["modFolder"]
                del modelParameters["compileMod"]
                # import cell template
                self.netParams.importCellParams(**modelParameters, conds=conds)

                # convert fron netpyne.specs.dict to dict
                self.netParams.cellParams[rule] = self.netParams.cellParams[
                    rule].todict()

                return utils.getJSONReply()
        except:
            return utils.getJSONError(
                "Error while importing the NetPyNE cell template",
                sys.exc_info())
        finally:
            os.chdir(owd)

    def exportModel(self, args):
        try:
            with redirect_stdout(sys.__stdout__):
                if not args['netCells']:
                    sim.initialize(netParams=self.netParams,
                                   simConfig=self.simConfig)
                sim.cfg.filename = args['fileName']
                include = [
                    el for el in specs.SimConfig().saveDataInclude
                    if el in args.keys() and args[el]
                ]
                if args['netCells']: include += ['netPops']
                sim.cfg.saveJson = True
                sim.saveData(include)
                sim.cfg.saveJson = False

                with open(f"{sim.cfg.filename}.json") as json_file:
                    data = json.load(json_file)
                    return data

            return utils.getJSONReply()
        except:
            return utils.getJSONError(
                "Error while exporting the NetPyNE model", sys.exc_info())

    def exportNeuroML(self, modelParams):
        try:
            with redirect_stdout(sys.__stdout__):
                sim.exportNeuroML2(modelParams['fileName'], specs.SimConfig())
            return utils.getJSONReply()
        except:
            return utils.getJSONError(
                "Error while exporting the NetPyNE model", sys.exc_info())

    def importNeuroML(self, modelParams):
        try:
            with redirect_stdout(sys.__stdout__):
                sim.initialize()
                sim.importNeuroML2(modelParams['neuroMLFolder'],
                                   simConfig=specs.SimConfig(),
                                   simulate=False,
                                   analyze=False)
                self.geppetto_model = self.model_interpreter.getGeppettoModel(
                    sim)
            return json.loads(
                GeppettoModelSerializer.serialize(self.geppetto_model))

        except:
            return utils.getJSONError(
                "Error while exporting the NetPyNE model", sys.exc_info())

    def deleteModel(self, modelParams):
        try:
            with redirect_stdout(sys.__stdout__):
                self.netParams = specs.NetParams()
                self.simConfig = specs.SimConfig()
                sim.initialize(specs.NetParams(), specs.SimConfig())
                self.geppetto_model = None
        except:
            return utils.getJSONError(
                "Error while exporting the NetPyNE model", sys.exc_info())

        try:
            # This function fails is some keys don't exists
            # sim.clearAll()
            # TODO: as part of #264 we should remove the method and use clearAll intstead
            self.clearSim()
        except:
            pass

        return utils.getJSONReply()

    def instantiateNetPyNEModel(self):
        with redirect_stdout(sys.__stdout__):
            saveData = sim.allSimData if hasattr(
                sim, 'allSimData') and 'spkt' in sim.allSimData.keys() and len(
                    sim.allSimData['spkt']) > 0 else False
            sim.create(self.netParams, self.simConfig)
            sim.net.defineCellShapes(
            )  # creates 3d pt for cells with stylized geometries
            sim.gatherData(gatherLFP=False)
            if saveData:
                sim.allSimData = saveData  # preserve data from previous simulation

        return sim

    def simulateNetPyNEModel(self):
        with redirect_stdout(sys.__stdout__):
            sim.setupRecording()
            sim.simulate()
            sim.saveData()
        return sim

    def doIhaveInstOrSimData(self):
        """ Telling if we have an instance or simulated data.

        return [bool, bool]
        """
        with redirect_stdout(sys.__stdout__):
            out = [False, False]
            if hasattr(sim, 'net'):
                if hasattr(sim.net, 'cells') and hasattr(sim.net, 'pops'):
                    if len(sim.net.cells) > 0 and len(sim.net.pops.keys()) > 0:
                        out[0] = True
            if hasattr(sim, 'allSimData'):
                if 'spkt' in sim.allSimData.keys(
                ) and 'spkid' in sim.allSimData.keys():
                    if len(sim.allSimData['spkt']) > 0 and len(
                            sim.allSimData['spkid']) > 0:
                        out[1] = True

        return {'haveInstance': out[0], 'haveSimData': out[1]}

    def rename(self, path, oldValue, newValue):
        command = 'sim.rename(self.' + path + ',"' + oldValue + '","' + newValue + '")'
        logging.debug('renaming ' + command)
        eval(command)

        for model, synched_component in list(
                jupyter_geppetto.synched_models.items()):
            if model != '' and oldValue in model and path in model:  #
                jupyter_geppetto.synched_models.pop(model)
                newModel = re.sub(
                    "(['])(?:(?=(\\?))\2.)*?\1",
                    lambda x: x.group(0).replace(oldValue, newValue, 1), model)
                logging.debug("Rename funct - Model is " + model +
                              " newModel is " + newModel)
                jupyter_geppetto.synched_models[newModel] = synched_component
        with redirect_stdout(sys.__stdout__):
            if "popParams" in path:
                self.propagate_field_rename("pop", newValue, oldValue)
            elif "stimSourceParams" in path:
                self.propagate_field_rename("source", newValue, oldValue)
            elif "synMechParams" in path:
                self.propagate_field_rename("synMech", newValue, oldValue)

        return 1

    def getPlotSettings(self, plot_name):
        if self.simConfig.analysis and plot_name in self.simConfig.analysis:
            return self.simConfig.analysis[plot_name]
        return {}

    def getDirList(self, dir=None, onlyDirs=False, filterFiles=False):
        # Get Current dir
        if dir == None or dir == '':
            dir = os.path.join(os.getcwd(), NETPYNE_WORKDIR_PATH)
        dir_list = []
        file_list = []
        for f in sorted(os.listdir(str(dir)), key=str.lower):
            ff = os.path.join(dir, f)
            if os.path.isdir(ff):
                dir_list.append({
                    'title': f,
                    'path': ff,
                    'load': False,
                    'children': [{
                        'title': 'Loading...'
                    }]
                })
            elif not onlyDirs:
                if not filterFiles or os.path.isfile(ff) and ff.endswith(
                        filterFiles):
                    file_list.append({'title': f, 'path': ff})
        return dir_list + file_list

    def checkAvailablePlots(self):
        return analysis.checkAvailablePlots()

    def getPlot(self, plotName, LFPflavour, theme='gui'):
        try:
            with redirect_stdout(sys.__stdout__):
                args = self.getPlotSettings(plotName)
                if LFPflavour:
                    args['plots'] = [LFPflavour]

                args['showFig'] = False

                if plotName.startswith('iplot'):
                    # This arg brings dark theme. But some plots are broken by it
                    args['theme'] = theme

                    if plotName in ("iplotConn",
                                    "iplot2Dnet") and sim.net.allCells:
                        # To prevent unresponsive kernel, we don't show conns if they become too many
                        num_conn = sum([
                            len(cell.conns) for cell in sim.net.allCells
                            if cell.conns
                        ])
                        if num_conn > NUM_CONN_LIMIT:
                            args["showConns"] = False

                    html = getattr(analysis, plotName)(**args)
                    if not html or html == -1:
                        return ""

                    # some plots return "fig", some return "(fig, data)"
                    if plotName in ('iplotRaster', 'iplotRxDConcentration',
                                    'iplot2Dnet'):
                        html = html[0]

                    return html

                else:

                    figData = getattr(analysis, plotName)(**args)

                    if isinstance(figData, tuple):
                        fig = figData[0]
                        if fig == -1:
                            return fig
                        elif isinstance(fig, list):
                            return [ui.getSVG(fig[0])]
                        elif isinstance(fig, dict):
                            svgs = []
                            for key, value in fig.items():
                                svgs.append(ui.getSVG(value))
                            return svgs
                        else:
                            return [ui.getSVG(fig)]
                    else:
                        return figData
        except Exception as e:
            # TODO: Extract these two lines as a function and call it in every catch clause
            err = "There was an exception in %s():" % (e.plotName)
            logging.exception(("%s \n %s \n%s" % (err, e, sys.exc_info())))

    def getAvailablePops(self):
        return list(self.netParams.popParams.keys())

    def getAvailableCellModels(self):
        cellModels = set([])
        for p in self.netParams.popParams:
            if 'cellModel' in self.netParams.popParams[p]:
                cm = self.netParams.popParams[p]['cellModel']
                if cm not in cellModels:
                    cellModels.add(cm)
        return list(cellModels)

    def getAvailableCellTypes(self):
        cellTypes = set([])
        for p in self.netParams.cellParams:
            cellTypes.add(p)
        return list(cellTypes)

    def getAvailableSections(self):
        sections = {}
        for cellRule in self.netParams.cellParams:
            sections[cellRule] = list(
                self.netParams.cellParams[cellRule]['secs'].keys())
        return sections

    def getAvailableStimSources(self):
        return list(self.netParams.stimSourceParams.keys())

    def getAvailableSynMech(self):
        return list(self.netParams.synMechParams.keys())

    def getAvailableMechs(self):
        mechs = mechVarList()['mechs']
        for key in list(mechs.keys()):
            if 'ion' in key: del mechs[key]
        for key in ["morphology", "capacitance", "extracellular"]:
            del mechs[key]
        return list(mechs.keys())

    def getMechParams(self, mechanism):
        params = mechVarList()['mechs'][mechanism]
        return [value[:-(len(mechanism) + 1)] for value in params]

    def getAvailablePlots(self):
        plots = [
            "iplotRaster", "iplotSpikeHist", "plotSpikeStats", "iplotRatePSD",
            "iplotTraces", "iplotLFP", "plotShape", "plot2Dnet", "iplotConn",
            "granger"
        ]

        return [
            plot for plot in plots
            if plot not in list(self.simConfig.analysis.keys())
        ]

    def getInclude(self, model):
        with redirect_stdout(sys.__stdout__):
            if model in list(netpyne_geppetto.simConfig.analysis.keys()):
                if 'include' in list(
                        netpyne_geppetto.simConfig.analysis[model].keys()):
                    return netpyne_geppetto.simConfig.analysis[model][
                        'include']
                else:
                    return False
            else:
                return False

    def getGIDs(self):
        # pop sizes and gids returned in a dict
        out = {}
        with redirect_stdout(sys.__stdout__):
            for key in self.netParams.popParams.keys():
                if 'numCells' in self.netParams.popParams[key]:
                    out[key] = self.netParams.popParams[key]['numCells']
                else:
                    out[key] = 0

            out['gids'] = int(np.sum([v for k, v in list(out.items())]))

        return out

    def deleteParam(self, model, label):
        try:
            if isinstance(model, list):  # just for cellParams
                if len(model) == 1:
                    self.netParams.cellParams[model[0]]["secs"].pop(label)
                elif len(model) == 2:
                    self.netParams.cellParams[model[0]]["secs"][
                        model[1]]["mechs"].pop(label)
                else:
                    pass
            else:
                # remove rule
                rule = getattr(self.netParams, model).pop(label)

                # side effect on other rules
                if "popParams" in model:
                    self.propagate_field_rename("pop", None, label)
                    self.propagate_field_rename("cellModel", None,
                                                rule['cellModel'])
                    self.propagate_field_rename("cellType", None,
                                                rule['cellType'])

                elif "stimSourceParams" in model:

                    self.propagate_field_rename("source", None, label)
                elif "synMechParams" in model:
                    self.propagate_field_rename("synMech", None, label)
            return True
        except:
            return False

    def validateFunction(self, functionString):
        if isinstance(functionString, (float, int)):
            return True
        return validateFunction(functionString, self.netParams.__dict__)

    def exportHLS(self, args):
        def convert2bool(string):
            return string.replace('true', 'True').replace('false',
                                                          'False').replace(
                                                              'null', 'False')

        def header(title, spacer='-'):
            return '\n# ' + title.upper() + ' ' + spacer * (77 -
                                                            len(title)) + '\n'

        try:
            params = ['popParams', 'cellParams', 'synMechParams']
            params += ['connParams', 'stimSourceParams', 'stimTargetParams']

            fname = args['fileName'] if args['fileName'][
                -3:] == '.py' else args['fileName'] + '.py'

            with open(fname, 'w') as script:
                script.write('from netpyne import specs, sim\n')
                script.write(header('documentation'))
                script.write(
                    "''' Script generated with NetPyNE-UI. Please visit:\n")
                script.write(
                    "    - https://www.netpyne.org\n    - https://github.com/MetaCell/NetPyNE-UI\n'''\n"
                )
                script.write(header('script', spacer='='))
                script.write('netParams = specs.NetParams()\n')
                script.write('simConfig = specs.SimConfig()\n')
                script.write(header('single value attributes'))
                for attr, value in list(self.netParams.__dict__.items()):
                    if attr not in params:
                        if value != getattr(specs.NetParams(), attr):
                            script.write('netParams.' + attr + ' = ')
                            script.write(
                                convert2bool(json.dumps(value, indent=4)) +
                                '\n')

                script.write(header('network attributes'))
                for param in params:
                    for key, value in list(
                            getattr(self.netParams, param).items()):
                        script.write("netParams." + param + "['" + key +
                                     "'] = ")
                        script.write(
                            convert2bool(json.dumps(value, indent=4)) + '\n')

                script.write(header('network configuration'))
                for attr, value in list(self.simConfig.__dict__.items()):
                    if value != getattr(specs.SimConfig(), attr):
                        script.write('simConfig.' + attr + ' = ')
                        script.write(
                            convert2bool(json.dumps(value, indent=4)) + '\n')

                script.write(header('create simulate analyze  network'))
                script.write(
                    '# sim.createSimulateAnalyze(netParams=netParams, simConfig=simConfig)\n'
                )

                script.write(header('end script', spacer='='))

            with open(fname) as f:
                return f.read()

        except:
            return utils.getJSONError(
                "Error while importing the NetPyNE model", sys.exc_info())

    def propagate(self, model, label, cond, new, old):
        with redirect_stdout(sys.__stdout__):
            if model == 'analysis':
                analysis = getattr(self.simConfig, model)
                for plot in analysis.keys():
                    if cond in analysis[plot].keys():
                        for index, item in enumerate(analysis[plot][cond]):
                            if isinstance(item, str):
                                if item == old:
                                    if new == None:
                                        analysis[plot][cond].remove(item)
                                        break
                                    else:
                                        analysis[plot][cond][index] = new
                            else:
                                if isinstance(item[0], str):
                                    if item[0] == old:
                                        if new == None:
                                            analysis[plot][cond].pop(index)
                                            break
                                        else:
                                            analysis[plot][cond][index] = [
                                                new, item[1]
                                            ]
            else:
                obj = getattr(self.netParams, model)
                for key in obj.keys():
                    if label in list(obj[key][cond].keys()):
                        if isinstance(obj[key][cond][label], str):
                            if old == obj[key][cond][label]:
                                if new == '' or new == None:
                                    obj[key].pop(label)
                                else:
                                    obj[key][cond][label] = new
                        elif isinstance(obj[key][cond][label], list):
                            if old in obj[key][cond][label]:
                                if new == '' or new == None:
                                    obj[key][cond][label] = [
                                        value
                                        for value in obj[key][cond][label]
                                        if value != old
                                    ]
                                else:
                                    obj[key][cond][label] = [
                                        value if value != old else new
                                        for value in obj[key][cond][label]
                                    ]
                            if len(obj[key][cond][label]) == 0:
                                obj[key][cond].pop(label)
                        else:
                            pass

    def propagate_field_rename(self, label, new, old):
        def unique(label=label, old=old):
            classes = []
            for p in self.netParams.popParams:
                if label in self.netParams.popParams[p]:
                    classes.append(self.netParams.popParams[p][label])
            if classes.count(old) > 0:
                return False
            else:
                return True

        if label == 'source':
            self.propagate_stim_source_rename(new, old)
            return True
        elif label == 'synMech':
            self.propagate_syn_mech_rename(new, old)
            return True
        else:
            if unique():
                for (model, cond) in [['cellParams', 'conds'],
                                      ['connParams', 'preConds'],
                                      ['connParams', 'postConds'],
                                      ['stimTargetParams', 'conds'],
                                      ['analysis', 'include']]:
                    self.propagate(model, label, cond, new, old)
                return True
            else:
                return False

    def propagate_section_rename(self, new, old):
        for label in self.netParams.cellParams:
            if 'secs' in self.netParams.cellParams[label]:
                for sec in self.netParams.cellParams[label]['secs']:
                    if 'topol' in self.netParams.cellParams[label]['secs'][
                            sec]:
                        if 'parentSec' in self.netParams.cellParams[label][
                                'secs'][sec]['topol']:
                            if self.netParams.cellParams[label]['secs'][sec][
                                    'topol']['parentSec'] == old:
                                if new == None:
                                    self.netParams.cellParams[label]['secs'][
                                        sec]['topol'].pop('parentSec')
                                else:
                                    self.netParams.cellParams[label]['secs'][
                                        sec]['topol']['parentSec'] = new

    def propagate_stim_source_rename(self, new, old):
        for label in self.netParams.stimTargetParams:
            if old == self.netParams.stimTargetParams[label]['source']:
                if new == None:
                    self.netParams.stimTargetParams[label].pop('source')
                else:
                    self.netParams.stimTargetParams[label]['source'] = new

    def propagate_syn_mech_rename(self, new, old):
        for label in self.netParams.stimTargetParams:
            if 'source' in self.netParams.stimTargetParams[label]:
                if self.netParams.stimTargetParams[label][
                        'source'] in self.netParams.stimSourceParams:
                    if 'type' in self.netParams.stimSourceParams[
                            self.netParams.stimTargetParams[label]['source']]:
                        if self.netParams.stimSourceParams[
                                self.netParams.stimTargetParams[label]
                            ['source']]['type'] == 'NetStim':
                            if old == self.netParams.stimTargetParams[label][
                                    'synMech']:
                                if new == None:
                                    self.netParams.stimTargetParams[label].pop(
                                        'synMech')
                                else:
                                    self.netParams.stimTargetParams[label][
                                        'synMech'] = new

    def clearSim(self):
        # clean up
        sim.pc.barrier()
        sim.pc.gid_clear()  # clear previous gid settings

        # clean cells and simData in all nodes
        sim.clearObj([
            cell.__dict__ if hasattr(cell, '__dict__') else cell
            for cell in sim.net.cells
        ])
        if 'stims' in list(sim.simData.keys()):
            sim.clearObj([stim for stim in sim.simData['stims']])

        for key in list(sim.simData.keys()):
            del sim.simData[key]

        if hasattr(sim, 'net'):
            for c in sim.net.cells:
                del c
            for p in sim.net.pops:
                del p
            if hasattr(sim.net, 'params'):
                del sim.net.params

        # clean cells and simData gathered in master node
        if sim.rank == 0:
            if hasattr(sim.net, 'allCells'):
                sim.clearObj([
                    cell.__dict__ if hasattr(cell, '__dict__') else cell
                    for cell in sim.net.allCells
                ])
            if hasattr(sim, 'allSimData'):
                if 'stims' in list(sim.allSimData.keys()):
                    sim.clearObj([stim for stim in sim.allSimData['stims']])
                for key in list(sim.allSimData.keys()):
                    del sim.allSimData[key]
                del sim.allSimData

            import matplotlib
            matplotlib.pyplot.clf()
            matplotlib.pyplot.close('all')

        if hasattr(sim, 'net'):
            if hasattr(sim.net, 'allCells'):
                for c in sim.net.allCells:
                    del c
                del sim.net.allCells
            if hasattr(sim.net, 'allPops'):
                for p in sim.net.allPops:
                    del p

            del sim.net

        import gc
        gc.collect()

    def create_celltype_from_template(self,
                                      label="CellType",
                                      conds={},
                                      cell_template_name="Blank"):
        try:
            with redirect_stdout(sys.__stdout__):
                self.netParams.addCellParamsTemplate(
                    label=label, template=cell_template_name)
            return True
        except:
            return utils.getJSONError(
                f"Error while creating cellType from template {cell_template_name}",
                sys.exc_info())
示例#5
0
class NetPyNEGeppetto:
    def __init__(self):
        self.model_interpreter = NetPyNEModelInterpreter()

        # Geppetto model of a created network
        self.geppetto_model = None

        self.netParams = specs.NetParams()
        self.simConfig = specs.SimConfig()
        self.run_config = model.RunConfig()

        self.experiments = experiments

        model.register(metadata)

        synchronization.startSynchronization(self.__dict__)
        logging.debug("Initializing the original model")

        jupyter_geppetto.context = {'netpyne_geppetto': self}

        # Set running experiments without any subprocess to ERRROR
        experiments.get_experiments()
        running_exps = experiments.get_by_states([
            model.ExperimentState.PENDING, model.ExperimentState.SIMULATING,
            model.ExperimentState.INSTANTIATING
        ])
        if not simulations.local.is_running():
            [experiments.set_to_error(e) for e in running_exps]

    def getData(self):
        return {
            "metadata": metadata,
            "netParams": self.netParams.todict(),
            "simConfig": self.simConfig.todict(),
            "isDocker": os.path.isfile('/.dockerenv'),
            "currentFolder": os.getcwd(),
            "tuts": self.find_tutorials(),
            "cores": simulations.local.cpus
        }

    def getModelAsJson(self):
        # TODO: netpyne should offer a method asJSON (#240)
        #  that returns the JSON model without dumping to to disk.
        obj = netpyne_utils.replaceFuncObj(self.netParams.__dict__)
        obj = netpyne_utils.replaceDictODict(obj)
        return obj

    def get_run_configuration(self):
        return dataclasses.asdict(self.run_config)

    def edit_run_configuration(self, configDictionary: dict):
        self.run_config = from_dict(model.RunConfig, configDictionary)

    def cloneExperiment(self, payload: dict):
        """ Loads experiment from disk and replaces experiment in design with it.

        1. Replaces current experiment in design with copy of stored experiment.
        2. Replace current model specification with spec of stored experiment.

        :param payload: { name: str, replaceModelSpec: bool, replaceExperiment: bool }
        """
        name = payload.get('name')

        # Creates new Experiment in design based on `name` experiment.
        if payload.get('replaceExperiment', True):
            experiments.replace_current_with(name)

        # Replaces model specification
        if payload.get('replaceModelSpec', True):
            path = os.path.join(constants.EXPERIMENTS_FOLDER_PATH, name)
            if self.doIhaveInstOrSimData()['haveInstance']:
                sim.clearAll()

            sim.initialize()
            sim.loadNetParams(os.path.join(path, experiments.NET_PARAMS_FILE))
            sim.loadSimCfg(os.path.join(path, experiments.SIM_CONFIG_FILE))
            self.netParams = sim.net.params
            self.simConfig = sim.cfg
            netpyne_ui_utils.remove(self.simConfig.todict())
            netpyne_ui_utils.remove(self.netParams.todict())

    def viewExperimentResult(self, payload: dict):
        """ Loads the output file of a simulated experiment trial.

        :param payload: {name: str, trial: str, onlyModelSpecification: bool}
        :return: geppetto model
        """
        name = payload.get("name", None)
        trial = payload.get("trial", None)
        only_model_spec = payload.get("onlyModelSpecification", False)

        file = experiments.get_trial_output_path(name, trial)
        if file is None or not os.path.exists(file):
            return utils.getJSONError(
                f"Couldn't find output file of condition. Please take a look at the simulation log.",
                "")

        if self.doIhaveInstOrSimData()['haveInstance']:
            sim.clearAll()

        sim.initialize()

        if only_model_spec:
            # Load only model specification
            sim.loadNetParams(file)
            sim.loadSimCfg(file)
            self.netParams = sim.net.params
            self.simConfig = sim.cfg
            netpyne_ui_utils.remove(self.simConfig.todict())
            netpyne_ui_utils.remove(self.netParams.todict())
            return
        else:
            # Load the complete simulation
            sim.loadAll(file)
            self._create3D_shapes(file)
            self.geppetto_model = self.model_interpreter.getGeppettoModel(sim)
            return json.loads(
                GeppettoModelSerializer.serialize(self.geppetto_model))

    def stopExperiment(self, experiment_name):
        simulations.local.stop()
        return {"message": f"Stopped simulation of {experiment_name}"}

    def find_tutorials(self):
        only_files = [
            f for f in os.listdir(constants.NETPYNE_WORKDIR_PATH)
            if os.path.isfile(os.path.join(constants.NETPYNE_WORKDIR_PATH, f))
        ]

        def _filter(_file):
            return '.py' in _file and 'tut' in _file and 'gui' in _file

        return list(filter(_filter, only_files))

    def instantiateNetPyNEModelInGeppetto(self, args):
        try:
            with redirect_stdout(sys.__stdout__):
                if not args.get("usePrevInst", False):
                    netpyne_model = self.instantiateNetPyNEModel()
                    self.geppetto_model = self.model_interpreter.getGeppettoModel(
                        netpyne_model)

                return json.loads(
                    GeppettoModelSerializer.serialize(self.geppetto_model))
        except Exception as e:
            message = "Error while instantiating the NetPyNE model"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())

    def simulate_experiment_trials(self, experiment: model.Experiment):
        try:
            working_directory = self._prepare_batch_files(experiment)
        except OSError:
            experiment.state = model.ExperimentState.ERROR
            return utils.getJSONError("The specified folder already exists",
                                      "")

        try:
            simulations.run(platform="local",
                            parallel=self.run_config.parallel,
                            cores=self.run_config.cores,
                            method=self.run_config.type,
                            batch=True,
                            asynchronous=self.run_config.asynchronous,
                            working_directory=working_directory)
        except InvalidConfigError as e:
            experiment.state = model.ExperimentState.ERROR
            return utils.getJSONError(str(e), "")

        if self.run_config.asynchronous:
            message = f"Experiment {experiment.name} started. " \
                  f"You can view the Experiment status in the Experiment Manager."
        else:
            message = f"Experiment {experiment.name} finished, you can view the results in the Experiment Manager."

        return utils.getJSONError(message, "")

    def simulate_single_model(self,
                              experiment: model.Experiment = None,
                              use_prev_inst: bool = False):
        if experiment:
            working_directory = self._prepare_simulation_files(
                experiment, use_prev_inst)

            simulations.run(
                parallel=self.run_config.parallel,
                cores=self.run_config.cores,
                asynchronous=self.run_config.asynchronous,
                method=simulations.MPI_BULLETIN,
                working_directory=working_directory,
            )

            if self.run_config.asynchronous:
                message = "Experiment is pending! " \
                  f"Results will be stored in your workspace at ./{os.path.join(constants.EXPERIMENTS_FOLDER, experiment.name)}"
                return utils.getJSONError(message, "")
            else:
                sim.load(f'{constants.MODEL_OUTPUT_FILENAME}.json')
                self.geppetto_model = self.model_interpreter.getGeppettoModel(
                    sim)
                response = json.loads(
                    GeppettoModelSerializer.serialize(self.geppetto_model))
                return response

        else:
            # Run in same process
            if not use_prev_inst:
                logging.debug('Instantiating single thread simulation')
                netpyne_model = self.instantiateNetPyNEModel()

                self.geppetto_model = self.model_interpreter.getGeppettoModel(
                    netpyne_model)

            simulations.run()

            if self.geppetto_model:
                response = json.loads(
                    GeppettoModelSerializer.serialize(self.geppetto_model))
                return response

    def simulateNetPyNEModelInGeppetto(self, args):
        """ Starts simulation of the currently loaded NetPyNe model.

        * runConfiguration is used to determine asynch/synch & other parameters.
        * complete flag in args decides if we simulate single model as Experiment or complete Experiment.
        * if Experiment in design does not exist, we create a new one & start single sim.
        * All Simulations run in different process.

        :param args: { allTrials: bool, usePrevInst: bool }
        :return: geppetto model.
        """
        allTrials = args.get('allTrials', True)
        use_prev_inst = args.get('usePrevInst', False)
        sim_id = args.get('simId', 0)

        try:
            experiment = experiments.get_current()
            if experiment:
                if self.experiments.any_in_state([
                        model.ExperimentState.PENDING,
                        model.ExperimentState.SIMULATING
                ]):
                    return utils.getJSONError(
                        "Experiment is already simulating or pending", "")

                if simulations.local.is_running():
                    simulations.local.stop()

                experiment.state = model.ExperimentState.PENDING

                try:
                    if allTrials:
                        if len(experiment.trials) == 1 and experiment.trials[
                                0].id == experiments.BASE_TRIAL_ID:
                            # special case where we don't want to run a batch simulation
                            return self.simulate_single_model(
                                experiment, use_prev_inst)
                        else:
                            return self.simulate_experiment_trials(experiment)
                    else:
                        return self.simulate_single_model(
                            experiment, use_prev_inst)
                except Exception:
                    experiment.state = model.ExperimentState.ERROR
                    message = (
                        "Unknown error during simulation of Experiment. SimulationId %i"
                        % sim_id)
                    logging.exception(message)
                    return utils.getJSONError(
                        "Unknown error during simulation of Experiment",
                        sys.exc_info(), {"sim_id": sim_id})

            else:
                return self.simulate_single_model(use_prev_inst=use_prev_inst)

        except Exception as e:
            message = (
                "Error while simulating the NetPyNE model: %s. SimulationId %f"
                % (e, sim_id))
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info(),
                                      {"sim_id": sim_id})

    def _prepare_simulation_files(self,
                                  experiment: model.Experiment = None,
                                  use_prev_inst: bool = False) -> str:
        """Prepares template files and netpyne model files for a single simulation """
        exp = copy.deepcopy(experiment)
        # Remove parameter & trials for single run
        exp.params = []
        exp.trials = []

        save_folder_path = os.path.join(constants.NETPYNE_WORKDIR_PATH,
                                        constants.EXPERIMENTS_FOLDER, exp.name)
        try:
            os.makedirs(save_folder_path)
        except OSError:
            raise

        if use_prev_inst:
            sim.cfg.saveJson = True
            oldName = sim.cfg.filename
            sim.cfg.filename = constants.MODEL_OUTPUT_FILENAME

            # workaround for issue with empty LFP dict when calling saveData()
            if 'LFP' in sim.allSimData:
                del sim.allSimData['LFP']

            # TODO: store in experiments folder!
            sim.saveData()
            sim.cfg.filename = oldName
            template_name = constants.TEMPLATE_FILENAME_SINGLE_RUN_INSTANTIATED
        else:
            # Create netParams and SimConfig
            self.netParams.save(
                os.path.join(save_folder_path, experiments.NET_PARAMS_FILE))

            simCfg = copy.copy(self.simConfig)
            # filename and simLabel must be set to define the output filename
            simCfg.saveJson = True
            simCfg.filename = 'model_output'
            simCfg.simLabel = 'model_output'
            simCfg.saveDataInclude = [
                "simData", "simConfig", "netParams", "net"
            ]
            simCfg.save(
                os.path.join(save_folder_path, experiments.SIM_CONFIG_FILE))

            template_name = constants.TEMPLATE_FILENAME_SINGLE_RUN

        # Create Experiment Config
        config_dict = dataclasses.asdict(exp)
        config_dict["runCfg"] = dataclasses.asdict(self.run_config)
        experiment_config = os.path.join(save_folder_path,
                                         experiments.EXPERIMENT_FILE)
        json.dump(config_dict,
                  open(experiment_config, 'w'),
                  default=str,
                  sort_keys=True,
                  indent=4)

        # Copy Template
        template = os.path.join(os.path.dirname(__file__), "templates",
                                template_name)
        copyfile(
            template,
            os.path.join(save_folder_path, constants.SIMULATION_SCRIPT_NAME))

        return save_folder_path

    def _prepare_batch_files(self, experiment: model.Experiment) -> str:
        """Creates template files and netpyne model files in the experiment folder.
        
        Only for an experiment consisting of many trials.

        :param experiment: given experiment
        :return: working directory path
        """
        exp = copy.deepcopy(experiment)
        exp.params = self.experiments.process_params(exp.params)

        netParams = copy.deepcopy(self.netParams)
        netParams.mapping = {p.mapsTo: p.mapsTo.split('.') for p in exp.params}

        simCfg = copy.copy(self.simConfig)
        simCfg.saveJson = True
        simCfg.saveDataInclude = ["simData", "simConfig", "netParams", "net"]

        config_dict = dataclasses.asdict(exp)
        config_dict["runCfg"] = dataclasses.asdict(self.run_config)

        save_folder_path = os.path.join(constants.NETPYNE_WORKDIR_PATH,
                                        constants.EXPERIMENTS_FOLDER, exp.name)
        try:
            os.makedirs(save_folder_path)
        except OSError:
            raise

        simCfg.save(os.path.join(save_folder_path,
                                 experiments.SIM_CONFIG_FILE))
        netParams.save(
            os.path.join(save_folder_path, experiments.NET_PARAMS_FILE))

        experiment_json = os.path.join(save_folder_path,
                                       experiments.EXPERIMENT_FILE)
        json.dump(config_dict,
                  open(experiment_json, 'w'),
                  default=str,
                  sort_keys=True,
                  indent=4)

        template_single_run = os.path.join(
            os.path.dirname(__file__), "templates",
            constants.TEMPLATE_FILENAME_BATCH_RUN)
        template_batch = os.path.join(os.path.dirname(__file__), "templates",
                                      constants.TEMPLATE_FILENAME_BATCH)
        copyfile(template_single_run, os.path.join(save_folder_path, 'run.py'))
        # TODO: name should be batch.py not init.py
        copyfile(
            template_batch,
            os.path.join(save_folder_path, constants.SIMULATION_SCRIPT_NAME))

        return save_folder_path

    def loadModel(self, args):
        """ Imports a model stored as file in json format.

        :param args:
        :return:
        """
        if not any([
                args[option] for option in
            ['loadNetParams', 'loadSimCfg', 'loadSimData', 'loadNet']
        ]):
            return utils.getJSONError(
                "Error while loading data",
                'You have to select at least one option')

        try:
            owd = os.getcwd()
            compileModMechFiles(args['compileMod'], args['modFolder'])
        except Exception:
            message = "Error while importing/compiling mods"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())
        finally:
            os.chdir(owd)

        try:
            with redirect_stdout(sys.__stdout__):
                sim.initialize()
                wake_up_geppetto = False
                if all([
                        args[option] for option in
                    ['loadNetParams', 'loadSimCfg', 'loadSimData', 'loadNet']
                ]):
                    wake_up_geppetto = True
                    if self.doIhaveInstOrSimData()['haveInstance']:
                        sim.clearAll()
                    sim.initialize()
                    sim.loadAll(args['jsonModelFolder'])
                    self.netParams = sim.net.params
                    self.simConfig = sim.cfg
                    netpyne_ui_utils.remove(self.netParams.todict())
                    netpyne_ui_utils.remove(self.simConfig.todict())
                else:
                    if args['loadNet']:
                        wake_up_geppetto = True
                        if self.doIhaveInstOrSimData()['haveInstance']:
                            sim.clearAll()
                        sim.initialize()
                        sim.loadNet(args['jsonModelFolder'])

                    # TODO (https://github.com/Neurosim-lab/netpyne/issues/360)
                    if args['loadSimData']:
                        wake_up_geppetto = True
                        if not self.doIhaveInstOrSimData()['haveInstance']:
                            sim.create(specs.NetParams(), specs.SimConfig())
                            sim.net.defineCellShapes()
                            sim.gatherData(gatherLFP=False)
                        sim.loadSimData(args['jsonModelFolder'])

                    if args['loadSimCfg']:
                        sim.loadSimCfg(args['jsonModelFolder'])
                        self.simConfig = sim.cfg
                        netpyne_ui_utils.remove(self.simConfig.todict())

                    if args['loadNetParams']:
                        if self.doIhaveInstOrSimData()['haveInstance']:
                            sim.clearAll()
                        sim.loadNetParams(args['jsonModelFolder'])
                        self.netParams = sim.net.params
                        netpyne_ui_utils.remove(self.netParams.todict())

                if wake_up_geppetto:
                    self._create3D_shapes(args['jsonModelFolder'])

                    # TODO: Fix me - gatherData will remove allSimData!
                    sim.gatherData()

                    self.geppetto_model = self.model_interpreter.getGeppettoModel(
                        sim)
                    return json.loads(
                        GeppettoModelSerializer.serialize(self.geppetto_model))
                else:
                    return utils.getJSONReply()
        except Exception:
            message = "Error while loading the NetPyNE model"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())

    def _create3D_shapes(self, json_path: str):
        """ Creates cellShapes for 3D viewer.

        Performed as final step after `json_path` was loaded.
        """
        if len(sim.net.cells) > 0:
            section = list(sim.net.cells[0].secs.keys())[0]
            if 'pt3d' not in list(sim.net.cells[0].secs[section].geom.keys()):
                sim.net.defineCellShapes()
                sim.gatherData()
                # Load again because gatherData removed simData
                sim.loadSimData(json_path)

    def importModel(self, modelParameters):
        """ Imports a model stored in form of Python files.

        :param modelParameters:
        :return:
        """
        if self.doIhaveInstOrSimData()['haveInstance']:
            # TODO: this must be integrated into the general lifecycle of "model change -> simulate"
            #   Shouldn't be specific to Import
            sim.clearAll()

        try:
            # Get Current dir
            owd = os.getcwd()

            compileModMechFiles(modelParameters['compileMod'],
                                modelParameters['modFolder'])

            with redirect_stdout(sys.__stdout__):
                # NetParams
                net_params_path = str(modelParameters["netParamsPath"])
                sys.path.append(net_params_path)
                os.chdir(net_params_path)
                # Import Module
                net_params_module_name = importlib.import_module(
                    str(modelParameters["netParamsModuleName"]))
                # Import Model attributes
                self.netParams = getattr(
                    net_params_module_name,
                    str(modelParameters["netParamsVariable"]))

                if isinstance(self.netParams, dict):
                    self.netParams = specs.NetParams(self.netParams)

                if isinstance(self.simConfig, dict):
                    self.simConfig = specs.SimConfig(self.simConfig)

                for key, value in self.netParams.cellParams.items():
                    if hasattr(value, 'todict'):
                        self.netParams.cellParams[key] = value.todict()

                # SimConfig
                sim_config_path = str(modelParameters["simConfigPath"])
                sys.path.append(sim_config_path)
                os.chdir(sim_config_path)
                # Import Module
                sim_config_module_name = importlib.import_module(
                    str(modelParameters["simConfigModuleName"]))
                # Import Model attributes
                self.simConfig = getattr(
                    sim_config_module_name,
                    str(modelParameters["simConfigVariable"]))

                # TODO: when should sim.initialize be called?
                #   Only on import or better before every simulation or network instantiation?
                sim.initialize()
            return utils.getJSONReply()
        except Exception:
            message = "Error while importing the NetPyNE model"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())
        finally:
            os.chdir(owd)

    def importCellTemplate(self, modelParameters):
        try:
            with redirect_stdout(sys.__stdout__):
                rule = modelParameters["label"]
                # Get Current dir
                owd = os.getcwd()

                conds = {} if rule not in self.netParams.cellParams else self.netParams.cellParams[
                    rule]['conds']

                compileModMechFiles(modelParameters["compileMod"],
                                    modelParameters["modFolder"])

                del modelParameters["modFolder"]
                del modelParameters["compileMod"]
                # import cell template
                self.netParams.importCellParams(**modelParameters, conds=conds)

                # convert fron netpyne.specs.dict to dict
                self.netParams.cellParams[rule] = self.netParams.cellParams[
                    rule].todict()

                return utils.getJSONReply()
        except Exception:
            message = "Error while importing the NetPyNE cell template"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())
        finally:
            os.chdir(owd)

    def exportModel(self, args):
        try:
            with redirect_stdout(sys.__stdout__):
                if not args['netCells']:
                    sim.initialize(netParams=self.netParams,
                                   simConfig=self.simConfig)
                sim.cfg.filename = args['fileName']
                include = [
                    el for el in specs.SimConfig().saveDataInclude
                    if el in args.keys() and args[el]
                ]
                if args['netCells']: include += ['netPops']
                sim.cfg.saveJson = True
                sim.saveData(include)
                sim.cfg.saveJson = False

                with open(f"{sim.cfg.filename}_data.json") as json_file:
                    data = json.load(json_file)
                    return data

        except Exception:
            message = "Error while exporting the NetPyNE model"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())

    def exportNeuroML(self, modelParams):
        try:
            with redirect_stdout(sys.__stdout__):
                sim.exportNeuroML2(modelParams['fileName'], specs.SimConfig())
            return utils.getJSONReply()
        except Exception:
            message = "Error while exporting the NetPyNE model"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())

    def importNeuroML(self, modelParams):
        try:
            with redirect_stdout(sys.__stdout__):
                sim.initialize()
                sim.importNeuroML2(modelParams['neuroMLFolder'],
                                   simConfig=specs.SimConfig(),
                                   simulate=False,
                                   analyze=False)
                self.geppetto_model = self.model_interpreter.getGeppettoModel(
                    sim)
            return json.loads(
                GeppettoModelSerializer.serialize(self.geppetto_model))

        except Exception:
            message = "Error while exporting the NetPyNE model"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())

    def deleteModel(self, modelParams):
        try:
            with redirect_stdout(sys.__stdout__):
                self.netParams = specs.NetParams()
                self.simConfig = specs.SimConfig()
                sim.initialize(specs.NetParams(), specs.SimConfig())
                self.geppetto_model = None
        except Exception:
            message = "Error while exporting the NetPyNE model"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())

        try:
            sim.clearAll()
        except:
            logging.exception("Failed to clear simulation")

        return utils.getJSONReply()

    def instantiateNetPyNEModel(self):
        with redirect_stdout(sys.__stdout__):
            saveData = sim.allSimData if hasattr(
                sim, 'allSimData') and 'spkt' in sim.allSimData.keys() and len(
                    sim.allSimData['spkt']) > 0 else False

            #netcoded = jsonpickle.encode(self.netParams, unpicklable=False)
            #simcoded = jsonpickle.encode(self.simConfig, unpicklable=False)
            sim.create(self.netParams, self.simConfig)
            sim.net.defineCellShapes(
            )  # creates 3d pt for cells with stylized geometries
            sim.gatherData(gatherLFP=False)

            if saveData:
                sim.allSimData = saveData  # preserve data from previous simulation

        return sim

    def doIhaveInstOrSimData(self):
        """ Telling if we have an instance or simulated data.

        return [bool, bool]
        """
        with redirect_stdout(sys.__stdout__):
            out = [False, False]
            if hasattr(sim, 'net'):
                if hasattr(sim.net, 'cells') and hasattr(sim.net, 'pops'):
                    if len(sim.net.cells) > 0 and len(sim.net.pops.keys()) > 0:
                        out[0] = True
            if hasattr(sim, 'allSimData'):
                if 'spkt' in sim.allSimData.keys(
                ) and 'spkid' in sim.allSimData.keys():
                    if len(sim.allSimData['spkt']) > 0 and len(
                            sim.allSimData['spkid']) > 0:
                        out[1] = True

        return {'haveInstance': out[0], 'haveSimData': out[1]}

    def rename(self, path, oldValue, newValue):
        command = 'sim.rename(self.' + path + ',"' + oldValue + '","' + newValue + '")'
        logging.debug('renaming ' + command)

        eval(command)

        for model, synched_component in list(
                jupyter_geppetto.synched_models.items()):
            if model != '' and oldValue in model and path in model:  #
                jupyter_geppetto.synched_models.pop(model)
                new_model = re.sub(
                    "(['])(?:(?=(\\?))\2.)*?\1",
                    lambda x: x.group(0).replace(oldValue, newValue, 1), model)
                logging.debug("Rename funct - Model is " + model +
                              " newModel is " + new_model)
                jupyter_geppetto.synched_models[new_model] = synched_component

        with redirect_stdout(sys.__stdout__):
            if "popParams" in path:
                self.propagate_field_rename("pop", newValue, oldValue)
            elif "stimSourceParams" in path:
                self.propagate_field_rename("source", newValue, oldValue)
            elif "synMechParams" in path:
                self.propagate_field_rename("synMech", newValue, oldValue)

        return 1

    def getPlotSettings(self, plot_name):
        if self.simConfig.analysis and plot_name in self.simConfig.analysis:
            return self.simConfig.analysis[plot_name]
        return {}

    def getDirList(self, dir=None, onlyDirs=False, filterFiles=False):
        # Get Current dir
        if dir is None or dir == '':
            dir = os.path.join(os.getcwd(), constants.NETPYNE_WORKDIR_PATH)
        dir_list = []
        file_list = []
        for f in sorted(os.listdir(str(dir)), key=str.lower):
            ff = os.path.join(dir, f)
            if os.path.isdir(ff):
                dir_list.append({
                    'title': f,
                    'path': ff,
                    'load': False,
                    'children': [{
                        'title': 'Loading...'
                    }]
                })
            elif not onlyDirs:
                if not filterFiles or os.path.isfile(ff) and ff.endswith(
                        filterFiles):
                    file_list.append({'title': f, 'path': ff})
        return dir_list + file_list

    def checkAvailablePlots(self):
        return analysis.checkAvailablePlots()

    def getPlot(self, plotName, LFPflavour, theme='gui'):
        try:
            with redirect_stdout(sys.__stdout__):
                args = self.getPlotSettings(plotName)
                if LFPflavour:
                    args['plots'] = [LFPflavour]

                args['showFig'] = False

                if plotName.startswith('iplot'):
                    # This arg brings dark theme. But some plots are broken by it
                    args['theme'] = theme

                    if plotName in ("iplotConn", "iplot2Dnet") and hasattr(
                            sim, 'net') and sim.net.allCells:

                        def conns_length(cell) -> int:
                            if type(cell) is dict:
                                return len(cell.get('conns', []))
                            else:
                                return len(getattr(cell, 'conns', []))

                        # To prevent unresponsive kernel, we don't show conns if they become too many
                        num_conn = sum(
                            [conns_length(cell) for cell in sim.net.allCells])
                        if num_conn > NUM_CONN_LIMIT:
                            args["showConns"] = False

                    html = getattr(analysis, plotName)(**args)
                    if not html or html == -1:
                        return ""

                    # some plots return "fig", some return "(fig, data)"
                    if plotName in ('iplotRaster', 'iplotRxDConcentration',
                                    'iplot2Dnet'):
                        html = html[0]

                    return html

                else:
                    fig_data = getattr(analysis, plotName)(**args)
                    if isinstance(fig_data, tuple):
                        fig = fig_data[0]
                        if fig == -1:
                            return fig
                        elif isinstance(fig, list):
                            return [ui.getSVG(fig[0])]
                        elif isinstance(fig, dict):
                            svgs = []
                            for key, value in fig.items():
                                svgs.append(ui.getSVG(value))
                            return svgs
                        else:
                            return [ui.getSVG(fig)]
                    else:
                        if plotName == 'plotEEG':
                            return self.simConfig.filename + '_EEG.png'
                        elif plotName == 'plotDipole':
                            return self.simConfig.filename + '_dipole.png'
                        else:
                            return fig_data
        except Exception as e:
            err = "There was an exception in %s():" % (e.plotName)
            logging.exception(("%s \n %s \n%s" % (err, e, sys.exc_info())))

    def getAvailablePops(self):
        return list(self.netParams.popParams.keys())

    def getAvailableCellModels(self):
        cell_models = set([])
        for p in self.netParams.popParams:
            if 'cellModel' in self.netParams.popParams[p]:
                cm = self.netParams.popParams[p]['cellModel']
                if cm not in cell_models:
                    cell_models.add(cm)
        return list(cell_models)

    def getAvailableCellTypes(self):
        cell_types = set([])
        for p in self.netParams.cellParams:
            cell_types.add(p)
        return list(cell_types)

    def getAvailableSections(self):
        sections = {}
        for cellRule in self.netParams.cellParams:
            sections[cellRule] = list(
                self.netParams.cellParams[cellRule]['secs'].keys())
        return sections

    def getAvailableStimSources(self):
        return list(self.netParams.stimSourceParams.keys())

    def getAvailableSynMech(self):
        return list(self.netParams.synMechParams.keys())

    def getAvailableMechs(self):
        mechs = mechVarList()['mechs']
        for key in list(mechs.keys()):
            if 'ion' in key: del mechs[key]
        for key in ["morphology", "capacitance", "extracellular"]:
            del mechs[key]
        return list(mechs.keys())

    def getMechParams(self, mechanism):
        params = mechVarList()['mechs'][mechanism]
        return [value[:-(len(mechanism) + 1)] for value in params]

    def getAvailablePlots(self):
        plots = [
            "iplotRaster", "iplotSpikeHist", "plotSpikeStats", "iplotRatePSD",
            "iplotTraces", "iplotLFP", "plotShape", "plot2Dnet", "iplotConn",
            "granger", "plotDipole", "plotEEG"
        ]

        return [
            plot for plot in plots
            if plot not in list(self.simConfig.analysis.keys())
        ]

    def getInclude(self, model):
        with redirect_stdout(sys.__stdout__):
            if model in list(netpyne_geppetto.simConfig.analysis.keys()):
                if 'include' in list(
                        netpyne_geppetto.simConfig.analysis[model].keys()):
                    return netpyne_geppetto.simConfig.analysis[model][
                        'include']
                else:
                    return False
            else:
                return False

    def getGIDs(self):
        # pop sizes and gids returned in a dict
        out = {}
        with redirect_stdout(sys.__stdout__):
            for key in self.netParams.popParams.keys():
                if 'numCells' in self.netParams.popParams[key]:
                    out[key] = self.netParams.popParams[key]['numCells']
                else:
                    out[key] = 0

            out['gids'] = int(np.sum([v for k, v in list(out.items())]))

        return out

    def deleteParam(self, model, label):
        try:
            if isinstance(model, list):  # just for cellParams
                if len(model) == 1:
                    self.netParams.cellParams[model[0]]["secs"].pop(label)
                elif len(model) == 2:
                    self.netParams.cellParams[model[0]]["secs"][
                        model[1]]["mechs"].pop(label)
                else:
                    pass
            else:
                # remove rule
                rule = getattr(self.netParams, model).pop(label)

                # side effect on other rules
                if "popParams" in model:
                    self.propagate_field_rename("pop", None, label)
                    if 'cellModel' in rule:
                        self.propagate_field_rename("cellModel", None,
                                                    rule['cellModel'])
                    if 'cellType' in rule:
                        self.propagate_field_rename("cellType", None,
                                                    rule['cellType'])

                elif "stimSourceParams" in model:

                    self.propagate_field_rename("source", None, label)
                elif "synMechParams" in model:
                    self.propagate_field_rename("synMech", None, label)
            return True
        except Exception as e:
            logging.exception(f"Error while deleting parameter: {label}")
            return False

    def validateFunction(self, functionString):
        if isinstance(functionString, (float, int)):
            return True
        return validateFunction(functionString, self.netParams.__dict__)

    def exportHLS(self, args):
        def convert2bool(string):
            return string.replace('true', 'True').replace('false',
                                                          'False').replace(
                                                              'null', 'False')

        def header(title, spacer='-'):
            return '\n# ' + title.upper() + ' ' + spacer * (77 -
                                                            len(title)) + '\n'

        try:
            params = ['popParams', 'cellParams', 'synMechParams']
            params += ['connParams', 'stimSourceParams', 'stimTargetParams']

            fname = args['fileName']
            if not fname:
                # default option
                fname = 'output.py'

            if not fname[-3:] == '.py':
                fname = f"{fname}.py"

            # TODO: use methods offered by netpyne to create this script!
            with open(fname, 'w') as script:
                script.write("from netpyne import specs, sim\n")
                script.write(header("documentation"))
                script.write(
                    "Script generated with NetPyNE-UI. Please visit:\n")
                script.write(
                    "    - https://www.netpyne.org\n    - https://github.com/MetaCell/NetPyNE-UI\n\n"
                )
                script.write(header("script", spacer="="))
                script.write("netParams = specs.NetParams()\n")
                script.write("simConfig = specs.SimConfig()\n")
                script.write(header("single value attributes"))
                for attr, value in list(self.netParams.__dict__.items()):
                    if attr not in params:
                        if value != getattr(specs.NetParams(), attr):
                            script.write("netParams." + attr + " = ")
                            script.write(
                                convert2bool(json.dumps(value, indent=4)) +
                                "\n")

                script.write(header("network attributes"))
                for param in params:
                    for key, value in list(
                            getattr(self.netParams, param).items()):
                        script.write("netParams." + param + "[" + key + "] = ")
                        script.write(
                            convert2bool(json.dumps(value, indent=4)) + "\n")

                script.write(header("network configuration"))
                for attr, value in list(self.simConfig.__dict__.items()):
                    if value != getattr(specs.SimConfig(), attr):
                        script.write("simConfig." + attr + " = ")
                        script.write(
                            convert2bool(json.dumps(value, indent=4)) + "\n")

                script.write(header("create simulate analyze  network"))
                script.write(
                    "# sim.createSimulateAnalyze(netParams=netParams, simConfig=simConfig)\n"
                )

                script.write(header("end script", spacer="="))

            with open(fname) as f:
                file_b64 = base64.b64encode(bytes(f.read(), 'utf-8')).decode()
                export_info = {"fileContent": file_b64, "fileName": fname}
                return export_info

        except Exception:
            message = "Error while exporting NetPyNE model to python"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())

    def propagate(self, model, label, cond, new, old):
        with redirect_stdout(sys.__stdout__):
            if model == 'analysis':
                analysis = getattr(self.simConfig, model)
                for plot in analysis.keys():
                    if cond in analysis[plot].keys():
                        for index, item in enumerate(analysis[plot][cond]):
                            if isinstance(item, str) or isinstance(item, int):
                                if item == old:
                                    if new == None:
                                        analysis[plot][cond].remove(item)
                                        break
                                    else:
                                        analysis[plot][cond][index] = new
                            else:
                                if isinstance(item[0], str):
                                    if item[0] == old:
                                        if new == None:
                                            analysis[plot][cond].pop(index)
                                            break
                                        else:
                                            analysis[plot][cond][index] = [
                                                new, item[1]
                                            ]
            else:
                obj = getattr(self.netParams, model)
                for key in obj.keys():
                    if cond in obj[key] and label in list(
                            obj[key][cond].keys()):
                        if isinstance(obj[key][cond][label], str):
                            if old == obj[key][cond][label]:
                                if new == '' or new == None:
                                    obj[key][cond].pop(label)
                                else:
                                    obj[key][cond][label] = new
                        elif isinstance(obj[key][cond][label], list):
                            if old in obj[key][cond][label]:
                                if new == '' or new == None:
                                    obj[key][cond][label] = [
                                        value
                                        for value in obj[key][cond][label]
                                        if value != old
                                    ]
                                else:
                                    obj[key][cond][label] = [
                                        value if value != old else new
                                        for value in obj[key][cond][label]
                                    ]
                            if len(obj[key][cond][label]) == 0:
                                obj[key][cond].pop(label)
                        else:
                            pass

    def propagate_field_rename(self, label, new, old):
        def unique(label=label, old=old):
            classes = []
            for p in self.netParams.popParams:
                if label in self.netParams.popParams[p]:
                    classes.append(self.netParams.popParams[p][label])
            if classes.count(old) > 0:
                return False
            else:
                return True

        if label == 'source':
            self.propagate_stim_source_rename(new, old)
            return True
        elif label == 'synMech':
            self.propagate_syn_mech_rename(new, old)
            return True
        else:
            if unique():
                for (model, cond) in [['cellParams', 'conds'],
                                      ['connParams', 'preConds'],
                                      ['connParams', 'postConds'],
                                      ['stimTargetParams', 'conds'],
                                      ['analysis', 'include']]:
                    self.propagate(model, label, cond, new, old)
                return True
            else:
                return False

    def propagate_section_rename(self, new, old):
        for label in self.netParams.cellParams:
            if 'secs' in self.netParams.cellParams[label]:
                for sec in self.netParams.cellParams[label]['secs']:
                    if 'topol' in self.netParams.cellParams[label]['secs'][
                            sec]:
                        if 'parentSec' in self.netParams.cellParams[label][
                                'secs'][sec]['topol']:
                            if self.netParams.cellParams[label]['secs'][sec][
                                    'topol']['parentSec'] == old:
                                if new == None:
                                    self.netParams.cellParams[label]['secs'][
                                        sec]['topol'].pop('parentSec')
                                else:
                                    self.netParams.cellParams[label]['secs'][
                                        sec]['topol']['parentSec'] = new

    def propagate_stim_source_rename(self, new, old):
        for label in self.netParams.stimTargetParams:
            if old == self.netParams.stimTargetParams[label]['source']:
                if new == None:
                    self.netParams.stimTargetParams[label].pop('source')
                else:
                    self.netParams.stimTargetParams[label]['source'] = new

    def propagate_syn_mech_rename(self, new, old):
        for label in self.netParams.stimTargetParams:
            if 'source' in self.netParams.stimTargetParams[label]:
                if self.netParams.stimTargetParams[label][
                        'source'] in self.netParams.stimSourceParams:
                    if 'type' in self.netParams.stimSourceParams[
                            self.netParams.stimTargetParams[label]['source']]:
                        if self.netParams.stimSourceParams[
                                self.netParams.stimTargetParams[label]
                            ['source']]['type'] == 'NetStim':
                            if old == self.netParams.stimTargetParams[label][
                                    'synMech']:
                                if new is None:
                                    self.netParams.stimTargetParams[label].pop(
                                        'synMech')
                                else:
                                    self.netParams.stimTargetParams[label][
                                        'synMech'] = new

    def create_celltype_from_template(self,
                                      label="CellType",
                                      conds={},
                                      cell_template_name="Blank"):
        try:
            with redirect_stdout(sys.__stdout__):
                self.netParams.addCellParamsTemplate(
                    label=label, template=cell_template_name)
            return True
        except Exception:
            message = f"Error while creating cellType from template {cell_template_name}"
            logging.exception(message)
            return utils.getJSONError(message, sys.exc_info())