From 5c977cc3878e1d738799ab93f5d49461fa2b54ca Mon Sep 17 00:00:00 2001 From: rasmusvt Date: Mon, 25 Oct 2021 08:33:58 +0200 Subject: [PATCH] Add placeholder functions to xrd/io.py --- beamtime/halvorsen.txt | 5 - beamtime/test.txt | 1 - beamtime/xrd/io.py | 315 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+), 6 deletions(-) delete mode 100644 beamtime/halvorsen.txt delete mode 100644 beamtime/test.txt diff --git a/beamtime/halvorsen.txt b/beamtime/halvorsen.txt deleted file mode 100644 index cecc2a9..0000000 --- a/beamtime/halvorsen.txt +++ /dev/null @@ -1,5 +0,0 @@ -'''test''' - -# changez -jkonkjnmkjnkj -5616521656 \ No newline at end of file diff --git a/beamtime/test.txt b/beamtime/test.txt deleted file mode 100644 index ff62eb7..0000000 --- a/beamtime/test.txt +++ /dev/null @@ -1 +0,0 @@ -dfgdfg diff --git a/beamtime/xrd/io.py b/beamtime/xrd/io.py index 349f635..7706ce3 100644 --- a/beamtime/xrd/io.py +++ b/beamtime/xrd/io.py @@ -3,6 +3,12 @@ import pandas as pd import numpy as np import os +import zipfile +import io +import sys +import glob +import xml.etree.ElementTree as ET + def get_image_array(path): @@ -141,3 +147,312 @@ def view_integrator(calibrant): print("\nIntegrator: \n", ai) +def brml_reader(file_name): + """ + From: https://github.com/aboulle/DxTools/blob/master/data_reader.py + + Extracts brml into a temporary unzip file, and parses all xml files. + For every intensity value, saves all relevant motor coordinates and sensor values. + All values are save in temporary SPEC-style tmp file. + """ +#***************************************************************************************************** +# Unzip xml files +#***************************************************************************************************** + extract_path = os.path.join(os.getcwd(),"unzip") + if sys.platform == "win32": + print("Detected platform: Windows") + os.system("RMDIR "+ extract_path +" /s /q") + elif sys.platform == "darwin": + print("Detected platform: MacOS") + os.system("rm -rf "+ extract_path) + elif sys.platform == "linux" or sys.platform == "linux2": + print("Detected platform: Linux") + os.system("rm -rf "+ extract_path) + + #Extract all RawData*.xml files and InstructionContainer the brml to temporary unzip file + with zipfile.ZipFile(file_name,"r") as brml: + for info in brml.infolist(): + if ("RawData" in info.filename) or ("InstructionContainer" in info.filename): + #if ("RawData" in info.filename): + brml.extract(info.filename, extract_path) +#***************************************************************************************************** +# For time counting, the number of days is initialized to 0. +# Compatibility fixes with D8 advance and older Discover: offsets, chi and tx, ty are initialized to 0 +#***************************************************************************************************** + # Initialize the number of days to 0 + n_day = 0. + # Initialize all offsets to 0 + off_tth = off_om = off_phi = off_chi = off_tx = off_ty = 0 + # Set Chi, tx and ty to 0 for D8 advance (July 2017 Julia Stroh) + chi = tx = ty = "0" +#***************************************************************************************************** +#Modification June 2017 (Duc Dinh) +#In some RawData.xml files, wavelength and static motors are missing. +#Find wl and static motors in MeasurementContainer.xml +#***************************************************************************************************** + data_path = os.path.join(extract_path, "*0","InstructionContainer.xml") + for file in sorted(glob.glob(data_path)): + tree = ET.parse(file) + root = tree.getroot() + for chain in root.findall("./ComparisonMethod/HrxrdAlignmentData"): + wl = chain.find("WaveLength").attrib["Value"] + + for chain in root.findall("./ComparisonMethod/HrxrdAlignmentData/Data"): + if chain.get("LogicName") == "TwoTheta": + tth = chain.find("TheoreticalPosition").attrib["Value"] + off_tth = chain.find("PositionOffset").attrib["Value"] + tth = str(float(tth)-float(off_tth)) + + if chain.get("LogicName") == "Theta": + om = chain.find("TheoreticalPosition").attrib["Value"] + off_om = chain.find("PositionOffset").attrib["Value"] + om = str(float(om)-float(off_om)) + + if chain.get("LogicName") == "Chi": + chi = chain.find("TheoreticalPosition").attrib["Value"] + off_chi = chain.find("PositionOffset").attrib["Value"] + chi = str(float(chi)-float(off_chi)) + + if chain.get("LogicName") == "Phi": + phi = chain.find("TheoreticalPosition").attrib["Value"] + off_phi = chain.find("PositionOffset").attrib["Value"] + phi = str(float(phi)-float(off_phi)) + + if chain.get("LogicName") == "X": + tx = chain.find("TheoreticalPosition").attrib["Value"] + off_tx = chain.find("PositionOffset").attrib["Value"] + tx = str(float(tx)-float(off_tx)) + + if chain.get("LogicName") == "Y": + ty = chain.find("TheoreticalPosition").attrib["Value"] + off_ty = chain.find("PositionOffset").attrib["Value"] + ty = str(float(ty)-float(off_ty)) + os.remove(file) + + #Create ouput file + outfile = open("tmp", "w", encoding='utf8') # Create output data file + outfile.write("#temperature khi phi x y theta offset 2theta scanning motor intensity time\n") +#***************************************************************************************************** +# Finds scan type, wl, scanning motors and fixed motors values in RawData*.xml +#***************************************************************************************************** + data_path = os.path.join(extract_path, "*0","*.xml") #reading files in Experiment0 folder + for file in sorted(glob.glob(data_path), key=file_nb): + new_file = 0 + check_temperature = 0 + check_1Dmode = 0 + #parsing XML file + tree = ET.parse(file) + root = tree.getroot() + #obtain scan type + for chain in (root.findall("./DataRoutes/DataRoute/ScanInformation") or root.findall("./ScanInformation")): + scan_type = chain.get("VisibleName") + if ("PSD" in scan_type) or ("Psd" in scan_type): + scan_type = "PSDFIXED" + if ("Coupled" in scan_type) or ("coupled" in scan_type) or ("2Theta-Omega" in scan_type): + scan_type = "COUPLED" + if ("Rocking" in scan_type) or ("rocking" in scan_type): + scan_type = "THETA" + + # Check if temperature is recorded + for chain in (root.findall("./DataRoutes/DataRoute/DataViews/RawDataView/Recording") or root.findall("./DataViews/RawDataView/Recording")): + if "Temperature" in chain.get("LogicName"): + check_temperature = 1 + + #Find wl in RawData.xml + for chain in root.findall("./FixedInformation/Instrument/PrimaryTracks/TrackInfoData/MountedOptics/InfoData/Tube/WaveLengthAlpha1"): + wl = chain.get("Value") + + # Find the fast-scanning axis + for chain in (root.findall("./DataRoutes/DataRoute/ScanInformation/ScanAxes/ScanAxisInfo") or root.findall("./ScanInformation/ScanAxes/ScanAxisInfo")): + if new_file == 0: + if chain.get("AxisName") == "TwoTheta": #Added offset correction / June 2017. Only relevant if offset in InstructionContainer. 0 otherwise. + off_scan = float(off_tth) + elif chain.get("AxisName") == "Theta": + off_scan = float(off_om) + else: + off_scan = 0 + step = chain.find("Increment").text + start = chain.find("Start").text + stop = chain.find("Stop").text + ref = chain.find("Reference").text + start = str(float(ref)+float(start)-off_scan) #Added offset correction / June 2017. + #start = str(float(ref)+float(start)) + new_file += 1 + + # Find scanning motors + for chain in (root.findall("./DataRoutes/DataRoute/ScanInformation/ScanAxes/ScanAxisInfo") or root.findall("./ScanInformation/ScanAxes/ScanAxisInfo")): + if chain.get("AxisName") == "TwoTheta": + tth = chain.find("Start").text + ref = chain.find("Reference").text + tth = str(float(ref)+float(tth)-float(off_tth)) #Added offset correction / June 2017. + #tth = str(float(ref)+float(tth)) + + if chain.get("AxisName") == "Theta": + om = chain.find("Start").text + ref = chain.find("Reference").text + om = str(float(ref)+float(om)-float(off_om)) #Added offset correction / June 2017. + #om = str(float(ref)+float(om)) + + if chain.get("AxisName") == "Chi": + chi = chain.find("Start").text + ref = chain.find("Reference").text + chi = str(float(ref)+float(chi)-float(off_chi)) #Added offset correction / June 2017. + #chi = str(float(ref)+float(chi)) + + if chain.get("AxisName") == "Phi": + phi = chain.find("Start").text + ref = chain.find("Reference").text + phi = str(float(ref)+float(phi)-float(off_phi)) #Added offset correction / June 2017. + #phi = str(float(ref)+float(phi)) + + if chain.get("AxisName") == "X": + tx = chain.find("Start").text + ref = chain.find("Reference").text + tx = str(float(ref)+float(tx)-float(off_tx)) #Added offset correction / June 2017. + #tx = str(float(ref)+float(tx)) + + if chain.get("AxisName") == "Y": + ty = chain.find("Start").text + ref = chain.find("Reference").text + ty = str(float(ref)+float(ty)-float(off_ty)) #Added offset correction / June 2017. + #ty = str(float(ref)+float(ty)) + + # Find static motors + for chain in root.findall("./FixedInformation/Drives/InfoData"): + if chain.get("LogicName") == "TwoTheta": + tth = chain.find("Position").attrib["Value"] + tth = str(float(tth)-float(off_tth)) #Added offset correction / June 2017. + + if chain.get("LogicName") == "Theta": + om = chain.find("Position").attrib["Value"] + om = str(float(om)-float(off_om)) #Added offset correction / June 2017. + + if chain.get("LogicName") == "Chi": + chi = chain.find("Position").attrib["Value"] + chi = str(float(chi)-float(off_chi)) #Added offset correction / June 2017. + + if chain.get("LogicName") == "Phi": + phi = chain.find("Position").attrib["Value"] + phi = str(float(phi)-float(off_phi)) #Added offset correction / June 2017. + + if chain.get("LogicName") == "X": + tx = chain.find("Position").attrib["Value"] + tx = str(float(tx)-float(off_tx)) #Added offset correction / June 2017. + + if chain.get("LogicName") == "Y": + ty = chain.find("Position").attrib["Value"] + ty = str(float(ty)-float(off_ty)) #Added offset correction / June 2017. + + offset = str(float(om) - float(tth)/2.) + +#***************************************************************************************************** +# This section computes scanning time, scanning angular range and scanning speed +# in order to convert 2th values to time values (July 2017, Julia Stroh) +#***************************************************************************************************** + for chain in (root.findall("./TimeStampStarted")): + d_start = ((chain.text).split("T")[0]).split("-")[2] + t_start = ((chain.text).split("T")[1]).split("+")[0] + h_start, min_start, sec_start = t_start.split(":") + t_start = float(h_start)*3600 + float(min_start)*60 + float(sec_start) + + if file_nb(file)==0: + abs_start = t_start + for chain in (root.findall("./TimeStampFinished")): + d_stop = ((chain.text).split("T")[0]).split("-")[2] + t_stop = ((chain.text).split("T")[1]).split("+")[0] + h_stop, min_stop, sec_stop = t_stop.split(":") + t_stop = float(h_stop)*3600 + float(min_stop)*60 + float(sec_stop) + + # Check if detector is in 1D mode + for chain in (root.findall("./DataRoutes/DataRoute/ScanInformation") or root.findall("./ScanInformation")): + if chain.find("TimePerStep").text != chain.find("TimePerStepEffective").text: + check_1Dmode = 1 + + # Check if day changed between start and stop and correct accordingly + if d_stop != d_start: + t_stop += 24*3600. + total_scan_time = t_stop - t_start + + #scanning range + dth_scan = float(stop)-float(start) + #psd range + dth_psd = 0 + for chain in root.findall("./FixedInformation/Detectors/InfoData/AngularOpening"): + dth_psd = chain.get("Value") + total_dth = float(dth_psd)*check_1Dmode+float(dth_scan) + + scan_speed = total_dth / total_scan_time +#***************************************************************************************************** +# Finds intensity values. If temperature is recorded, also fin temperature values. +# The intensity data is formatted differently in PSDfixed mode and when temperature is recorded +#***************************************************************************************************** + if "PSDFIXED" in scan_type: + if check_temperature == 0: + for chain in (root.findall("./DataRoutes/DataRoute") or root.findall("./")): + intensity = (chain.find("Datum").text).split(',') + + for chain in (root.findall("./DataRoutes/DataRoute/DataViews/RawDataView/Recording") or root.findall("./DataViews/RawDataView/Recording")): + if chain.get("LogicName") == "Counter1D": + n_channels = int(chain.find("Size/X").text) + + line_count = 0 + int_shift = len(intensity) - n_channels + for i in range(n_channels): #the intensity values are shifted to the right by int_shift + if i == 0: + scanning = float(start) + else: + scanning += float(step) + line_count += 1 + t_2th = (t_start+n_day*24*3600 - abs_start)+((float(dth_psd)*check_1Dmode + scanning - float(start)) / scan_speed) + outfile.write("25" + " " + (chi) + " " + (phi) + + " " + (tx) + " " + (ty) + " " + (om) + + " " + (offset) + " " + (tth) + " " + str(scanning) + + " " + intensity[i+int_shift] +" " + str(t_2th) +'\n') + else: + return implementation_warning, 0, 0 + + #if "COUPLED" in scan_type: + # to do check in brml that all scans (except psd fixed) share the same data structure (wrt temperature) + else: + if check_temperature == 0: + line_count = 0 + for chain in (root.findall("./DataRoutes/DataRoute/Datum") or root.findall("./Datum")): + if line_count == 0: + scanning = float(start) + else: + scanning += float(step) + line_count += 1 + intensity = (chain.text).split(',')[-1] + #compute time corresponding to scanning angle (July 2017) + t_2th = (t_start+n_day*24*3600 - abs_start)+((float(dth_psd)*check_1Dmode + scanning - float(start)) / scan_speed) + outfile.write("25" + " " + (chi) + " " + (phi) + + " " + (tx) + " " + (ty) + " " + (om) + + " " + (offset) + " " + (tth) + " " + str(round(scanning, 4)) + + " " + intensity + " " + str(t_2th) +'\n') + else: + line_count = 0 + for chain in (root.findall("./DataRoutes/DataRoute/Datum") or root.findall("./Datum")): + if line_count == 0: + scanning = float(start) + else: + scanning += float(step) + line_count += 1 + t_2th = (t_start+n_day*24*3600 - abs_start)+((float(dth_psd)*check_1Dmode + scanning - float(start)) / scan_speed) + intensity = (chain.text).split(',')[-2] + temperature = (chain.text).split(',')[-1] + outfile.write(temperature + " " + (chi) + " " + (phi) + + " " + (tx) + " " + (ty) + " " + (om) + + " " + (offset) + " " + (tth) + " " + str(round(scanning, 4)) + + " " + intensity + " " + str(t_2th) +'\n') + + if d_stop != d_start: + n_day+=1 + + outfile.close() + if sys.platform == "win32": + os.system("RMDIR "+ extract_path +" /s /q") + elif sys.platform == "darwin": + os.system("rm -rf "+ extract_path) + elif sys.platform == "linux" or sys.platform == "linux2": + os.system("rm -rf "+ extract_path) + return scan_type, line_count, wl \ No newline at end of file