Commit aebe559b authored by Carsten Richter's avatar Carsten Richter

Merge branch 'spec-calib' into 'master'

Read calibration and energy from spec

Closes #31 and #35

See merge request !65
parents 44d4d59a b646f86a
Pipeline #4193 failed with stages
in 3 minutes and 3 seconds
......@@ -29,6 +29,7 @@ __authors__ = ["D. Naudet"]
__license__ = "MIT"
__date__ = "15/09/2016"
import logging
import os
import time
import shutil
......@@ -46,6 +47,8 @@ from ..widgets.Buttons import FixedSizePushButon
from silx.gui import qt as Qt
_logger = logging.getLogger(__name__)
_HELP_WIDGET_STYLE = """
QLabel {
border-radius: 10px;
......@@ -881,14 +884,14 @@ class MergeWidget(Qt.QDialog):
assert_non_none(acqParamWid.beam_energy)
name = 'Direct beam'
dir_beam_h = assert_non_none(acqParamWid.direct_beam_h)
dir_beam_v = assert_non_none(acqParamWid.direct_beam_v)
merger.center_chan = [dir_beam_h, dir_beam_v]
dir_beam_h = assert_non_none(acqParamWid.direct_beam_h)
merger.center_chan = [dir_beam_v, dir_beam_h]
name = 'Channel per degree'
chpdeg_h = assert_non_none(acqParamWid.chperdeg_h)
chpdeg_v = assert_non_none(acqParamWid.chperdeg_v)
merger.chan_per_deg = [chpdeg_h, chpdeg_v]
chpdeg_h = assert_non_none(acqParamWid.chperdeg_h)
merger.chan_per_deg = [chpdeg_v, chpdeg_h]
name = 'Prefix'
prefix = self.__output['prefix']
......@@ -1159,8 +1162,27 @@ class MergeWidget(Qt.QDialog):
nNoMatch = len(no_match_ids)
nNoImg = len(no_img_ids)
# Retrieve calibration from selected ids
self.__scansGbx.setEnabled(enable)
self.__acqParamsGbx.setEnabled(len(matched_ids) > 0)
self.__acqParamsGbx.setEnabled(len(selected_ids) > 0)
# Set-up default values from first selected scan
if len(selected_ids) > 0:
calib = self.__merger.get_calibration(selected_ids[0])
if calib:
_logger.info("Load calibration information from scan %s",
selected_ids[0])
if 'mononrj' in calib:
# Convert from keV to eV
self.__acqParamWid.beam_energy = calib['mononrj'] * 1000
if 'pixperdeg' in calib:
self.__acqParamWid.chperdeg_v = calib['pixperdeg']
self.__acqParamWid.chperdeg_h = calib['pixperdeg']
if 'cen_pix_x' in calib:
self.__acqParamWid.direct_beam_h = calib['cen_pix_x']
if 'cen_pix_y' in calib:
self.__acqParamWid.direct_beam_v = calib['cen_pix_y']
self.__totalScansEdit.setText(str(nTotal))
self.__selectedScansEdit.setText(str(nSelected))
......
......@@ -84,10 +84,10 @@ class ConversionParamsWidget(Qt.QWidget):
self.__acqParamWid = AcqParamsWidget()
# Set default values with provided info
self.__acqParamWid.beam_energy = beamEnergy
self.__acqParamWid.direct_beam_h = directBeam[0]
self.__acqParamWid.direct_beam_v = directBeam[1]
self.__acqParamWid.chperdeg_h = channelsPerDegree[0]
self.__acqParamWid.chperdeg_v = channelsPerDegree[1]
self.__acqParamWid.direct_beam_v = directBeam[0]
self.__acqParamWid.direct_beam_h = directBeam[1]
self.__acqParamWid.chperdeg_v = channelsPerDegree[0]
self.__acqParamWid.chperdeg_h = channelsPerDegree[1]
grpLayout.addWidget(self.__acqParamWid)
self.layout().addWidget(acqParamsGbx)
......@@ -427,8 +427,8 @@ class ConversionParamsWidget(Qt.QWidget):
If one input is missing, it returns None.
"""
directBeam = (self.__acqParamWid.direct_beam_h,
self.__acqParamWid.direct_beam_v)
directBeam = (self.__acqParamWid.direct_beam_v,
self.__acqParamWid.direct_beam_h)
return None if None in directBeam else directBeam
def getChannelsPerDegree(self):
......@@ -436,8 +436,8 @@ class ConversionParamsWidget(Qt.QWidget):
If one input is missing, it returns None.
"""
channelsPerDegree = (self.__acqParamWid.chperdeg_h,
self.__acqParamWid.chperdeg_v)
channelsPerDegree = (self.__acqParamWid.chperdeg_v,
self.__acqParamWid.chperdeg_h)
return None if None in channelsPerDegree else channelsPerDegree
......
......@@ -73,8 +73,8 @@ class AcqParamsWidget(Qt.QWidget):
# ===========
row = 0
h_layout = Qt.QHBoxLayout()
beam_nrg_edit = dblLineEditWidget(8)
h_layout.addWidget(beam_nrg_edit)
self.__beam_nrg_edit = dblLineEditWidget(8)
h_layout.addWidget(self.__beam_nrg_edit)
h_layout.addWidget(Qt.QLabel('<b>eV</b>'))
layout.addWidget(Qt.QLabel('Beam energy :'), row, 0)
......@@ -96,12 +96,12 @@ class AcqParamsWidget(Qt.QWidget):
h_layout = Qt.QHBoxLayout()
layout.addLayout(h_layout, row, 1,
alignment=Qt.Qt.AlignLeft | Qt.Qt.AlignTop)
dir_beam_h_edit = dblLineEditWidget(6)
self.__dir_beam_v_edit = dblLineEditWidget(6)
h_layout.addWidget(Qt.QLabel('v='))
h_layout.addWidget(dir_beam_h_edit)
dir_beam_v_edit = dblLineEditWidget(6)
h_layout.addWidget(self.__dir_beam_v_edit)
self.__dir_beam_h_edit = dblLineEditWidget(6)
h_layout.addWidget(Qt.QLabel(' h='))
h_layout.addWidget(dir_beam_v_edit)
h_layout.addWidget(self.__dir_beam_h_edit)
h_layout.addWidget(Qt.QLabel('<b>px</b>'))
layout.addWidget(Qt.QLabel('Direct beam :'), row, 0)
......@@ -121,12 +121,12 @@ class AcqParamsWidget(Qt.QWidget):
h_layout = Qt.QHBoxLayout()
layout.addLayout(h_layout, row, 1,
alignment=Qt.Qt.AlignLeft | Qt.Qt.AlignTop)
chpdeg_h_edit = dblLineEditWidget(6)
self.__chpdeg_v_edit = dblLineEditWidget(6)
h_layout.addWidget(Qt.QLabel('v='))
h_layout.addWidget(chpdeg_h_edit)
chpdeg_v_edit = dblLineEditWidget(6)
h_layout.addWidget(self.__chpdeg_v_edit)
self.__chpdeg_h_edit = dblLineEditWidget(6)
h_layout.addWidget(Qt.QLabel(' h='))
h_layout.addWidget(chpdeg_v_edit)
h_layout.addWidget(self.__chpdeg_h_edit)
h_layout.addWidget(Qt.QLabel('<b>px</b>'))
layout.addWidget(Qt.QLabel('Chan. per deg. :'), row, 0)
......@@ -144,13 +144,6 @@ class AcqParamsWidget(Qt.QWidget):
self.setSizePolicy(Qt.QSizePolicy(Qt.QSizePolicy.Fixed,
Qt.QSizePolicy.Fixed))
# named tuple with references to all the important widgets
self.__beam_nrg_edit = beam_nrg_edit
self.__dir_beam_h_edit = dir_beam_h_edit
self.__dir_beam_v_edit = dir_beam_v_edit
self.__chpdeg_h_edit = chpdeg_h_edit
self.__chpdeg_v_edit = chpdeg_v_edit
def clear(self):
self.__beam_nrg_edit.clear()
self.__dir_beam_h_edit.clear()
......
......@@ -382,7 +382,7 @@ class KmapMerger(object):
try:
scan = spec_h5[scan_id]
except KeyError:
raise ValueError('Scan ID {0} not found.')
raise ValueError('Scan ID {0} not found.'.format(scan_id))
command = scan['title'][()]
......@@ -393,6 +393,38 @@ class KmapMerger(object):
'Failed to parse command line for scan ID {0} : '
'{1}.'.format(scan_id, command))
def get_calibration(self, scan_id):
"""Retrieve calibration info from scan header
:param str scan_id: ID of the scan from which to get information
"""
with h5py.File(self.__spec_h5, 'r') as spec_h5:
try:
scan = spec_h5[scan_id]
except KeyError:
raise ValueError('Scan ID {0} not found.'.format(scan_id))
converters = {
'cen_pix_x': float,
'cen_pix_y': float,
'pixperdeg': float,
'mononrj': lambda nrj: float(nrj[:-3]) # Ends with keV
}
calibration = {}
# Parse spec header to find calibration
header = scan['instrument/specfile/scan_header'][()]
for line in header:
if line.startswith('#UDETCALIB ') or line.startswith('#UMONO '):
params = line.split(' ')[1].strip().split(',')
for item in params:
if '=' in item:
key, value = item.split('=')
if key in converters:
calibration[key] = converters[key](value)
return calibration
def check_overwrite(self):
"""
Returns a list of the files that already exist and that will be
......
......@@ -49,8 +49,6 @@ _IMAGEFILE_LINE_PATTERN = ('^#C imageFile '
'nextNr\[(?P<nextNr>[^\]]*)\] '
'suffix\[(?P<suffix>[^\]]*)\]$')
# #######################################################################
# #######################################################################
......@@ -62,24 +60,23 @@ KmapMatchResults = namedtuple('KmapMatchResults',
'no_img_info', 'error',
'spec_h5'])
# #######################################################################
# #######################################################################
class KmapSpecParser(object):
(READY, RUNNING, DONE,
ERROR, CANCELED, UNKNOWN) = __STATUSES = range(6)
""" Available status codes """
"""Available status codes"""
status = property(lambda self: self.__status)
""" Current status code of this instance """
"""Current status code of this instance"""
statusMsg = property(lambda self: self.__status_msg)
""" Status message if any, or None """
"""Status message if any, or None"""
results = property(lambda self: self.__results)
""" Parse results. KmapParseResults instance. """
"""Parse results. KmapMatchResults instance."""
def __init__(self,
spec_fname,
......@@ -92,6 +89,7 @@ class KmapSpecParser(object):
"""
Parser for the Kmap SPEC files. This loads a spec file, converts
it to HDF5 and then tries to match scans and edf image files.
:param spec_fname: Path to the spec file.
:param spec_h5: Name of the HDF5 file that will be created and filled
with the contents of the SPEC file
......@@ -131,27 +129,25 @@ class KmapSpecParser(object):
self.__set_status(self.READY)
def __set_status(self, status, msg=None):
"""
Sets the status of this instance.
"""Sets the status of this instance.
:param status:
:param msg:
:return:
"""
assert status in self.__STATUSES
self.__status = status
self.__status_msg = msg
def parse(self, blocking=True):
"""
Starts the parsing.
"""Starts the parsing.
:param blocking: if False, the parsing will be done in a separate
thread and this method will return immediately.
:return:
"""
if self.__thread and self.__thread.is_alive():
raise RuntimeError('This KmapSpecParser instance is already '
'parsing.')
raise RuntimeError(
'This KmapSpecParser instance is already parsing.')
self.__results = None
......@@ -162,10 +158,7 @@ class KmapSpecParser(object):
thread.start()
def __run_parse(self):
"""
Runs the parsing.
:return:
"""
"""Runs the parsing."""
self.__set_status(self.RUNNING)
......@@ -185,8 +178,6 @@ class KmapSpecParser(object):
if self.__callback:
self.__callback()
return self.__results
def wait(self):
"""
Waits until parsing is done, or returns if it is not running.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment