diff --git a/src/ev_calculator.py b/src/ev_calculator.py
index ebd126a..2c79627 100644
--- a/src/ev_calculator.py
+++ b/src/ev_calculator.py
@@ -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]
+
+
+
+
diff --git a/src/sensors_polling_timer.py b/src/sensors_polling_timer.py
index cb44fb3..a971930 100644
--- a/src/sensors_polling_timer.py
+++ b/src/sensors_polling_timer.py
@@ -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
diff --git a/src/style.css b/src/style.css
index 834eb1c..ffd44b5 100644
--- a/src/style.css
+++ b/src/style.css
@@ -1,5 +1,5 @@
label.lumos-big-result {
- font-size: 80px;
+ font-size: 60px;
font-weight: 800;
}
diff --git a/src/widgets/aperture_priority_page.py b/src/widgets/aperture_priority_page.py
index 682d093..74297f9 100644
--- a/src/widgets/aperture_priority_page.py
+++ b/src/widgets/aperture_priority_page.py
@@ -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("{}".format(nearestValue))
@Gtk.Template.Callback()
def onApertureChanged(self, dropDown: Gtk.DropDown, _: any):
self.updateView()
+
diff --git a/src/widgets/aperture_priority_page.ui b/src/widgets/aperture_priority_page.ui
index af56d19..516dc92 100644
--- a/src/widgets/aperture_priority_page.ui
+++ b/src/widgets/aperture_priority_page.ui
@@ -30,6 +30,7 @@