diff --git a/access_node/controllers/nest_controller.py b/access_node/controllers/nest_controller.py
index a93be66989ec1f02e3081fceb691d292e908306d..0e907f4c0aec80af97a79e7451bc4de9e6b705f2 100644
--- a/access_node/controllers/nest_controller.py
+++ b/access_node/controllers/nest_controller.py
@@ -1,6 +1,8 @@
import connexion
import six
+from access_node.models.multimeter_info import MultimeterInfo # noqa: E501
+from access_node.models.multimeter_measurement import MultimeterMeasurement # noqa: E501
from access_node.models.neuron_properties import NeuronProperties # noqa: E501
from access_node.models.simulation_time_info import SimulationTimeInfo # noqa: E501
from access_node.models.spikes import Spikes # noqa: E501
@@ -37,6 +39,89 @@ def get_gids_in_population(population_id): # noqa: E501
return gids
+def get_multimeter_info(): # noqa: E501
+ """Retreives the available multimeters and their properties.
+
+ # noqa: E501
+
+
+ :rtype: MultimeterInfo
+ """
+ multimeter_info = requests.get(nodes.info_node+'/multimeter_info').json()
+ return multimeter_info
+
+
+def get_multimeter_measurements(multimeter_id, attribute, _from=None, to=None, gids=None, offset=None, limit=None): # noqa: E501
+ """Retrieves the measurements for a multimeter (optional) and GIDS (optional).
+
+ # noqa: E501
+
+ :param multimeter_id: The multimeter to query
+ :type multimeter_id:
+ :param attribute: The attribute to query (e.g., 'V_m' for the membrane potential)
+ :type attribute: str
+ :param _from: The start time (including) to be queried.
+ :type _from: float
+ :param to: The end time (excluding) to be queried.
+ :type to: float
+ :param gids: A list of GIDs queried for spike data.
+ :type gids: List[int]
+ :param offset: The offset into the result.
+ :type offset: int
+ :param limit: The maximum of entries to be result.
+ :type limit: int
+
+ :rtype: MultimeterMeasurement
+ """
+ mult_info = get_multimeter_info()
+
+ mult_gids = []
+ multimeter_exists = False
+ for mult in mult_info:
+ if mult['id'] == multimeter_id:
+ multimeter_exists = True
+ if attribute not in mult['attributes']:
+ return Status(code=400, message="Given multimeter does not measure given attribute")
+ mult_gids = mult['gids']
+ break
+ if not multimeter_exists:
+ return Status(code=400, message="Given multimeter does not exist")
+
+ if gids == None:
+ gids = mult_gids
+ else:
+ for gid in gids:
+ if gid not in mult_gids:
+ return Status(code=400, message="Gid "+str(gid)+" is not measured by given Multimeter")
+
+ init = True
+ sim_times = []
+ measurement = MultimeterMeasurement([],[],[])
+ for node in nodes.simulation_nodes:
+ response = requests.get(
+ 'http://'+node+'/multimeter_measurement', params={"multimeter_id": multimeter_id, "attribute": attribute, "_from": _from, "to": to, "gids": gids}).json()
+ if init:
+ sim_times = response['simulation_times']
+ measurement = MultimeterMeasurement(sim_times, gids, [None for x in range(0,(len(sim_times)*len(gids)))])
+ init = False
+ for x in range(len(response['gids'])):
+ gid = response['gids'][x]
+ index = measurement.gids.index(gid)
+ index_offset = index * len(sim_times)
+ for y in range(len(sim_times)):
+ measurement.values[index_offset+y] = response['values'][x*len(sim_times)+y]
+
+ # offset and limit
+ if (offset is None):
+ offset = 0
+ if (limit is None or (limit + offset) > len(measurement.gids)):
+ limit = len(measurement.gids) - offset
+ measurement.gids = measurement.gids[offset:offset+limit]
+ measurement.values = measurement.values[offset*len(sim_times):(offset+limit)*len(sim_times)]
+
+ return measurement
+
+
def get_neuron_properties(gids=None): # noqa: E501
"""Retrieves the properties of the specified neurons.
@@ -110,10 +195,10 @@ def get_spikes(_from=None, to=None, gids=None, offset=None, limit=None): # noqa
# offset and limit
if (offset is None):
offset = 0
- if (limit is None):
- limit = len(spikes.gids)
- spikes.gids = spikes.gids[offset:limit]
- spikes.simulation_times = spikes.simulation_times[offset:limit]
+ if (limit is None or (limit + offset) > len(spikes.gids)):
+ limit = len(spikes.gids) - offset
+ spikes.gids = spikes.gids[offset:offset+limit]
+ spikes.simulation_times = spikes.simulation_times[offset:offset+limit]
return spikes
@@ -153,9 +238,9 @@ def get_spikes_by_population(population_id, _from=None, to=None, offset=None, li
# offset and limit
if (offset is None):
offset = 0
- if (limit is None):
- limit = len(spikes.gids)
- spikes.gids = spikes.gids[offset:limit]
- spikes.simulation_times = spikes.simulation_times[offset:limit]
+ if (limit is None or (limit + offset) > len(spikes.gids)):
+ limit = len(spikes.gids) - offset
+ spikes.gids = spikes.gids[offset:offset+limit]
+ spikes.simulation_times = spikes.simulation_times[offset:offset+limit]
return spikes
diff --git a/access_node/models/__init__.py b/access_node/models/__init__.py
index adb0bd4e94b21e8539ac6ebf06224346f13842a8..477be9dfc6edecc6159fb56ff87b12f76a4ec25b 100644
--- a/access_node/models/__init__.py
+++ b/access_node/models/__init__.py
@@ -3,6 +3,9 @@
# flake8: noqa
from __future__ import absolute_import
# import models into model package
+from access_node.models.multimeter_info import MultimeterInfo
+from access_node.models.multimeter_info_inner import MultimeterInfoInner
+from access_node.models.multimeter_measurement import MultimeterMeasurement
from access_node.models.neuron_properties import NeuronProperties
from access_node.models.simulation_time_info import SimulationTimeInfo
from access_node.models.spikes import Spikes
diff --git a/access_node/models/multimeter_info.py b/access_node/models/multimeter_info.py
new file mode 100644
index 0000000000000000000000000000000000000000..d66278e6d45a5dd9b862265eda003b7e951ceb61
--- /dev/null
+++ b/access_node/models/multimeter_info.py
@@ -0,0 +1,38 @@
+# coding: utf-8
+
+from __future__ import absolute_import
+from datetime import date, datetime # noqa: F401
+
+from typing import List, Dict # noqa: F401
+
+from access_node.models.base_model_ import Model
+from access_node.models.multimeter_info_inner import MultimeterInfoInner # noqa: F401,E501
+from access_node import util
+
+
+class MultimeterInfo(Model):
+ """NOTE: This class is auto generated by the swagger code generator program.
+
+ Do not edit the class manually.
+ """
+
+ def __init__(self): # noqa: E501
+ """MultimeterInfo - a model defined in Swagger
+
+ """
+ self.swagger_types = {
+ }
+
+ self.attribute_map = {
+ }
+
+ @classmethod
+ def from_dict(cls, dikt) -> 'MultimeterInfo':
+ """Returns the dict as a model
+
+ :param dikt: A dict.
+ :type: dict
+ :return: The MultimeterInfo of this MultimeterInfo. # noqa: E501
+ :rtype: MultimeterInfo
+ """
+ return util.deserialize_model(dikt, cls)
diff --git a/access_node/models/multimeter_info_inner.py b/access_node/models/multimeter_info_inner.py
new file mode 100644
index 0000000000000000000000000000000000000000..fff3b96048fb1f578bca87fa076de688c483d89f
--- /dev/null
+++ b/access_node/models/multimeter_info_inner.py
@@ -0,0 +1,116 @@
+# coding: utf-8
+
+from __future__ import absolute_import
+from datetime import date, datetime # noqa: F401
+
+from typing import List, Dict # noqa: F401
+
+from access_node.models.base_model_ import Model
+from access_node import util
+
+
+class MultimeterInfoInner(Model):
+ """NOTE: This class is auto generated by the swagger code generator program.
+
+ Do not edit the class manually.
+ """
+
+ def __init__(self, id: int=None, attributes: List[str]=None, gids: List[int]=None): # noqa: E501
+ """MultimeterInfoInner - a model defined in Swagger
+
+ :param id: The id of this MultimeterInfoInner. # noqa: E501
+ :type id: int
+ :param attributes: The attributes of this MultimeterInfoInner. # noqa: E501
+ :type attributes: List[str]
+ :param gids: The gids of this MultimeterInfoInner. # noqa: E501
+ :type gids: List[int]
+ """
+ self.swagger_types = {
+ 'id': int,
+ 'attributes': List[str],
+ 'gids': List[int]
+ }
+
+ self.attribute_map = {
+ 'id': 'id',
+ 'attributes': 'attributes',
+ 'gids': 'gids'
+ }
+
+ self._id = id
+ self._attributes = attributes
+ self._gids = gids
+
+ @classmethod
+ def from_dict(cls, dikt) -> 'MultimeterInfoInner':
+ """Returns the dict as a model
+
+ :param dikt: A dict.
+ :type: dict
+ :return: The MultimeterInfo_inner of this MultimeterInfoInner. # noqa: E501
+ :rtype: MultimeterInfoInner
+ """
+ return util.deserialize_model(dikt, cls)
+
+ @property
+ def id(self) -> int:
+ """Gets the id of this MultimeterInfoInner.
+
+
+ :return: The id of this MultimeterInfoInner.
+ :rtype: int
+ """
+ return self._id
+
+ @id.setter
+ def id(self, id: int):
+ """Sets the id of this MultimeterInfoInner.
+
+
+ :param id: The id of this MultimeterInfoInner.
+ :type id: int
+ """
+
+ self._id = id
+
+ @property
+ def attributes(self) -> List[str]:
+ """Gets the attributes of this MultimeterInfoInner.
+
+
+ :return: The attributes of this MultimeterInfoInner.
+ :rtype: List[str]
+ """
+ return self._attributes
+
+ @attributes.setter
+ def attributes(self, attributes: List[str]):
+ """Sets the attributes of this MultimeterInfoInner.
+
+
+ :param attributes: The attributes of this MultimeterInfoInner.
+ :type attributes: List[str]
+ """
+
+ self._attributes = attributes
+
+ @property
+ def gids(self) -> List[int]:
+ """Gets the gids of this MultimeterInfoInner.
+
+
+ :return: The gids of this MultimeterInfoInner.
+ :rtype: List[int]
+ """
+ return self._gids
+
+ @gids.setter
+ def gids(self, gids: List[int]):
+ """Sets the gids of this MultimeterInfoInner.
+
+
+ :param gids: The gids of this MultimeterInfoInner.
+ :type gids: List[int]
+ """
+
+ self._gids = gids
diff --git a/access_node/models/multimeter_measurement.py b/access_node/models/multimeter_measurement.py
new file mode 100644
index 0000000000000000000000000000000000000000..7c5b77bfaf18d042427abb033e03c2893209fb84
--- /dev/null
+++ b/access_node/models/multimeter_measurement.py
@@ -0,0 +1,120 @@
+# coding: utf-8
+
+from __future__ import absolute_import
+from datetime import date, datetime # noqa: F401
+
+from typing import List, Dict # noqa: F401
+
+from access_node.models.base_model_ import Model
+from access_node import util
+
+
+class MultimeterMeasurement(Model):
+ """NOTE: This class is auto generated by the swagger code generator program.
+
+ Do not edit the class manually.
+ """
+
+ def __init__(self, simulation_times: List[float]=None, gids: List[int]=None, values: List[float]=None): # noqa: E501
+ """MultimeterMeasurement - a model defined in Swagger
+
+ :param simulation_times: The simulation_times of this MultimeterMeasurement. # noqa: E501
+ :type simulation_times: List[float]
+ :param gids: The gids of this MultimeterMeasurement. # noqa: E501
+ :type gids: List[int]
+ :param values: The values of this MultimeterMeasurement. # noqa: E501
+ :type values: List[float]
+ """
+ self.swagger_types = {
+ 'simulation_times': List[float],
+ 'gids': List[int],
+ 'values': List[float]
+ }
+
+ self.attribute_map = {
+ 'simulation_times': 'simulation_times',
+ 'gids': 'gids',
+ 'values': 'values'
+ }
+
+ self._simulation_times = simulation_times
+ self._gids = gids
+ self._values = values
+
+ @classmethod
+ def from_dict(cls, dikt) -> 'MultimeterMeasurement':
+ """Returns the dict as a model
+
+ :param dikt: A dict.
+ :type: dict
+ :return: The MultimeterMeasurement of this MultimeterMeasurement. # noqa: E501
+ :rtype: MultimeterMeasurement
+ """
+ return util.deserialize_model(dikt, cls)
+
+ @property
+ def simulation_times(self) -> List[float]:
+ """Gets the simulation_times of this MultimeterMeasurement.
+
+ This array is always sorted. # noqa: E501
+
+ :return: The simulation_times of this MultimeterMeasurement.
+ :rtype: List[float]
+ """
+ return self._simulation_times
+
+ @simulation_times.setter
+ def simulation_times(self, simulation_times: List[float]):
+ """Sets the simulation_times of this MultimeterMeasurement.
+
+ This array is always sorted. # noqa: E501
+
+ :param simulation_times: The simulation_times of this MultimeterMeasurement.
+ :type simulation_times: List[float]
+ """
+
+ self._simulation_times = simulation_times
+
+ @property
+ def gids(self) -> List[int]:
+ """Gets the gids of this MultimeterMeasurement.
+
+
+ :return: The gids of this MultimeterMeasurement.
+ :rtype: List[int]
+ """
+ return self._gids
+
+ @gids.setter
+ def gids(self, gids: List[int]):
+ """Sets the gids of this MultimeterMeasurement.
+
+
+ :param gids: The gids of this MultimeterMeasurement.
+ :type gids: List[int]
+ """
+
+ self._gids = gids
+
+ @property
+ def values(self) -> List[float]:
+ """Gets the values of this MultimeterMeasurement.
+
+ This array contains the measured values for each gid and time to get the value for gid n at time t you have to use the index n * length(simulation_times) + t # noqa: E501
+
+ :return: The values of this MultimeterMeasurement.
+ :rtype: List[float]
+ """
+ return self._values
+
+ @values.setter
+ def values(self, values: List[float]):
+ """Sets the values of this MultimeterMeasurement.
+
+ This array contains the measured values for each gid and time to get the value for gid n at time t you have to use the index n * length(simulation_times) + t # noqa: E501
+
+ :param values: The values of this MultimeterMeasurement.
+ :type values: List[float]
+ """
+
+ self._values = values
diff --git a/access_node/swagger/swagger.yaml b/access_node/swagger/swagger.yaml
index 13f7feec99343ab3d1ff280da80641de0581e9c2..e170db5f1a20d15fcff36f764ff41a12a3251c74 100644
--- a/access_node/swagger/swagger.yaml
+++ b/access_node/swagger/swagger.yaml
@@ -214,6 +214,93 @@ paths:
type: "string"
example: "Error message"
x-swagger-router-controller: "access_node.controllers.nest_controller"
+ /multimeter_info:
+ get:
+ tags:
+ - "nest"
+ summary: "Retreives the available multimeters and their properties."
+ operationId: "get_multimeter_info"
+ consumes:
+ - "application/json"
+ produces:
+ - "application/json"
+ parameters: []
+ responses:
+ 200:
+ description: "Operation successful."
+ schema:
+ $ref: "#/definitions/MultimeterInfo"
+ 400:
+ description: "Operation failed."
+ schema:
+ type: "string"
+ example: "Error message"
+ x-swagger-router-controller: "access_node.controllers.nest_controller"
+ /multimeter_measurement:
+ get:
+ tags:
+ - "nest"
+ summary: "Retrieves the measurements for a multimeter (optional) and GIDS (optional)."
+ operationId: "get_multimeter_measurements"
+ consumes:
+ - "application/json"
+ produces:
+ - "application/json"
+ parameters:
+ - name: "multimeter_id"
+ in: "query"
+ description: "The multimeter to query"
+ required: true
+ type: "number"
+ format: "integer"
+ - name: "attribute"
+ in: "query"
+ description: "The attribute to query (e.g., 'V_m' for the membrane potential)"
+ required: true
+ type: "string"
+ - name: "from"
+ in: "query"
+ description: "The start time (including) to be queried."
+ required: false
+ type: "number"
+ format: "double"
+ - name: "to"
+ in: "query"
+ description: "The end time (excluding) to be queried."
+ required: false
+ type: "number"
+ format: "double"
+ - name: "gids"
+ in: "query"
+ description: "A list of GIDs queried for spike data."
+ required: false
+ type: "array"
+ items:
+ type: "integer"
+ format: "uint64"
+ - name: "offset"
+ in: "query"
+ description: "The offset into the result."
+ required: false
+ type: "integer"
+ format: "uint64"
+ - name: "limit"
+ in: "query"
+ description: "The maximum of entries to be result."
+ required: false
+ type: "integer"
+ format: "uint64"
+ responses:
+ 200:
+ description: "Operation successful."
+ schema:
+ $ref: "#/definitions/MultimeterMeasurement"
+ 400:
+ description: "Operation failed."
+ schema:
+ type: "string"
+ example: "Error message"
+ x-swagger-router-controller: "access_node.controllers.nest_controller"
/population/${population_id}/gids:
get:
tags:
@@ -265,6 +352,50 @@ definitions:
gids:
- 6.027456183070403
- 6.027456183070403
+ MultimeterInfo:
+ type: "array"
+ items:
+ $ref: "#/definitions/MultimeterInfo_inner"
+ example:
+ - id: 0
+ attributes:
+ - "V_m"
+ MultimeterMeasurement:
+ type: "object"
+ properties:
+ simulation_times:
+ type: "array"
+ description: "This array is always sorted."
+ items:
+ type: "number"
+ format: "double"
+ gids:
+ type: "array"
+ items:
+ type: "integer"
+ format: "uint64"
+ values:
+ type: "array"
+ description: "This array contains the measured values for each gid and time\
+ \ to get the value for gid n at time t you have to use the index n * length(simulation_times)\
+ \ + t"
+ items:
+ type: "number"
+ example:
+ simulation_times:
+ - 0.1
+ - 0.2
+ gids:
+ - 1
+ - 2
+ - 3
+ values:
+ - 0.123
+ - 0.123
+ - 0.123
+ - 0.123
+ - 0.123
+ - 0.123
NeuronProperties:
type: "object"
properties:
@@ -296,3 +427,17 @@ definitions:
current: 1.4658129805029452
start: 0.8008281904610115
end: 6.027456183070403
+ MultimeterInfo_inner:
+ properties:
+ id:
+ type: "integer"
+ format: "uint64"
+ attributes:
+ type: "array"
+ items:
+ type: "string"
+ gids:
+ type: "array"
+ items:
+ type: "integer"
+ format: "uint64"