import os, sys import numpy as np import datetime sys.path.append('/Users/ganeva/build/parse/parse-1.6.6') from parse import * class DNSdata: """ class which describes the DNS data structure will be used for data read-in and write-out routines """ def __init__(self): self.title = "" self.experiment_number = "" self.run_number = "" self.start_time = "" self.end_time = "" self.duration = None self.deterota = 0 self.wavelength = None # Angstrom self.ndet = 24 self.sample_name = "" self.userid = "" self.user_name = "" self.sample_description = "" self.coil_status = "" self.befilter_status = "" self.notes = "" self.monochromator_angle = None # degree self.monochromator_position = None self.huber = None self.cradle_lower = None self.cradle_upper = None self.slit_i_upper_blade_position = None self.slit_i_lower_blade_position = None self.slit_i_left_blade_position = None self.slit_i_right_blade_position = None self.slit_f_upper_blade_position = None self.slit_f_lower_blade_position = None self.detector_position_vertical = None self.polarizer_translation = None self.polarizer_rotation = None self.flipper_precession_current = None self.flipper_z_compensation_current = None self.a_coil_current = None self.b_coil_current = None self.c_coil_current = None self.z_coil_current = None self.t1 = None # T1 self.t2 = None # T2 self.tsp = None # T_setpoint self.tof_channel_number = None self.tof_channel_width = None self.tof_delay_time = None self.tof_elastic_channel = None self.chopper_rotation_speed = None self.chopper_slits = None self.monitor_counts = None def read_legacy(self, filename): """ reads the DNS legacy ascii file into the DNS data object """ with open(filename, 'r') as fhandler: # read file content and split it into blocks splitsymbol = '#--------------------------------------------------------------------------' unparsed = fhandler.read() blocks = unparsed.split(splitsymbol) # parse each block # parse block 0 (header) # [TODO:] rewrite to get rid of dependence on parse res = parse("# DNS Data userid={userid},exp={exp_id},file={run_number},sample={sample_name}", blocks[0]) # [TODO:] raise exception on the wrong file format #if not res: # print "Wrong file format." # sys.exit() self.run_number = res['run_number'] self.experiment_number = res['exp_id'] self.sample_name = res['sample_name'] self.userid = res['userid'] # parse block 1 (general information) b1splitted = map(str.strip, blocks[1].split('#')) b1rest = [el for el in b1splitted] # otherwise unexpected behaviour due to the removed lines for line in b1splitted: res = parse('User: {user_name}', line) if res: self.user_name = res['user_name'] b1rest.remove(line) res = parse('Sample: {sample_descr}', line) if res: self.sample_description = res['sample_descr'] b1rest.remove(line) res = parse('{coil_status} xyz-coil,', line) if res: self.coil_status = res['coil_status'] b1rest.remove(line) res = parse('{filter_status} Be-filter', line) if res: self.befilter_status = res['filter_status'] b1rest.remove(line) # the rest unparsed lines go to notes for the moment # [TODO]: parse more information about the sample, e.g. space group etc. self.notes = ' '.join(b1rest) # parse block 2 (wavelength and mochromator angle) # for the moment, only theta and lambda are needed b2splitted = map(str.strip, blocks[2].split('#')) # assume that theta and lambda are always on the fixed positions # assume theta is give in degree, lambda in nm line = b2splitted[2].split() self.monochromator_angle = float(line[2]) self.wavelength = float(line[3])*10.0 # parse block 3 (motors position) b3splitted = map(str.strip, blocks[3].split('#')) self.monochromator_position = float(b3splitted[2].split()[1]) # DeteRota, angle of rotation of detector bank self.deterota = float(b3splitted[3].split()[1]) # Huber default units degree self.huber = float(b3splitted[5].split()[1]) self.cradle_lower = float(b3splitted[6].split()[1]) self.cradle_upper = float(b3splitted[7].split()[1]) # Slit_i, convert mm to meter self.slit_i_upper_blade_position = 0.001*float(b3splitted[9].split()[2]) self.slit_i_lower_blade_position = 0.001*float(b3splitted[10].split()[1]) self.slit_i_left_blade_position = 0.001*float(b3splitted[11].split()[2]) self.slit_i_right_blade_position = 0.001*float(b3splitted[12].split()[1]) # Slit_f self.slit_f_upper_blade_position = 0.001*float(b3splitted[14].split()[1]) self.slit_f_lower_blade_position = 0.001*float(b3splitted[15].split()[1]) # Detector_position vertical self.detector_position_vertical = 0.001*float(b3splitted[16].split()[1]) # Polarizer self.polarizer_translation = 0.001*float(b3splitted[19].split()[1]) self.polarizer_rotation = float(b3splitted[20].split()[1]) # parse block 4 (B-fields), only currents in A are taken b4splitted = map(str.strip, blocks[4].split('#')) self.flipper_precession_current = float(b4splitted[2].split()[1]) self.flipper_z_compensation_current = float(b4splitted[3].split()[1]) self.a_coil_current = float(b4splitted[4].split()[1]) self.b_coil_current = float(b4splitted[5].split()[1]) self.c_coil_current = float(b4splitted[6].split()[1]) self.z_coil_current = float(b4splitted[7].split()[1]) # parse block 5 (Temperatures) # assume: T1=cold_head_temperature, T2=sample_temperature b5splitted = map(str.strip, blocks[5].split('#')) self.t1 = float(b5splitted[2].split()[1]) self.t2 = float(b5splitted[3].split()[1]) self.tsp = float(b5splitted[4].split()[1]) # parse block 6 (TOF parameters) b6splitted = map(str.strip, blocks[6].split('#')) self.tof_channel_number = int(b6splitted[2].split()[2]) self.tof_channel_width = float(b6splitted[3].split()[3]) self.tof_delay_time = float(b6splitted[4].split()[2]) self.tof_elastic_channel = int(b6splitted[6].split()[3]) # chopper rotation speed self.chopper_rotation_speed = float(b6splitted[7].split()[2]) # chopper number of slits self.chopper_slits = int(b6splitted[5].split()[2]) # parse block 7 (Time and monitor) # assume everything to be at the fixed positions b7splitted = map(str.strip, blocks[7].split('#')) # duration line = b7splitted[2].split() self.duration = float(line[1]) # assume seconds [TODO]: check # monitor data line = b7splitted[3].split() self.monitor_counts = int(line[1]) # start_time and end_time outfmt = "%Y-%m-%dT%H:%M:%S" sinfmt = "start at %a %b %d %H:%M:%S %Y" einfmt = "stopped at %a %b %d %H:%M:%S %Y" self.start_time = datetime.datetime.strptime(b7splitted[5], sinfmt).strftime(outfmt) self.end_time = datetime.datetime.strptime(b7splitted[6], einfmt).strftime(outfmt) if __name__== '__main__': fname = sys.argv[1] d = DNSdata() d.read_legacy(fname) print d.__dict__