Skip to content

Conversation

@JanNolten
Copy link

@JanNolten JanNolten commented Nov 10, 2025

  1. Creation of schema structure
  2. Creation of base scripts
  3. Creation of Pydantic Models for elephant.statistics, elephant.spike_train_correlation and elephant.spike_train_synchrony functions and classes
  4. Creation of tests
  5. Bug fixes
  6. Implemented validation for elephant.statistics, elephant.spike_train_correlation and elephant.spike_train_synchrony functions and classes

@mdenker mdenker self-assigned this Nov 11, 2025
@mdenker mdenker added the enhancement Editing an existing module, improving something label Nov 11, 2025
@coveralls
Copy link
Collaborator

coveralls commented Nov 11, 2025

Coverage Status

coverage: 88.305% (+0.04%) from 88.262%
when pulling 91df787 on JanNolten:feature/partial
into 5392583 on NeuralEnsemble:master.

return len(obj)
elif isinstance(obj, neo.core.spiketrainlist.SpikeTrainList):
return len(obj)

Copy link
Author

Choose a reason for hiding this comment

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

Added getting length of SpikeTrainList, to check if it is empty or has a min_length.


def validate_array_content(value, info, allowed_types: tuple, allow_none: bool, min_length: int, allowed_content_types: tuple, min_length_content: int = 0):
validate_type_length(value, info, allowed_types, allow_none, min_length)
hasContentLength = False
Copy link
Author

Choose a reason for hiding this comment

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

If hasContentLength is not set to True in the loop, then it would have never been initialized.

@classmethod
def validate_spiketrains(cls, v, info):
return fv.validate_spiketrains(v, info)
return fv.validate_spiketrains(v, info, min_length=0)
Copy link
Author

Choose a reason for hiding this comment

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

spiketrains is also allowed to be empty

# Call function with validated data unpacked
return func(**validated.model_dump())
return func(*args, **kwargs)

Copy link
Author

Choose a reason for hiding this comment

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

Because no normalization happens in the Pydantic models. It is safer to just pass the original arguments

if kwargs.pop("not_validate", False):
# skip validation, call inner function directly
return func(*args, **kwargs)

Copy link
Author

@JanNolten JanNolten Nov 20, 2025

Choose a reason for hiding this comment

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

Should be able to call function without validation, if it does not work how it should or if the user knows he has valid data and therefore wants to save some calculation time.

cv = scipy.stats.variation
@validate_with(PydanticCv)
def cv(*args, **kwargs):
return scipy.stats.variation(*args, **kwargs)
Copy link
Author

@JanNolten JanNolten Nov 20, 2025

Choose a reason for hiding this comment

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

This is the simplest way I found, to use a decorator for cv, but maybe it could be done without changing the previous code.

# Tau max with no units
tau_max = 1
self.assertRaises(ValueError,
self.assertRaises((ValueError, TypeError),
Copy link
Author

Choose a reason for hiding this comment

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

Because the Pydantic Model is more specific, it sometimes raises a different error type than the function, so the test should allow both types

skip_validation = False

def deactivate_validation():
skip_validation = True
Copy link
Author

Choose a reason for hiding this comment

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

Should also be able to disable the validation globally, so it does not get annoying, if you never want to use it.

return decorator

def activate_validation():
global skip_validation
Copy link
Author

Choose a reason for hiding this comment

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

Made it global so it gets stored globally and therefore stores the value correctly

(elephant.statistics.instantaneous_rate, PydanticInstantaneousRate, {"spiketrains": [], "sampling_period": 0.01 * pq.s}),
(elephant.statistics.optimal_kernel_bandwidth, PydanticOptimalKernelBandwidth, {"spiketimes": np.array([])}),
(elephant.statistics.cv2, PydanticCv2, {"time_intervals": np.array([])*pq.s}),
])
Copy link
Author

Choose a reason for hiding this comment

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

Forgot to pass in sampling_period into instantaneous_rate

@kohlerca kohlerca added this to the v1.3.0 milestone Dec 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Editing an existing module, improving something

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants