Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

timeseries that can handle strings #43

Merged
merged 7 commits into from
Nov 25, 2024

Conversation

melissakey
Copy link
Contributor

This fix allows the libxdf package to support strings (issue # 19). I also cleaned up "case 3" in the load_xdf file. part is required to support strings, but a lot of it is just reducing repetitive code.

Note that string support requires C++17 for std::variant

@Yida-Lin
Copy link
Member

Hi, thank you very much for the PR.

This PR is quite large; for historical reason, this library currently does not have unit tests, hence a large change like this is quite risky.

Is it possible to split this into multiple smaller PRs? This would make review much easier and much less risky.

Thank you very much in advance.

xdf.cpp Outdated Show resolved Hide resolved
xdf.cpp Outdated Show resolved Hide resolved
xdf.h Show resolved Hide resolved
xdf.h Outdated
@@ -174,7 +175,7 @@ class Xdf
*
* \sa offsets
*/
void detrend();
//void detrend();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please uncomment.

@Yida-Lin
Copy link
Member

Please also address the CI run issues above; seems only the ubuntu run finished successfully.

Thank you very much!

@melissakey
Copy link
Contributor Author

I looked through the details of the CI run issues, and I think they are running older versions of C++ that cannot handle std::variant. Both machines I have been using to develop/test this are M-series Macs, and it compiles just fine on both of them - but I verified that both used compilers with C++17 (or later) first.

This is my first experience with a PR, and I'm not entirely sure what the CI process consists of. (Apologies for your needing to deal with an amateur.)

If I'm reading the run issues right, the two options are either (1) try again with a newer compiler or (2) use a template instead of std::variant. Let me know your thoughts. I'm happy to assist in any way I can (just realize that I'm learning on the job here).

@Yida-Lin
Copy link
Member

Yida-Lin commented Nov 12, 2024

I looked through the details of the CI run issues, and I think they are running older versions of C++ that cannot handle std::variant. Both machines I have been using to develop/test this are M-series Macs, and it compiles just fine on both of them - but I verified that both used compilers with C++17 (or later) first.

This is my first experience with a PR, and I'm not entirely sure what the CI process consists of. (Apologies for your needing to deal with an amateur.)

If I'm reading the run issues right, the two options are either (1) try again with a newer compiler or (2) use a template instead of std::variant. Let me know your thoughts. I'm happy to assist in any way I can (just realize that I'm learning on the job here).

Thank you very much!

This library was written many years ago, and looking back from today's perspective, there is a lot that can be improved. Thank you for making the step forward!

Regarding C++17: I am all for a newer version, potentially even targeting C++20 if possible. Regarding std::variant: I personally think template would probably be more suitable (but I would need to take a closer look on feasibility).

Would you mind making a separate PR bumping the C++ version to 20? Alternatively I can make one later today as well. Thank you very much.

xdf.cpp Outdated Show resolved Hide resolved
xdf.cpp Outdated
}
} else {
//read the data
if(streams[index].info.channel_format.compare("float32") == 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can extract a const to reuse.

xdf.cpp Outdated
float data;
Xdf::readBin(file, &data);
streams[index].time_series[v].emplace_back(data);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be better to extract a function to re-use code (inside an anonymous namespace):


namespace {

// Reads data of type T up to `channel_count` and appends
// to `stream.time_series`.
templace <typename T>
void append_data(Stream& stream) {
  for (int v = 0; v < stream.info.channel_count; ++v) {
    T data;
    Xdf::readBin(file, &data);
    stream.time_series[v].push_back(std::move(data));
  }
}

} // namespace

Xdf::Xdf ...

and use it like

append_data<double>(streams[index]);

xdf.h Show resolved Hide resolved
xdf.cpp Outdated

// Fill inbuf with the numeric values from the row
for(auto& val : row) {
std::visit([&inbuf, &read](auto&& arg) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These probably would be more readable with std::transform together with template.

https://cplusplus.com/reference/algorithm/transform/

@cbrnr
Copy link
Collaborator

cbrnr commented Nov 12, 2024

I only have a general comment on the structure of these changes (since my C++ is very limited these days). The PR is quite large mainly because it simplifies control flow by removing or summarizing redundant parts. Would it be clearer if the overall structure remained the same and only the string-related parts were adjusted? This would probably also make it easier to review.

Also, some changes don't follow the library's four-space indentation style. Please make sure that each block is indented by four spaces (a few are only indented by two).

@melissakey
Copy link
Contributor Author

Out of curiosity, can you check to see if this works now that it's running C++20? My C++ is very limited, and while I understand that a template solution is better than what I've done, it's not something I have the bandwidth to figure out right now, unfortunately.

@Yida-Lin
Copy link
Member

Out of curiosity, can you check to see if this works now that it's running C++20? My C++ is very limited, and while I understand that a template solution is better than what I've done, it's not something I have the bandwidth to figure out right now, unfortunately.

Hello, I just tried running CI again and seems there are some compiling errors. Would you mind helping taking a look?

Once it compiles I'd be happy to approve the change; we can figure out template and other improvements in the future.

Thank you very much.

@cbrnr
Copy link
Collaborator

cbrnr commented Nov 14, 2024

Before merging this PR, would it be possible to test the library with the XDF files available here:

https://osf.io/uc7wn/

There are several XDF files in the corresponding folder, which should work with the current release. Since we don't have unit tests, we should at least make sure that we do not introduce regressions that lead to errors loading these files.

@melissakey
Copy link
Contributor Author

I can look into the errors tomorrow and check to make sure it works on the test cases. Thanks!

@melissakey
Copy link
Contributor Author

I believe this should be working now.

Let me know if there are still issues - I did test the various files from https://osf.io/uc7wn/, with the only issue being the one noticed in PR#26.

@melissakey
Copy link
Contributor Author

I should also add - I am about 99% sure that event_map is no longer being used in this version. I have not removed that code, but it may be extraneous at this point.

@Yida-Lin
Copy link
Member

Thank you; I was traveling in the last few days and will take a closer look this week.

@Yida-Lin Yida-Lin merged commit 0983273 into xdf-modules:main Nov 25, 2024
5 checks passed
@Yida-Lin
Copy link
Member

Sorry for the delay; looks great! Thank you very much for your contribution.

@cbrnr
Copy link
Collaborator

cbrnr commented Nov 25, 2024

@Yida-Lin xdf.pro should have been updated to include c++17 instead of c++11 – could you please push a hotfix?

@cbrnr
Copy link
Collaborator

cbrnr commented Nov 25, 2024

Also, I now get errors when building SigViewer with these changes:

src/file_handling_impl/xdf_reader.cpp:341:26: error: non-const lvalue reference to type 'vector<std::variant<int, float, double, long long, std::string>, allocator<std::variant<int, float, double, long long, std::string>>>' cannot bind to a value of unrelated type 'vector<float, allocator<float>>'
  341 |                 row.swap(nothing);
      |                          ^~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:716:72: note: passing argument to parameter here
  716 |   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector&)
      |                                                                        ^
src/file_handling_impl/xdf_reader.cpp:359:27: error: assigning to 'float' from incompatible type 'value_type' (aka 'std::variant<int, float, double, long long, std::string>')
  359 |                     *pt = row[i];
      |                           ^~~~~~
src/file_handling_impl/xdf_reader.cpp:369:89: error: invalid operands to binary expression ('value_type' (aka 'std::variant<int, float, double, long long, std::string>') and 'value_type')
  369 |                             *(pt + interpolation) = row[i] + interpolation * ((row[i+1] - row[i])) / (interval + 1);
      |                                                                                ~~~~~~~~ ^ ~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qmargins.h:159:34: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QMargins' for 1st argument
  159 | Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &m1, const QMargins &m2) noexcept
      |                                  ^         ~~~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qmargins.h:177:34: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QMargins' for 1st argument
  177 | Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &lhs, int rhs) noexcept
      |                                  ^         ~~~~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qmargins.h:391:35: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QMarginsF' for 1st argument
  391 | Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
      |                                   ^         ~~~~~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qmargins.h:409:35: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QMarginsF' for 1st argument
  409 | Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &lhs, qreal rhs) noexcept
      |                                   ^         ~~~~~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qsize.h:184:37: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QSize' for 1st argument
  184 | Q_DECL_CONSTEXPR inline const QSize operator-(const QSize &s1, const QSize &s2) noexcept
      |                                     ^         ~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qsize.h:359:38: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QSizeF' for 1st argument
  359 | Q_DECL_CONSTEXPR inline const QSizeF operator-(const QSizeF &s1, const QSizeF &s2) noexcept
      |                                      ^         ~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qpoint.h:174:38: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QPoint' for 1st argument
  174 | Q_DECL_CONSTEXPR inline const QPoint operator-(const QPoint &p1, const QPoint &p2)
      |                                      ^         ~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qpoint.h:375:39: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QPointF' for 1st argument
  375 | Q_DECL_CONSTEXPR inline const QPointF operator-(const QPointF &p1, const QPointF &p2)
      |                                       ^         ~~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qrect.h:476:31: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QRect' for 1st argument
  476 | Q_DECL_CONSTEXPR inline QRect operator-(const QRect &lhs, const QMargins &rhs) noexcept
      |                               ^         ~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qrect.h:889:32: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QRectF' for 1st argument
  889 | Q_DECL_CONSTEXPR inline QRectF operator-(const QRectF &lhs, const QMarginsF &rhs) noexcept
      |                                ^         ~~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtGui.framework/Headers/qtransform.h:417:19: note: candidate function not viable: no known conversion from 'value_type' (aka 'std::variant<int, float, double, long long, std::string>') to 'const QTransform' for 1st argument
  417 | inline QTransform operator -(const QTransform &a, qreal n)
      |                   ^          ~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__iterator/reverse_iterator.h:288:1: note: candidate template ignored: could not match 'reverse_iterator' against 'variant'
  288 | operator-(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
      | ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__iterator/move_iterator.h:304:1: note: candidate template ignored: could not match 'move_iterator' against 'variant'
  304 | operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -> decltype(__x.base() - __y.base()) {
      | ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__iterator/wrap_iter.h:182:5: note: candidate template ignored: could not match '__wrap_iter' against 'variant'
  182 |     operator-(const __wrap_iter<_Iter1>& __x,
      |     ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__ios/fpos.h:60:40: note: candidate template ignored: could not match 'fpos' against 'variant'
   60 | inline _LIBCPP_HIDE_FROM_ABI streamoff operator-(const fpos<_StateT>& __x, const fpos<_StateT>& __y) {
      |                                        ^
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qsharedpointer_impl.h:847:63: note: candidate template ignored: could not match 'QSharedPointer' against 'variant'
  847 | Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
      |                                                               ^
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qsharedpointer_impl.h:852:63: note: candidate template ignored: could not match 'QSharedPointer' against 'variant'
  852 | Q_INLINE_TEMPLATE typename QSharedPointer<T>::difference_type operator-(const QSharedPointer<T> &ptr1, X *ptr2)
      |                                                               ^
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qsharedpointer_impl.h:857:63: note: candidate template ignored: could not match 'T *' against 'value_type' (aka 'std::variant<int, float, double, long long, std::string>')
  857 | Q_INLINE_TEMPLATE typename QSharedPointer<X>::difference_type operator-(T *ptr1, const QSharedPointer<X> &ptr2)
      |                                                               ^
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qpoint.h:395:39: note: candidate function not viable: requires single argument 'p', but 2 arguments were provided
  395 | Q_DECL_CONSTEXPR inline const QPointF operator-(const QPointF &p)
      |                                       ^         ~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qpoint.h:198:38: note: candidate function not viable: requires single argument 'p', but 2 arguments were provided
  198 | Q_DECL_CONSTEXPR inline const QPoint operator-(const QPoint &p)
      |                                      ^         ~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qmargins.h:476:35: note: candidate function not viable: requires single argument 'margins', but 2 arguments were provided
  476 | Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &margins) noexcept
      |                                   ^         ~~~~~~~~~~~~~~~~~~~~~~~~
/opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qmargins.h:272:34: note: candidate function not viable: requires single argument 'margins', but 2 arguments were provided
  272 | Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &margins) noexcept
      |                                  ^         ~~~~~~~~~~~~~~~~~~~~~~~
src/file_handling_impl/xdf_reader.cpp:378:26: error: non-const lvalue reference to type 'vector<std::variant<int, float, double, long long, std::string>, allocator<std::variant<int, float, double, long long, std::string>>>' cannot bind to a value of unrelated type 'vector<float, allocator<float>>'
  378 |                 row.swap(nothing);
      |                          ^~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:716:72: note: passing argument to parameter here
  716 |   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector&)
      |                                                                        ^
In file included from src/file_handling_impl/xdf_reader.cpp:7:
In file included from src/file_handling_impl/xdf_reader.h:10:
In file included from src/file_handling/file_signal_reader.h:8:
In file included from src/file_handling/basic_header.h:9:
In file included from src/base/signal_channel.h:12:
In file included from /opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/QString:1:
In file included from /opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qstring.h:49:
In file included from /opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qchar.h:43:
In file included from /opt/homebrew/Cellar/qt@5/5.15.16/lib/QtCore.framework/Headers/qglobal.h:142:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/algorithm:1794:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__algorithm/copy.h:40:19: error: assigning to 'float' from incompatible type 'std::variant<int, float, double, long long, std::string>'
   40 |       *__result = *__first;
      |                   ^~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__algorithm/copy_move_common.h:109:19: note: in instantiation of function template specialization 'std::__copy_loop<std::_ClassicAlgPolicy>::operator()<std::variant<int, float, double, long long, std::string> *, std::variant<int, float, double, long long, std::string> *, float *>' requested here
  109 |   auto __result = _Algorithm()(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__out_first));
      |                   ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__algorithm/copy_move_common.h:133:15: note: in instantiation of function template specialization 'std::__unwrap_and_dispatch<std::__overload<std::__copy_loop<std::_ClassicAlgPolicy>, std::__copy_trivial>, std::__wrap_iter<std::variant<int, float, double, long long, std::string> *>, std::__wrap_iter<std::variant<int, float, double, long long, std::string> *>, float *, 0>' requested here
  133 |   return std::__unwrap_and_dispatch<_Algorithm>(std::move(__first), std::move(__last), std::move(__out_first));
      |               ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__algorithm/copy.h:111:15: note: in instantiation of function template specialization 'std::__dispatch_copy_or_move<std::_ClassicAlgPolicy, std::__copy_loop<std::_ClassicAlgPolicy>, std::__copy_trivial, std::__wrap_iter<std::variant<int, float, double, long long, std::string> *>, std::__wrap_iter<std::variant<int, float, double, long long, std::string> *>, float *>' requested here
  111 |   return std::__dispatch_copy_or_move<_AlgPolicy, __copy_loop<_AlgPolicy>, __copy_trivial>(
      |               ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__algorithm/copy.h:118:15: note: in instantiation of function template specialization 'std::__copy<std::_ClassicAlgPolicy, std::__wrap_iter<std::variant<int, float, double, long long, std::string> *>, std::__wrap_iter<std::variant<int, float, double, long long, std::string> *>, float *>' requested here
  118 |   return std::__copy<_ClassicAlgPolicy>(__first, __last, __result).second;
      |               ^
src/file_handling_impl/xdf_reader.cpp:334:22: note: in instantiation of function template specialization 'std::copy<std::__wrap_iter<std::variant<int, float, double, long long, std::string> *>, float *>' requested here
  334 |                 std::copy(row.begin(), row.end(), raw_data->begin() + startingPosition);
      |                      ^
5 errors generated.
make: *** [tmp/release/xdf_reader.o] Error 1

It seems related to the std::variant change. Do you have time to look?

@Yida-Lin Yida-Lin mentioned this pull request Nov 25, 2024
@Yida-Lin
Copy link
Member

Hi @cbrnr , sorry about that; for changing C++11 to a higher version in xdf.pro, I created #44. Please take a look when convenient.

For the std::variant change, let me take a closer look this week and see if I can update it to using template.

@cbrnr
Copy link
Collaborator

cbrnr commented Nov 25, 2024

Thanks @Yida-Lin, I think templates would indeed be a preferable solution here.

@Yida-Lin
Copy link
Member

Yida-Lin commented Dec 15, 2024

Hi, sorry it took a while, I am looking into addressing @cbrnr 's issue above with compiling with SigViewer.

But I just realized an issue: why did we want to store strings in time_series anyways? Prior to this PR, libxdf actually already supported string, but it was stored in eventMap, i.e. it is not a time series, but a string event.

Because SigViewer relies on the eventMap to render those string events, even if I fix the compiling issue, I think it will not work correctly anymore.

If we just want to fix #19 , then I think the fix should be on eventMap instead. This way we also don't need std::variant.

If I understood correctly, #19 was not complaining about libxdf not supporting strings, but rather the dimension is incorrect (only reading N instead of M x N).

Sorry I overlooked this earlier, would appreciate some clarifications. Thanks! @melissakey

@cbrnr
Copy link
Collaborator

cbrnr commented Dec 15, 2024

If I understood correctly, #19 was not complaining about libxdf not supporting strings, but rather the dimension is incorrect (only reading N instead of M x N).

Yes, that's exactly right.

@Yida-Lin
Copy link
Member

Thanks @cbrnr . If that's the case, unfortunately we'd need to revert this PR. The fix should be applied to the usage with regard to eventMap instead.

Please let me know if I misunderstood anything; otherwise I will apply the revert and the new fix some time this week. Thanks!

@cbrnr
Copy link
Collaborator

cbrnr commented Dec 16, 2024

I would think so, yes, because this PR also explicitly mentioned to fix #19 (which BTW is still open). Can you confirm @melissakey?

@melissakey
Copy link
Contributor Author

melissakey commented Dec 16, 2024

The challenge with eventMap goes beyond reading N instead of M x N. The eventMap object appears to be designed for stream-agnostic data such as notes. In fact, in the demonstrations of LSL that my data originates from, multiple notes were produced that belong in a 1-channel, stream-agnostic location. eventMap is perfect for that, and if all the strings were notes, the original code would work fine.

In addition to those notes, I also have M x N streams coming from a cognitive task where some of the fields are strings. In the current version of the output, the cog task produces 4 streams, each with a different number of columns, 2 of which contain strings. In each of these streams, both M and N are stream-specific, which means that eventMap, as currently conceived, is not appropriate - partially because of the M X N issue, but mostly because it's not stream-specific.

For this task, there is no scenario in which we can remove strings altogether. One of the fields will contain a randomly generated list of numbers/letters where the length is determined by the difficulty of the task. More generally, we pair a lot of cognitive assessment data containing a mixture of strings and numeric data with physiological data that is typically numeric.

Looking at the test case from #19, it's not clear whether that string data should be treated as stream-agnostic event data requiring multiple fields (e.g. appropriate to eventMap, but with more flexibility) or a stream (more similar to what I have).

I don't know much about the interface with SigViewer, so I'm not entirely sure what to say on that account. How would it/should it handle Pandas DataFrames with mixed-type data?

@Yida-Lin
Copy link
Member

I see. Thanks @melissakey .

So how about this: looks to me that Stream contains an M x N matrix, but it also has a stream.info.channel_format, which means all items inside the M x N matrix are of the same type, right? I guess we could add a template <typename T> to Stream to generalize the use case, and get rid of eventMap (which would require updating the SigViewer code but it shouldn't be too complicated).

Let me know what you think, cc @cbrnr

@cbrnr
Copy link
Collaborator

cbrnr commented Dec 17, 2024

I trust your expertise @Yida-Lin! If SigViewer needs to be updated, it would be great if you could do that too!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants