Skip to content

Setting Verbose #2631

Closed
Purva-Chaudhari wants to merge 14 commits intoMDAnalysis:developfrom
Purva-Chaudhari:develop
Closed

Setting Verbose #2631
Purva-Chaudhari wants to merge 14 commits intoMDAnalysis:developfrom
Purva-Chaudhari:develop

Conversation

@Purva-Chaudhari
Copy link
Copy Markdown

@Purva-Chaudhari Purva-Chaudhari commented Mar 16, 2020

Fixes #2504

Changes made in this Pull Request:

  • Deprecation warning for start/stop/ step
  • verbose set

PR Checklist

  • Tests?
  • Docs?
  • CHANGELOG updated?
  • Issue raised/referenced?

@Purva-Chaudhari
Copy link
Copy Markdown
Author

@lilyminium over-ridding needs to be done only when verbose is set to True in run (as i observed in some of the test cases) Hence i set it this way. But still if this doesn,t work i have another approach in mind . Do let me know,
Thanking you

Copy link
Copy Markdown
Member

@IAlibay IAlibay left a comment

Choose a reason for hiding this comment

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

Some initial comments, probably will need some clarifications of the logic here, apologies if I'm just failing to understand what you are trying to do here.

self.start = start
self.stop = stop
self.step = step
if start is not None:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Quick question here, is there a case where check_slice_indices returns None for either of start, stop or step? As far as I was aware it already returned ints?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I am sorry got confused with issue #2206 requirements asking to Adjust AnalysisBase.init() so that start/stop/step are stored in the respective private variables. Also make sure that the DeprecationWarning is raised even if any of the deprecated kwargs is None (currently missing).

Will remove that part for now and work on it after solving this one

elif step is not None:
self._step = step
else:
warnings.warn("Deprecation Warning", DeprecationWarning)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Aside from the above comment, I'm not sure I understand how this relates to setting verbose. Apologies if I'm just missing something simple, any chance you could provide extra information on why you're doing this?

# if verbose unchanged, use class default
verbose = getattr(self, '_verbose', False) if verbose is None else verbose

if verbose == True : self.verbose = verbose
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Based on line 142, shouldn't this be self._verbose?
Also, I'm probably getting the logic wrong here, but wouldn't it be best to always set self._verbose here? What if you have a case where you pass False to run() but True to __init__, in this construct self._verbose would be set to True even if verbose is currently False right?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

In case of parameter overriding for the run class can it be directly:
verbose = getattr(self, '_verbose', False) if verbose is None else verbose
-> self._verbose = verbose after the line

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Please do correct me if i am going wrong in understanding the requirement. (Just re-read the comments regarding deprecation.)

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 17, 2020

Codecov Report

Merging #2631 into develop will decrease coverage by 0.11%.
The diff coverage is 100.00%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #2631      +/-   ##
===========================================
- Coverage    91.00%   90.88%   -0.12%     
===========================================
  Files          174      174              
  Lines        23550    23256     -294     
  Branches      3083     3077       -6     
===========================================
- Hits         21431    21137     -294     
  Misses        1497     1497              
  Partials       622      622              
Impacted Files Coverage Δ
package/MDAnalysis/analysis/base.py 100.00% <100.00%> (ø)
package/MDAnalysis/auxiliary/base.py 88.19% <0.00%> (-0.74%) ⬇️
package/MDAnalysis/coordinates/chain.py 87.37% <0.00%> (-0.59%) ⬇️
package/MDAnalysis/coordinates/TRZ.py 83.46% <0.00%> (-0.38%) ⬇️
package/MDAnalysis/coordinates/base.py 93.46% <0.00%> (-0.36%) ⬇️
package/MDAnalysis/coordinates/DMS.py 88.23% <0.00%> (-0.34%) ⬇️
package/MDAnalysis/coordinates/GMS.py 85.41% <0.00%> (-0.30%) ⬇️
package/MDAnalysis/coordinates/INPCRD.py 90.62% <0.00%> (-0.29%) ⬇️
package/MDAnalysis/coordinates/GSD.py 86.95% <0.00%> (-0.28%) ⬇️
package/MDAnalysis/coordinates/TXYZ.py 90.10% <0.00%> (-0.22%) ⬇️
... and 32 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4102481...a9b410b. Read the comment docs.

@Purva-Chaudhari
Copy link
Copy Markdown
Author

Purva-Chaudhari commented Mar 18, 2020

@IAlibay Could you please have a look and suggest. I think there is no need to introduce a new subclass / method for overriding if its only within for the run class. Do correct me if I am wrong .

If this works fine I would simultaneously start with issue #2206 Since they are all related

@IAlibay
Copy link
Copy Markdown
Member

IAlibay commented Mar 18, 2020

@IAlibay Could you please have a look and suggest. I think there is no need to introduce a new subclass / method for overriding if its only within for the run class. Do correct me if I am wrong .

If this works fine I would simultaneously start with issue #2206 Since they are all related

@Purva-Chaudhari as far as I can tell this should work, you'll probably want to introduce a test though. Probably something similar to:

def test_verbose(u):
a = FrameAnalysis(u.trajectory, verbose=True)
assert a._verbose

But testing the influence of verbose being set when calling run.

@IAlibay
Copy link
Copy Markdown
Member

IAlibay commented Mar 18, 2020

I do wonder if it might be cheaper / safer to just explicitly pass verbose to _setup_frames (in the same manner as start, stop, and step). Especially if the long term idea is to make all those values only temporarily overriden by run (#2206).

Maybe one of the @MDAnalysis/coredevs might have some thoughts on this?

@orbeckst
Copy link
Copy Markdown
Member

I like @IAlibay 's idea to pass verbose through to

def _setup_frames(self, trajectory, start=None, stop=None, step=None):

instead of setting/unsetting AnalysisBase._verbose. This looks like a clean solution that makes sure that run(..., verbose=VALUE) is only temporary.

@Purva-Chaudhari
Copy link
Copy Markdown
Author

Purva-Chaudhari commented Mar 19, 2020

@IAlibay so should I pass verbose explicitly to _setup_frames . In that case of temporary overriding, the line : verbose = getattr(self, '_verbose', False) in _setup_frames can be removed and i guess then we don,t have to set self._verbose in run/_setup_frames.

Should I make this change and then introduce test?

@IAlibay
Copy link
Copy Markdown
Member

IAlibay commented Mar 19, 2020

@IAlibay so should I pass verbose explicitly to _setup_frames . In that case of temporary overriding, the line : verbose = getattr(self, '_verbose', False) in _setup_frames can be removed and i guess then we don,t have to set self._verbose in run/_setup_frames.

Should I make this change and then introduce test?

@Purva-Chaudhari Looks like the idea is popular, please do go ahead 👍

@Purva-Chaudhari
Copy link
Copy Markdown
Author

@IAlibay Could you please suggest me further

Copy link
Copy Markdown
Member

@IAlibay IAlibay left a comment

Choose a reason for hiding this comment

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

@Purva-Chaudhari Please see below for some documentation changes.

We also probably need some tests here. I can't think of a simple way to check that ProgressMeter was passed the right value (@orbeckst any thoughts here?). But at the very least we could check that calling run with a value that overrides the value set on object creation is temporary. As previously mentioned, I'd suggest this be an additional test in mdanalysis/testsuite/MDAnalysisTests/analysis/test_base.py, doing something similar to test_verbose, but checking _verbose after calling run(verbose=somevalue).

def _setup_frames(self, trajectory, start=None, stop=None, step=None, verbose = None):
"""
Pass a Reader object and define the desired iteration pattern
through the trajectory
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The docstring needs updating to reflect that verbose is now an explicit argument to _setup_frames. Please also include a .. versionchanged entry detailing that the verbose argument was added in 1.0.0.

interval = 1

verbose = getattr(self, '_verbose', False)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Probably don't need two empty lines here.

@@ -134,7 +134,7 @@ def _setup_frames(self, trajectory, start=None, stop=None, step=None):
if interval == 0:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do also add a versionchanged to run to document this new behaviour (i.e. temporary overriding of __init__ set verbose).

@IAlibay
Copy link
Copy Markdown
Member

IAlibay commented Mar 19, 2020

@Purva-Chaudhari also don't forget to update CHANGELOG and AUTHORS!

@Purva-Chaudhari
Copy link
Copy Markdown
Author

@IAlibay , @orbeckst for the case of testing of temporary overriding should I return verbose too from run method and in testsuite/MDAnalysisTests/analysis/test_base.py, i would then introduce test_verbose_run() as
a, run_verbose = FrameAnalysis(u.trajectory).run(verbose = True)
assert run_verbose

@jbarnoud
Copy link
Copy Markdown
Contributor

The verbosity is not a result, it should not be returned. Checking stdout or stderr would be better.

@orbeckst
Copy link
Copy Markdown
Member

@joaomcteixeira could you please also keep an eye on this PR and help out @IAlibay who is already doing many others. Thanks!

@lilyminium
Copy link
Copy Markdown
Member

Sorry for not seeing this earlier @Purva-Chaudhari. I think you should be able to check the verbosity of the ProgressMeter at FrameAnalysis._pm.verbose and compare that to the verbosity of the analysis class at FrameAnalysis._verbose?

@Purva-Chaudhari
Copy link
Copy Markdown
Author

Purva-Chaudhari commented Mar 20, 2020

Sorry for not seeing this earlier @Purva-Chaudhari. I think you should be able to check the verbosity of the ProgressMeter at FrameAnalysis._pm.verbose and compare that to the verbosity of the analysis class at FrameAnalysis._verbose?

@lilyminium The temporary overriding of verbose is done by passing it to _setup_frames as suggested by @IAlibay , self._verbose is not set. So I guess I need to compare FrameAnalysis._pm.verbose with the verbose in run, right?. FrameAnalysis._verbose would not be overridden.
Please do correct me if its wrong
So do I have to check for assert_equal (both the verbose)

@lilyminium
Copy link
Copy Markdown
Member

@Purva-Chaudhari yes, you would be checking that the verbose you pass into run is the same as the ProgressMeter but not necessarily the same as the FrameAnalysis value.

@IAlibay
Copy link
Copy Markdown
Member

IAlibay commented Mar 20, 2020

@Purva-Chaudhari can you solve your merge conflicts, that way we can see if Travis runs green.

Copy link
Copy Markdown
Member

@IAlibay IAlibay left a comment

Choose a reason for hiding this comment

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

Starting to look good, some docstring changes, and an extension of the test.

@@ -123,6 +123,9 @@ def _setup_frames(self, trajectory, start=None, stop=None, step=None):
stop frame of analysis
step : int, optional
number of frames to skip between each analysed frame
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please do add verbose to the parameter list please.

number of frames to skip between each analysed frame

.. versionchanged:: 1.0.0
added verbose argument
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Identation issue, should be:

.. versionchanged:: 1.0.0
   Verbose argument is now passed explicitly from :meth:`AnalysisBase.run`.

Turn on verbosity

.. versionchanged:: 1.0.0
verbose explicitly passed to _setup_frames as argument for temporary
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same as above, please do use :meth: and :class: docstring decorators too if you can, that way users can navigate to the right place when looking at the sphinx documentation.



def test_verbose_run(u):
a = FrameAnalysis(u.trajectory, verbose=False).run(verbose = True)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

PEP8 correction: no spaces around = please.

assert a._verbose


def test_verbose_run(u):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Here it would be good to test multiple cases using pytest.mark.parametrize, i.e. the cases of:

init, run
True, True
False, True
True, False
False, False

Let us know if you need any help to work out how to use parametrize. See test_AnalysisFromFunction for an example of it.

Copy link
Copy Markdown
Author

@Purva-Chaudhari Purva-Chaudhari Mar 20, 2020

Choose a reason for hiding this comment

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

@pytest.mark.parametrize('verbose, verbose_r',[(True,True), (True,False), (False,True), (False,False)])
def test_verbose_run(u,verbose, verbose_r)
a = FrameAnalysis(u.trajectory, verbose=verbose).run(verbose = verbose_r)
(should I include the four conditions )

if (a._verbose == True and a._pm.verbose == True):
assert a._verbose
assert a._pm.verbose
elif (a._verbose == True and a._pm.verbose == False):
assert a._verbose
assert not a._pm.verbose
elif (a._verbose == False and a._pm.verbose == True):
assert not a._verbose
assert a._pm.verbose
elif (a._verbose == False and a._pm.verbose == False):
assert not a._verbose
assert not a._pm.verbose

or simply
assert a._verbose
assert a._pm.verbose

Please see if this is correct or no

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You don't need the if/else construct, just assert that the a._verbose and a._pm.verbose values match the expected inputs verbose and verbose_r.

Obviously, this is all dependent on #2631 (comment)

@jbarnoud
Copy link
Copy Markdown
Contributor

There is a pull request about replacing the progress meter to use tqmd. It is worth checking that the testing strategy remains valid.

@lilyminium
Copy link
Copy Markdown
Member

lilyminium commented Mar 20, 2020

Unfortunately, I think #2617 actually makes this PR redundant since it never sets verbose or passes it to _setup_frames, but just makes the progress bar in run().

Edit: hopefully a better way to say this: PR #2617 removes the original problem in #2504 because the progress bar does not depend on _setup_frames either getting verbose passed as an argument or having _verbose be an attribute.

@jbarnoud
Copy link
Copy Markdown
Contributor

jbarnoud commented Mar 20, 2020 via email

@jbarnoud jbarnoud mentioned this pull request Mar 20, 2020
4 tasks
@Purva-Chaudhari
Copy link
Copy Markdown
Author

What should I do further then?

self._verbose = verbose

def _setup_frames(self, trajectory, start=None, stop=None, step=None):
def _setup_frames(self, trajectory, start=None, stop=None, step=None, verbose = None):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

use verbose=None without spaces

@joaomcteixeira
Copy link
Copy Markdown
Member

Hi @Purva-Chaudhari ,

Just a small comment on to properly develop on a fork. I see you have made the changes in your forked develop branch. This is not completely wrong, but it is best to branch out first to a new branch that addresses only the PR/issue in question. And then, Pull Request that branch to the main repository base. If you continue developing new features in the fork base branch, as per habit, it may get really problematic if you have to deal with complex merge conflicts in future situations.

Copy link
Copy Markdown
Member

@joaomcteixeira joaomcteixeira left a comment

Choose a reason for hiding this comment

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

I have had a look at the implementation details. I could not evaluate the whole functionality at this time. Can anyone provide me a quick way to run an example on this? Thanks!

:meth:`AnalysisBase.run`.
"""
self._trajectory = trajectory
start, stop, step = trajectory.check_slice_indices(start, stop, step)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would not use temporary variables here. You create a place for a bug to happen.
directly assign the returned values from trajectory.check_slice_indeces to the self.start .stop and .step.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

and on line 139 use the self. attributes instead of the temporary variables. It looks innocent I know but with time these kinds of practices start to accumulate and having their tool.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since this is historical AnalysisBase stuff, @richardjgowers might be best placed to discuss if there were any specific reasons for this (I think it was added in #460).

This behaviour is probably going to need to change in light of #2206, so I'm not sure if it's not best to just tackle all this in a separate PR?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These are valid comments, though these changes are out of scope of this pull request.

interval = 1

verbose = getattr(self, '_verbose', False)
self._pm = ProgressMeter(self.n_frames if self.n_frames else 1,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Python tip:

a = None or  1
# or
b = 0 or 77

😉

"""
logger.info("Choosing frames to analyze")
# if verbose unchanged, use class default
verbose = getattr(self, '_verbose', False) if verbose is None else verbose
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

To my understanding, there is no need to use getattr here. getattr and setattr are used on dynamic operations, not on static ones.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Hi @Purva-Chaudhari ,

Just a small comment on to properly develop on a fork. I see you have made the changes in your forked develop branch. This is not completely wrong, but it is best to branch out first to a new branch that addresses only the PR/issue in question. And then, Pull Request that branch to the main repository base. If you continue developing new features in the fork base branch, as per habit, it may get really problematic if you have to deal with complex merge conflicts in future situations.

Sorry was sort of new to open source, will ensure this henceforth

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No problem. I understood that. You did a very nice first attempt. 😉 that's why I commented on it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Here self._verbose may not be defined, so the getattr is necessary. Another possibility would be to wrap the call in a try, but it would be more cluttered.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

To my understanding, there is no need to use getattr here. getattr and setattr are used on dynamic operations, not on static ones.

should I make it verbose = False if none else verbose ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

isn't self._verbose defined in the __init__? link

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It is indeed. My bad.


def test_verbose_run(u):
a = FrameAnalysis(u.trajectory, verbose=False).run(verbose = True)
assert not a._verbose
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

assert a._verbose is False

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

not a._verbose is correct. There is no reason to compare the identity with the False singleton; in theory, everything that is considered false by python would be a valid value here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Correct. Thanks for the feedback!

verbose = getattr(self, '_verbose', False) if verbose is None else verbose

self._setup_frames(self._trajectory, start, stop, step)
self._setup_frames(self._trajectory, start, stop, step, verbose)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think this is correct. Why should a method of a class receive an argument that is an attribute of that same class when the method being called is not a @staticmethod ? (may be this is not from this PR and I am missing something)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

start, stop, step, and verbose are historically argument of the class, though we are deprecating them from the initializer in favour of the same arguments in the run method.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry, I was referring to the self._trajectory. Because it also gets assigned again on _setup_frames. But this is for other PR/issue, indeed.

def test_verbose_run(u):
a = FrameAnalysis(u.trajectory, verbose=False).run(verbose = True)
assert not a._verbose
assert a._pm.verbose
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

same here is True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same as above.

@orbeckst
Copy link
Copy Markdown
Member

@Purva-Chaudhari , PR #2617 (which will be merged soon) makes issue #2504 go away by design so I am sorry to say that this PR that you have been working on will be closed without merging. I understand that you and various mentors have put a lot of effort into it. This would have been your first contribution and in this way you would have qualified for submitting a GSoC proposal.

From what I can see from this PR, we would have eventually merged it as it was close to acceptance. So I am going to say that we will accept your GSoC proposal submission on the basis of your work seen in this PR #2631 unless you get another PR merged by 3/31/2020 (and we obviously encourage you to do so).

@orbeckst for @MDAnalysis/gsoc-mentors

@orbeckst orbeckst closed this Mar 20, 2020
@Purva-Chaudhari
Copy link
Copy Markdown
Author

@orbeckst Thank you for your acceptance regarding proposal, wanted to ask if I could work on an issue not labelled as gsoc starter. I see many of the gsoc labelled issues already taken. Any suggestions regarding any small issue to get solved please let me know,
Thanking you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

verbose not set in analysis.AnalysisBase.run

6 participants