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
SANS Loki basic workflow #60
Conversation
…one folder for convienece at the moment
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.
Thanks for this addition! A number of comments below (if have not looked at the notebook yet). I think either @nvaytet or myself would pair-program with you to address some potentially more complex bits, and to ensure that this is in line with our latest guidelines (for example, helping in setting up unit tests).
src/ess/loki/load_files.py
Outdated
sample.masks[f"mask_{i}_xml"] = mask_xml["spectrum", :spectrum_size].data | ||
background.masks[f"mask_{i}_xml"] = mask_xml["spectrum", :spectrum_size].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.
- Looks SANS2D specific again (with the
spectrum_size
argument)? - Is there a more sensible mask name than just enumerating? Maybe parts of the filename?
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.
Some initial thoughts/comments.
src/ess/loki/load_files.py
Outdated
import scippneutron as scn | ||
|
||
|
||
def load_isis(filename, spectrum_size, tof_bins): |
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.
You could put these functions into an io
submodule
" !python make_config.py -h # change to `-f path` or run in terminal\n", | ||
"\n", | ||
"path = dataconfig.data_root\n", | ||
"direct_beam_file = 'DIRECT_SANS2D_REAR_34327_4m_8mm_16Feb16.dat'\n", |
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 these files should be put somewhere so that the notebook can find them so it can run. We should put them on the dmsc web server.
"background_transmission_run_number = 63159 \n", | ||
"direct_run_number = 63091\n", | ||
"\n", | ||
"mask_1 = f'{path}/MASK_SANS2D_REAR_Edges_16Mar2015.xml'\n", |
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 don't really understand the point of having all these masks in xml files.
From the names, it seems they are masking either tubes or physical regions in space.
We should be able to come up with a programmatic way of masking the tubes, maybe if we reshape the data into logical (tube,straw,pixel
) dimensions?
Maybe some masking based on count values would also be more compact?
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 agree, but I believe this is simply for reproducing specific SANS2D results, so maybe ok for that, as long as we ensure that for ESS instruments a better mechanism is put in place?
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"setup_offsets(sample, sample_trans, background, background_trans, direct, sample_pos_z_offset, bench_pos_y_offset, monitor4_pos_z_offset)" |
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 interface to this function is slightly odd. It assumes you always have the same list of input DataArrays, which hampers portability.
The function should probably just take in a single DataArray to apply corrections on, and then you call the function on the DataArrays you wish to correct.
In addition, have you thought about putting your data in a Dataset, so you can do these kind of things in a single call?
import scipp as sc | ||
|
||
|
||
def setup_offsets( |
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.
Change to accept only one input data array.
You should also add type hints to the arguments
src/ess/sans/sans.py
Outdated
from .normalization import solid_angle, transmission_fraction | ||
|
||
|
||
def to_wavelength( |
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.
Can we do this in a more succint way via transform_coords
?
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.
Maybe not, because this is essentially doing half of a SANS data reduction?
@SimonHeybrock @nvaytet thanks for useful comments! I will start off from addressing obvious cases and then indeed pair programing session(s) would be very useful. I can also see some more open questions e.g. xml mask files that may require some broader discussion but I guess we can take it at the later stage. |
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.
Just a few minor more comments/questions from my side:
src/ess/loki/load_sans2d.py
Outdated
idf_filename, | ||
mask_files, | ||
data_set, | ||
spectrum_size, |
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.
Why is this parameter required? Isn't it just data_set.sizes['spectrum']
?
Note that we typically use ds
as a generic variable names for datasets (and da
for data arrays).
src/ess/sans/normalization.py
Outdated
|
||
def covert_and_rebin(data, wavelength_bins, begin, end): | ||
""" | ||
Convertining and rebinning shifted 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.
Convertining and rebinning shifted data | |
Convertining and rebinning shifted data |
This docstring does not say more than the function name? What is the actual function purpose?
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.
Before this function was called setup
and I thought I can give it more descriptive name. Can revert it to setup
if it works better.
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 if a function is just used within a file then a good name may not be so important, but it seems this is imported elsewhere (sans.py
) so we probably want something that is truly descriptive?
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.
Indeed, it was initially used internally in one file but then it turned out that can be applied elswhere. Maybe contrib.py
is anyway better place for such helper function?
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.
contrib.py
was menat for things that may eventuallt make it into scipp itself. I think that is quite unlikely for this particular function.
src/ess/sans/normalization.py
Outdated
background = (below.sum() + above.sum()) / sc.scalar(below.sizes[dim] + | ||
above.sizes[dim]) |
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.
What if someone puts a mask on a monitor?
src/ess/sans/normalization.py
Outdated
:param dim: In the case of a numerator containing event data, this is the dimension | ||
along which the lookup operation should be performed. This can be omitted in | ||
case the denominator has only one dimension. |
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 appreciate the idea to keep this flexible, but is this ever not Q
in SANS?
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.
ok, I hard-coded the Q
in the function body instead.
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.
A few extra comments from reviewing the notebooks:
"tof_masked_region = sc.concat([sample.coords['tof']['tof', 0],\n", | ||
" mask_tof_min, mask_tof_max,\n", | ||
" sample.coords['tof']['tof', -1]], dim='tof')\n", |
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 assumes event data. Maybe mention this on top of the notebook?
"\n", | ||
"**Note:** We use programatic masks here and not those stored in xml files.\n", | ||
"\n", | ||
"# Mask bad pixels\n", |
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.
"# Mask bad pixels\n", | |
"### Mask bad pixels\n", |
?
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"result = sample_q.bins.sum() - background_q.bins.sum()\n", |
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.
Two notes here:
- Instead of
sum()
once could usehistogram()
here to define different Q bins. - This can be done in event mode, see https://scipp.github.io/user-guide/binned-data/computation.html#Subtraction.
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 thought I would keep the same binning as was requested at the top of the notebook?
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.
Possibly, but there may be performance advantages to use a coarse Q binning when the computing I(Q) numerator. Not saying the change this now, but you may put a note, maybe?
" data_incident_monitor=binned['background'].attrs[\"monitor2\"].value,\n", | ||
" data_transmission_monitor=binned['background'].attrs[\"monitor4\"].value,\n", | ||
" direct_incident_monitor=binned['direct'].attrs[\"monitor2\"].value,\n", | ||
" direct_transmission_monitor=binned['direct'].attrs[\"monitor4\"].value,\n", |
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 is repeated many times. How about changing the functions to take a dict of monitors as input?
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 we would be relying on special keys inside the to_I_of_Q
function?
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.
Well, you are anyway relying on special function parameter names?
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 added dicts, and used recursion in some functions to make them accept dict for convenience.
I think it works quite nicely.
src/ess/sans/i_of_q.py
Outdated
if isinstance(data, dict): | ||
return { |
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.
Note sure about having this recursion everywhere?
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.
ok i'll remove it 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.
I meant everywhere. Can this be solved in a more Pythonic way, without having to handle dicts in every function?
@SimonHeybrock |
It is fine to use the data. I will provide reference to the publication. |
Reduced data has been published in https://aip.scitation.org/doi/full/10.1063/5.0059238 (it is one of data sets in Fig5d - hd-DES_10_h-C16EO8). It should be sufficent to reference the paper |
@wpotrzebowski can you have a quick look to see if the way I added the citation is ok? |
Basic workflow for LoKI demonstarted on SANS2D data.