LorenFrankLab / spyglass

Neuroscience data analysis framework for reproducible research built by Loren Frank Lab at UCSF
https://lorenfranklab.github.io/spyglass/
MIT License
83 stars 40 forks source link

Sometimes, the nwb file path is not made from ```SPYGLASS_BASE_DIR```. #258

Closed shijiegu closed 2 years ago

shijiegu commented 2 years ago

Describe the bug The nwb file path is not made from SPYGLASS_BASE_DIR.

To Reproduce Steps to reproduce the behavior:

  1. Make an nwb file with /opt/stelmo
  2. Do IntervalPositionInfo.populate() on a machine that mounts stelmo at / directly.

Expected behavior If on a different machine, the SPYGLASS_BASE_DIR on /stelmo, the code should run. SpikeSortingRecording.populate() uses SPYGLASS_BASE_DIR

Screenshots

Computing position for: {'position_info_param_name': 'default_decoding', 'nwb_file_name': 'fern20211007_.nwb', 'interval_list_name': 'pos 0 valid times'}
Writing new NWB file fern20211007_1KSTEBUVJM.nwb
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Input In [4], in <cell line: 27>()
     15     IntervalPositionInfoSelection.insert1(
     16         {'nwb_file_name': nwb_copy_file_name,
     17          'interval_list_name': pos_intvl,
     18          'position_info_param_name': 'default' #default parameters are in the database already
     19         }, skip_duplicates=True)
     21     IntervalPositionInfoSelection.insert1(
     22         {'nwb_file_name': nwb_copy_file_name,
     23          'interval_list_name': pos_intvl,
     24          'position_info_param_name': 'default_decoding' #upsampled for decoding, default parameters are in the database already
     25         }, skip_duplicates=True)
---> 27 IntervalPositionInfo.populate()

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/autopopulate.py:229, in AutoPopulate.populate(self, suppress_errors, return_exception_objects, reserve_jobs, order, limit, max_calls, display_progress, processes, make_kwargs, *restrictions)
    225 if processes == 1:
    226     for key in (
    227         tqdm(keys, desc=self.__class__.__name__) if display_progress else keys
    228     ):
--> 229         error = self._populate1(key, jobs, **populate_kwargs)
    230         if error is not None:
    231             error_list.append(error)

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/autopopulate.py:281, in AutoPopulate._populate1(self, key, jobs, suppress_errors, return_exception_objects, make_kwargs)
    279 self.__class__._allow_insert = True
    280 try:
--> 281     make(dict(key), **(make_kwargs or {}))
    282 except (KeyboardInterrupt, SystemExit, Exception) as error:
    283     try:

File ~/Documents/spyglass/src/spyglass/common/common_position.py:81, in IntervalPositionInfo.make(self, key)
     78 print(f'Computing position for: {key}')
     79 key['analysis_file_name'] = AnalysisNwbfile().create(
     80     key['nwb_file_name'])
---> 81 raw_position = (RawPosition() &
     82                 {'nwb_file_name': key['nwb_file_name'],
     83                  'interval_list_name': key['interval_list_name']
     84                  }).fetch_nwb()[0]
     85 position_info_parameters = (
     86     PositionInfoParameters() &
     87     {'position_info_param_name': key['position_info_param_name']
     88      }).fetch1()
     90 head_position = pynwb.behavior.Position()

File ~/Documents/spyglass/src/spyglass/common/common_behav.py:89, in RawPosition.fetch_nwb(self, *attrs, **kwargs)
     88 def fetch_nwb(self, *attrs, **kwargs):
---> 89     return fetch_nwb(self, (Nwbfile, 'nwb_file_abs_path'), *attrs, **kwargs)

File ~/Documents/spyglass/src/spyglass/common/dj_helper_fn.py:74, in fetch_nwb(query_expression, nwb_master, *attrs, **kwargs)
     71 if not attrs:
     72     attrs = query_expression.heading.names
---> 74 rec_dicts = (query_expression * tbl.proj(nwb2load_filepath=attr_name)
     75              ).fetch(*attrs, 'nwb2load_filepath', **kwargs)
     77 if not rec_dicts or not np.any(['object_id' in key for key in rec_dicts[0]]):
     78     return rec_dicts

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/fetch.py:228, in Fetch.__call__(self, offset, limit, order_by, format, as_dict, squeeze, download_path, *attrs)
    226 attributes = [a for a in attrs if not is_key(a)]
    227 ret = self._expression.proj(*attributes)
--> 228 ret = ret.fetch(
    229     offset=offset,
    230     limit=limit,
    231     order_by=order_by,
    232     as_dict=False,
    233     squeeze=squeeze,
    234     download_path=download_path,
    235     format="array",
    236 )
    237 if attrs_as_dict:
    238     ret = [
    239         {k: v for k, v in zip(ret.dtype.names, x) if k in attrs}
    240         for x in ret
    241     ]

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/fetch.py:288, in Fetch.__call__(self, offset, limit, order_by, format, as_dict, squeeze, download_path, *attrs)
    285     raise e
    286 for name in heading:
    287     # unpack blobs and externals
--> 288     ret[name] = list(map(partial(get, heading[name]), ret[name]))
    289 if format == "frame":
    290     ret = pandas.DataFrame(ret).set_index(heading.primary_key)

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/fetch.py:50, in _get(connection, attr, data, squeeze, download_path)
     46 if data is None:
     47     return
     49 extern = (
---> 50     connection.schemas[attr.database].external[attr.store]
     51     if attr.is_external
     52     else None
     53 )
     55 # apply attribute adapter if present
     56 adapt = attr.adapter.get if attr.adapter else lambda x: x

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/external.py:477, in ExternalMapping.__getitem__(self, store)
    470 """
    471 Triggers the creation of an external table.
    472 Should only be used when ready to save or read from external storage.
    473 :param store: the name of the store
    474 :return: the ExternalTable object for the store
    475 """
    476 if store not in self._tables:
--> 477     self._tables[store] = ExternalTable(
    478         connection=self.schema.connection,
    479         store=store,
    480         database=self.schema.database,
    481     )
    482 return self._tables[store]

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/external.py:56, in ExternalTable.__init__(self, connection, store, database)
     54 self._s3 = None
     55 if self.spec["protocol"] == "file" and not Path(self.spec["location"]).is_dir():
---> 56     raise FileNotFoundError(
     57         "Inaccessible local directory %s" % self.spec["location"]
     58     ) from None

FileNotFoundError: Inaccessible local directory /opt/stelmo/nwb/raw
lfrank commented 2 years ago

The best solution here is to fix the mount point to always be /stelmo

Can you do that?

On May 24, 2022, at 5:13 PM, Shijie Gu @.***> wrote:

 Describe the bug The nwb file path is not made from SPYGLASS_BASE_DIR. To Reproduce Steps to reproduce the behavior: Make an nwb file with /opt/stelmo Do IntervalPositionInfo.populate() on a machine that mounts stelmo at / directly. ‍ ‍ ‍ ‍ ‍ ‍ ‍ ZjQcmQRYFpfptBannerStart This Message Is From an External Sender This message came from outside your organization.

ZjQcmQRYFpfptBannerEnd

Describe the bug The nwb file path is not made from SPYGLASS_BASE_DIR.

To Reproduce Steps to reproduce the behavior:

  1. Make an nwb file with /opt/stelmo
  2. Do IntervalPositionInfo.populate() on a machine that mounts stelmo at / directly.

Expected behavior If on a different machine, the SPYGLASS_BASE_DIR on /stelmo, the code should run. SpikeSortingRecording.populate() uses SPYGLASS_BASE_DIR

Screenshots

Computing position for: {'position_info_param_name': 'default_decoding', 'nwb_filename': 'fern20211007.nwb', 'interval_list_name': 'pos 0 valid times'} Writing new NWB file fern20211007_1KSTEBUVJM.nwb

FileNotFoundError Traceback (most recent call last) Input In [4], in <cell line: 27>() 15 IntervalPositionInfoSelection.insert1( 16 {'nwb_file_name': nwb_copy_file_name, 17 'interval_list_name': pos_intvl, 18 'position_info_param_name': 'default' #default parameters are in the database already 19 }, skip_duplicates=True) 21 IntervalPositionInfoSelection.insert1( 22 {'nwb_file_name': nwb_copy_file_name, 23 'interval_list_name': pos_intvl, 24 'position_info_param_name': 'default_decoding' #upsampled for decoding, default parameters are in the database already 25 }, skip_duplicates=True) ---> 27 IntervalPositionInfo.populate()

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/autopopulate.py:229, in AutoPopulate.populate(self, suppress_errors, return_exception_objects, reserve_jobs, order, limit, max_calls, display_progress, processes, make_kwargs, *restrictions) 225 if processes == 1: 226 for key in ( 227 tqdm(keys, desc=self.class.name) if display_progress else keys 228 ): --> 229 error = self._populate1(key, jobs, **populate_kwargs) 230 if error is not None: 231 error_list.append(error)

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/autopopulate.py:281, in AutoPopulate._populate1(self, key, jobs, suppress_errors, return_exception_objects, make_kwargs) 279 self.class._allow_insert = True 280 try: --> 281 make(dict(key), **(make_kwargs or {})) 282 except (KeyboardInterrupt, SystemExit, Exception) as error: 283 try:

File ~/Documents/spyglass/src/spyglass/common/common_position.py:81, in IntervalPositionInfo.make(self, key) 78 print(f'Computing position for: {key}') 79 key['analysis_file_name'] = AnalysisNwbfile().create( 80 key['nwb_file_name']) ---> 81 raw_position = (RawPosition() & 82 {'nwb_file_name': key['nwb_file_name'], 83 'interval_list_name': key['interval_list_name'] 84 }).fetch_nwb()[0] 85 position_info_parameters = ( 86 PositionInfoParameters() & 87 {'position_info_param_name': key['position_info_param_name'] 88 }).fetch1() 90 head_position = pynwb.behavior.Position()

File ~/Documents/spyglass/src/spyglass/common/common_behav.py:89, in RawPosition.fetch_nwb(self, *attrs, kwargs) 88 def fetch_nwb(self, *attrs, *kwargs): ---> 89 return fetch_nwb(self, (Nwbfile, 'nwb_file_abs_path'), attrs, kwargs)

File ~/Documents/spyglass/src/spyglass/common/dj_helper_fn.py:74, in fetch_nwb(query_expression, nwb_master, *attrs, kwargs) 71 if not attrs: 72 attrs = query_expression.heading.names ---> 74 rec_dicts = (query_expression tbl.proj(nwb2load_filepath=attr_name) 75 ).fetch(attrs, 'nwb2load_filepath', kwargs) 77 if not rec_dicts or not np.any(['object_id' in key for key in rec_dicts[0]]): 78 return rec_dicts

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/fetch.py:228, in Fetch.call(self, offset, limit, order_by, format, as_dict, squeeze, download_path, attrs) 226 attributes = [a for a in attrs if not is_key(a)] 227 ret = self._expression.proj(attributes) --> 228 ret = ret.fetch( 229 offset=offset, 230 limit=limit, 231 order_by=order_by, 232 as_dict=False, 233 squeeze=squeeze, 234 download_path=download_path, 235 format="array", 236 ) 237 if attrs_as_dict: 238 ret = [ 239 {k: v for k, v in zip(ret.dtype.names, x) if k in attrs} 240 for x in ret 241 ]

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/fetch.py:288, in Fetch.call(self, offset, limit, order_by, format, as_dict, squeeze, download_path, *attrs) 285 raise e 286 for name in heading: 287 # unpack blobs and externals --> 288 ret[name] = list(map(partial(get, heading[name]), ret[name])) 289 if format == "frame": 290 ret = pandas.DataFrame(ret).set_index(heading.primary_key)

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/fetch.py:50, in _get(connection, attr, data, squeeze, download_path) 46 if data is None: 47 return 49 extern = ( ---> 50 connection.schemas[attr.database].external[attr.store] 51 if attr.is_external 52 else None 53 ) 55 # apply attribute adapter if present 56 adapt = attr.adapter.get if attr.adapter else lambda x: x

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/external.py:477, in ExternalMapping.getitem(self, store) 470 """ 471 Triggers the creation of an external table. 472 Should only be used when ready to save or read from external storage. 473 :param store: the name of the store 474 :return: the ExternalTable object for the store 475 """ 476 if store not in self._tables: --> 477 self._tables[store] = ExternalTable( 478 connection=self.schema.connection, 479 store=store, 480 database=self.schema.database, 481 ) 482 return self._tables[store]

File ~/anaconda3/envs/spyglass/lib/python3.8/site-packages/datajoint/external.py:56, in ExternalTable.init(self, connection, store, database) 54 self._s3 = None 55 if self.spec["protocol"] == "file" and not Path(self.spec["location"]).is_dir(): ---> 56 raise FileNotFoundError( 57 "Inaccessible local directory %s" % self.spec["location"] 58 ) from None

FileNotFoundError: Inaccessible local directory /opt/stelmo/nwb/raw

— Reply to this email directly, view it on GitHubhttps://urldefense.com/v3/__https://github.com/LorenFrankLab/spyglass/issues/258__;!!LQC6Cpwp!pfb4tOLL8ROVLatmic5wGFFzyc3qiLww0sZARBT-oVT5Uu7tOLpY1OAcssONoX2EIHABrIHivyfQtSe5VKJYNt_2LQ$, or unsubscribehttps://urldefense.com/v3/__https://github.com/notifications/unsubscribe-auth/ABV4PSIJ5DVJPBH3VUFF7LLVLVWBBANCNFSM5W3JM5DQ__;!!LQC6Cpwp!pfb4tOLL8ROVLatmic5wGFFzyc3qiLww0sZARBT-oVT5Uu7tOLpY1OAcssONoX2EIHABrIHivyfQtSe5VKINXpeQBw$. You are receiving this because you are subscribed to this thread.Message ID: @.***>

shijiegu commented 2 years ago

This is a serious bug because this time around I made everything on Virga with /stelmo