В комментарии упоминается - контрольная точка и поездная точка выглядят как строки. Чтобы подтвердить это, вы можете добавить print(type(testpoint))
и print(type(trainpoint))
к своему коду, чтобы узнать, какого типа они на самом деле. Если они действительно являются строками (и ошибка предполагает это); предполагая, что они являются числами, хранящимися в виде строк, вы можете просто преобразовать их в int или float, выполнив что-то вроде:
dist = np.sqrt(np.sum(np.power(float(testpoint)-float(trainpoint), 2)))
замените int на float в зависимости от ваших требований.
Существует несколько способов решения этой проблемы, но фундаментальная проблема заключается в том, что вы не можете использовать оператор - для строк - так же, как указывает ошибка.
Действительно ли обновлением является ObservableCollection на потоке UI, действительно вызывающем так большую часть узкого места для Вашего приложения? В противном случае палка с обновлением его на потоке UI. Помните, это не действительно контекстное переключение, это происходит, когда Вы выполняете что-то с Диспетчером - вместо этого, Вы просто отправляете задание потоку UI, который является уже рабочим потоком, на который ОС будет контекст переключаться в какой-то момент так или иначе. Поток UI осуществляет Ваше отправленное задание внутренней очереди и выполняет его. Вы не вызываете контекстное переключение сами.
Можно использовать старый добрый BackgroundWorker также в WPF (как в Windows Forms). Это примет к модели потоков WPF и также обеспечит хорошую абстракцию.