def _elucidate_reflection_parameter_file(self, ws_name): r""" Search a parameter file for the selected reflection and with valid-from, valid-to dates framing the starting date for the run(s) Parameters ---------- ws_name: str Name of the workspace from which to retrieve the starting date Returns ------- str Full path to the parameter file """ prefix = 'BASIS_{}_Parameters'.format(self._reflection['name']) instr_directories = [DEFAULT_CONFIG_DIR] start_date = str(mtd[ws_name].getRun().startTime()).strip() parm_files = ExperimentInfo.getResourceFilenames( prefix, ['xml'], instr_directories, start_date) parm_file = parm_files[0] # first in the list is the most appropriate # store selected parameter file in the logs mtd[ws_name].getRun().addProperty('reflParmFile', os.path.basename(parm_file), True) return parm_file
def get_idf_path_from_workspace(workspace): """ Gets the full IDF path from a workspace. It queries the workspace for the start time and instrument name. It gets the IDF path from the ExperimentInfo. :param workspace: the workspace for which we want the full IDF path. :return: the full IDF path for the instrument of the workspace. """ run = workspace.run() instrument = workspace.getInstrument() instrument_name = instrument.getName() instrument_name = sanitise_instrument_name(instrument_name) if run.hasProperty("start_time"): time = run.getProperty("start_time").value idf_path = ExperimentInfo.getInstrumentFilename(instrument_name, time) elif run.hasProperty("run_start"): time = run.getProperty("run_start").value idf_path = ExperimentInfo.getInstrumentFilename(instrument_name, time) else: idf_path = None return idf_path
def GetPixelSize(): # reads current IDF and get pixelsize from there """ To get pixel size for Bilby detectors from the Bilby_Definition.xml file """ from mantid.api import ExperimentInfo import xml.etree.cElementTree as ET currentIDF = ExperimentInfo.getInstrumentFilename("Bilby") #print currentIDF tree = ET.parse(currentIDF) for node in tree.iter(): if node.tag=="{http://www.mantidproject.org/IDF/1.0}height": name = node.attrib.get('val') break pixelsize = float(name) return pixelsize
def get_pixel_size(): # reads current IDF and get pixelsize from there """ To get pixel size for Bilby detectors from the Bilby_Definition.xml file """ from mantid.api import ExperimentInfo import xml.etree.cElementTree as ET currentIDF = ExperimentInfo.getInstrumentFilename("Bilby") # print currentIDF tree = ET.parse(currentIDF) for node in tree.iter(): if node.tag == "{http://www.mantidproject.org/IDF/1.0}height": name = node.attrib.get('val') break pixelsize = float(name) return pixelsize
def get_instrument_paths_for_sans_file(file_name=None, file_information=None): """ Gets the Instrument Definition File (IDF) path and the Instrument Parameter Path (IPF) path associated with a file. :param file_name: the file name is a name fo a SANS data file, e.g. SANS2D0001234. This or the file_information has to be specified. :param file_information: a file_information object. either this or the file_name has to be specified. :return: the IDF path and the IPF path """ def get_file_location(path): return os.path.dirname(path) def get_ipf_equivalent_name(path): # If XXX_Definition_Yyy.xml is the IDF name, then the equivalent IPF name is: XXX_Parameters_Yyy.xml base_file_name = os.path.basename(path) return base_file_name.replace(DEFINITION, PARAMETERS) def get_ipf_standard_name(path): # If XXX_Definition_Yyy.xml is the IDF name, then the standard IPF name is: XXX_Parameters.xml base_file_name = os.path.basename(path) elements = base_file_name.split("_") return elements[0] + PARAMETERS_XML_SUFFIX def check_for_files(directory, path): # Check if XXX_Parameters_Yyy.xml exists in the same folder ipf_equivalent_name = get_ipf_equivalent_name(path) ipf_equivalent = os.path.join(directory, ipf_equivalent_name) if os.path.exists(ipf_equivalent): return ipf_equivalent # Check if XXX_Parameters.xml exists in the same folder ipf_standard_name = get_ipf_standard_name(path) ipf_standard = os.path.join(directory, ipf_standard_name) if os.path.exists(ipf_standard): return ipf_standard # Does not seem to be in the folder return None def get_ipf_for_rule_1(path): # Check if can be found in the same folder directory = get_file_location(path) return check_for_files(directory, path) def get_ipf_for_rule_2(path): # Check if can be found in the instrument folder directory = ConfigService.getInstrumentDirectory() return check_for_files(directory, path) # Get the measurement date if not isinstance(file_information, SANSFileInformation): file_information_factory = SANSFileInformationFactory() file_information = file_information_factory.create_sans_file_information( file_name) measurement_time = file_information.get_date() # For some odd reason the __str__ method of DateAndTime adds a space which we need to strip here. It seems # to be on purpose though since the export method is called IS08601StringPlusSpace --> hence we need to strip it # ourselves measurement_time_as_string = str(measurement_time).strip() # Get the instrument instrument = file_information.get_instrument() instrument_as_string = instrument.value # Get the idf file path # IMPORTANT NOTE: I profiled the call to ExperimentInfo.getInstrumentFilename and it dominates # the state creation. Ironically this routine is exported from C++. The problem is # that we are performing XML parsing on the C++ side, which is costly. There is a # movement currently towards making the IDF redundant and storing instrument info # as native nexus information. # TODO for optimization: Add the IDF path to a global cache layer which takes the # instrument name and the from-to dates idf_path = ExperimentInfo.getInstrumentFilename( instrument_as_string, measurement_time_as_string) idf_path = os.path.normpath(idf_path) if not os.path.exists(idf_path): raise RuntimeError( "SANSFileInformation: The instrument definition file {0} does not seem to " "exist.".format(str(idf_path))) # Get the ipf path. This is slightly more complicated. See the Mantid documentation for the naming rules. Currently # they are: # 1. If the IDF is not in the instrument folder and there is another X_Parameters.xml in the same folder, # this one in the same folder will be used instead of any parameter file in the instrument folder. # 2. If you want one parameter file for your IDF file, name your IDF file X_Definition_Yyy.xml and the parameter # file X_Parameters_Yyy.xml , where Yyy is any combination a characters you find appropriate. If your IDF # file is not in the instrument folder, the parameter file can be in either the same folder or in the instrument # folder, but it can only be in the instrument folder, if the same folder has no X_Parameters.xml or # X_Parameters_Yyy.xml file. If there is no X_Parameters_Yyy.xml file, X_Parameters.xml would be used. ipf_rule1 = get_ipf_for_rule_1(idf_path) if ipf_rule1: return idf_path, ipf_rule1 ipf_rule2 = get_ipf_for_rule_2(idf_path) if ipf_rule2: return idf_path, ipf_rule2 raise RuntimeError( "SANSFileInformation: There does not seem to be a corresponding instrument parameter file " "available for {0}".format(str(idf_path)))
def get_instrument_paths_for_sans_file(file_name): """ Gets the Instrument Definition File (IDF) path and the Instrument Parameter Path (IPF) path associated with a file. :param file_name: the file name is a name fo a SANS data file, e.g. SANS2D0001234 :return: the IDF path and the IPF path """ def get_file_location(path): return os.path.dirname(path) def get_ipf_equivalent_name(path): # If XXX_Definition_Yyy.xml is the IDF name, then the equivalent IPF name is: XXX_Parameters_Yyy.xml base_file_name = os.path.basename(path) return base_file_name.replace("Definition", "Parameters") def get_ipf_standard_name(path): # If XXX_Definition_Yyy.xml is the IDF name, then the standard IPF name is: XXX_Parameters.xml base_file_name = os.path.basename(path) elements = base_file_name.split("_") return elements[0] + "_Parameters.xml" def check_for_files(directory, path): # Check if XXX_Parameters_Yyy.xml exists in the same folder ipf_equivalent_name = get_ipf_equivalent_name(path) ipf_equivalent = os.path.join(directory, ipf_equivalent_name) if os.path.exists(ipf_equivalent): return ipf_equivalent # Check if XXX_Parameters.xml exists in the same folder ipf_standard_name = get_ipf_standard_name(path) ipf_standard = os.path.join(directory, ipf_standard_name) if os.path.exists(ipf_standard): return ipf_standard # Does not seem to be in the folder return None def get_ipf_for_rule_1(path): # Check if can be found in the same folder directory = get_file_location(path) return check_for_files(directory, path) def get_ipf_for_rule_2(path): # Check if can be found in the instrument folder directory = ConfigService.getInstrumentDirectory() return check_for_files(directory, path) # Get the measurement date file_information_factory = SANSFileInformationFactory() file_information = file_information_factory.create_sans_file_information(file_name) measurement_time = file_information.get_date() # For some odd reason the __str__ method of DateAndTime adds a space which we need to strip here. It seems # to be on purpose though since the export method is called IS08601StringPlusSpace --> hence we need to strip it # ourselves measurement_time_as_string = str(measurement_time).strip() # Get the instrument instrument = file_information.get_instrument() instrument_as_string = SANSInstrument.to_string(instrument) # Get the idf file path idf_path = ExperimentInfo.getInstrumentFilename(instrument_as_string, measurement_time_as_string) idf_path = os.path.normpath(idf_path) if not os.path.exists(idf_path): raise RuntimeError("SANSFileInformation: The instrument definition file {0} does not seem to " "exist.".format(str(idf_path))) # Get the ipf path. This is slightly more complicated. See the Mantid documentation for the naming rules. Currently # they are: # 1. If the IDF is not in the instrument folder and there is another X_Parameters.xml in the same folder, # this one in the same folder will be used instead of any parameter file in the instrument folder. # 2. If you want one parameter file for your IDF file, name your IDF file X_Definition_Yyy.xml and the parameter # file X_Parameters_Yyy.xml , where Yyy is any combination a characters you find appropriate. If your IDF # file is not in the instrument folder, the parameter file can be in either the same folder or in the instrument # folder, but it can only be in the instrument folder, if the same folder has no X_Parameters.xml or # X_Parameters_Yyy.xml file. If there is no X_Parameters_Yyy.xml file, X_Parameters.xml would be used. ipf_rule1 = get_ipf_for_rule_1(idf_path) if ipf_rule1: return idf_path, ipf_rule1 ipf_rule2 = get_ipf_for_rule_2(idf_path) if ipf_rule2: return idf_path, ipf_rule2 raise RuntimeError("SANSFileInformation: There does not seem to be a corresponding instrument parameter file " "available for {0}".format(str(idf_path)))
def get_instrument_paths_for_sans_file(file_name=None, file_information=None): """ Gets the Instrument Definition File (IDF) path and the Instrument Parameter Path (IPF) path associated with a file. :param file_name: the file name is a name fo a SANS data file, e.g. SANS2D0001234. This or the file_information has to be specified. :param file_information: a file_information object. either this or the file_name has to be specified. :return: the IDF path and the IPF path """ def get_file_location(path): return os.path.dirname(path) def get_ipf_equivalent_name(path): # If XXX_Definition_Yyy.xml is the IDF name, then the equivalent IPF name is: XXX_Parameters_Yyy.xml base_file_name = os.path.basename(path) return base_file_name.replace(DEFINITION, PARAMETERS) def get_ipf_standard_name(path): # If XXX_Definition_Yyy.xml is the IDF name, then the standard IPF name is: XXX_Parameters.xml base_file_name = os.path.basename(path) elements = base_file_name.split("_") return elements[0] + PARAMETERS_XML_SUFFIX def check_for_files(directory, path): # Check if XXX_Parameters_Yyy.xml exists in the same folder ipf_equivalent_name = get_ipf_equivalent_name(path) ipf_equivalent = os.path.join(directory, ipf_equivalent_name) if os.path.exists(ipf_equivalent): return ipf_equivalent # Check if XXX_Parameters.xml exists in the same folder ipf_standard_name = get_ipf_standard_name(path) ipf_standard = os.path.join(directory, ipf_standard_name) if os.path.exists(ipf_standard): return ipf_standard # Does not seem to be in the folder return None def get_ipf_for_rule_1(path): # Check if can be found in the same folder directory = get_file_location(path) return check_for_files(directory, path) def get_ipf_for_rule_2(path): # Check if can be found in the instrument folder directory = ConfigService.getInstrumentDirectory() return check_for_files(directory, path) # Get the measurement date if not isinstance(file_information, SANSFileInformation): file_information_factory = SANSFileInformationFactory() file_information = file_information_factory.create_sans_file_information(file_name) measurement_time = file_information.get_date() # For some odd reason the __str__ method of DateAndTime adds a space which we need to strip here. It seems # to be on purpose though since the export method is called IS08601StringPlusSpace --> hence we need to strip it # ourselves measurement_time_as_string = str(measurement_time).strip() # Get the instrument instrument = file_information.get_instrument() instrument_as_string = SANSInstrument.to_string(instrument) # Get the idf file path # IMPORTANT NOTE: I profiled the call to ExperimentInfo.getInstrumentFilename and it dominates # the state creation. Ironically this routine is exported from C++. The problem is # that we are performing XML parsing on the C++ side, which is costly. There is a # movement currently towards making the IDF redundant and storing instrument info # as native nexus information. # TODO for optimization: Add the IDF path to a global cache layer which takes the # instrument name and the from-to dates idf_path = ExperimentInfo.getInstrumentFilename(instrument_as_string, measurement_time_as_string) idf_path = os.path.normpath(idf_path) if not os.path.exists(idf_path): raise RuntimeError("SANSFileInformation: The instrument definition file {0} does not seem to " "exist.".format(str(idf_path))) # Get the ipf path. This is slightly more complicated. See the Mantid documentation for the naming rules. Currently # they are: # 1. If the IDF is not in the instrument folder and there is another X_Parameters.xml in the same folder, # this one in the same folder will be used instead of any parameter file in the instrument folder. # 2. If you want one parameter file for your IDF file, name your IDF file X_Definition_Yyy.xml and the parameter # file X_Parameters_Yyy.xml , where Yyy is any combination a characters you find appropriate. If your IDF # file is not in the instrument folder, the parameter file can be in either the same folder or in the instrument # folder, but it can only be in the instrument folder, if the same folder has no X_Parameters.xml or # X_Parameters_Yyy.xml file. If there is no X_Parameters_Yyy.xml file, X_Parameters.xml would be used. ipf_rule1 = get_ipf_for_rule_1(idf_path) if ipf_rule1: return idf_path, ipf_rule1 ipf_rule2 = get_ipf_for_rule_2(idf_path) if ipf_rule2: return idf_path, ipf_rule2 raise RuntimeError("SANSFileInformation: There does not seem to be a corresponding instrument parameter file " "available for {0}".format(str(idf_path)))