Skip to content
Snippets Groups Projects
dnsdata.py 8.33 KiB
Newer Older
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__