Beispiel #1
0
def test_load_via_exact_match():
    make_dynamic_algorithm_without_fileproperty("DummyLoader")
    # scn.load will need to check file exists
    # DummyLoader simply returns a TableWorkspace
    with tempfile.NamedTemporaryFile() as fp:
        scn.load(fp.name, mantid_alg="DummyLoader")
        # Sanity check corrupt full path will fail
        with pytest.raises(ValueError):
            scn.load("fictional_" + fp.name, mantid_alg="DummyLoader")
Beispiel #2
0
def test_extract_energy_initial():
    from mantid.simpleapi import mtd
    mtd.clear()
    ds = scn.load(scn.data.get_path("CNCS_51936_event.nxs"),
                  mantid_args={"SpectrumMax": 1})
    assert sc.identical(ds.coords["incident_energy"],
                        sc.scalar(value=3.0, unit=sc.Unit("meV")))
Beispiel #3
0
    def test_fit(self):
        """
        Tests that the fit executes, and the outputs
        are moved into the dataset. Does not check the fit values.
        """
        from mantid.simpleapi import mtd
        mtd.clear()

        data = scn.load(scn.data.get_path("iris26176_graphite002_sqw.nxs"))

        params, diff = scn.fit(data['Q', 0],
                               mantid_args={
                                   'Function':
                                   'name=LinearBackground,A0=0,A1=1',
                                   'StartX': 0,
                                   'EndX': 3
                               })

        # check that no workspaces have been leaked in the ADS
        assert len(mtd) == 0
        assert 'data' in diff
        assert 'calculated' in diff
        assert 'diff' in diff
        assert 'status' in params.coords
        assert 'function' in params.coords
        assert 'cost_function' in params.coords
        assert 'chi^2/d.o.f.' in params.coords
def process_event_data(file, lambda_binning):
    """
    Load and reduce event data (used for Vanadium and Empty instrument)

    file: Nexus file to be loaded and its data reduced in this script

    lambda_binning: lambda_min, lamba_max, number_of_bins

    """

    # load nexus file
    event_data = scn.load(file,
                          advanced_geometry=True,
                          load_pulse_times=False,
                          mantid_args={'LoadMonitors': True})

    # ################################
    # Monitor correction
    # extract monitor and convert from tof to wavelength
    mon4_lambda = scn.convert(event_data.attrs['monitor4'].values,
                              'tof',
                              'wavelength',
                              scatter=False)

    mon4_smooth = smooth_data(mon4_lambda, dim='wavelength', NPoints=40)

    del mon4_lambda

    # ################################
    # vana and EC
    # convert to lambda
    event_lambda = scn.convert(event_data, 'tof', 'wavelength', scatter=True)

    # normalize to monitor
    lambda_min, lambda_max, number_bins = lambda_binning

    edges_lambda = sc.Variable(['wavelength'],
                               unit=sc.units.angstrom,
                               values=np.linspace(lambda_min,
                                                  lambda_max,
                                                  num=number_bins))

    mon_rebin = sc.rebin(mon4_smooth, 'wavelength', edges_lambda)

    del mon4_smooth

    event_lambda_norm = event_lambda.bins / sc.lookup(func=mon_rebin,
                                                      dim='wavelength')

    del mon_rebin, event_lambda

    return event_lambda_norm
Beispiel #5
0
 def test_EventWorkspace_with_monitors(self):
     from mantid.simpleapi import mtd
     mtd.clear()
     ds = scn.load(scn.data.get_path("CNCS_51936_event.nxs"),
                   mantid_args={
                       "LoadMonitors": True,
                       "SpectrumMax": 1
                   })
     self.assertEqual(len(mtd), 0, mtd.getObjectNames())
     attrs = [str(key) for key in ds.attrs.keys()]
     expected_monitor_attrs = {"monitor2", "monitor3"}
     assert expected_monitor_attrs.issubset(attrs)
     for monitor_name in expected_monitor_attrs:
         monitor = ds.attrs[monitor_name].value
         assert isinstance(monitor, sc.DataArray)
         assert monitor.shape == [200001]
         self.check_monitor_metadata(monitor)
Beispiel #6
0
 def test_Workspace2D_with_include_monitors(self):
     from mantid.simpleapi import mtd
     mtd.clear()
     # This test would use 20 GB of memory if "SpectrumMax" was not set
     ds = scn.load(scn.data.get_path("WISH00016748.raw"),
                   mantid_args={
                       "LoadMonitors": "Include",
                       "SpectrumMax": 100
                   })
     self.assertEqual(len(mtd), 0, mtd.getObjectNames())
     attrs = [str(key) for key in ds.attrs.keys()]
     expected_monitor_attrs = {
         "monitor1", "monitor2", "monitor3", "monitor4", "monitor5"
     }
     assert expected_monitor_attrs.issubset(attrs)
     for monitor_name in expected_monitor_attrs:
         monitor = ds.attrs[monitor_name].value
         assert isinstance(monitor, sc.DataArray)
         assert monitor.shape == [4471]
         self.check_monitor_metadata(monitor)
Beispiel #7
0
def test_load_error_when_file_not_found_via_exact_match():
    make_dynamic_algorithm_without_fileproperty("DummyLoader")
    with pytest.raises(ValueError):
        # DummyLoader has no FileProperty and forces
        # load to evaluate the path given as an absolute path
        scn.load("fictional.nxs", mantid_alg="DummyLoader")
Beispiel #8
0
def test_load_error_when_file_not_found_via_fuzzy_match():
    with pytest.raises(ValueError):
        scn.load("fictional.nxs")
Beispiel #9
0
 def setup(self):
     da = scn.load(scn.data.get_path('PG3_4844_event.nxs'))
     self.var_tof = da
     self.var_wavelength = scn.convert(self.var_tof, "tof", "wavelength",
                                       False)
     self.var_energy = scn.convert(self.var_tof, "tof", "energy", False)
def powder_reduction(sample='sample.nxs',
                     calibration=None,
                     vanadium=None,
                     empty_instr=None,
                     lambda_binning=(0.7, 10.35, 5615),
                     **absorp):
    """
    Simple WISH reduction workflow

    Note
    ----

    The sample data were not recorded using the same layout
    of WISH as the Vanadium and empty instrument. That's why:
    - loading calibration for Vanadium used a different IDF
    - the Vanadium correction involved cropping the sample data
      to the first 5 groups (panels)
    ----

    Corrections applied:
    - Vanadium correction
    - Absorption correction
    - Normalization by monitors
    - Conversion considering calibration
    - Masking and grouping detectors into panels

    Parameters
    ----------
    sample: Nexus event file

    calibration: .cal file following Mantid's standards
        The columns correspond to detectors' IDs, offset, selection of 
        detectors and groups

    vanadium: Nexus event file

    empty_instr: Nexus event file

    lambda_binning: min, max and number of steps for binning in wavelength
                    min and max are in Angstroms

    **absorp: dictionary containing information to correct absorption for
              Sample and Vanadium.
              There could be only up to two elements related to the correction
              for Vanadium:
              the radius and height of the cylindrical sample shape.
              To distinguish them from the inputs related to the sample, their
              names in the dictionary  are 'CylinderVanadiumRadius' and
              'CylinderVanadiumHeight'. The other keysof the 'absorp'
              dictionary follow Mantid's syntax and are related to the sample
              data only.
              See help of Mantid's algorithm CylinderAbsorption for details
              https://docs.mantidproject.org/nightly/algorithms/CylinderAbsorption-v1.html

    Returns
    -------
    Scipp dataset containing reduced data in d-spacing

    Hints
    -----

    To plot the output data, one can histogram in d-spacing and sum according
    to groups using scipp.histogram and sc.sum, respectively.

    """
    # Load counts
    sample_data = scn.load(sample,
                           advanced_geometry=True,
                           load_pulse_times=False,
                           mantid_args={'LoadMonitors': True})

    # Load calibration
    if calibration is not None:
        input_load_cal = {"InstrumentName": "WISH"}
        cal = load_calibration(calibration, mantid_args=input_load_cal)
        # Merge table with detector->spectrum mapping from sample
        # (implicitly checking that detectors between sample and calibration
        # are the same)
        cal_sample = sc.merge(cal, sample_data.coords['detector_info'].value)
        # Compute spectrum mask from detector mask
        mask = sc.groupby(cal_sample['mask'], group='spectrum').any('detector')

        # Compute spectrum groups from detector groups
        g = sc.groupby(cal_sample['group'], group='spectrum')

        group = g.min('detector')

        assert sc.identical(group, g.max('detector')), \
            "Calibration table has mismatching group for detectors in same spectrum"

        sample_data.coords['group'] = group.data
        sample_data.masks['mask'] = mask.data

        del cal

    # Correct 4th monitor spectrum
    # There are 5 monitors for WISH. Only one, the fourth one, is selected for
    # correction (like in the real WISH workflow).

    # Select fourth monitor and convert from tof to wavelength
    mon4_lambda = scn.convert(sample_data.attrs['monitor4'].values,
                              'tof',
                              'wavelength',
                              scatter=False)

    # Spline background
    # mon4_spline_background = bspline_background(mon4_lambda,
    #                                             sc.Dim('wavelength'),
    #                                             smoothing_factor=70)

    # Smooth monitor
    mon4_smooth = smooth_data(
        mon4_lambda,  # mon4_spline_background,
        dim='wavelength',
        NPoints=40)
    # Delete intermediate data
    del mon4_lambda  # , mon4_spline_background

    # Correct data
    # 1. Normalize to monitor
    # Convert to wavelength (counts)
    sample_lambda = scn.convert(sample_data, 'tof', 'wavelength', scatter=True)

    del sample_data

    # Rebin monitors' data
    lambda_min, lambda_max, number_bins = lambda_binning

    edges_lambda = sc.Variable(['wavelength'],
                               unit=sc.units.angstrom,
                               values=np.linspace(lambda_min,
                                                  lambda_max,
                                                  num=number_bins))
    mon_rebin = sc.rebin(mon4_smooth, 'wavelength', edges_lambda)

    # Realign sample data
    sample_lambda = sample_lambda.bins / sc.lookup(func=mon_rebin,
                                                   dim='wavelength')

    del mon_rebin, mon4_smooth

    # 2. absorption correction
    if bool(absorp):
        # Copy dictionary of absorption parameters
        absorp_sample = absorp.copy()
        # Remove input related to Vanadium if present in absorp dictionary
        found_vana_info = [
            key for key in absorp_sample.keys() if 'Vanadium' in key
        ]

        for item in found_vana_info:
            absorp_sample.pop(item, None)

        # Calculate absorption correction for sample data
        correction = absorption_correction(sample, lambda_binning,
                                           **absorp_sample)

        # the 3 following lines of code are to place info about source and
        # sample position at the right place in the correction dataArray in
        # order to proceed to the normalization

        del correction.coords['source_position']
        del correction.coords['sample_position']
        del correction.coords['position']

        correction_rebin = sc.rebin(correction, 'wavelength', edges_lambda)

        del correction

        sample_lambda = sample_lambda.bins / sc.lookup(func=correction_rebin,
                                                       dim='wavelength')

    # 3. Convert to d-spacing with option of taking calibration into account
    if calibration is None:
        # No calibration data, use standard convert algorithm
        sample_dspacing = scn.convert(sample_lambda, 'tof', 'dspacing')
    else:
        # Calculate dspacing from calibration file
        sample_dspacing = convert_with_calibration(sample_lambda, cal_sample)
        del cal_sample

    del sample_lambda

    # 4. Focus panels
    # Assuming sample is in d-spacing: Focus into groups
    focused = sc.groupby(sample_dspacing,
                         group='group').bins.concatenate('spectrum')

    del sample_dspacing

    # 5. Vanadium correction (requires Vanadium and Empty instrument)
    if vanadium is not None and empty_instr is not None:
        print("Proceed with reduction of Vanadium data ")

        vana_red_focused = process_vanadium_data(vanadium, empty_instr,
                                                 lambda_binning, calibration,
                                                 **absorp)

        # The following selection of groups depends on the loaded data for
        # Sample, Vanadium and Empty instrument
        focused = focused['group', 0:5].copy()

        # histogram vanadium for normalizing + cleaning 'metadata'
        d_min, d_max, number_dbins = (1., 10., 2000)

        edges_dspacing = sc.Variable(['dspacing'],
                                     unit=sc.units.angstrom,
                                     values=np.linspace(d_min,
                                                        d_max,
                                                        num=number_dbins))
        vana_histo = sc.histogram(vana_red_focused, edges_dspacing)

        del vana_red_focused
        vana_histo.coords['detector_info'] = focused.coords[
            'detector_info'].copy()
        # del vana_histo.coords['source_position']
        # del vana_histo.coords['sample_position']

        # normalize by vanadium
        result = focused.bins / sc.lookup(func=vana_histo, dim='dspacing')

        del vana_histo, focused

    return result