Пример #1
0
    def _get_brain_info_from_storage(cls, experiment_id, context_id):
        """
        Gathers from the storage the brain script and the populations by getting the BIBI
        configuration file.

        :param experiment_id: the id of the experiment in which to look for the brain information
        :param context_id: the context ID for collab based simulations
        :return: A tuple with the path to the brain file and a list of populations
        """
        del context_id  # Unused

        request_token = UserAuthentication.get_header_token()

        experiment_file = cls.storage_client.get_file(
            request_token, experiment_id, 'experiment_configuration.exc', by_name=True)

        bibi_filename = exp_conf_api_gen.CreateFromDocument(experiment_file).bibiConf.src

        # find the brain filename from the bibi
        bibi_file = cls.storage_client.get_file(
            request_token, experiment_id, bibi_filename, by_name=True)

        bibi_file_obj = bibi_api_gen.CreateFromDocument(bibi_file)
        brain_filename = os.path.basename(bibi_file_obj.brainModel.file)

        brain_filepath = cls.storage_client.clone_file(brain_filename, request_token, experiment_id)

        neurons_config = get_all_neurons_as_dict(bibi_file_obj.brainModel.populations)

        neurons_config_clean = \
            [SimulationResetStorage._get_experiment_population(name, v)
             for (name, v) in neurons_config.iteritems()]

        return brain_filepath, neurons_config_clean, neurons_config
Пример #2
0
    def _hack_(self):
        """
        TODO: please remove me at earliest convenience

        HACK for the inconsistent proxy and backend behavior
        Replace exc and bibi representation by reading from storage
        Proxy might have changed something that backend is not aware of
        """
        from hbp_nrp_backend.storage_client_api.StorageClient import StorageClient
        import urllib

        client = StorageClient()

        latest_exc = client.get_file(self._sim_config.token,
                                     urllib.quote_plus(
                                         self._sim_config.experiment_id),
                                     self._sim_config.exc_path.rel_path,
                                     by_name=True)
        latest_bibi = client.get_file(self._sim_config.token,
                                      urllib.quote_plus(
                                          self._sim_config.experiment_id),
                                      self._sim_config.bibi_path.rel_path,
                                      by_name=True)

        try:
            self._exc_dom = exc_parser.CreateFromDocument(latest_exc)
            self._bibi_dom = bibi_parser.CreateFromDocument(latest_bibi)

        except Exception as ex:
            raise Exception(
                "Something went horribly wrong while creating latest "
                "config objects with following exception {}".format(str(ex)))
Пример #3
0
    def reset_from_storage_all(cls, simulation, experiment_id, context_id):
        """
        Reset states machines and transfer functions

        :param: the simulation id
        :param: the experiment id
        :param: the context_id for collab based simulations
        """

        SimUtil.clear_dir(simulation.lifecycle.sim_dir)

        token = UserAuthentication.get_header_token()
        cls.storage_client.clone_all_experiment_files(
            token, experiment_id, destination_dir=simulation.lifecycle.sim_dir)

        with open(simulation.lifecycle.experiment_path) as exc_file:
            exc = exp_conf_api_gen.CreateFromDocument(exc_file.read())

        bibi_path = os.path.join(os.path.dirname(simulation.lifecycle.experiment_path),
                                 exc.bibiConf.src)
        with open(bibi_path) as bibi_file:
            bibi = bibi_api_gen.CreateFromDocument(bibi_file.read())

        cls.reset_brain(simulation, experiment_id, context_id)
        cls.reset_transfer_functions(simulation, bibi, simulation.lifecycle.sim_dir)
        cls.reset_state_machines(simulation, exc, simulation.lifecycle.sim_dir)
Пример #4
0
    def test_brain_reset_from_storage(self, mock_get_exp_data,
                                      mock_get_model_path,
                                      mock_get_experiment_path):
        simulations.append(
            Simulation(3, 'experiments/experiment_data/test_5.exc', None,
                       'default-owner', 'created'))
        simulations[2].cle = mock.MagicMock()
        simulations[2].cle.set_simulation_brain.return_value = Mock(
            error_message="")

        mock_get_experiment_path.return_value = PATH
        mock_get_model_path.return_value = os.path.join(PATH, 'models')

        bibi_path = os.path.join(PATH,
                                 'experiments/experiment_data/bibi_4.bibi')
        experiment_file_path = os.path.join(
            PATH, 'experiments/experiment_data/test_5.exc')

        with open(experiment_file_path) as exd_file:
            experiment = exp_conf_api_gen.CreateFromDocument(exd_file.read())

        with open(bibi_path) as b_file:
            bibi = bibi_api_gen.CreateFromDocument(b_file.read())

        mock_get_exp_data.return_value = experiment, bibi

        with patch("__builtin__.open", mock_open(read_data="data")) as mock_file, \
                patch('os.listdir', return_value=['nrpTemp']) as mock_tempfile:
            response = self.client.put('/simulation/2/reset',
                                       data=json.dumps({
                                           'resetType':
                                           ResetSimulationRequest.RESET_BRAIN
                                       }))
            self.assertEqual(200, response.status_code)
Пример #5
0
    def test_reset_is_called_properly(self, mock_lifecycle, mock_storage_client,
                                      mock_get_experiment_data, mock_copy_tree,
                                      mock_get_brain_info_from_storage):
        simulations[0].cle = mock.MagicMock()
        simulations[0].cle.set_simulation_transfer_function.return_value = None

        mock_get_brain_info_from_storage.return_value = os.path.join(PATH,
                                                                     'models/braitenberg.py'), {}, {}

        experiment_file_path = os.path.join(PATH, 'experiments/experiment_data/test_1.exc')

        with open(experiment_file_path) as exd_file:
            try:
                experiment = exp_conf_api_gen.CreateFromDocument(
                    exd_file.read())
            except ValidationError, ve:
                raise Exception("Could not parse experiment configuration {0:s} due to validation "
                                "error: {1:s}".format(experiment_file_path, str(ve)))

            bibi_file = experiment.bibiConf.src
            bibi_file_abs = os.path.join(EXPERIMENT_DATA_PATH, bibi_file)
            with open(bibi_file_abs) as b_file:
                try:
                    bibi = bibi_api_gen.CreateFromDocument(b_file.read())
                except ValidationError, ve:
                    raise Exception("Could not parse brain configuration {0:s} due to validation "
                                    "error: {1:s}".format(bibi_file_abs, str(ve)))
    def setUp(self):
        dir = os.path.split(__file__)[0]
        with open(os.path.join(
                dir, "experiment_data/milestone2.bibi")) as bibi_file:
            bibi = bibi_api_gen.CreateFromDocument(bibi_file.read())
        with open(os.path.join(
                dir, "experiment_data/ExDXMLExample.exc")) as exd_file:
            exd = exp_conf_api_gen.CreateFromDocument(exd_file.read())

        exd.path = "/somewhere/over/the/rainbow/exc"
        exd.dir = "/somewhere/over/the/rainbow"
        bibi.path = "/somewhere/over/the/rainbow/bibi"

        models_path_patch = patch(
            "hbp_nrp_cleserver.server.CLEGazeboSimulationAssembly.models_path",
            "/somewhere/near/the/rainbow")
        models_path_patch.start()
        self.addCleanup(models_path_patch.stop)

        with patch("hbp_nrp_cleserver.server.CLEGazeboSimulationAssembly.os",
                   MockOs):
            self.launcher = CLEGazeboSimulationAssembly.CLEGazeboSimulationAssembly(
                42, exd, bibi, gzserver_host="local")
        self.launcher.cle_server = Mock()
        self.launcher.gzweb = Mock()
        self.launcher.gzserver = Mock()
        self.launcher.gazebo_recorder = Mock()
        self.launcher.ros_notificator = Mock()
        self.launcher.ros_launcher = Mock()
Пример #7
0
    def get(self, sim_id):
        """
        Gets simulation resource files of the experiment running for the simulation ID

        :param sim_id: The simulation ID

        :> json string resources: Resource files

        :status 500: {0}
        :status 404: {1}. Or, {2}.
        :status 200: Success. The simulation BIBI configuration files were retrieved
        """

        simulation = _get_simulation_or_abort(sim_id)
        experiment_file = simulation.lifecycle.experiment_path

        if not os.path.isfile(experiment_file):
            raise NRPServicesClientErrorException(
                ErrorMessages.EXPERIMENT_CONF_FILE_NOT_FOUND_404,
                error_code=404)
        with open(experiment_file) as exd_file:
            experiment_dom = exp_conf_api_gen.CreateFromDocument(
                exd_file.read())

        bibi_fullpath = os.path.join(
            simulation.lifecycle.simulation_root_folder,
            experiment_dom.bibiConf.src)

        if not os.path.isfile(bibi_fullpath):
            raise NRPServicesClientErrorException(
                ErrorMessages.EXPERIMENT_BIBI_FILE_NOT_FOUND_404,
                error_code=404)

        resources = []
        for conf in experiment_dom.configuration:
            resources.append({'file': conf.src, 'type': conf.type})

        with open(bibi_fullpath) as _file:
            bibi_dom = bibi_api_gen.CreateFromDocument(_file.read())

        for conf in bibi_dom.configuration:
            resources.append({'file': conf.src, 'type': conf.type})

        if simulation.private:
            for conf in resources:
                conf['file'] = os.path.join(
                    '/config-from-cloned-folder',
                    os.path.basename(
                        simulation.lifecycle.simulation_root_folder),
                    os.path.basename(conf['file']))
        else:
            # Get the template experiment folder name, e.g., "template_husky"
            experiment_folder = os.path.basename(
                os.path.dirname(experiment_file))
            for conf in resources:
                conf['file'] = os.path.join('/config-from-template-folder',
                                            experiment_folder, conf['file'])

        return {'resources': resources}, 200
Пример #8
0
 def setUp(self):
     dir = os.path.split(__file__)[0]
     with open(os.path.join(dir, "experiment_data/milestone2.bibi")) as bibi_file:
         bibi = bibi_api_gen.CreateFromDocument(bibi_file.read())
     with open(os.path.join(dir, "experiment_data/ExDXMLExample.exc")) as exd_file:
         exd = exp_conf_api_gen.CreateFromDocument(exd_file.read())
     exd.path = "/somewhere/over/the/rainbow/exc"
     exd.dir = "/somewhere/over/the/rainbow"
     bibi.path = "/somewhere/over/the/rainbow/bibi"
     self.models_path_patch=patch("hbp_nrp_cleserver.server.CLEGazeboSimulationAssembly.models_path", new="/somewhere/near/the/rainbow")
     self.models_path_patch.start()
     self.launcher = SynchronousNestSimulation(42, exd, bibi, gzserver_host="local")
Пример #9
0
 def test_load_brain_storage(self, mocked_storage):
     mocked_storage().get_folder_uuid_by_name.return_value = 'brains'
     mocked_storage().get_temp_directory.return_value = PATH
     with open(os.path.join(PATH,'experiment_data/braitenberg.py')) as brain:
         brain_contents = brain.read()
     mocked_storage().get_file.return_value = brain_contents
     with open(os.path.join(PATH, "experiment_data/milestone2_1.bibi")) as bibi_file:
         bibi = bibi_api_gen.CreateFromDocument(bibi_file.read())
     self.launcher._SimulationAssembly__bibi = bibi
     braincontrol, braincomm, brainfilepath, neurons_config = self.launcher._load_brain(1234)
     self.assertEqual(brainfilepath, os.path.join(PATH, 'braitenberg.py'))
     self.assertEqual(neurons_config, {u'sensors': slice(0L, 5L, None), u'actors': slice(5L, 8L, None)})
Пример #10
0
 def test_reset_transfer_functions(self):
     simulations[0].cle = mock.MagicMock()
     tf_sources_list = ['# Imported Python Transfer Function\[email protected]("recorder", filename="all_spikes.csv", headers=["id", "time"])\[email protected]("record_neurons", nrp.brain.record, nrp.spike_recorder)\[email protected](Topic(\'/monitor/spike_recorder\', cle_ros_msgs.msg.SpikeEvent))\ndef csv_spike_monitor(t, recorder, record_neurons):\n    for i in range(0, len(record_neurons.times)):\n        recorder.record_entry(\n            record_neurons.times[i][0],\n            record_neurons.times[i][1]\n        )\n', '# Imported Python Transfer Function\n#\nimport hbp_nrp_cle.tf_framework as nrp\n# This specifies that the neurons 0 to 2 of the circuit population\n# should be monitored. You can see them in the spike train widget\[email protected](nrp.brain.record, nrp.spike_recorder)\ndef all_neurons_spike_monitor(t):\n    # Uncomment to log into the \'log-console\' visible in the simulation\n    # clientLogger.info("Time: ", t)\n    return True\n#\n',
                       '# Imported Python Transfer Function\n#\nimport hbp_nrp_cle.tf_framework as nrp\nfrom hbp_nrp_cle.robotsim.RobotInterface import Topic\nimport std_msgs.msg\[email protected]("output_neuron", nrp.brain.neurons[1], nrp.leaky_integrator_alpha)\[email protected](Topic(\'/robot/eye_version/pos\', std_msgs.msg.Float64))\n# Example TF: get output neuron voltage and output some value on robot actuator to change eyes position whever an output spike is detected. You could do something else with the voltage here and command the robot accordingly.\ndef turn_eyes(t, output_neuron):\n    data = 0.3\n    if output_neuron.voltage < 0.0001:\n        data = -0.3\n    return std_msgs.msg.Float64(data)\n#\n', '# Imported Python Transfer Function\n#\nfrom sensor_msgs.msg import JointState\[email protected]("joints", Topic("/robot/joints", JointState))\[email protected](Topic(\'/joint_states\', JointState))\ndef joint_states_passthrough(t, joints):\n    return joints.value\n#\n', '# Imported Python Transfer Function\n#\nimport hbp_nrp_cle.tf_framework as nrp\nfrom hbp_nrp_cle.robotsim.RobotInterface import Topic\nimport sensor_msgs.msg\[email protected]("camera", Topic(\'/icub_model/left_eye_camera/image_raw\', sensor_msgs.msg.Image))\[email protected]("input_neuron", nrp.brain.neurons[0], nrp.poisson)\[email protected]()\n# Example TF: get image and fire at constant rate. You could do something with the image here and fire accordingly.\ndef grab_image(t, camera, input_neuron):\n    image = camera.value\n    input_neuron.rate = 10\n#\n']
     tf_activation_list = [True, True]
     simulations[0].cle.get_simulation_transfer_functions.return_value = (tf_sources_list, tf_activation_list)
     simulations[0].cle.add_simulation_transfer_function.return_value = None
     bibi_file_abs = os.path.join(os.path.split(
         __file__)[0], "experiments", "experiment_data", "bibi_1.bibi")
     with open(bibi_file_abs) as b_file:
         bibi = bibi_api_gen.CreateFromDocument(b_file.read())
     SimulationResetStorage.resetTransferFunctions(simulations[0], bibi, PATH)
     simulations[0].cle.get_simulation_transfer_functions.assert_called()
     simulations[0].cle.delete_simulation_transfer_function.assert_called_with('grab_image')
Пример #11
0
    def _read_exc_and_bibi_dom_objects(self):
        """
        Parse experiment and bibi and return the DOM objects
        """
        # Read exc
        with open(self._exc_path.abs_path) as excFile:
            try:
                self._exc_dom = exc_parser.CreateFromDocument(excFile.read())
            except ValidationError as ve:
                raise Exception(
                    "Could not parse experiment config {0} due to validation "
                    "error: {1}".format(self._exc_path.abs_path, str(ve)))

        self._bibi_path = ResourcePath(self._exc_dom.bibiConf.src,
                                       self.sim_dir)
        logger.info("Bibi absolute path:" + self._bibi_path.abs_path)

        # Read bibi
        with open(self._bibi_path.abs_path) as bibiFile:
            try:
                self._bibi_dom = bibi_parser.CreateFromDocument(
                    bibiFile.read())
            except ValidationError as ve:
                raise Exception(
                    "Could not parse brain configuration {0:s} due to validation "
                    "error: {1:s}".format(self._bibi_path.abs_path, str(ve)))
            except NamespaceError as ne:
                # first check to see if the BIBI file appears to have a valid namespace
                namespace = str(ne).split(" ", 1)[0]
                if not namespace.startswith("http://schemas.humanbrainproject.eu/SP10") or \
                        not namespace.endswith("BIBI"):
                    raise Exception(
                        "Unknown brain configuration file format for: {0:s} with "
                        "namespace: {1:s}".format(self._bibi_path.abs_path,
                                                  namespace))

                # notify the user that their file is out of date
                raise Exception(
                    "The BIBI file for the requested experiment is out of date and no "
                    "longer supported. Please contact neurorobotics@humanbrainproject."
                    "eu with the following information for assistance in updating this"
                    " file.\n\nExperiment Configuration:\n\tName: {0:s}\n\tBIBI: {1:s}"
                    "\n\tVersion: {2:s}".format(self._exc_dom.name,
                                                self._bibi_path.abs_path,
                                                namespace))

        # set config version based of something
        self.exc_version = Version.CURRENT
    def test_experiment_transfer_functions_put(self):
        experiment_id = '123456'
        data = {'transfer_functions': [self.tf1, self.tf2]}
        bibi_original_path = os.path.join(self.test_directory, "experiments", "experiment_data","bibi_1.bibi")
        bibi_temp_path = os.path.join(self.temp_directory, "bibi_test.xml")
        shutil.copyfile(bibi_original_path, bibi_temp_path)
        with open(bibi_temp_path) as bibi_xml:
            bibi = bibi_api_gen.CreateFromDocument(bibi_xml.read())

        exp_temp_path = os.path.join(os.path.split(__file__)[0], "experiments", "experiment_data", "test_1.exc")
        with open(exp_temp_path) as exp_xml:
            exp = exp_xml.read()

        self.mock_storageClient_instance.get_file.return_value = exp
        self.mock_storageClient_instance.parse_and_check_file_is_valid.return_value = bibi
        
        response = self.client.put('/experiment/' + experiment_id + '/transfer-functions', data=json.dumps(data))
        self.assertEqual(response.status_code, 200)
Пример #13
0
    def test_invalid_simulation(self):
        dir = os.path.split(__file__)[0]
        with open(os.path.join(dir, "experiment_data/milestone2.bibi")) as bibi_file:
            bibi = bibi_api_gen.CreateFromDocument(bibi_file.read())
        with open(os.path.join(dir, "experiment_data/ExDXMLExample.exc")) as exd_file:
            exd = exp_conf_api_gen.CreateFromDocument(exd_file.read())
        exd.path = "/somewhere/over/the/rainbow/exc"
        exd.dir = "/somewhere/over/the/rainbow"
        exd.physicsEngine = None
        bibi.path = "/somewhere/over/the/rainbow/bibi"
        models_path_patch = patch("hbp_nrp_cleserver.server.CLEGazeboSimulationAssembly.models_path",
                                       new=None)
        models_path_patch.start()
        with self.assertRaises(Exception):
            SynchronousNestSimulation(42, exd, bibi, gzserver_host="local")
        models_path_patch.stop()

        with self.assertRaises(Exception):
            SynchronousNestSimulation(42, exd, bibi, gzserver_host="bullshit")
Пример #14
0
    def test_reset_from_storage_all(self,
                                    mock_get_header_token,
                                    mock_copy_tree,
                                    mock_get_experiment_data,
                                    mock_resetBrain,
                                    mock_resetTFs,
                                    mock_resetSMs,
                                    mock_dirname):
        self.mock_storageClient_instance.clone_all_experiment_files.return_value = '_', {
            'experiment_conf': 'fakeFolder/fakeExp'}

        mock_resetBrain.return_value = None
        mock_resetTFs.return_value = None
        mock_resetSMs.return_value = None
        mock_dirname.return_value = os.path.join(PATH, 'experiments/experiment_data')
        simulations[0].cle = mock.MagicMock()
        simulations[0].cle.set_simulation_transfer_function.return_value = None

        experiment_file_path = os.path.join(PATH, 'experiments/experiment_data/test_5.exc')

        with open(experiment_file_path) as exd_file:
            try:
                experiment = exp_conf_api_gen.CreateFromDocument(
                    exd_file.read())
            except ValidationError, ve:
                raise Exception("Could not parse experiment configuration {0:s} due to validation "
                                "error: {1:s}".format(experiment_file_path, str(ve)))

            bibi_file = experiment.bibiConf.src
            bibi_file_abs = os.path.join(EXPERIMENT_DATA_PATH, bibi_file)
            with open(bibi_file_abs) as b_file:
                try:
                    bibi = bibi_api_gen.CreateFromDocument(b_file.read())
                except ValidationError, ve:
                    raise Exception("Could not parse brain configuration {0:s} due to validation "
                                    "error: {1:s}".format(bibi_file_abs, str(ve)))
Пример #15
0
    def put(self, experiment_id):
        """
        Save a brain model PyNN of an experiment to the storage.
        :param path experiment_id: The experiment id

        :< json body json string data: PyNN script of the model
        :< json body json string brain_populations: neuron populations
        :< json body json string brain_populations: context_id of the sim

        :status 500: {0}
        :status 404: {1}
        :status 400: The request body is malformed
        :status 200: Success. File written.
        """
        from hbp_nrp_backend.storage_client_api.StorageClient \
            import StorageClient
        body = request.get_json(force=True)
        if 'data' not in body:
            raise NRPServicesClientErrorException(
                "Neural network python code should be sent in the body under the 'data' key"
            )
        context_id = body.get('context_id', None)

        # no need to rewrite a get_header function since the user
        # authentication already has one
        # Read the request data
        content_type = UserAuthentication.get_header(request, 'Content-type',
                                                     'text/plain')
        data = body['data']
        brain_populations = body.get('additional_populations')

        # Instantiate the storage client
        client = StorageClient()

        # find the bibi filename from the .exc
        experiment_file = client.get_file(
            UserAuthentication.get_header_token(request),
            experiment_id,
            'experiment_configuration.exc',
            byname=True)

        bibi_filename = exp_conf_api_gen.CreateFromDocument(
            experiment_file).bibiConf.src

        # find the brain filename from the bibi
        bibi_file = client.get_file(
            UserAuthentication.get_header_token(request),
            experiment_id,
            bibi_filename,
            byname=True)
        bibi_file_obj = bibi_api_gen.CreateFromDocument(bibi_file)
        brain_filename = bibi_file_obj.brainModel.file

        if 'storage://' in brain_filename:
            client.create_or_update(
                UserAuthentication.get_header_token(request),
                client.get_folder_uuid_by_name(
                    UserAuthentication.get_header_token(request), context_id,
                    'brains'), os.path.basename(brain_filename), data,
                content_type)
        else:
            client.create_or_update(
                UserAuthentication.get_header_token(request), experiment_id,
                os.path.basename(brain_filename), data, content_type)

        # remove all the populations
        del bibi_file_obj.brainModel.populations[:]

        if brain_populations is not None:
            self.parsePopulations(brain_populations, bibi_file_obj)

        # replace the bibi contents in the storage to match the new brain
        # definition
        client.create_or_update(
            UserAuthentication.get_header_token(request), experiment_id,
            bibi_filename,
            xml.dom.minidom.parseString(
                bibi_file_obj.toxml("utf-8")).toprettyxml(), "text/plain")

        return 200
Пример #16
0
        try:
            experiment = exp_conf_api_gen.CreateFromDocument(exd_file.read())
            experiment.path = experiment_file_path
        except ValidationError, ve:
            raise Exception("Could not parse experiment configuration {0:s} due to validation "
                            "error: {1:s}".format(experiment_file_path, str(ve)))

    bibi_file = experiment.bibiConf.src
    logger.info("Bibi: " + bibi_file)
    experiment_dir = os.path.dirname(experiment_file_path)
    bibi_file_abs = os.path.join(experiment_dir, bibi_file)
    experiment.dir = experiment_dir
    logger.info("BibiAbs:" + bibi_file_abs)
    with open(bibi_file_abs) as b_file:
        try:
            bibi = bibi_api_gen.CreateFromDocument(b_file.read())
            bibi.path = bibi_file_abs
        except ValidationError, ve:
            raise Exception("Could not parse brain configuration {0:s} due to validation "
                            "error: {1:s}".format(bibi_file_abs, str(ve)))
        except NamespaceError, ne:
            # first check to see if the BIBI file appears to have a valid
            # namespace
            namespace = str(ne).split(" ", 1)[0]
            if not namespace.startswith("http://schemas.humanbrainproject.eu/SP10") or \
               not namespace.endswith("BIBI"):
                raise Exception("Unknown brain configuration file format for: {0:s} with "
                                "namespace: {1:s}".format(bibi_file_abs, namespace))

            # notify the user that their file is out of date
            raise Exception("The BIBI file for the requested experiment is out of date and no "
    def get(self, exp_id):
        """
        Gets bibi file of the experiment specified with experiment ID.

        :param exp_id: The experiment ID

        :> json string filename: Name of the experiment file
        :> json string base64: Contents of the BIBI file encoded as base64

        :status 500: {0}
        :status 404: The experiment with the given ID was not found or the experiment BIBI file was
                     not found
        :status 200: Success. The experiment BIBI file was retrieved
        """
        # pylint: disable=too-many-locals
        filename = get_bibi_file(exp_id)

        if not os.path.isfile(filename):
            raise NRPServicesClientErrorException(
                ErrorMessages.EXPERIMENT_BIBI_FILE_NOT_FOUND_404,
                error_code=404)
        with open(filename) as bibi_file:
            bibi = bibi_api_gen.CreateFromDocument(bibi_file.read())
            assert isinstance(bibi, bibi_api_gen.BIBIConfiguration)

            tfs = []
            for tf in bibi.transferFunction:
                if isinstance(tf, bibi_api_gen.BIBITransferFunction):

                    if len(tf.deviceGroup) > 0 or isinstance(
                            tf, bibi_api_gen.Neuron2Monitor):
                        continue

                    devices = []
                    topics = []
                    impl = ""
                    for local in tf.local:
                        assert isinstance(local, bibi_api_gen.Local)
                        impl += local.name + " = " + print_expression(
                            local.body) + "\n"
                    for dev in tf.device:
                        assert isinstance(dev, bibi_api_gen.DeviceChannel)
                        dev_e = {
                            'parameterName': dev.name,
                            'type': dev.type,
                            'neurons': print_neurons(dev.neurons)
                        }
                        if dev.target is not None:
                            dev_e['target'] = dev.target
                        devices.append(dev_e)
                        if dev.body is not None:
                            impl += dev.name + "." + get_default_property(dev.type) + " = " + \
                                    print_expression(dev.body) + "\n"
                    for top in tf.topic:
                        assert isinstance(top, bibi_api_gen.TopicChannel)
                        topic_e = {
                            'parameterName': top.name,
                            'type': 'publisher'
                            if top.body is not None else 'subscriber',
                            'topic': top.topic,
                            'topicType': top.type
                        }
                        topics.append(topic_e)
                        if top.body is not None:
                            impl += top.name + ".send_message(" + print_expression(top.body) + \
                                    ")\n"
                    if isinstance(tf, bibi_api_gen.Neuron2Robot):
                        ret = tf.returnValue
                        assert isinstance(ret, bibi_api_gen.TopicChannel)
                        topic_e = {
                            'parameterName': '__return__',
                            'type': 'publisher',
                            'topic': ret.topic,
                            'topicType': ret.type
                        }
                        topics.append(topic_e)
                        impl += "return " + print_expression(ret.body)
                    tf_e = {
                        'name': tf.name,
                        'devices': devices,
                        'topics': topics,
                        'body': impl
                    }
                    tfs.append(tf_e)
            return {'transferFunctions': tfs}, 200