Clearer error handling, rounding values to nearest stop

This commit is contained in:
Daniele Verducci 2024-05-22 08:55:14 +02:00
parent b1f31c08cf
commit e4a7e4fcef
8 changed files with 95 additions and 21 deletions

View File

@ -18,15 +18,84 @@ K = 12.5
class EVCalculator:
DEFAULT_ISO_SPEED = 100
APERTURE_VALUES = {
1/32: "1/32",
1/22: "1/22",
1/16: "1/16",
1/11: "1/11",
1/8: "1/8",
1/5.6: "1/5.6",
1/4: "1/4",
1/2.8: "1/2.8",
1/2: "1/2",
1/1.4: "1/1.4"
}
SHUTTER_SPEED_VALUES = {
1/4000: "1/4000",
1/2000: "1/2000",
1/1000: "1/1000",
1/500: "1/500",
1/250: "1/250",
1/125: "1/125",
1/60: "1/60",
1/30: "1/30",
1/15: "1/15",
1/8: "1/8",
1/4: "1/4",
1/2: "1/2",
1: "1",
2: "2",
4: "4",
8: "8",
15: "15",
30: "30"
}
def luxToEV(lux: float) -> float:
# Wikipedia (https://en.wikipedia.org/wiki/Light_meter#Exposure_equations)
# says E = 2.5 * (2^EV), so the inverse is EV = ln(2*E/5)/ln(2)
return log(2*lux/5, 2)
def calcShutterSpeed(isoSpeed: int, lux: float, aperture: float):
return (aperture*aperture*K)/(lux*isoSpeed)
result = (aperture*aperture*K)/(lux*isoSpeed)
print("aperture: {}, K: {}, lux: {}, isoSpeed: {}, result: {}".format(aperture, K, lux, isoSpeed, result))
return result
def calcAperture(isoSpeed: int, lux: float, shutterSpeed: float):
# shutterSpeed is in seconds
return sqrt(lux*isoSpeed*shutterSpeed/K)
def toNearestStr(valueToRound: float, roundingValues: dict[float,str]) -> [str, bool]:
# Rounds to the nearest value in the provided ORDERED dict.
# The dict is expected to have a float value as key and the corresponding human readable string value as value
# Returns the string value and a boolean set to true if the value was in the list range.
roundingNumericValues = list(roundingValues.keys())
roundingStringValues = list(roundingValues.values())
first = roundingNumericValues[0]
last = roundingNumericValues[-1]
if valueToRound < first / 1.5:
# More than half stop below minimum value!
return [roundingStringValues[0], False]
if valueToRound > last * 1.5:
# More than half stop above maximum value!
return [roundingStringValues[-1], False]
# Note: range(roundingValues - 1) to exclude last element
for i in range(len(roundingNumericValues) - 1):
value = float(roundingNumericValues[i])
nextValue = float(roundingNumericValues[i + 1])
limit = (value + nextValue) / 2
if valueToRound <= limit:
return [roundingStringValues[i], True]
return [roundingStringValues[-1], True]

View File

@ -1,6 +1,7 @@
from gi.repository import Gio, GLib
from threading import Timer
from enum import Enum
import traceback
# window.py
#
@ -46,6 +47,7 @@ class SensorsPollingTimer(Timer):
self.function(value, unit) # Invoke callback
except Exception as e:
print(traceback.format_exc(e))
if not self.onError:
print("SensorsPollingTimer: error occurred, but no onError callback defined")
return

View File

@ -1,5 +1,5 @@
label.lumos-big-result {
font-size: 80px;
font-size: 60px;
font-weight: 800;
}

View File

@ -26,25 +26,15 @@ class AperturePriorityPage(Gtk.Box):
__gtype_name__ = 'AperturePriorityPage'
# Values of aperture dropdown entries defined in the .ui file
__aperture_priority_speed_dropdown_values = [
1/32,
1/22,
1/16,
1/11,
1/8,
1/5.6,
1/4,
1/2.8,
1/2,
1/1.4
]
# TODO: Load dropdown strings from APERTURE_VALUES.values()
__aperture_priority_speed_dropdown_values = list(EVCalculator.APERTURE_VALUES.keys())
# Widgets
aperture_priority_aperture_dropdown = Gtk.Template.Child()
aperture_priority_time_label = Gtk.Template.Child()
__sensorValue = None
__isoSpeed = 100
__isoSpeed = EVCalculator.DEFAULT_ISO_SPEED
def onValuesChanged(self, isoSpeed: int, sensorValue: float, sensorUnit: str):
# Check the unit is absolute ("lux")
@ -64,9 +54,16 @@ class AperturePriorityPage(Gtk.Box):
def updateView(self):
apertureValue = self.__aperture_priority_speed_dropdown_values[self.aperture_priority_aperture_dropdown.get_selected()]
shutterSpeed = EVCalculator.calcShutterSpeed(self.__isoSpeed, self.__sensorValue, apertureValue)
# TODO: Round shutter speed value to nearest existing value and set label color to red if outside 1 stop range
self.aperture_priority_time_label.set_label("1/ {:.5f}".format(shutterSpeed))
# Round shutter speed value to nearest existing value and set label color to red if outside 1 stop range
[nearestValue, isInsideRange] = EVCalculator.toNearestStr(shutterSpeed, EVCalculator.SHUTTER_SPEED_VALUES)
if isInsideRange:
self.aperture_priority_time_label.set_label(nearestValue)
else:
self.aperture_priority_time_label.set_label("<span foreground=\"red\">{}</span>".format(nearestValue))
@Gtk.Template.Callback()
def onApertureChanged(self, dropDown: Gtk.DropDown, _: any):
self.updateView()

View File

@ -30,6 +30,7 @@
<child>
<object class="GtkLabel" id="aperture_priority_time_label">
<property name="label" translatable="no">--s</property>
<property name="use-markup">true</property>
<style>
<class name="lumos-big-result"/>
</style>

View File

@ -52,7 +52,7 @@ class TimePriorityPage(Gtk.Box):
time_priority_aperture_label = Gtk.Template.Child()
__sensorValue = None
__isoSpeed = 100
__isoSpeed = EVCalculator.DEFAULT_ISO_SPEED
def onValuesChanged(self, isoSpeed: int, sensorValue: float, sensorUnit: str):
# Check the unit is absolute ("lux")
@ -71,8 +71,13 @@ class TimePriorityPage(Gtk.Box):
def updateView(self):
shutterSpeed = self.__time_priority_speed_dropdown_values[self.time_priority_speed_dropdown.get_selected()]
apertureValue = EVCalculator.calcAperture(self.__isoSpeed, self.__sensorValue, shutterSpeed)
# TODO: Round aperture value to nearest existing value and set label color to red if outside 1 stop range
self.time_priority_aperture_label.set_label("f/ {:.2f}".format(apertureValue))
# Round aperture value to nearest existing value and set label color to red if outside range
[nearestValue, isInsideRange] = EVCalculator.toNearestStr(shutterSpeed, EVCalculator.APERTURE_VALUES)
if isInsideRange:
self.time_priority_aperture_label.set_label(nearestValue)
else:
self.time_priority_aperture_label.set_label("<span foreground=\"red\">{}</span>".format(nearestValue))
@Gtk.Template.Callback()
def onShutterSpeedChanged(self, dropDown: Gtk.DropDown, _: any):

View File

@ -30,6 +30,7 @@
<child>
<object class="GtkLabel" id="time_priority_aperture_label">
<property name="label" translatable="no">f/--</property>
<property name="use-markup">true</property>
<style>
<class name="lumos-big-result"/>
</style>

View File

@ -69,7 +69,6 @@ class LumosWindow(Adw.ApplicationWindow):
self.sensor_unit_error_banner.set_revealed(True)
def onError(self, e: Exception):
print(e)
self.lastError = e
self.error_banner.set_revealed(True)