diff --git a/Framework/CurveFitting/src/Algorithms/ConvolutionFit.cpp b/Framework/CurveFitting/src/Algorithms/ConvolutionFit.cpp index 1c95eb627adaac9bd13b64e2ac32226bc291b938..379a89585d55f93162174201312b773acf30d588 100644 --- a/Framework/CurveFitting/src/Algorithms/ConvolutionFit.cpp +++ b/Framework/CurveFitting/src/Algorithms/ConvolutionFit.cpp @@ -255,7 +255,7 @@ ConvolutionFit<QENSFitSequential>::seeAlso() const { template <> const std::vector<std::string> ConvolutionFit<QENSFitSimultaneous>::seeAlso() const { - return {"QENSSimultaneousFit"}; + return {"QENSFitSimultaneous"}; } template <typename Base> diff --git a/Framework/Kernel/inc/MantidKernel/FacilityInfo.h b/Framework/Kernel/inc/MantidKernel/FacilityInfo.h index a1af17b73ffdf1e1d46f9216b83ec58abef0acd8..b6864a40674a6efa4a8cc1c1bf84898d59f263f3 100644 --- a/Framework/Kernel/inc/MantidKernel/FacilityInfo.h +++ b/Framework/Kernel/inc/MantidKernel/FacilityInfo.h @@ -67,6 +67,9 @@ public: /// Returns the preferred file extension const std::string &preferredExtension() const { return m_extensions.front(); } + /// Returns the time zone designation compatible with pytz + const std::string &timezone() const { return m_timezone; } + /// Return the archive search interface names const std::vector<std::string> &archiveSearch() const { return m_archiveSearch; @@ -104,6 +107,7 @@ private: void fillDelimiter(const Poco::XML::Element *elem); void fillExtensions(const Poco::XML::Element *elem); void fillArchiveNames(const Poco::XML::Element *elem); + void fillTimezone(const Poco::XML::Element *elem); void fillInstruments(const Poco::XML::Element *elem); void fillHTTPProxy(const Poco::XML::Element *elem); void fillComputeResources(const Poco::XML::Element *elem); @@ -115,6 +119,7 @@ private: CatalogInfo m_catalogs; ///< Gain access to the catalogInfo class. const std::string m_name; ///< facility name + std::string m_timezone; ///< Timezone designation in pytz int m_zeroPadding; ///< default zero padding for this facility std::string m_delimiter; ///< default delimiter between instrument name and run number diff --git a/Framework/Kernel/src/FacilityInfo.cpp b/Framework/Kernel/src/FacilityInfo.cpp index 519821a771f7cb4d3cda1d77225ab79699cdd621..3bb73e78e160b83af60709304c807002d33a2218 100644 --- a/Framework/Kernel/src/FacilityInfo.cpp +++ b/Framework/Kernel/src/FacilityInfo.cpp @@ -14,6 +14,7 @@ #include <Poco/DOM/Element.h> #include <Poco/DOM/NodeList.h> +#include <Poco/DOM/Text.h> #include <MantidKernel/StringTokenizer.h> using Poco::XML::Element; @@ -31,9 +32,10 @@ Logger g_log("FacilityInfo"); * @throw std::runtime_error if name or file extensions are not defined */ FacilityInfo::FacilityInfo(const Poco::XML::Element *elem) - : m_catalogs(elem), m_name(elem->getAttribute("name")), m_zeroPadding(0), - m_delimiter(), m_extensions(), m_archiveSearch(), m_instruments(), - m_noFilePrefix(), m_multiFileLimit(100), m_computeResources() { + : m_catalogs(elem), m_name(elem->getAttribute("name")), m_timezone(), + m_zeroPadding(0), m_delimiter(), m_extensions(), m_archiveSearch(), + m_instruments(), m_noFilePrefix(), m_multiFileLimit(100), + m_computeResources() { if (m_name.empty()) { g_log.error("Facility name is not defined"); throw std::runtime_error("Facility name is not defined"); @@ -44,6 +46,7 @@ FacilityInfo::FacilityInfo(const Poco::XML::Element *elem) fillDelimiter(elem); fillExtensions(elem); fillArchiveNames(elem); + fillTimezone(elem); fillComputeResources(elem); fillNoFilePrefix(elem); fillMultiFileLimit(elem); @@ -129,6 +132,25 @@ void FacilityInfo::fillArchiveNames(const Poco::XML::Element *elem) { } } +void FacilityInfo::fillTimezone(const Poco::XML::Element *elem) { + Poco::AutoPtr<Poco::XML::NodeList> pNL_timezones = + elem->getElementsByTagName("timezone"); + if (pNL_timezones->length() == 0) { + g_log.notice() << "No timezone specified for " << m_name + << " in Facilities.xml\n"; + } else if (pNL_timezones->length() == 1) { + pNL_timezones = pNL_timezones->item(0)->childNodes(); + if (pNL_timezones->length() > 0) { + Poco::XML::Text *txt = + dynamic_cast<Poco::XML::Text *>(pNL_timezones->item(0)); + m_timezone = txt->getData(); + } + } else { + throw std::runtime_error("Facility " + m_name + + " has more than one timezone specified"); + } +} + /// Called from constructor to fill instrument list void FacilityInfo::fillInstruments(const Poco::XML::Element *elem) { Poco::AutoPtr<Poco::XML::NodeList> pNL_instrument = diff --git a/Framework/PythonInterface/mantid/api/src/CloneMatrixWorkspace.cpp b/Framework/PythonInterface/mantid/api/src/CloneMatrixWorkspace.cpp index 96e717d9fe33a4179d54c8a1c6daafeaecbe1e80..6cddb55e64639578d7b6b1b5cea7d71854a1a30d 100644 --- a/Framework/PythonInterface/mantid/api/src/CloneMatrixWorkspace.cpp +++ b/Framework/PythonInterface/mantid/api/src/CloneMatrixWorkspace.cpp @@ -3,6 +3,7 @@ //----------------------------------------------------------------------------- #include "MantidPythonInterface/api/CloneMatrixWorkspace.h" #include "MantidAPI/MatrixWorkspace.h" +#include "MantidKernel/MultiThreaded.h" #include <boost/python/extract.hpp> @@ -33,8 +34,8 @@ enum DataField { XValues = 0, YValues = 1, EValues = 2, DxValues = 3 }; */ PyArrayObject *cloneArray(MatrixWorkspace &workspace, DataField field, const size_t start, const size_t endp1) { - const size_t numHist = endp1 - start; - npy_intp stride(0); + const npy_intp numHist(endp1 - start); + npy_intp stride{0}; // Find out which function we need to call to access the data using ArrayAccessFn = @@ -57,7 +58,7 @@ PyArrayObject *cloneArray(MatrixWorkspace &workspace, DataField field, else dataAccesor = &MatrixWorkspace::readE; } - npy_intp arrayDims[2] = {static_cast<npy_intp>(numHist), stride}; + npy_intp arrayDims[2] = {numHist, stride}; PyArrayObject *nparray = reinterpret_cast<PyArrayObject *>( PyArray_NewFromDescr(&PyArray_Type, PyArray_DescrFromType(NPY_DOUBLE), 2, // rank 2 @@ -65,10 +66,11 @@ PyArrayObject *cloneArray(MatrixWorkspace &workspace, DataField field, nullptr, nullptr, 0, nullptr)); double *dest = reinterpret_cast<double *>( PyArray_DATA(nparray)); // HEAD of the contiguous numpy data array - for (size_t i = start; i < endp1; ++i) { - const MantidVec &src = (workspace.*(dataAccesor))(i); - std::copy(src.begin(), src.end(), dest); - dest += stride; // Move the ptr to the start of the next 1D array + + PARALLEL_FOR_IF(threadSafe(workspace)) + for (npy_intp i = 0; i < numHist; ++i) { + const MantidVec &src = (workspace.*(dataAccesor))(start + i); + std::copy(src.begin(), src.end(), std::next(dest, i * stride)); } return nparray; } diff --git a/Framework/PythonInterface/mantid/kernel/src/Exports/FacilityInfo.cpp b/Framework/PythonInterface/mantid/kernel/src/Exports/FacilityInfo.cpp index c1b175e05bef42ed2d80f7443cbb5a4965bdb22f..126ef07243fbfc0116bc49996075e05c95cafeee 100644 --- a/Framework/PythonInterface/mantid/kernel/src/Exports/FacilityInfo.cpp +++ b/Framework/PythonInterface/mantid/kernel/src/Exports/FacilityInfo.cpp @@ -12,55 +12,48 @@ void export_FacilityInfo() { register_ptr_to_python<FacilityInfo *>(); class_<FacilityInfo>("FacilityInfo", no_init) - .def("name", &FacilityInfo::name, arg("self"), return_value_policy<copy_const_reference>(), "Returns name of the facility as definined in the Facilities.xml " "file") - .def("__str__", &FacilityInfo::name, arg("self"), return_value_policy<copy_const_reference>(), "Returns name of the facility as definined in the Facilities.xml " "file") - .def("zeroPadding", &FacilityInfo::zeroPadding, arg("self"), "Returns default zero padding for this facility") - .def("delimiter", &FacilityInfo::delimiter, arg("self"), return_value_policy<copy_const_reference>(), "Returns the delimiter between the instrument name and the run " "number.") - .def("extensions", &FacilityInfo::extensions, arg("self"), "Returns the list of file extensions that are considered as " "instrument data files.") - .def("preferredExtension", &FacilityInfo::preferredExtension, arg("self"), return_value_policy<copy_const_reference>(), "Returns the extension that is preferred for this facility") - + .def("timezone", &FacilityInfo::timezone, arg("self"), + return_value_policy<copy_const_reference>(), + "Returns the timezone appropriate for the facility. If there is not " + "a timezone specified this returns an empty string.") .def("archiveSearch", &FacilityInfo::archiveSearch, arg("self"), return_value_policy<copy_const_reference>(), "Return the archive search interface names") - .def("instruments", (const std::vector<InstrumentInfo> &(FacilityInfo::*)() const) & FacilityInfo::instruments, arg("self"), return_value_policy<copy_const_reference>(), "Returns a list of instruments of this facility as defined in the " "Facilities.xml file") - .def("instruments", (std::vector<InstrumentInfo>( FacilityInfo::*)(const std::string &) const) & FacilityInfo::instruments, (arg("self"), arg("technique")), "Returns a list of instruments of given technique") - .def("instrument", &FacilityInfo::instrument, (arg("self"), arg("instrumentName")), return_value_policy<copy_const_reference>(), "Returns the instrument with the given name") - .def("computeResources", &FacilityInfo::computeResources, arg("self"), "Returns a vector of the available compute resources"); } diff --git a/Framework/PythonInterface/mantid/plots/helperfunctions.py b/Framework/PythonInterface/mantid/plots/helperfunctions.py index f576696e5d899b8de1bc144cc5bc5818c9e9aac7..e418f85d238be750b55e9fbc11803beb8d9522fa 100644 --- a/Framework/PythonInterface/mantid/plots/helperfunctions.py +++ b/Framework/PythonInterface/mantid/plots/helperfunctions.py @@ -275,7 +275,7 @@ def get_matrix_2d_data(workspace, distribution, histogram2D=False): if workspace.isHistogramData(): if not distribution: - z = z / (x[:, 1:] - x[:, 0:-1]) + z /= x[:, 1:] - x[:, 0:-1] if histogram2D: if len(y) == z.shape[0]: y = boundaries_from_points(y) diff --git a/Framework/PythonInterface/test/python/mantid/kernel/FacilityInfoTest.py b/Framework/PythonInterface/test/python/mantid/kernel/FacilityInfoTest.py index c26dc1d6941a33dfa76e997d14e1509681777ce7..9ab1d94d1280607a488038fa954d6fb00ee95932 100644 --- a/Framework/PythonInterface/test/python/mantid/kernel/FacilityInfoTest.py +++ b/Framework/PythonInterface/test/python/mantid/kernel/FacilityInfoTest.py @@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function) import unittest from mantid.kernel import FacilityInfo, InstrumentInfo, ConfigService - +import pytz class FacilityInfoTest(unittest.TestCase): @@ -24,8 +24,16 @@ class FacilityInfoTest(unittest.TestCase): self.assertTrue(len(test_facility.instruments()) > 30) self.assertTrue(len(test_facility.instruments("Neutron Diffraction"))> 10) self.assertTrue(isinstance(test_facility.instrument("WISH"), InstrumentInfo)) + self.assertEquals(test_facility.timezone(), "Europe/London") + def test_timezones(self): + # verify that all of the timezones can get converted by pytz + for facility in ConfigService.getFacilities(): + if len(facility.timezone()) == 0: + continue # don't test empty strings + tz = pytz.timezone(facility.timezone()) + print(facility.name(), tz) + self.assertEquals(str(tz), facility.timezone()) if __name__ == '__main__': unittest.main() - diff --git a/docs/source/api/python/mantid/kernel/DateAndTime.rst b/docs/source/api/python/mantid/kernel/DateAndTime.rst index d4685c4379c8e9853dbd70ea9abbfc5c625bd066..2298ddeb90438933e8087b7b75b7fc459681c93f 100644 --- a/docs/source/api/python/mantid/kernel/DateAndTime.rst +++ b/docs/source/api/python/mantid/kernel/DateAndTime.rst @@ -25,6 +25,16 @@ With :class:`numpy.datetime64`, finding the number of seconds between two times diff = (timeArray[-1]-timeArray[0]) / np.timedelta64(1, 's') +For converting :class:`numpy.datetime64` data to a string for the default facilty, use :func:`numpy.datetime_as_string` explicitly (assuming the times are a variable named ``times``) + +.. code-block:: python + + import pytz + tz = pytz.timezone(ConfigService.getFacility().timezone()) + times = numpy.datetime_as_string(times, timezone=tz) + +This is how numpy internally converts :class:`numpy.datetime64` to strings for printing, but the selection of timezone is explicit (using `pytz <https://pythonhosted.org/pytz/>`_) to allow for matching where the data was recorded rather than the system's timezone. + .. module:`mantid.kernel` .. autoclass:: mantid.kernel.DateAndTime diff --git a/docs/source/concepts/FacilitiesFile.rst b/docs/source/concepts/FacilitiesFile.rst index 9aabbc28b73e08a87e09ecb43163499dbec4a0b5..f6bb2c5de734477e2e0ea24da7549921c592788c 100644 --- a/docs/source/concepts/FacilitiesFile.rst +++ b/docs/source/concepts/FacilitiesFile.rst @@ -24,13 +24,12 @@ component of a facility. A simple facility definition would be <?xml version="1.0" encoding="UTF-8"?> <facilities> - <facility name="BrandNew" delimiter="_" zeropadding="8" FileExtensions=".nxs,.n*"> + <timezone>UTC</timezone> <instrument name="ABCDEF"/> </facility> - </facilities> which would define a facility called *BrandNew* with an instrument @@ -42,6 +41,9 @@ called *ABCDEF*. The facilities attributes have the following meanings: padded to when constructing a file name; - ``FileExtensions`` should list the extensions of the data files for the facility. The first is taken as the preferred extension. +- ``timezone`` specifies what timezone the facility is in for use with + `pytz <https://pythonhosted.org/pytz/>`_. Valid timezones can be found + in python by looking at the list in ``pytz.all_timezones`` An instrument can have further attributes which define properties of the that instrument rather than the facility as a whole, e.g. @@ -90,4 +92,4 @@ The file should be located in the directory pointed to by the -.. categories:: Concepts \ No newline at end of file +.. categories:: Concepts diff --git a/docs/source/release/v3.13.0/framework.rst b/docs/source/release/v3.13.0/framework.rst index b41bb85a368c5c56f8d7d241607904cec3e46714..eb7b33baefb2a0c64d47742e8a5907633d3998eb 100644 --- a/docs/source/release/v3.13.0/framework.rst +++ b/docs/source/release/v3.13.0/framework.rst @@ -18,7 +18,7 @@ Instrument Definition Updates Stability --------- -- Mantid now handles poor network stability better when reading live data from the ISIS DAE. Mantid will now timeout after a couple of minutes of loss of network connectivity and remains responsive during this time. You can alter the duration of this timeout by adding a line to the mantid.user.properties file like: +- Mantid now handles poor network stability better when reading live data from the ISIS DAE. Mantid will now timeout after a couple of minutes of loss of network connectivity and remains responsive during this time. You can alter the duration of this timeout by adding a line to the mantid.user.properties file like: ``` ISISDAE.Timeout = 100 #seconds @@ -72,6 +72,7 @@ Improvements - :ref:`Stitch1D <algm-Stitch1D>` can treat point data. - The algorithm :ref:`SortXAxis <algm-SortXAxis>` has a new input option that allows ascending (default) and descending sorting. The documentation needed to be corrected in general. - :ref:`LoadNexusMonitors <algm-LoadNexusMonitors>` has changed its properties for clarification. This has also propagated to :ref:`LoadEventNexus <algm-LoadEventNexus>` and :ref:`LoadEventAndCompress <algm-LoadEventAndCompress>` +- :class:`mantid.kernel.FacilityInfo` has an additional field with the timezone for use in converting ``numpy.datetime64`` values to strings Bugfixes ######## diff --git a/instrument/Facilities.xml b/instrument/Facilities.xml index 0afe386037f5a86bf700fb3ab0623daaa9b56943..8991cff6158ce5b18accdf9af77720a703665f06 100644 --- a/instrument/Facilities.xml +++ b/instrument/Facilities.xml @@ -22,6 +22,8 @@ </filelocation> </catalog> + <timezone>Europe/London</timezone> + <instrument name="ALF"> <technique>Single Crystal Diffraction</technique> <livedata> @@ -376,6 +378,8 @@ <facility name="HFIR" FileExtensions=".nxs,.dat,.xml"> + <timezone>US/Eastern</timezone> + <instrument name="HB1"> <technique>Triple Axis Spectroscopy</technique> </instrument> @@ -453,6 +457,8 @@ </filelocation> </catalog> + <timezone>US/Eastern</timezone> + <instrument name="DAS"> <technique>technique</technique> </instrument> @@ -602,12 +608,16 @@ </facility> <facility name="NCNR" FileExtensions=".dat,.xml"> + <timezone>US/Eastern</timezone> + <instrument name="NGSANS"> <technique>Small Angle Scattering</technique> </instrument> </facility> <facility name="LENS" FileExtensions=".nxs,.dat,.xml"> + <timezone>US/Eastern</timezone> + <instrument name="SANS"> <technique>Small Angle Scattering</technique> </instrument> @@ -615,6 +625,7 @@ </facility> <facility name="ILL" zeropadding="6" FileExtensions=".nxs,.hdf,.inx,.asc" nofileprefix="True" multifilelimit="1000"> + <timezone>Europe/Paris</timezone> <instrument name="IN4"> <technique>Neutron Spectroscopy</technique> @@ -693,6 +704,7 @@ </facility> <facility name="SINQ" FileExtensions=".hdf"> + <timezone>Europe/Zurich</timezone> <instrument name="HRPT"> <technique>Neutron Diffraction</technique> @@ -767,6 +779,7 @@ </facility> <facility name="SmuS" FileExtensions=".nxs,.xml"> + <timezone>Europe/Zurich</timezone> <instrument name="GPD"> <zeropadding size="3"/> @@ -782,6 +795,8 @@ <!-- Reactor Orphee (France) --> <facility name="LLB" FileExtensions=".nxs,.hdf"> + <timezone>Europe/Paris</timezone> + <instrument name="MIBEMOL"> <technique>Neutron Spectroscopy</technique> <technique>Reactor Direct Geometry Spectroscopy</technique> @@ -790,6 +805,8 @@ <!-- Facility MLZ (FRMII) (Germany) --> <facility name="MLZ" FileExtensions=".nxs,.d_dat,.001,.mtxt,.mdat"> + <timezone>Europe/Berlin</timezone> + <instrument name="DNS"> <technique>Neutron Spectroscopy</technique> <technique>Reactor Direct Geometry Spectroscopy</technique> @@ -816,6 +833,8 @@ <!-- ANSTO --> <facility name="ANSTO" FileExtensions=".nxs,.tar"> + <timezone>Australia/Sydney</timezone> + <instrument name="Bilby"> <technique>Small Angle Scattering</technique> </instrument> @@ -823,6 +842,8 @@ <!-- HZB --> <facility name="HZB" FileExtensions=".nxs"> + <timezone>Europe/Berlin</timezone> + <instrument name="EXED"> <technique>TOF Direct Geometry Spectroscopy</technique> <technique>Single Crystal Diffraction</technique> @@ -840,6 +861,8 @@ <!-- Test Facility to allow example usage of Live listeners against "Fake" instrument sources --> <facility name="TEST_LIVE" FileExtensions=".nxs,.raw"> + <timezone>UTC</timezone> + <instrument name="ISIS_Histogram"> <technique>Test Listener</technique> <livedata> diff --git a/instrument/Schema/Facilities/1.0/FacilitiesSchema.xsd b/instrument/Schema/Facilities/1.0/FacilitiesSchema.xsd index ae7f344680f097c9f6fe08c26363d9bb94f3729f..853be40f4a7795c2f6a12a0c8ff5e4334239c44b 100644 --- a/instrument/Schema/Facilities/1.0/FacilitiesSchema.xsd +++ b/instrument/Schema/Facilities/1.0/FacilitiesSchema.xsd @@ -1,5 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?> -<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attributeFormDefault="unqualified" elementFormDefault="qualified" +<?xml version="1.0" encoding="utf-8"?> +<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0"> <xs:element name="facilities"> <xs:complexType> @@ -68,7 +68,8 @@ </xs:element> <xs:attribute name="name" type="xs:string"/> </xs:complexType> - </xs:element> + </xs:element> + <xs:element name="timezone" type="xs:string" minOccurs="0" maxOccurs="1"/> <xs:element name="instrument" maxOccurs="unbounded"> <xs:complexType> <xs:choice maxOccurs="unbounded"> diff --git a/scripts/FilterEvents/eventFilterGUI.py b/scripts/FilterEvents/eventFilterGUI.py index 7d09cfbff12c1349c8052bd922102e7c24ce6c5d..386fce5c2b7843c02dfaaed9c7707590800ba686 100644 --- a/scripts/FilterEvents/eventFilterGUI.py +++ b/scripts/FilterEvents/eventFilterGUI.py @@ -710,14 +710,14 @@ class MainWindow(QtGui.QMainWindow): # append 1 more log if original log only has 1 value tf = self._dataWS.getRun().getProperty("proton_charge").times[-1] - vectimes.append(tf) + vectimes = numpy.append(vectimes,tf) vecvalue = numpy.append(vecvalue, vecvalue[-1]) - vecreltimes = [float(t - t0) / numpy.timedelta64(1, 's') for t in vectimes] + vecreltimes = (vectimes - t0) / numpy.timedelta64(1, 's') # Set to plot - xlim = [min(vecreltimes), max(vecreltimes)] - ylim = [min(vecvalue), max(vecvalue)] + xlim = [vecreltimes.min(), vecreltimes.max()] + ylim = [vecvalue.min(), vecvalue.max()] self.ui.mainplot.set_xlim(xlim[0], xlim[1]) self.ui.mainplot.set_ylim(ylim[0], ylim[1]) diff --git a/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py b/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py index 71a8328b19ea12b75a70e0c98667a7a936fc8407..108fa378b3b971e318e2ce72da12e880c400e3e4 100644 --- a/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py +++ b/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py @@ -251,7 +251,7 @@ class DiffractionReductionScripter(BaseReductionScripter): runnumbers_str = str(runsetupdict["RunNumber"]) if runnumbers_str.count(':') > 0: runnumbers_str = runnumbers_str.replace(':', '-') - runnumbers_str = FileFinder.findRuns('{}_{}'.format(self.instrument_name, runnumbers_str)) + runnumbers_str = FileFinder.findRuns('{}{}'.format(self.instrument_name, runnumbers_str)) runnumbers_str = [os.path.split(filename)[-1] for filename in runnumbers_str] # create an integer version