odml_utils.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. # -*- coding: utf-8 -*-
  2. '''
  3. Convenience functions to work with the odML metadata collection of the reach-
  4. to-grasp experiment.
  5. Authors: Julia Sprenger, Lyuba Zehl, Michael Denker
  6. Copyright (c) 2017, Institute of Neuroscience and Medicine (INM-6),
  7. Forschungszentrum Juelich, Germany
  8. All rights reserved.
  9. Redistribution and use in source and binary forms, with or without
  10. modification, are permitted provided that the following conditions are met:
  11. * Redistributions of source code must retain the above copyright notice, this
  12. list of conditions and the following disclaimer.
  13. * Redistributions in binary form must reproduce the above copyright notice,
  14. this list of conditions and the following disclaimer in the documentation
  15. and/or other materials provided with the distribution.
  16. * Neither the names of the copyright holders nor the names of the contributors
  17. may be used to endorse or promote products derived from this software without
  18. specific prior written permission.
  19. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  23. FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. '''
  30. import itertools
  31. import numpy as np
  32. def get_TrialCount(doc, trialtype=None, performance_code=None):
  33. """
  34. Returns a list of trials ids
  35. Args:
  36. doc (odml.doc.BaseDocument):
  37. odML Document of reach-to-grasp project
  38. trialtype (str or int):
  39. If stated, returns only count of trials with given trial type
  40. performance_code (int):
  41. If stated, returns only count of trials with given performance code
  42. Returns:
  43. (int):
  44. Number of specified trials
  45. """
  46. sec = doc['Recording']['TaskSettings']
  47. if performance_code == 255:
  48. output = sec.properties['CorrectTrialCount'].value.data
  49. elif performance_code == 191:
  50. output = sec.properties['GripErrorTrialCount'].value.data
  51. elif performance_code in [0, 159, 161, 163, 167, 175]:
  52. subsec = sec['TrialTypeSettings']
  53. else:
  54. output = sec.properties['TotalTrialCount'].value.data
  55. # TODO: extend to trial types and other performance codes
  56. return output
  57. def get_TrialIDs(doc, idtype='TrialID'):
  58. """
  59. Returns a list of trials ids
  60. Args:
  61. doc (odml.doc.BaseDocument):
  62. odML Document of reach-to-grasp project
  63. Returns:
  64. (list of int):
  65. Trial id list
  66. """
  67. output = []
  68. sec = doc['Recording']['TaskSettings']
  69. def ff(x): return x.name.startswith('Trial_')
  70. for trsec in sec.itersections(filter_func=ff):
  71. def FF(x): return x.name == idtype
  72. output.append(
  73. [p for p in trsec.iterproperties(filter_func=FF)][0].value.data)
  74. return sorted(output)
  75. def get_TrialType(doc, trialid, code=True):
  76. """
  77. Returns trial type (code or abbreviation) for wanted trial
  78. Args:
  79. doc (odml.doc.BaseDocument):
  80. odML Document of reach-to-grasp project
  81. trialid (int):
  82. ID of wanted trial
  83. code (boolean):
  84. If True (default), integer code of trial type is returned
  85. If False, string abbreviation of trial type is returned
  86. Returns:
  87. (int or str):
  88. trial type for wanted trial
  89. """
  90. def ff(x): return x.name == 'Trial_%03i' % trialid
  91. sec = [s for s in doc.itersections(filter_func=ff)][0]
  92. output = sec.properties['TrialType'].value.data
  93. return output
  94. def get_PerformanceCode(doc, trialid, code=True):
  95. """
  96. Returns the performance of the monkey in the given trial either as code or
  97. abbreviation.
  98. Args:
  99. doc (odml.doc.BaseDocument):
  100. odML Document of reach-to-grasp project
  101. trialid (int):
  102. ID of wanted trial
  103. code (boolean):
  104. If True (default), integer code of trial performance is returned
  105. If False, abbreviation of trial performance is returned
  106. Returns:
  107. (int or string):
  108. performance code or abbreviation for wanted trial
  109. """
  110. def ff1(x): return x.name == 'Trial_%03i' % trialid
  111. sec = [s for s in doc.itersections(filter_func=ff1)][0]
  112. def ff2(x): return x.name == 'PerformanceCode'
  113. output = [p for p in sec.iterproperties(filter_func=ff2)][0].value.data
  114. if code:
  115. return output
  116. else:
  117. def ff3(x): return x.name == 'PerformanceCodes'
  118. sec = [s for s in doc.itersections(filter_func=ff3)][0]
  119. def ff4(x): return x.name == 'pc_%i' % output
  120. output = [p for p in sec.iterproperties(filter_func=ff4)][0].value.data
  121. return output
  122. def get_OccurringTrialTypes(doc, code=True):
  123. """
  124. Returns all occurring trial types (code or abbreviations)
  125. Args:
  126. doc (odml.doc.BaseDocument):
  127. odML Document of reach-to-grasp project
  128. code (boolean):
  129. If True, integer code of trial type is returned
  130. If False, string abbreviation of trial type is returned
  131. Returns:
  132. (list of int or str):
  133. list of occurring trial types
  134. """
  135. trial_id_list = get_TrialIDs(doc)
  136. output = np.unique([get_TrialType(doc, trid, code=code) for trid in
  137. trial_id_list]).tolist()
  138. return output
  139. def get_trialids_pc(doc, performance_code):
  140. """
  141. Returns a list of trials ids which have the given performance code
  142. Args:
  143. doc (odml.doc.BaseDocument):
  144. odML Document of reach-to-grasp project
  145. trialtype (int or str):
  146. trial type of wanted trials
  147. Returns:
  148. (list of int):
  149. Trial id list with the given trial type
  150. """
  151. trialids = get_TrialIDs(doc)
  152. if isinstance(performance_code, int):
  153. code = True
  154. else:
  155. code = False
  156. output = []
  157. for trid in trialids:
  158. if get_PerformanceCode(doc, trid, code) == performance_code:
  159. output.append(trid)
  160. return output
  161. def get_trialids_trty(doc, trialtype):
  162. """
  163. Returns a list of trials ids which have the given trial type
  164. Args:
  165. doc (odml.doc.BaseDocument):
  166. odML Document of reach-to-grasp project
  167. trialtype (int or str):
  168. trial type of wanted trials
  169. Returns:
  170. (list of int):
  171. Trial id list with the given trial type
  172. """
  173. trialids = get_TrialIDs(doc)
  174. if isinstance(trialtype, int):
  175. code = True
  176. else:
  177. code = False
  178. output = []
  179. for trid in trialids:
  180. if get_TrialType(doc, trid, code) == trialtype:
  181. output.append(trid)
  182. return output