Source code for pyEvalData.io.scan

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# The MIT License (MIT)
# Copyright (c) 2015-2021 Daniel Schick
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.

from .. import config
import logging

__all__ = ['Scan']

__docformat__ = 'restructuredtext'

import numpy as np


[docs]class Scan(object): """Scan Representation of a scan which holds the relevant data and meta information. Args: number (uint): number of the scan. Keyword Args: cmd (str): scan command. user (str): scan user. date (str): scan date. time (str): scan time. int_time (float): integration time. init_mopo (dict(float)): initial motor position. header (str): full scan header. Attributes: log (logging.logger): logger instance from logging. number (uint): number of the scan. meta (dict): meta data dictionary. data (ndarray[float]): data recarray. """ def __init__(self, number, **kwargs): self.log = logging.getLogger(__name__) self.log.setLevel(config.LOG_LEVEL) self.log.debug('Creating scan #{:d}'.format(number)) self.number = np.uint64(number) # initialize empty data array and circumvent # check for recarray here self._data = None self.scalar_data_names = [] self.oned_data_names = [] self.twod_data_names = [] self.index_data() self.meta = {} self.meta['number'] = self.number self.meta['cmd'] = kwargs.get('cmd', '') self.meta['user'] = kwargs.get('user', '') self.meta['date'] = kwargs.get('date', '') self.meta['time'] = kwargs.get('time', '') self.meta['int_time'] = kwargs.get('int_time', '') self.meta['init_mopo'] = kwargs.get('init_mopo', {}) self.meta['header'] = kwargs.get('header', '') def __getattr__(self, attr): """__getattr__ Allows to access the data and meta(init_mopo) keys as scan attributes. Returns: attr (ndarray[float]|float|str): data/meta values. """ # check data recarray try: return self.data[attr] except (ValueError, IndexError, TypeError): pass # check meta dict try: return self.meta[attr] except KeyError: pass # check meta init_mopo dict try: return self.meta['init_mopo'][attr] except KeyError: raise AttributeError('\'{:s}\' has no attribute \'{:s}\''.format(__name__, attr))
[docs] def index_data(self): """index_data Check the dimensions of the data recarray elements and remember the names for scaler, 1d, and 2d data columns. """ if self.data is not None: for descr in self.data.dtype.descr: try: if len(descr[2]) == 1: self.oned_data_names.append(descr[0]) elif len(descr[2]) == 2: self.twod_data_names.append(descr[0]) except Exception: self.scalar_data_names.append(descr[0])
[docs] def get_scalar_data(self): """get_scalar_data Returns only scalar data from the data recarray. Returns: data (ndarray[float]): scalar data. """ if self.scalar_data_names == []: return None else: return self.data[self.scalar_data_names]
[docs] def get_oned_data(self): """get_oned_data Returns only 1d data from the data recarray. Returns: data (ndarray[float]): 1d data. """ if self.oned_data_names == []: return None else: return self.data[self.oned_data_names]
[docs] def get_twod_data(self): """get_twod_data Returns only 2d data from the data recarray. Returns: data (ndarray[float]): 2d data. """ if self.twod_data_names == []: return None else: return self.data[self.twod_data_names]
[docs] def clear_data(self): """clear_data Clears the data to save memory. """ self._data = None self.log.debug('Cleared data for scan #{:d}'.format(self.number))
@property def data(self): return self._data @data.setter def data(self, data): if isinstance(data, np.recarray): self._data = data elif data is None: self.log.info('Scan #{:d} contains no data!'.format(self.number)) self._data = None else: raise TypeError('Data must be a numpy.recarray!')