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

[MRG] ENH: Added instance type check for plot_dipole function and also a test for it #606

Merged
merged 14 commits into from Mar 16, 2023

Conversation

raj1701
Copy link
Contributor

@raj1701 raj1701 commented Mar 6, 2023

Closes #511
I made changes in plot_dipole function in viz.py to type of argument 1. Iteration is used when a list of dipoles is passed. I have included a test in test_dipole.py where [dipole, integer] is passed as an argument to plot_dipole() and the appropriate error message is checked using pytest.

@raj1701 raj1701 changed the title Added instance type check for plot_dipole function and also a test for it ENH: Added instance type check for plot_dipole function and also a test for it Mar 7, 2023
@raj1701
Copy link
Contributor Author

raj1701 commented Mar 7, 2023

I have removed the flake8 errors

hnn_core/viz.py Outdated
Comment on lines 282 to 283
else:
if not isinstance(dpl, Dipole):
Copy link
Collaborator

Choose a reason for hiding this comment

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

do you need to nest here? Zen of Python:

Flat is better than nested

Copy link
Collaborator

Choose a reason for hiding this comment

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

do you ever enter this condition? See above in L271 ... it is turned into a list

hnn_core/viz.py Outdated
@@ -273,6 +273,18 @@ def plot_dipole(dpl, tmin=None, tmax=None, ax=None, layer='agg', decim=None,
elif average:
dpl = dpl + [average_dipoles(dpl)]

if type(dpl) == list:
Copy link
Collaborator

Choose a reason for hiding this comment

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

use isinstance for type checks ... and in any case object equality is not done using ==. You should use is.

Copy link
Contributor Author

@raj1701 raj1701 Mar 7, 2023

Choose a reason for hiding this comment

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

Sorry @jasmainak , I missed the L271. This condition is redundant and also the else block. I have updated the changes. Please check them

@jasmainak
Copy link
Collaborator

You should use the phrase "closes #511", otherwise the linked PR will not get closed when this PR is merged. See:

https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword

@codecov-commenter
Copy link

codecov-commenter commented Mar 7, 2023

Codecov Report

Merging #606 (f62a159) into master (d5d1a03) will decrease coverage by 0.07%.
The diff coverage is 100.00%.

❗ Current head f62a159 differs from pull request most recent head fc1e84c. Consider uploading reports for the commit fc1e84c to get more accurate results

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

@@            Coverage Diff             @@
##           master     #606      +/-   ##
==========================================
- Coverage   92.19%   92.12%   -0.07%     
==========================================
  Files          22       22              
  Lines        4229     4231       +2     
==========================================
- Hits         3899     3898       -1     
- Misses        330      333       +3     
Impacted Files Coverage Δ
hnn_core/viz.py 89.23% <100.00%> (+0.04%) ⬆️

... and 1 file with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

hnn_core/viz.py Outdated
@@ -273,6 +273,11 @@ def plot_dipole(dpl, tmin=None, tmax=None, ax=None, layer='agg', decim=None,
elif average:
dpl = dpl + [average_dipoles(dpl)]

for single_dpl in dpl:
if not isinstance(single_dpl, Dipole):
raise ValueError('Arg 1 should be of type dipole or list of dipol'
Copy link
Collaborator

Choose a reason for hiding this comment

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

say dpl instead of Arg 1 since that's what we call it in the function signature. And nitpick but dipole -> Dipole since class names are always capitalized in PEP convention

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure will make these changes

@jasmainak
Copy link
Collaborator

Can you update whats_new.rst ?

@raj1701
Copy link
Contributor Author

raj1701 commented Mar 8, 2023

Should I update in Current Changelog in whats_new.rst?

@@ -32,6 +32,9 @@ Changelog
- Add ability to record voltages and synaptic currents from all sections in :class:`~hnn_core.CellResponse`,
by `Nick Tolley`_ in :gh:`502`.

- Add ability to check instance type of Dipole in :func:`~hnn_core.viz.plot_dipole`,
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is more of a bugfix I would say ... but this will not get rendered properly. Did you check how to build the documentation in the contributing guide:

https://jonescompneurolab.github.io/hnn-core/dev/contributing.html

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure I will put it in bugfix and check the rendering properly

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey @jasmainak I made all changes. Please check them once

doc/whats_new.rst Outdated Show resolved Hide resolved
Copy link
Collaborator

@jasmainak jasmainak left a comment

Choose a reason for hiding this comment

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

good by me. @rythorpe @ntolley merge button is yours. Please "squash and merge" since there are merge commits in the history.

hnn_core/viz.py Outdated
Comment on lines 278 to 279
raise ValueError('dpl should be of type Dipole or list of Dipole, '
f'but {single_dpl} is a {type(single_dpl)}')
Copy link
Contributor

Choose a reason for hiding this comment

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

If single_dpl happens to be a list or ndarray, this error message will be long and potentially hard to read.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What alternative do you suggest moving forward here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
raise ValueError('dpl should be of type Dipole or list of Dipole, '
f'but {single_dpl} is a {type(single_dpl)}')
raise ValueError('dpl should be of type Dipole or list of Dipole '
f'but is of type {type(single_dpl)}')

Copy link
Contributor

Choose a reason for hiding this comment

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

We just don't want the traceback to be huge if the user accidentally enters dpl as a list of list or ndarray.

hnn_core/viz.py Outdated Show resolved Hide resolved
doc/whats_new.rst Outdated Show resolved Hide resolved
@rythorpe
Copy link
Contributor

rythorpe commented Mar 9, 2023

Also, you'll need to rebase @raj1701. Let me know if you need help with this.

@raj1701
Copy link
Contributor Author

raj1701 commented Mar 9, 2023

I can give it a shot. I'll contact you if I get stuck.

@raj1701
Copy link
Contributor Author

raj1701 commented Mar 9, 2023

@rythorpe I thinks I was successful with the rebase. Please check once. Thanks

hnn_core/viz.py Outdated
Comment on lines 276 to 277
raise ValueError('dpl should be of type Dipole, '
f'but {single_dpl } is a {type(single_dpl )}')
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
raise ValueError('dpl should be of type Dipole, '
f'but {single_dpl } is a {type(single_dpl )}')
raise ValueError('dpl should be of type Dipole or list of Dipole, '
f'but is a list containing type {type(single_dpl)}')

hnn_core/viz.py Outdated Show resolved Hide resolved
@rythorpe
Copy link
Contributor

rythorpe commented Mar 9, 2023

You're almost done @raj1701, just a minor adjustment to the warning message!

hnn_core/viz.py Outdated
if not isinstance(single_dpl, Dipole):
raise ValueError('dpl should be of type Dipole or list of '
'Dipole, but is a list containing '
f'type {type(single_dpl )}')
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
f'type {type(single_dpl )}')
f'type {type(single_dpl)}')

This is nitpicky, but we really want to keep the code as clean and readable as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed extra spaces

hnn_core/viz.py Outdated
dpl = dpl + [average_dipoles(dpl)]
else:
raise ValueError('dpl should be of type Dipole, '
f'but is a type {type(dpl )}')
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
f'but is a type {type(dpl )}')
f'but is a type {type(dpl)}')

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, I guess we should update this one to say "dpl should be of type Dipole or list of Dipole[...]" as we do above so that users don't get conflicting messages when errors pop up.

Copy link
Collaborator

@jasmainak jasmainak Mar 10, 2023

Choose a reason for hiding this comment

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

Actually, I just realized why don't we use _validate_type here like in the rest of the codebase? So we're not reinventing the wheel

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So instead of using isinstance(), _validate_type should be used ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

those are mostly doing other operations than type-checks after the isinstance ... in general, the smaller your diff is, the better. Larger diff and logic means we have to check carefully to make sure there are no corner cases. In this case, if _validate_type works, you should use it. It is also more DRY

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for _validate_type - I totally forgot about that function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok will add _validate_type in the code

hnn_core/viz.py Outdated
Comment on lines 273 to 279
elif isinstance(dpl, list):
for single_dpl in dpl:
_validate_type(single_dpl, Dipole, 'dpl', 'Dipole, list of Dipole')
if average:
dpl = dpl + [average_dipoles(dpl)]
else:
_validate_type(dpl, Dipole, 'dpl', 'Dipole, list of Dipole')
Copy link
Collaborator

Choose a reason for hiding this comment

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

do you even need to do this? Can't you just do:

_validate_type(dpl, Dipole, 'Dipole, list of Dipole')

?

Copy link
Contributor Author

@raj1701 raj1701 Mar 10, 2023

Choose a reason for hiding this comment

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

In the earlier code, there already was a else if ladder :
if isinstance(dpl, Dipole):
dpl = [dpl]
elif average:
dpl = dpl + [average_dipoles(dpl)]

-Now the 'dpl' can be of type Dipole or list of Dipole.

  • I think if we can pass multiple types to _validate_type() then we can do type checking in one go else we will be needing a similar else-if code.
  • Therefore I merged the two together.
  • The line 279 code is simply to point error. If the control reaches line 279, the type passed is always invalid. It is just a corner case where type error needs to be raised. eg- dpl is an integer 10 then control will reach line 279

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can try passing dipole and list of Dipole as types to _validate_type() like this
_validate_type(dpl,[Dipole, [Dipole]],'Dipole, list of Dipole')).
I will try this and let you know the results.
If there is some other way then please let me know

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can pass types = [Dipole,list] only. Is there a way to pass list of Dipoles as an argument? I tried with [Dipole] and list(Dipole) but both didn't work

@jasmainak
Copy link
Collaborator

Okay I simplified the logic a bit @raj1701 @rythorpe ... please take a look. It is slightly different from the original logic but I think it's not less correct. Wdyt?

@raj1701
Copy link
Contributor Author

raj1701 commented Mar 14, 2023

I think its correct and much more simplified. Now I get what you were trying to convey @jasmainak.

hnn_core/viz.py Outdated
Comment on lines 274 to 277
_validate_type(this_dpl, Dipole, 'dpl', 'Dipole, list of Dipole')

if average:
dpl = dpl + [average_dipoles(dpl)]
Copy link
Contributor

Choose a reason for hiding this comment

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

@jasmainak what if someone happens to pass in a numpy array of Dipole objects? This would be an easy mistake to make and would pass all of our checks, but would get weird on L277 when the averaging step assumes dpl + [average_dioles(dpl)] is an appending operation.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@rythorpe good catch! How about making use of duck typing? Unfortunately the numpy append does not work the same way as a list ... it does not work in-place. In MNE, we start most functions by saying arr = np.array(arr) to normalize lists and arrays, and then work pretending it's an array. That ship seems to have sailed here though. I could also place an explicit error if you prefer.

@jasmainak
Copy link
Collaborator

@raj1701 try not to make too many commits for a simple change. It will make your life difficult with respect to rebasing. Make use of git commit --amend or squash the commits so each commit represents a logical unit of code.

@rythorpe
Copy link
Contributor

Are we ready to rebase and merge @raj1701 @jasmainak?

@raj1701
Copy link
Contributor Author

raj1701 commented Mar 16, 2023

@raj1701 try not to make too many commits for a simple change. It will make your life difficult with respect to rebasing. Make use of git commit --amend or squash the commits so each commit represents a logical unit of code.

Yes will remember this. I faced many rebase errors here also.

@jasmainak jasmainak changed the title ENH: Added instance type check for plot_dipole function and also a test for it [MRG] ENH: Added instance type check for plot_dipole function and also a test for it Mar 16, 2023
@jasmainak
Copy link
Collaborator

Yep, I changed the PR to MRG. Please squash and merge @rythorpe !

@rythorpe rythorpe merged commit 664a5ad into jonescompneurolab:master Mar 16, 2023
8 checks passed
@rythorpe
Copy link
Contributor

Thanks @raj1701 and @jasmainak!

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.

plot_dipole function does not check instance type
4 participants