Browse Source

prepare minimal walkthrough

Keisuke Sehara 4 years ago
parent
commit
0f83f52bd4
3 changed files with 959 additions and 19 deletions
  1. 4 4
      datasets_metadata.json
  2. 23 5
      helper.py
  3. 932 10
      walkthrough.ipynb

+ 4 - 4
datasets_metadata.json

@@ -1,6 +1,6 @@
 {
     "tracking": {
-        "description": "whisker and nose tracking, based on python 'videobatch' program.",
+        "description": "whisker and nose tracking, based on high-speed videos taken at 200 Hz, and analyzed using the python 'videobatch' program.",
         "reference": [
             {
                 "role": "is-analyzed-using",
@@ -10,7 +10,7 @@
             {
                 "role": "is-performed-by",
                 "name": "Sina E. Dominiak",
-                "uri":  null,
+                "uri":  null
             },
             {
                 "role": "is-performed-by",
@@ -30,12 +30,12 @@
                 "suffix":      ".png"
             },
             "tracked": {
-                "description": "the CSV files containing tracked object positions in pixels. 'Slice' represents the frame index in the video of origin.",
+                "description": "the CSV files containing tracked object positions in pixels. 'Slice' represents the ZERO-STARTING frame index in the video of origin.",
                 "mimetype":    "text/csv",
                 "suffix":      ".csv"
             },
             "states": {
-                "description": "the CSV files containing information about correspondence between trial numbers, video frames and behavioral states.",
+                "description": "the CSV files containing information about correspondence between trial numbers, video frames (ONE-STARTING) and behavioral states.",
                 "mimetype":    "text/csv",
                 "suffix":      ".csv"
             }

+ 23 - 5
helper.py

@@ -50,6 +50,7 @@ This 'helper.py' is written to work at the **root directory of the dataset**.
 
 SESSION_PATTERN   = _re.compile(r'([a-zA-Z]+)([0-9]{4}-[0-9]{2}-[0-9]{2})-([0-9]+)')
 SUBDOMAIN_PATTERN = _re.compile(r'-([a-zA-Z0-9-]+)$')
+RUN_PATTERN       = _re.compile(r'_run([0-9]+)_')
 
 rootdir = _Path(__file__).parent
 
@@ -155,6 +156,9 @@ class dataspec(_cl.namedtuple('_dataspec', ('context', 'data'))):
         if name in self.context.keys():
             return self.context[name]
 
+    def convert_data(self, datafunc):
+        return self.__class__(self.context, datafunc(self.data))
+
 class predicate:
     _retrievable = ('datasets', 'subjects', 'domains', 'files', 'subdomains') \
                     + ('session_names', 'session_types', 'dates', 'session_indices')
@@ -171,6 +175,8 @@ class predicate:
             raise ValueError("use '<context>.has_subdomain(<subdom>)' expression for restricting to a subdomain")
         elif name in self._retrievable:
             return self.retrieve(name)
+        else:
+            raise AttributeError(name)
 
     def get_datasets(self, as_spec=True, recalculate=False):
         if ('datasets' not in self.__cached.keys()) or (recalculate == True):
@@ -291,8 +297,11 @@ class predicate:
                         subdomains = tuple(has_subdomain.group(1).split('-'))
                     else:
                         subdomains = ()
+                    has_run = RUN_PATTERN.search(child.name)
                     cxt               = dom.context.copy()
                     cxt['subdomains'] = subdomains
+                    if has_run:
+                        cxt['run'] = int(has_run.group(1))
                     # print(f"name={child.name}; subdomains={subdomains}")
                     if self.__validate__('subdomain', cxt):
                         spec = dataspec(cxt, child)
@@ -340,7 +349,7 @@ class predicate:
         return self.__join__('mul', other)
 
     def has_subdomain(self, subdom):
-        return conditional('has', 'subdomains', subdom)
+        return conditional('has', parameter(self, 'subdomains'), subdom)
 
 class _datasets(predicate):
     """manages file retrieval from datasets."""
@@ -363,6 +372,8 @@ class parameter:
     def __getattr__(self, name):
         if name == 'name':
             return self.__name
+        else:
+            raise AttributeError(name)
 
     def __repr__(self):
         parent = repr(self.__parent)
@@ -391,6 +402,9 @@ class parameter:
     def __le__(self, value):
         return self.__cond__('le', value)
 
+    def __validate__(self, param, context):
+        return self.__parent.__validate__(param, context)
+
 
 class conditional(predicate):
     """manages conditions in contexts."""
@@ -431,7 +445,9 @@ class conditional(predicate):
         return f"({self.__param} {self.opcode} {repr(self.__value)})"
 
     def __validate__(self, param, context):
-        if self.__param.name not in base_params:
+        if not self.__param.__validate__(param, context):
+            return False
+        elif self.__param.name not in base_params:
             # subject-, session- or trial- related variables
             if self.__param.name not in context.keys():
                 return True
@@ -439,12 +455,14 @@ class conditional(predicate):
                 or (param not in session_params):
             if param != self.__param.name:
                 return True
-        elif (self.__param.name == 'subdomains') and (self.__op == 'has'):
-            return (self.__value in context['subdomains'])
 
         op = self._ops.get(self.__op, None)
+        val = context.get(self.__param.name, None)
         if op:
-            return op(context.get(self.__param.name, None), self.__value)
+            if val:
+                return op(val, self.__value)
+            else:
+                return True
         else:
             raise ValueError(f'unknown operation: {op}')
 

File diff suppressed because it is too large
+ 932 - 10
walkthrough.ipynb