-
Notifications
You must be signed in to change notification settings - Fork 14
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
Review June 2020 #26
base: review/project_review_june_2020
Are you sure you want to change the base?
Review June 2020 #26
Conversation
Codecov Report
@@ Coverage Diff @@
## review/project_review_june_2020 #26 +/- ##
==================================================================
Coverage ? 90.61%
==================================================================
Files ? 37
Lines ? 6444
Branches ? 0
==================================================================
Hits ? 5839
Misses ? 605
Partials ? 0 Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In summary, there is not much wrong with the plotting code itself, but there is a lot of duplication.
I strongly recommend to make it so that make_sub_plot
and make_animation
are just calling make_plot
.
I would also try to split this in multiple files to make it easier to navigate. You don't have many files in that directory, so it should be fine to so that (i know that when you start getting many many files, it also starts to make things difficult to follow, but you are not there yet).
mcstasscript/interface/plotter.py
Outdated
|
||
index = -1 | ||
for data in data_list: | ||
index = index + 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
index
doesn't appear to be used in this loop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did a larger refactoring of the plotting functionality, this silly issue was removed. I can't respond directly to the top comment / summary, but the plotting code was refactored to remove the code duplication. The new version has been pushed to the master branch. The three classes are now all functions, which depend on a simpler underlying function. This also allowed easier and better testing!
mcstasscript/interface/plotter.py
Outdated
|
||
print("Plotting data with name " + data.metadata.component_name) | ||
if type(data.metadata.dimension) == int: | ||
fig = plt.figure(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i recommend to get the axes as an object here, as the get current axes method gca
is always prone to break, since some other axes somewhere else may become the current active axes.
fig = plt.figure(0) | |
fig, ax0 = plt.subplots() |
this way you are always sure which axes you are dealing with
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and maybe give the option to change the figsize
? plt.subplots(figsize=(12, 8))
(width and height in inches)
should be passed from input arguments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change was included in the refactor, the internal plotter function now uses fig and ax in the arguments which is provided by the calling function. In that way plt.gca is never used, and the ax object is used for all plotting.
figsize is now also a keyword argument in all three plotting functions.
mcstasscript/interface/plotter.py
Outdated
y_err = data.Error | ||
|
||
#(fig, ax0) = plt.errorbar(x, y, yerr=y_err) | ||
plt.errorbar(x, y, yerr=y_err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then call the methods on the axes, to also be sure they are plotting on the correct axes
plt.errorbar(x, y, yerr=y_err) | |
ax0.errorbar(x, y, yerr=y_err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All plotting is now done through the ax object instead of plt directly. Great suggestion.
mcstasscript/interface/plotter.py
Outdated
#(fig, ax0) = plt.errorbar(x, y, yerr=y_err) | ||
plt.errorbar(x, y, yerr=y_err) | ||
|
||
ax0 = plt.gca() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ax0 = plt.gca() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoided by giving the internal plotting function the ax as an argument.
mcstasscript/interface/plotter.py
Outdated
data.metadata.limits[1]*x_axis_mult) | ||
|
||
# Add a title | ||
plt.title(data.metadata.title) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
plt.title(data.metadata.title) | |
ax0.set_title(data.metadata.title) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
mcstasscript/interface/plotter.py
Outdated
plt.show() | ||
|
||
|
||
class make_sub_plot: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the recommended convention is to have uppercase letters in class names, and underscores in function names.
e.g. MakeSubPlot
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said, this class only has an __init__
and no other functions associated to it.
Maybe it can just be a function? Does it need to be a class? Is another class inheriting from it somehere?
If not, I would just make it a function, if it is just making a figure. Matplotlib will take care of keeping the figure alive for you, it doesn't need to be in a class. Especially since I don't really see the use of self
anywhere in here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make_plot, make_sub_plot and make_animation are now all functions!
mcstasscript/interface/plotter.py
Outdated
plt.show() | ||
|
||
|
||
class make_animation: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case this might be useful to have a class, see below
mcstasscript/interface/plotter.py
Outdated
# initialize plots | ||
|
||
data = data_list[0] | ||
if isinstance(data.metadata.dimension, int): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again i would try to just call make_plot
here instead of duplicating again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made a internal plotting function instead that make_plot, make_sub_plot and make_animation all use. The amount of duplication was really bad, glad to be rid of it!
mcstasscript/interface/plotter.py
Outdated
|
||
def init_1D(): | ||
# initialize function for animation | ||
er.set_data([], [], []) # wont work |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be very careful using functions inside function to access the scope of the __init__
. I would either
- pass things as arguments (e.g.
er
needs to be an input argument and this function needs to be outside of the class) - or use the fact that we are inside a class, and make
er
a member of the class (self.er = ...
) and then make these functions class members, i.e.
def init_1D(self):
self.er = set_data([], [], [])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The FuncAnimation need a function for updating the data with only an index as argument (unless I am misunderstanding), and in such I need to define a short function inside this function. I find it acceptable since the function is so short.
mcstasscript/interface/plotter.py
Outdated
|
||
class make_sub_plot: | ||
""" | ||
make_plot plots contents of McStasData objects |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make_plot plots contents of McStasData objects | |
make_sub_plot plots contents of McStasData objects |
copied and pasted from above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added additional text, but make_plot and make_sub_plot are still close in their description, as the functions are rather similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see that you have tests for the plot options, but can't really see tests on the plotting functions.
I know testing plotting is incredibly difficult, but maybe a first step would be to just call the plotting functions with different parameters, and simply make sure they don't throw any errors.
It would be a start.
|
||
def test_McStasPlotOptions_default_orders_of_mag(self): | ||
""" | ||
Test that newly created McStasMetaData has correct type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These docstrings all the same for all tests. Should be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have expanded the testing of McStasPlotOptions (only some options were tested), and updated their doc strings.
In addition a new file was added, test_Plotter.py, which adds 600 lines of testing for the plotting functionality, including running the internal plotter function (without plt.show() ) for all 1D/2D and log mode combinations.
This could obviously still be improved in the sense that actual plotting is not tested or visually compared to a known correct plot.
Include parameter information in metadata object. Will add a parameter attribute in extrat_info to make the parameters easily accessible from the McStasData object.
Added a metadata field. Added unittests. Also added __repr__ to configurator class.
Use these as baseclasses for the appropriate classes in McStasScript, and have made all required changes for the package to be functional. Unit tests are updated and everything seems to be in order. Am using direct access to underlying attributes a lot, so it is hard to change the underlying implementation in libpyvinyl without breaking this implementation. Will probably need a better contract with libpyvinyl to be more confident in the features I use will not be changed.
Syntax for running simulations have changed. Instrument class now based on libpyvinyl calculator. Jupyter notebook example available in example folder. Still todo: Update doc strings Update unit tests Update documentation
Allow components to use parameter objects for input. Updated example to show the new use.
method. It was required to register dynamic classes to globals. Avoid overwriting loaded classes by checking if attribute already defined. Updated example to show dump and load from dump.
McStasScript use a parameter class that inherits from the libpyvinyl parameter class as more checks and methods are needed. When importing from libpyvinyl versions, all attributes are included and the checks are made.
Now use output_path from BaseCalculator for folder name Set increment_folder_name to True as default.
Still work to do on documentation, need to ensure all doc strings are up to date, handle README and the pdf documentation.
Ensured declare and parameter variables print nicely in component print
Settings are now a dict which is updated by the settings method. The settings method contains input sanitation and is used in init. All examples and tutorials were checked for proper new usage. The components can now have parameters set with set_parameters using both keyword and dict argument.
Avoided using parameters in settings, these have to go through libpyvinyl parameters now. This changed interface a bit, but no issue.
and increment_folder_name set to False. Before it would load such a data file, which made unittests easier but was confusing for users. Now it will provide an error if the folder already exists. Furthermore, if a simulation does not produce a folder, a warning is shown, and the data returned is None. Tests updated to take this into account. Started helper file for tests.
Tests include a case of setting seed. Updated interface to disable threading as it caused crashes.
Removed intensity from event data, as it was only used in plotting, and now plotting of event data has been removed.
Improved reliability of reading NeXus data
…rs if run from within a related 'environment'
Simple solution to auto-detect McStas and McXtrace config
Allow McXtrace sessions to visualize using mxdisplay(-webgl/-pyqtgraph)
…r of components. When search statements are cleared, the component database is reset.
…r both parameters, AT and ROTATED. The system can be used for debugging, may be used for some automatic functions in the future.
Write component parameters
Fix bad escape sequence warning in python 3.11
… instead of near DEFINE and parameters. This syntax works where the others have issues.
Fixing SEARCH system
As this project has not been properly reviewed, it is necessary to make a complete review in order to assure quality.
Due to the size of the task, it is broken down to smaller tasks which are described on Jira to manage the work. This pull request will be used for adding review comments and improvements along the way without affecting the master branch.