Skip to content

Commit

Permalink
Merge commit 'e92bca0d6d5ae664606054b3ad33d0eb61a3dc86' into v0.6
Browse files Browse the repository at this point in the history
  • Loading branch information
drogenlied committed Nov 24, 2016
2 parents f449265 + e92bca0 commit bfbd69b
Show file tree
Hide file tree
Showing 21 changed files with 1,295 additions and 385 deletions.
131 changes: 109 additions & 22 deletions core/util/units.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
"""

import numpy as np
import pyqtgraph.functions as fn
try:
import pyqtgraph.functions as fn
except:
fn = None
import math


def get_unit_prefix_dict():
Expand All @@ -47,9 +51,79 @@ def get_unit_prefix_dict():
'E': 1e18,
'Z': 1e21,
'Y': 1e24
}
}
return unit_prefix_dict


class ScaledFloat(float):
"""
Format code 'r' for scaled output.
Examples
--------
>>> '{:.0r}A'.format(ScaledFloat(50))
50 A
>>> '{:.1r}A'.format(ScaledFloat(1.5e3))
1.5 kA
>>> '{:.1r}A'.format(ScaledFloat(2e-3))
2.0 mA
>>> '{:rg}A'.format(ScaledFloat(2e-3))
2 mA
>>> '{:rf}A'.format(ScaledFloat(2e-3))
2.000000 mA
"""

@property
def scale(self):
"""
Returns the scale.
Examples
--------
1e-3: m
1e6: M
"""
exponent = math.floor(math.log10(abs(self)) / 3)
if exponent < -8:
exponent = -8
if exponent > 8:
exponent = 8
prefix = 'yzafpnum kMGTPEZY'
return prefix[8 + exponent].strip()

def __format__(self, fmt):
"""
Fromats the string using format fmt.
r for scaled output.
Parameters
----------
fmt : str format string
"""
autoscale = False
if (len(fmt) >= 2):
if fmt[-2] == 'r':
autoscale = True
fmt = fmt[:-2] + fmt[-1]
elif fmt[-1] == 'r':
autoscale = True
fmt = fmt[:-1] + 'f'
elif fmt[-1] == 'r':
autoscale = True
fmt = fmt[:-1] + 'f'
if (autoscale):
scale = self.scale
if (scale == 'u'):
index = 'micro'
else:
index = scale
value = self / get_unit_prefix_dict()[index]
return '{:s} {:s}'.format(value.__format__(fmt), scale)
else:
return super().__format__(fmt)


def create_formatted_output(param_dict, num_sig_digits=5):
""" Display a parameter set nicely in SI units.
Expand Down Expand Up @@ -86,45 +160,54 @@ def create_formatted_output(param_dict, num_sig_digits=5):
"""
if (fn is None):
raise Exception('This function requires pyqtgraph.')

output_str = ''
atol = 1e-18 # absolute tolerance for the detection of zero.

for entry in param_dict:
if param_dict[entry].get('error') is not None:

value, error, digit = round_value_to_error(param_dict[entry]['value'], param_dict[entry]['error'])

if np.isclose(value, 0.0, atol=atol) or np.isnan(error) or np.isclose(error, 0.0, atol=atol) or np.isinf(error):
value, error, digit = round_value_to_error(
param_dict[entry]['value'], param_dict[entry]['error'])

if (np.isclose(value, 0.0, atol=atol)
or np.isnan(error)
or np.isclose(error, 0.0, atol=atol)
or np.isinf(error)):
sc_fact, unit_prefix = fn.siScale(param_dict[entry]['value'])
str_val = '{0:.{1}e}'.format(param_dict[entry]['value'], num_sig_digits-1)
str_val = '{0:.{1}e}'.format(
param_dict[entry]['value'], num_sig_digits - 1)
if np.isnan(np.float(str_val)):
value = np.NAN
elif np.isinf(np.float(str_val)):
value = np.inf
else:
value = float('{0:.{1}e}'.format(param_dict[entry]['value'], num_sig_digits-1))
value = float('{0:.{1}e}'.format(
param_dict[entry]['value'], num_sig_digits - 1))

else:
# the factor 10 moves the displayed digit by one to the right,
# so that the values from 100 to 0.1 are displayed within one
# range, rather then from the value 1000 to 1, which is default.
sc_fact, unit_prefix = fn.siScale(error*10)

# range, rather then from the value 1000 to 1, which is
# default.
sc_fact, unit_prefix = fn.siScale(error * 10)

output_str += '{0}: {1} \u00B1 {2} {3}{4} \n'.format(entry,
round(value*sc_fact, num_sig_digits-1),
round(error*sc_fact, num_sig_digits-1),
round(
value * sc_fact, num_sig_digits - 1),
round(
error * sc_fact, num_sig_digits - 1),
unit_prefix,
param_dict[entry]['unit'],
param_dict[entry][
'unit'],
)

else:
output_str += '{0}: '.format(entry) + fn.siFormat(param_dict[entry]['value'],
precision=num_sig_digits,
suffix=param_dict[entry]['unit']) + '\n'

precision=num_sig_digits,
suffix=param_dict[entry]['unit']) + '\n'

return output_str

Expand Down Expand Up @@ -192,7 +275,7 @@ def round_value_to_error(value, error):
# check if error is zero, since that is an invalid input!
if np.isclose(error, 0.0, atol=atol) or np.isnan(error) or np.isinf(error):
#self.log.error('Cannot round to the error, since either a zero error ')
#logger.warning('Cannot round to the error, since either a zero error '
# logger.warning('Cannot round to the error, since either a zero error '
# 'value was passed for the number {0}, or the error is '
# 'NaN: Error value: {1}. '.format(value, error))

Expand All @@ -205,7 +288,7 @@ def round_value_to_error(value, error):
log_val = np.log10(abs(error))

if log_val < 0:
round_digit = -(int(log_val)-1)
round_digit = -(int(log_val) - 1)
else:
round_digit = -(int(log_val))

Expand Down Expand Up @@ -239,7 +322,7 @@ def get_relevant_digit(entry):
return int(np.log10(entry))
else:
# catch the asymmetric behaviour of the log and int operation.
return int(int(np.abs(np.log10(entry)))+1 + np.log10(entry)) - (int(np.abs(np.log10(entry))) +1)
return int(int(np.abs(np.log10(entry))) + 1 + np.log10(entry)) - (int(np.abs(np.log10(entry))) + 1)


def get_si_norm(entry):
Expand All @@ -253,11 +336,12 @@ def get_si_norm(entry):
float normalization: the factor with which to divide the number.
"""
val = get_relevant_digit(entry)
fact = int(val/3)
power = int(3*fact)
fact = int(val / 3)
power = int(3 * fact)
norm = 10**(power)

return entry/norm, norm
return entry / norm, norm


def is_number(test_value):
""" Check whether passed value is a number
Expand All @@ -266,6 +350,7 @@ def is_number(test_value):
"""
return is_integer(test_value) or is_float(test_value) or is_complex(test_value)


def is_integer(test_value):
""" Check all available integer representations.
Expand All @@ -276,13 +361,15 @@ def is_integer(test_value):
np.uint, np.uint8, np.uint16, np.uint32,
np.uint64]


def is_float(test_value):
""" Check all available float representations.
@return: bool, True if the passed value is a float, otherwise false.
"""
return type(test_value) in [np.float, np.float16, np.float32, np.float64]


def is_complex(test_value):
""" Check all available complex representations.
Expand Down
87 changes: 87 additions & 0 deletions documentation/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Changelog {#changelog}

## Relese 0.6

## Release 0.5

Released on 30 Dec 2015.
Available at https://qosvn.physik.uni-ulm.de/svn/qudi/tags/release-0.5

Notes about this release are probably missing due to holidays.

* Two photon counters supported in NI card counter and counter logic

## Release 0.4

Released on 30.10.2015.
Available at https://qosvn.physik.uni-ulm.de/svn/qudi/tags/release-0.4

New features:

* Tilted scanning
* ODMR remembers settings
* ODMR can save raw data
* Working and tested support for Radiant Dyes flip mirrors
* support for taking spectra from spectrometer via WinSpec32
* POI positions are now actually updated when the tracked POI moves
* remote module support is more robust now
* fixed a crash when changing confocal color bar while scanning
* winspec32 spectrometer support
* configurable settling time at start of optimization scans
* option for surface-subtraction in the depth optimization scan
* ALPHA Task interface
* PRE-ALPHA for pulsed experiments

## Release 0.3

Released on 31.07.2015. Available at https://qosvn.physik.uni-ulm.de/svn/qudi/tags/release-0.3

New features:

* Manager now includes log and iPython console
* Manager can load and save the configuration
* Manager can show active threads and remotely shared modules
* QuDi remembers which configuration file is loaded
* QuDi can restart to load new configuration
* SmiQ R&S 06ATE works for ODMR
* Dockwidgets in ODMR
* Laser scanning with a remote wavemeter is now tested and confirmed working
* Zoom with mouse in Confocal

Additionally, lots of bugs were fixed.

## Release 0.2

Release-0.2 is available since 07.07.2015.
It can be found using: https://qosvn.physik.uni-ulm.de/svn/qudi/tags/release-0.2

New features:

* New Log style
* (Manager shows module state)
* Continues scan xy/depth (loop scan)
* Rotate confocal images (rotates only the image, not the cursor!!!)
* POI Manager GUI: restore default widget location (size might not be as default)
* Cursor and arrow keys: right/left(x-direction) up/down(y-direction) Bild up/Bild down(z-direction); big step size with shift;step size can be changes in the settings
* Clock time sample shift POI Manager
* Centiles of colorbars is now working during a scan
* All save files should now have the same time in the lable
* duration of periodic optimiser changeable working during period
* improved explanation in the data file of the Confocal scans
* Added tooltips to Confocal and Optimiser settings

## Release 0.1

Release-0.1 is the first release of the QuDi software project.
It can be found via SVN Checkout using this URL: https://qosvn.physik.uni-ulm.de/svn/qudi/tags/release-0.1
It is possible to do basic measurements and the following modules are working:

* Counter
* Confocal scanning
* Laser scanning
* POI managing
* ODMR

The basics of all these modules are working but there is plenty room for improvement.
At this stage the GUI is still under active development and so users should expect some interface items to change in future releases.

1 change: 1 addition & 0 deletions documentation/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


* [License](@ref license)
* [Changelog](@ref changelog)
* Setup
* [Installation](@ref installation)
* [Required packages](@ref required-python-packages)
Expand Down
Loading

1 comment on commit bfbd69b

@drogenlied
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pleased to announce the software release 0.6.
This release appears in conjunction with our paper about Qudi which will be submitted to SoftwareX with preprints available on arXiv shortly.

Please sign in to comment.