diff --git a/.gitignore b/.gitignore
index 592b2fb..317f5c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,7 +72,8 @@ temp/
venv*
*.dmg
*.spec
-!examples/ear_score.csv
+!examples/*.csv
+!examples/*.mp4
paper/paper.jats
paper/paper.pdf
diff --git a/examples/ear_score.csv b/examples/ear_score_240.csv
similarity index 100%
rename from examples/ear_score.csv
rename to examples/ear_score_240.csv
diff --git a/examples/ear_score_30.csv b/examples/ear_score_30.csv
new file mode 100644
index 0000000..e975fde
--- /dev/null
+++ b/examples/ear_score_30.csv
@@ -0,0 +1,251 @@
+frame,EAR2D6_l,EAR2D6_r,EAR2D6_valid,BS_Valid
+0, 0.30839515, 0.31717056,True,True
+1, 0.30697849, 0.31643425,True,True
+2, 0.31780323, 0.32533049,True,True
+3, 0.31657635, 0.31336477,True,True
+4, 0.31764210, 0.31694362,True,True
+5, 0.31386926, 0.31409277,True,True
+6, 0.31484655, 0.31612779,True,True
+7, 0.30915708, 0.31312242,True,True
+8, 0.30693714, 0.31124881,True,True
+9, 0.30799023, 0.31312242,True,True
+10, 0.30571419, 0.30799125,True,True
+11, 0.30042486, 0.30502849,True,True
+12, 0.28607607, 0.30721214,True,True
+13, 0.30121833, 0.30183604,True,True
+14, 0.29187137, 0.30210629,True,True
+15, 0.29767902, 0.29821654,True,True
+16, 0.29061937, 0.30378166,True,True
+17, 0.29875644, 0.29564100,True,True
+18, 0.29875644, 0.30551011,True,True
+19, 0.30571419, 0.29564100,True,True
+20, 0.29262141, 0.29620622,True,True
+21, 0.29262141, 0.29330723,True,True
+22, 0.27219442, 0.27695657,True,True
+23, 0.01769842, 0.01282979,True,True
+24, 0.01231288, 0.02070684,True,True
+25, 0.02101940, 0.01370297,True,True
+26, 0.04426898, 0.02246624,True,True
+27, 0.03302003, 0.00803064,True,True
+28, 0.07497124, 0.02872804,True,True
+29, 0.19807905, 0.19991081,True,True
+30, 0.23124061, 0.24272208,True,True
+31, 0.25739383, 0.26800041,True,True
+32, 0.26600419, 0.27675620,True,True
+33, 0.26620216, 0.28076742,True,True
+34, 0.27219442, 0.28631641,True,True
+35, 0.27817795, 0.28247069,True,True
+36, 0.27817795, 0.28490235,True,True
+37, 0.27819434, 0.28490235,True,True
+38, 0.28417787, 0.29053216,True,True
+39, 0.28076650, 0.29130211,True,True
+40, 0.29126256, 0.29442629,True,True
+41, 0.29036380, 0.29442629,True,True
+42, 0.28054342, 0.28490235,True,True
+43, 0.28688787, 0.29672592,True,True
+44, 0.28076650, 0.29109611,True,True
+45, 0.28670108, 0.28816167,True,True
+46, 0.28076650, 0.28816167,True,True
+47, 0.28417787, 0.29109611,True,True
+48, 0.28784117, 0.29340709,True,True
+49, 0.28790582, 0.29821654,True,True
+50, 0.28435252, 0.29672592,True,True
+51, 0.28076650, 0.29055364,True,True
+52, 0.06502978, 0.03658265,True,True
+53, 0.02024917, 0.02625834,True,True
+54, 0.02000166, 0.01876873,True,True
+55, 0.00874105, 0.02432521,True,True
+56, 0.01492190, 0.02768382,True,True
+57, 0.00863546, 0.02092892,True,True
+58, 0.01492190, 0.03351722,True,True
+59, 0.01236170, 0.01641662,True,True
+60, 0.01233816, 0.01856745,True,True
+61, 0.01831858, 0.00802237,True,True
+62, 0.04230399, 0.00000000,True,True
+63, 0.06181197, 0.02005528,True,True
+64, 0.20705129, 0.22071539,True,True
+65, 0.24511024, 0.24825420,True,True
+66, 0.26281608, 0.27651996,True,True
+67, 0.27138363, 0.28679968,True,True
+68, 0.27138363, 0.29316770,True,True
+69, 0.29029085, 0.30401200,True,True
+70, 0.29152860, 0.30015060,True,True
+71, 0.29287058, 0.30957440,True,True
+72, 0.27435362, 0.29465200,True,True
+73, 0.27774988, 0.29391477,True,True
+74, 0.29281205, 0.29593631,True,True
+75, 0.28205807, 0.30210629,True,True
+76, 0.28360660, 0.29316770,True,True
+77, 0.28491334, 0.30566975,True,True
+78, 0.29736310, 0.29793630,True,True
+79, 0.28449054, 0.30401200,True,True
+80, 0.28346620, 0.30158417,True,True
+81, 0.28915019, 0.29647832,True,True
+82, 0.28346620, 0.28974773,True,True
+83, 0.29029085, 0.29873282,True,True
+84, 0.29520791, 0.29873282,True,True
+85, 0.29047551, 0.30129435,True,True
+86, 0.28481250, 0.29235676,True,True
+87, 0.29038721, 0.30075286,True,True
+88, 0.29399576, 0.29478969,True,True
+89, 0.28474855, 0.29793630,True,True
+90, 0.29544620, 0.29760003,True,True
+91, 0.29047551, 0.29761966,True,True
+92, 0.29734401, 0.30129435,True,True
+93, 0.30882459, 0.30856107,True,True
+94, 0.30317851, 0.30566975,True,True
+95, 0.29734401, 0.30210629,True,True
+96, 0.29985247, 0.30129435,True,True
+97, 0.29991155, 0.30691690,True,True
+98, 0.29411627, 0.30639529,True,True
+99, 0.29736310, 0.30210629,True,True
+100, 0.30554130, 0.32070147,True,True
+101, 0.30754054, 0.31882648,True,True
+102, 0.31910433, 0.32414189,True,True
+103, 0.28094941, 0.27651996,True,True
+104, 0.01744879, 0.02406710,True,True
+105, 0.02247274, 0.03177595,True,True
+106, 0.00860217, 0.03313757,True,True
+107, 0.03164379, 0.01356214,True,True
+108, 0.06768018, 0.01817901,True,True
+109, 0.20271529, 0.22393133,True,True
+110, 0.24316228, 0.25774618,True,True
+111, 0.26001681, 0.28631641,True,True
+112, 0.28056569, 0.28220608,True,True
+113, 0.28056569, 0.29362676,True,True
+114, 0.27485479, 0.29931613,True,True
+115, 0.28094941, 0.29305686,True,True
+116, 0.26910210, 0.28466462,True,True
+117, 0.27036253, 0.28789544,True,True
+118, 0.27151763, 0.27901948,True,True
+119, 0.27870788, 0.29593631,True,True
+120, 0.28456170, 0.29593631,True,True
+121, 0.28913736, 0.29388577,True,True
+122, 0.28790582, 0.30129435,True,True
+123, 0.29387780, 0.30158417,True,True
+124, 0.29047551, 0.30639529,True,True
+125, 0.29152860, 0.30639529,True,True
+126, 0.29387249, 0.30034817,True,True
+127, 0.29174260, 0.30349620,True,True
+128, 0.29174260, 0.30202917,True,True
+129, 0.29274450, 0.30152513,True,True
+130, 0.29876218, 0.30924539,True,True
+131, 0.28607607, 0.30349620,True,True
+132, 0.28933412, 0.30017115,True,True
+133, 0.29876218, 0.31084737,True,True
+134, 0.28156328, 0.30535200,True,True
+135, 0.29876218, 0.31084737,True,True
+136, 0.30084331, 0.30034817,True,True
+137, 0.28824583, 0.30265839,True,True
+138, 0.28947251, 0.29738223,True,True
+139, 0.28476367, 0.29465200,True,True
+140, 0.29399576, 0.30616180,True,True
+141, 0.28122135, 0.29793630,True,True
+142, 0.08696232, 0.07316529,True,True
+143, 0.00872440, 0.02460670,True,True
+144, 0.01941004, 0.02893588,True,True
+145, 0.02526354, 0.03793540,True,True
+146, 0.02328699, 0.04282244,True,True
+147, 0.01221239, 0.01796818,True,True
+148, 0.03546387, 0.00549417,True,True
+149, 0.11005832, 0.05299722,True,True
+150, 0.22507869, 0.22884677,True,True
+151, 0.24808096, 0.25126705,True,True
+152, 0.26451688, 0.28204309,True,True
+153, 0.26857695, 0.28416769,True,True
+154, 0.27301256, 0.28416769,True,True
+155, 0.27997872, 0.28442911,True,True
+156, 0.28101880, 0.28939994,True,True
+157, 0.27989908, 0.28838177,True,True
+158, 0.27870788, 0.29340709,True,True
+159, 0.29038721, 0.29316770,True,True
+160, 0.27761239, 0.28227340,True,True
+161, 0.26704718, 0.28760540,True,True
+162, 0.26704718, 0.28281947,True,True
+163, 0.26590579, 0.28760540,True,True
+164, 0.28326359, 0.28204309,True,True
+165, 0.27880359, 0.27729200,True,True
+166, 0.27286259, 0.28416769,True,True
+167, 0.26590579, 0.28416769,True,True
+168, 0.28248591, 0.28733513,True,True
+169, 0.27448633, 0.27867187,True,True
+170, 0.27566412, 0.28389907,True,True
+171, 0.27556948, 0.28442911,True,True
+172, 0.27870788, 0.28389907,True,True
+173, 0.27884592, 0.28416769,True,True
+174, 0.26715126, 0.28913396,True,True
+175, 0.27424381, 0.29465200,True,True
+176, 0.26278444, 0.28389907,True,True
+177, 0.27884592, 0.28122140,True,True
+178, 0.26965958, 0.28706944,True,True
+179, 0.27884592, 0.29031120,True,True
+180, 0.27556948, 0.28706944,True,True
+181, 0.28467151, 0.28132200,True,True
+182, 0.27435362, 0.28939994,True,True
+183, 0.25727224, 0.26536923,True,True
+184, 0.02088370, 0.01338259,True,True
+185, 0.01360123, 0.01368535,True,True
+186, 0.01218968, 0.02069220,True,True
+187, 0.01489348, 0.02813706,True,True
+188, 0.01208685, 0.01339907,True,True
+189, 0.06587889, 0.02260906,True,True
+190, 0.07325627, 0.03493840,True,True
+191, 0.21407690, 0.22462453,True,True
+192, 0.24230951, 0.24911082,True,True
+193, 0.26417941, 0.27670971,True,True
+194, 0.26573676, 0.27592677,True,True
+195, 0.27774988, 0.29235676,True,True
+196, 0.27448633, 0.28363814,True,True
+197, 0.26603749, 0.28363814,True,True
+198, 0.27894167, 0.28387229,True,True
+199, 0.27190170, 0.28493478,True,True
+200, 0.27448633, 0.28733513,True,True
+201, 0.27774988, 0.28883339,True,True
+202, 0.28933412, 0.29235676,True,True
+203, 0.28607607, 0.28915618,True,True
+204, 0.28593776, 0.29492306,True,True
+205, 0.28028817, 0.28966629,True,True
+206, 0.27566412, 0.28957076,True,True
+207, 0.27661347, 0.29143903,True,True
+208, 0.26603749, 0.28915618,True,True
+209, 0.27904043, 0.28913396,True,True
+210, 0.28499447, 0.29465200,True,True
+211, 0.27566412, 0.29813491,True,True
+212, 0.27674727, 0.29465200,True,True
+213, 0.27566412, 0.28363814,True,True
+214, 0.28607607, 0.29465200,True,True
+215, 0.27129853, 0.29194358,True,True
+216, 0.28810647, 0.29543364,True,True
+217, 0.28476367, 0.28671125,True,True
+218, 0.28132988, 0.29170131,True,True
+219, 0.28217403, 0.29220632,True,True
+220, 0.28364877, 0.30042672,True,True
+221, 0.28476367, 0.30304016,True,True
+222, 0.28378281, 0.29687768,True,True
+223, 0.28396498, 0.30566975,True,True
+224, 0.28387867, 0.30017115,True,True
+225, 0.29422187, 0.30233665,True,True
+226, 0.28378281, 0.30233665,True,True
+227, 0.28607607, 0.30616180,True,True
+228, 0.07306278, 0.04001991,True,True
+229, 0.01190308, 0.02002629,True,True
+230, 0.01767767, 0.01979643,True,True
+231, 0.02384842, 0.01097841,True,True
+232, 0.03500224, 0.01201562,True,True
+233, 0.14034599, 0.10153823,True,True
+234, 0.20675459, 0.22546911,True,True
+235, 0.24530257, 0.25126705,True,True
+236, 0.24239267, 0.26500531,True,True
+237, 0.26391243, 0.27287946,True,True
+238, 0.25075540, 0.28025274,True,True
+239, 0.27674727, 0.28389907,True,True
+240, 0.26921031, 0.29143903,True,True
+241, 0.27909436, 0.29714485,True,True
+242, 0.27323818, 0.28154177,True,True
+243, 0.27372611, 0.28974508,True,True
+244, 0.26667730, 0.28667322,True,True
+245, 0.27129853, 0.28688769,True,True
+246, 0.26921031, 0.28736231,True,True
+247, 0.27690214, 0.28432221,True,True
+248, 0.27806570, 0.28974508,True,True
+249, 0.26818388, 0.28227222,True,True
diff --git a/examples/test_long.mp4 b/examples/test_long.mp4
new file mode 100644
index 0000000..d44581e
Binary files /dev/null and b/examples/test_long.mp4 differ
diff --git a/examples/test_short.mp4 b/examples/test_short.mp4
new file mode 100644
index 0000000..15dc3a8
Binary files /dev/null and b/examples/test_short.mp4 differ
diff --git a/frontend/app.py b/frontend/app.py
index 16f10f8..db097c5 100644
--- a/frontend/app.py
+++ b/frontend/app.py
@@ -7,7 +7,7 @@
import structlog
from PyQt6 import QtGui
-from PyQt6.QtWidgets import QMainWindow, QTabWidget, QProgressBar, QWidget
+from PyQt6.QtWidgets import QMainWindow, QTabWidget, QProgressBar, QWidget, QMessageBox
from frontend import config
from .ui_facial_feature_extraction import FacialFeatureExtraction
@@ -18,6 +18,29 @@
def add_space_between_words(text):
return re.sub(r"(\w)([A-Z])", r"\1 \2", text)
+LICENCE_TEXT = """
+JeFaPaTo is licensed under the MIT License.
+
+MIT License
+
+Copyright (c) [2023] [Tim Büchner]
+
+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.
+
+"""
+
class JeFaPaTo(QMainWindow, config.Config):
def __init__(self, args: argparse.Namespace) -> None:
"""
@@ -61,6 +84,16 @@ def __init__(self, args: argparse.Namespace) -> None:
self.statusBar().addPermanentWidget(self.progress_bar)
+ # Create menu bar
+ menu_bar = self.menuBar()
+ # Create Help menu
+ help_menu = menu_bar.addMenu("Help")
+
+ help_menu.addAction("About", self.show_about)
+ help_menu.addAction("Documentation", self.show_documentation)
+ help_menu.addAction("License", self.show_license)
+ help_menu.addAction("Acknowledgements", self.show_acknowledgements)
+
def closeEvent(self, event: QtGui.QCloseEvent) -> None:
"""
Event handler for the close event of the application window.
@@ -81,3 +114,64 @@ def closeEvent(self, event: QtGui.QCloseEvent) -> None:
self.save()
logger.info("Internal Shut Down complete", widget=self)
super().closeEvent(event)
+
+ def show_about(self):
+ """
+ Shows the About dialog.
+ """
+ ## use a dialog to show the about information
+ dialog = QMessageBox()
+ dialog.setWindowTitle("About JeFaPaTo")
+ dialog.setText("JeFaPaTo - Jena Facial Palsy Tool")
+ dialog.setInformativeText("""
+
+ - Version: 1.0.0
+ - Author: Tim Büchner
+ - License: MIT
+ - Link: Website
+
+ """)
+ dialog.setStandardButtons(QMessageBox.StandardButton.Ok)
+ dialog.exec()
+
+ def show_documentation(self):
+ """
+ Shows the Documentation dialog.
+ """
+ dialog = QMessageBox()
+ dialog.setWindowTitle("Documentation")
+ dialog.setText("Documentation")
+ dialog.setInformativeText("""
+ Documentation is available at our wiki page.
+ """
+ )
+ dialog.setStandardButtons(QMessageBox.StandardButton.Ok)
+ dialog.exec()
+
+ def show_license(self):
+ """
+ Shows the License dialog.
+ """
+ dialog = QMessageBox()
+ dialog.setWindowTitle("License")
+ dialog.setText("License")
+ dialog.setInformativeText(LICENCE_TEXT)
+ dialog.setStandardButtons(QMessageBox.StandardButton.Ok)
+ dialog.exec()
+
+ def show_acknowledgements(self):
+ """
+ Shows the Acknowledgements dialog.
+ """
+
+ dialog = QMessageBox()
+ dialog.setWindowTitle("Acknowledgements")
+ dialog.setText("Acknowledgements")
+ dialog.setInformativeText("""
+ JeFaPaTo is based on the MediaPipe library by Google.
+ We would like to thank the developers for their great work and the possibility to use their library.
+ Additionally, we would like to thank the OpenCV team for their great work and the possibility to use their library.
+ Also, we thank our medical partners for their support and feedback.
+ """)
+ dialog.setStandardButtons(QMessageBox.StandardButton.Ok)
+ dialog.exec()
diff --git a/frontend/gui_interface.py b/frontend/gui_interface.py
index 6e3df51..218479f 100644
--- a/frontend/gui_interface.py
+++ b/frontend/gui_interface.py
@@ -23,6 +23,9 @@ def __init__(self, parent: QtWidgets.QWidget):
self.parent = parent
self.stopped = False
+ self.update_counter = 0
+ self.update_interval = 10
+
def run(self):
while True:
if self.stopped:
@@ -31,10 +34,17 @@ def run(self):
def stop(self):
self.stopped = True
+
+ def set_update_interval(self, interval: int):
+ self.update_interval = interval
@facial_features.FaceAnalyzer.hookimpl
def updated_display(self, image: np.ndarray):
- self.sig_updated_display.emit(image)
+ self.update_counter += 1
+
+ if self.update_counter % self.update_interval == 0:
+ self.update_counter = 0
+ self.sig_updated_display.emit(image)
@facial_features.FaceAnalyzer.hookimpl
def updated_feature(self, feature_data: OrderedDict[str, Any]) -> None:
diff --git a/frontend/jwidgets/graph.py b/frontend/jwidgets/graph.py
index 88469ff..7cc0721 100644
--- a/frontend/jwidgets/graph.py
+++ b/frontend/jwidgets/graph.py
@@ -17,7 +17,7 @@ def __init__(self, background="default", x_lim_max=1000, **kargs):
self.plot_item.setLimits(xMin=0, xMax=x_lim_max)
self.plot_item.setXRange(0, x_lim_max)
- self.plot_item.setYRange(0, 1)
+ self.plot_item.setYRange(-0.05, 1)
self.axis_b: pg.AxisItem = self.plot_item.getAxis("bottom")
self.curves: list[pg.PlotDataItem] = []
diff --git a/frontend/jwidgets/videofacepreview.py b/frontend/jwidgets/videofacepreview.py
index 5f73729..31a340e 100644
--- a/frontend/jwidgets/videofacepreview.py
+++ b/frontend/jwidgets/videofacepreview.py
@@ -32,24 +32,24 @@ def load_file(self, file_path: Path) -> np.ndarray:
return self.get_frame(0)
- def in_range(self, frame_number: int) -> bool:
+ def in_range(self, frame_index: int) -> bool:
assert self.frame_count is not None
- return frame_number >= 0 and frame_number < self.frame_count
+ return frame_index >= 0 and frame_index < self.frame_count
- def get_frame(self, frame_number: int) -> np.ndarray:
+ def get_frame(self, frame_index: int) -> np.ndarray:
assert self.resource is not None
- self.resource.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
+ self.resource.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
ret, frame = self.resource.read()
if not ret:
- logger.error("Could not read frame", frame_number=frame_number, file_path=self.file_path)
+ logger.error("Could not read frame", frame_index=frame_index, file_path=self.file_path)
return np.zeros((300, 300, 3), dtype=np.uint8)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame_g = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
faces = self.face_finder.detectMultiScale(frame_g, 1.1, 5)
if len(faces) == 0:
- logger.warning("Could not find face", frame_number=frame_number, file_path=self.file_path)
+ logger.warning("Could not find face", frame_index=frame_index, file_path=self.file_path)
return frame
x, y, w, h = faces[0]
diff --git a/frontend/ui_eye_blinking_extraction.py b/frontend/ui_eye_blinking_extraction.py
index a0d5b26..277df2f 100644
--- a/frontend/ui_eye_blinking_extraction.py
+++ b/frontend/ui_eye_blinking_extraction.py
@@ -7,6 +7,7 @@
import pyqtgraph as pg
from qtpy import QtCore, QtGui, QtWidgets
+from qtpy.QtWidgets import QMessageBox, QLabel
from PyQt6.QtCore import pyqtSignal
from jefapato import blinking
@@ -14,6 +15,36 @@
logger = structlog.get_logger()
+#### Recommended Extracton Settings for Eye Blinking ####
+# @30 FPS
+# Minimum Distance: 10 Frames
+# Minimum Prominence: 0.1 EAR Score
+# Minimum Internal Width: 4 Frames
+# Maximum Internal Width: 20 Frames
+# Maximum Matching Distance: 15 Frames
+# Partial Threshold Left: 0.18 EAR Score
+# Partial Threshold Right: 0.18 EAR Score
+#
+# Smoothing
+# - Window Size: 7
+# - Polynomial Degree: 3
+#
+# ---
+#
+# @240 FPS
+# Minimum Distance: 50 Frames
+# Minimum Prominence: 0.1 EAR Score
+# Minimum Internal Width: 20 Frames
+# Maximum Internal Width: 100 Frames
+# Maximum Matching Distance: 30 Frames
+# Partial Threshold Left: 0.18 EAR Score
+# Partial Threshold Right: 0.18 EAR Score
+#
+# Smoothing
+# - Window Size: 7
+# - Polynomial Degree: 3
+
+
DOWNSAMPLE_FACTOR = 8
def to_float(value: str) -> float:
@@ -75,6 +106,21 @@ def sec_to_min(seconds: float) -> str:
seconds = int(seconds % 60)
return f"{minutes:02d}:{seconds:02d}"
+def create_help_button(tooltip: str, win=None) -> QtWidgets.QPushButton:
+ """
+ Create a help button with the given tooltip.
+
+ Args:
+ tooltip (str): The tooltip text to be displayed when hovering over the button.
+ win (QtWidgets.QWidget, optional): The parent widget for the help button. Defaults to None.
+
+ Returns:
+ QtWidgets.QPushButton: The created help button.
+ """
+ help_btn = QtWidgets.QPushButton(qta.icon("fa5s.question-circle"), "")
+ help_btn.setToolTip(tooltip)
+ help_btn.clicked.connect(lambda: QMessageBox.information(win, "Help", tooltip))
+ return help_btn
# TODO just make this a normal widget and not a splitter
class EyeBlinkingExtraction(QtWidgets.QSplitter, config.Config):
@@ -110,7 +156,7 @@ def __init__(self, parent):
self.scatter_l_part = self.graph.add_scatter()
self.scatter_r_part = self.graph.add_scatter()
- # UI elements
+ # UI elements
self.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.setAcceptDrops(True)
@@ -147,7 +193,7 @@ def __init__(self, parent):
# second tab is the text information
self.table_summary = jwidgets.JTableSummary()
-
+
self.graph_summary_visual = pg.GraphicsLayoutWidget()
self.summary_visual = pg.ViewBox(invertY=True, lockAspect=True, enableMenu=True, enableMouse=True)
self.summary_visual_image = pg.ImageItem()
@@ -192,8 +238,8 @@ def __init__(self, parent):
self.box_settings = QtWidgets.QGroupBox("Algorithm Settings")
# dont make the groupbox changeable in height
self.box_settings.setMinimumHeight(200)
- self.set_algo = QtWidgets.QFormLayout()
-
+ self.set_algo = QtWidgets.QGridLayout()
+
local = QtCore.QLocale(QtCore.QLocale.Language.English, QtCore.QLocale.Country.UnitedStates)
doulbe_validator = QtGui.QDoubleValidator()
doulbe_validator.setBottom(0)
@@ -205,45 +251,74 @@ def __init__(self, parent):
int_validator.setBottom(0)
int_validator.setLocale(local)
+ extraction_help_button = QtWidgets.QPushButton("Eye Blinking Extraction Help Description")
+ extraction_help_button.clicked.connect(lambda: QMessageBox.information(None, "Help", blinking.HELP_DESCRIPTION))
+ self.set_algo.addWidget(extraction_help_button, 0, 0, 1, 3)
+
le_minimum_distance = QtWidgets.QLineEdit()
le_minimum_distance.setValidator(int_validator)
self.add_handler("min_dist", le_minimum_distance, mapper=I2S, default=50)
- self.set_algo.addRow("Minimum Distance", le_minimum_distance)
+
+ self.set_algo.addWidget(QLabel("Minimum Distance"), 1, 0)
+ self.set_algo.addWidget(le_minimum_distance, 1, 1)
+ self.set_algo.addWidget(create_help_button("Minimum Distance: The minimum distance between two peaks in frames. Rec: 10@30FPS, 50@240FPS"), 1, 2)
le_minimum_prominence = QtWidgets.QLineEdit()
le_minimum_prominence.setValidator(doulbe_validator)
self.add_handler("min_prominence", le_minimum_prominence, mapper=F2S, default=0.1)
- self.set_algo.addRow("Minimum Prominence", le_minimum_prominence)
+ self.set_algo.addWidget(QLabel("Minimum Prominence"), 2, 0)
+ self.set_algo.addWidget(le_minimum_prominence, 2, 1)
+ self.set_algo.addWidget(create_help_button("Minimum Prominence: The minimum prominence of a peak in EAR score. Rec: 0.1"), 2, 2)
+
le_minimum_internal_width = QtWidgets.QLineEdit()
le_minimum_internal_width.setValidator(int_validator)
self.add_handler("min_width", le_minimum_internal_width, mapper=I2S, default=10)
- self.set_algo.addRow("Mininum Internal Width", le_minimum_internal_width)
+
+ self.set_algo.addWidget(QLabel("Minimum Internal Width"), 3, 0)
+ self.set_algo.addWidget(le_minimum_internal_width, 3, 1)
+ self.set_algo.addWidget(create_help_button("Minimum Internal Width: The minimum width of a peak in frames. Rec: 4@30FPS, 20@240FPS"), 3, 2)
le_maximum_internal_width = QtWidgets.QLineEdit()
le_maximum_internal_width.setValidator(int_validator)
self.add_handler("max_width", le_maximum_internal_width, mapper=I2S, default=100)
- self.set_algo.addRow("Maximum Internal Width", le_maximum_internal_width)
+
+ self.set_algo.addWidget(QLabel("Maximum Internal Width"), 4, 0)
+ self.set_algo.addWidget(le_maximum_internal_width, 4, 1)
+ self.set_algo.addWidget(create_help_button("Maximum Internal Width: The maximum width of a peak in frames. Rec: 20@30FPS, 100@240FPS"), 4, 2)
le_maximum_matching_dist = QtWidgets.QLineEdit()
le_maximum_matching_dist.setValidator(int_validator)
self.add_handler("maximum_matching_dist", le_maximum_matching_dist, mapper=I2S, default=30)
- self.set_algo.addRow("Maximum Matching Distance", le_maximum_matching_dist)
+
+ self.set_algo.addWidget(QLabel("Maximum Matching Distance"), 5, 0)
+ self.set_algo.addWidget(le_maximum_matching_dist, 5, 1)
+ self.set_algo.addWidget(create_help_button("Maximum Matching Distance: The maximum distance between two peaks to be matched in frames. Rec: 15@30FPS, 30@240FPS"), 5, 2)
le_partial_threshold_left = QtWidgets.QLineEdit()
self.add_handler("partial_threshold_l", le_partial_threshold_left, default="auto")
- self.set_algo.addRow("Partial Threshold Left", le_partial_threshold_left)
+
+ self.set_algo.addWidget(QLabel("Partial Threshold Left"), 6, 0)
+ self.set_algo.addWidget(le_partial_threshold_left, 6, 1)
+ self.set_algo.addWidget(create_help_button("Partial Threshold Left: The threshold for a partial blink in EAR score either 'auto' or a float number. Rec: 0.18"), 6, 2)
+
le_partial_threshold_right = QtWidgets.QLineEdit()
self.add_handler("partial_threshold_r", le_partial_threshold_right, default="auto")
- self.set_algo.addRow("Partial Threshold Right", le_partial_threshold_right)
+ self.set_algo.addWidget(QLabel("Partial Threshold Right"), 7, 0)
+ self.set_algo.addWidget(le_partial_threshold_right, 7, 1)
+ self.set_algo.addWidget(create_help_button("Partial Threshold Right: The threshold for a partial blink in EAR score either 'auto' or a float number. Rec: 0.18"), 7, 2)
+
# TODO this value is not saved in the config!
self.cb_video_fps = QtWidgets.QComboBox()
self.cb_video_fps.addItems(["24", "30", "60", "120", "240"])
self.cb_video_fps.setCurrentIndex(4)
self.cb_video_fps.currentIndexChanged.connect(self.compute_graph_axis)
- self.set_algo.addRow("Video FPS", self.cb_video_fps)
+ self.set_algo.addWidget(QLabel("Video FPS"), 8, 0)
+ self.set_algo.addWidget(self.cb_video_fps, 8, 1)
+ self.set_algo.addWidget(create_help_button("Video FPS: The frames per second of the video."), 8, 2)
+
box_smooth = QtWidgets.QGroupBox("Smoothing")
box_smooth.setCheckable(True)
self.add_handler("smooth", box_smooth)
@@ -252,16 +327,17 @@ def __init__(self, parent):
le_smooth_size = QtWidgets.QLineEdit()
le_smooth_size.setValidator(int_validator)
- self.add_handler("smooth_size", le_smooth_size, mapper=I2S, default=91)
+ self.add_handler("smooth_size", le_smooth_size, mapper=I2S, default=7)
box_smooth_layout.addRow("Window Size", le_smooth_size)
-
+
le_smooth_poly = QtWidgets.QLineEdit()
le_smooth_poly.setValidator(int_validator)
- self.add_handler("smooth_poly", le_smooth_poly, mapper=I2S, default=5)
+ self.add_handler("smooth_poly", le_smooth_poly, mapper=I2S, default=3)
box_smooth_layout.addRow("Polynomial Degree", le_smooth_poly)
- self.set_algo.addRow(box_smooth)
-
+ self.set_algo.addWidget(box_smooth, 9, 0, 1, 2)
+ self.set_algo.addWidget(create_help_button("Smoothing: The smoothing of the EAR data. Rec: Window Size: 7, Polynomial Degree: 3"), 9, 2)
+
# Visual Settings #
self.box_visuals = QtWidgets.QGroupBox("Graph Control")
self.set_visuals = QtWidgets.QFormLayout()
@@ -272,7 +348,7 @@ def __init__(self, parent):
self.cb_as_time.stateChanged.connect(self.compute_graph_axis)
btn_reset_graph = QtWidgets.QPushButton(qta.icon("msc.refresh"), "Reset Graph Y Range")
- btn_reset_graph.clicked.connect(lambda: self.graph.setYRange(0, 1))
+ btn_reset_graph.clicked.connect(lambda: self.graph.setYRange(-0.5, 1))
self.set_visuals.addRow(btn_reset_graph)
btn_reset_view = QtWidgets.QPushButton(qta.icon("msc.refresh"), "View Full Graph")
@@ -282,7 +358,7 @@ def __init__(self, parent):
# Export Settings #
self.overwrite_export = QtWidgets.QCheckBox("Overwrite Existing File")
self.add_handler("overwrite_export", self.overwrite_export, default=True)
-
+
self.format_export = QtWidgets.QComboBox()
self.format_export.addItems(["CSV", "Excel"])
self.format_export.setCurrentIndex(0)
@@ -300,7 +376,7 @@ def __init__(self, parent):
self.layout_settings.addWidget(self.la_current_file)
self.layout_settings.addWidget(self.face_preview, alignment=QtCore.Qt.AlignmentFlag.AlignCenter)
self.layout_settings.addWidget(jwidgets.JHLine())
-
+
self.layout_settings.addWidget(QtWidgets.QLabel("Left Eye"))
self.layout_settings.addWidget(self.comb_ear_l)
self.layout_settings.addWidget(QtWidgets.QLabel("Right Eye"))
@@ -330,7 +406,7 @@ def __init__(self, parent):
self.disable_column_selection()
self.disable_algorithm()
self.disable_export()
-
+
def get_selected_fps(self) -> int:
"""
Get the selected frames per second (fps) from the video fps combo box.
@@ -411,7 +487,7 @@ def select_column_left(self, index: int) -> None:
"""
if self.data_frame is None or self.data_frame_columns is None:
return
-
+
self.raw_ear_l = self.data_frame[self.data_frame_columns[index]].to_numpy()
self.update_plot_raw()
self.disable_export()
@@ -515,22 +591,19 @@ def extract_blinks(self) -> None:
None
"""
self.progress.setRange(0, 100)
-
self.progress.setValue(0)
+
+ if not self.validate_compute_parameters():
+ return
+ self.progress.setValue(30)
+
if not self.compute_intervals():
return
self.progress.setValue(60)
if not self.plot_intervals():
return
- self.progress.setValue(80)
-
- if self.blinking_l is None or self.blinking_r is None:
- logger.error("Somehow the blinking data frames are None")
- return
- if self.blinking_matched is None:
- logger.error("Somehow the matched blinking data frame is None")
- return
+ self.progress.setValue(90)
self.table_matched.set_data(self.blinking_matched)
self.progress.setValue(100)
@@ -538,88 +611,119 @@ def extract_blinks(self) -> None:
self.enable_export()
self.tab_widget_results.setCurrentIndex(0)
- def compute_intervals(self) -> None:
+ def validate_compute_parameters(self) -> bool:
"""
- Computes the intervals for eye blinking extraction based on the provided settings.
+ Validate the parameters for computing the intervals for eye blinking extraction.
Returns:
- None
-
- Raises:
- AssertionError: If the data frame or data frame columns are None.
- AssertionError: If the raw ear right or raw ear left are None.
- ValueError: If the same column is selected for both eyes.
- ValueError: If the blinking data frames cannot be matched.
-
+ bool: True if the parameters are valid, False otherwise.
"""
+ # check if the column selection index are not the same
+ if self.comb_ear_l.currentIndex() == self.comb_ear_r.currentIndex():
+ logger.error("The same column is selected for both eyes")
+ QMessageBox.critical("Blinking Extraction Error", "Both EAR columns are the same! Please select different columns and try again",)
+ return False
+
def validate_setting(setting_name: str) -> tuple[bool, int | float]:
try:
- value = self.get(setting_name)
+ _ = self.get(setting_name)
except ValueError:
logger.error("Error while validating the settings", setting=setting_name)
- jwidgets.JDialogWarn("Blinking Extraction Error", f"The setting {setting_name} is not a valid input.", "Please change your settings and try again")
- return False, None
- return True, value
+ QMessageBox.critical(None, "Blinking Extraction", f"The setting {setting_name} is not a valid input. Please change your settings and try again")
+ return False
+ return True
- # check if the column selection index are not the same
- if self.comb_ear_l.currentIndex() == self.comb_ear_r.currentIndex():
- logger.error("The same column is selected for both eyes")
- jwidgets.JDialogWarn("Blinking Extraction Error", "Both EAR columns are the same!", "Please select different columns and try again",)
+ if not validate_setting("partial_threshold_l"):
return False
-
- succ, partial_threshold_l = validate_setting("partial_threshold_l")
- if not succ:
+ if not validate_setting("partial_threshold_r"):
return False
- succ, partial_threshold_r = validate_setting("partial_threshold_r")
- if not succ:
+ if not validate_setting("min_dist"):
return False
- succ, minimum_distance = validate_setting("min_dist")
- if not succ:
+ if not validate_setting("min_prominence"):
return False
- succ, minimum_prominence = validate_setting("min_prominence")
- if not succ:
+ if not validate_setting("min_width"):
return False
- succ, minimum_internal_width = validate_setting("min_width")
- if not succ:
+ if not validate_setting("maximum_matching_dist"):
return False
- succ, maximum_matching_dist = validate_setting("maximum_matching_dist")
- if not succ:
+ if not validate_setting("max_width"):
return False
- succ, maximum_internal_width = validate_setting("max_width")
- if not succ:
+ if not validate_setting("smooth_size"):
return False
- succ, smooth_size = validate_setting("smooth_size")
- if not succ:
+ if not validate_setting("smooth_poly"):
return False
- succ, smooth_poly = validate_setting("smooth_poly")
- if not succ:
+
+ if (self.get("partial_threshold_l") == "auto" and self.get("partial_threshold_r") != "auto") or (
+ self.get("partial_threshold_l") != "auto" and self.get("partial_threshold_r") == "auto"):
+ QMessageBox.critical(None, "Blinking Extraction Warning", "Both partial thresholds need to be set to 'auto' or a value")
return False
- self.ear_l = blinking.smooth(self.raw_ear_l, smooth_size, smooth_poly) if self.get("smooth") else self.raw_ear_l
- self.ear_r = blinking.smooth(self.raw_ear_r, smooth_size, smooth_poly) if self.get("smooth") else self.raw_ear_r
+ return True
+
+ def compute_intervals(self) -> bool:
+ """
+ Computes the intervals for eye blinking extraction based on the provided settings.
+ Returns:
+ bool: True if the computation is successful, False otherwise.
+ """
+ try:
+ self.ear_l = blinking.smooth(self.raw_ear_l, self.get("smooth_size"), self.get("smooth_poly")) if self.get("smooth") else self.raw_ear_l
+ self.ear_r = blinking.smooth(self.raw_ear_r, self.get("smooth_size"), self.get("smooth_poly")) if self.get("smooth") else self.raw_ear_r
+ except Exception as e:
+ logger.error("Error while smoothing the EAR data", error=e)
+ QMessageBox.critical(None, "Blinking Extraction Error", f"The EAR data could not be smoothed. {e}")
+ return False
self.progress.setValue(40)
# if only one is set to auto, inform the user
- if (partial_threshold_l == "auto" and partial_threshold_r != "auto") or (partial_threshold_l != "auto" and partial_threshold_r == "auto"):
- jwidgets.JDialogWarn(
- "Blinking Extraction Warning",
- "Both partial thresholds are set to 'auto'",
- "This is not recommended, please change your settings and try again"
+ partial_threshold_l = "auto" if self.get("partial_threshold_l") == "auto" else float(self.get("partial_threshold_l"))
+ partial_threshold_r = "auto" if self.get("partial_threshold_r") == "auto" else float(self.get("partial_threshold_r"))
+
+ try:
+ min_dist = int(self.get("min_dist"))
+ min_prom = float(self.get("min_prominence"))
+ min_int_width = int(self.get("min_width"))
+ max_int_width = int(self.get("max_width"))
+
+ self.blinking_l, self.comp_partial_threshold_l = blinking.peaks(
+ time_series=self.ear_l,
+ minimum_distance=min_dist,
+ minimum_prominence=min_prom,
+ minimum_internal_width=min_int_width,
+ maximum_internal_width=max_int_width,
+ partial_threshold=partial_threshold_l
)
+ self.blinking_r, self.comp_partial_threshold_r = blinking.peaks(
+ time_series=self.ear_r,
+ minimum_distance=min_dist,
+ minimum_prominence=min_prom,
+ minimum_internal_width=min_int_width,
+ maximum_internal_width=max_int_width,
+ partial_threshold=partial_threshold_r
+ )
+ except Exception as e:
+ logger.error("Error while computing the intervals for eye blinking extraction", error=e)
+ QMessageBox.critical(None, "Error Blinking Extraction", f"Blinking Extraction Warning Error: {e}")
return False
+
+ if self.comp_partial_threshold_l is np.nan or self.comp_partial_threshold_r is np.nan:
+ QMessageBox.information(None, "Blinking Extraction Information", "We could not compute a automatic threshold based on the data. Continued with default `complete` label or run with sepecific thresholds. We recommend 0.18 for partial blinks.")
+ self.progress.setValue(50)
- partial_threshold_l = "auto" if partial_threshold_l == "auto" else float(partial_threshold_l)
- partial_threshold_r = "auto" if partial_threshold_r == "auto" else float(partial_threshold_r)
-
- self.blinking_l, self.comp_partial_threshold_l = blinking.peaks(self.ear_l, minimum_distance, minimum_prominence, minimum_internal_width, maximum_internal_width, partial_threshold_l)
- self.blinking_r, self.comp_partial_threshold_r = blinking.peaks(self.ear_r, minimum_distance, minimum_prominence, minimum_internal_width, maximum_internal_width, partial_threshold_r)
+ # check if the blinking data frames are empty
+ if self.blinking_l.empty or self.blinking_r.empty:
+ QMessageBox.warning(None, "Blinking Extraction Warning", "No blinks found in the data. Please check the data or settings and try again.")
+ return False
try:
- self.blinking_matched = blinking.match(self.blinking_l, self.blinking_r, tolerance=maximum_matching_dist)
+ self.blinking_matched = blinking.match(
+ blinking_l=self.blinking_l,
+ blinking_r=self.blinking_r,
+ tolerance=self.get("maximum_matching_dist")
+ )
except ValueError as e:
logger.error("Error while matching the blinking data frames", error=e)
- jwidgets.JDialogWarn( "Blinking Extraction Error", "The blinking could not be matched, likely none found", "Please change your settings and try again")
+ QMessageBox.critical("Blinking Extraction Error", "The blinking could not be matched, likely none found")
return False
return True
@@ -632,34 +736,39 @@ def plot_intervals(self) -> bool:
"""
if self.blinking_l is None or self.blinking_r is None:
return False
-
- self.curve_l.clear()
- self.curve_r.clear()
- self.curve_l.setData(self.ear_l)
- self.curve_r.setData(self.ear_r)
- # TODO add some kind of settings for the colors
- self.scatter_l_comp.clear()
- self.scatter_r_comp.clear()
- self.scatter_l_part.clear()
- self.scatter_r_part.clear()
-
- # get where the complete blinks are
- x = self.blinking_l[self.blinking_l["blink_type"] == "complete"]["apex_frame"].to_numpy()
- y = self.blinking_l[self.blinking_l["blink_type"] == "complete"]["ear_score"].to_numpy()
- self.scatter_l_comp.setData(x=x,y=y,symbol="o", pen={"color": "#00F", "width": 2})
- x = self.blinking_r[self.blinking_r["blink_type"] == "complete"]["apex_frame"].to_numpy()
- y = self.blinking_r[self.blinking_r["blink_type"] == "complete"]["ear_score"].to_numpy()
- self.scatter_r_comp.setData(x=x,y=y,symbol="o", pen={"color": "#F00", "width": 2})
-
- # get where the partial blinks are
- x = self.blinking_l[self.blinking_l["blink_type"] == "partial"]["apex_frame"].to_numpy()
- y = self.blinking_l[self.blinking_l["blink_type"] == "partial"]["ear_score"].to_numpy()
- self.scatter_l_part.setData(x=x,y=y, symbol="t", pen={"color": "#00F", "width": 2})
- x = self.blinking_r[self.blinking_r["blink_type"] == "partial"]["apex_frame"].to_numpy()
- y = self.blinking_r[self.blinking_r["blink_type"] == "partial"]["ear_score"].to_numpy()
- self.scatter_r_part.setData(x=x,y=y, symbol="t", pen={"color": "#F00", "width": 2})
-
+ try:
+ self.curve_l.clear()
+ self.curve_r.clear()
+ self.curve_l.setData(self.ear_l)
+ self.curve_r.setData(self.ear_r)
+
+ # TODO add some kind of settings for the colors
+ self.scatter_l_comp.clear()
+ self.scatter_r_comp.clear()
+ self.scatter_l_part.clear()
+ self.scatter_r_part.clear()
+
+ # get where the complete blinks are
+ x = self.blinking_l[self.blinking_l["blink_type"] == "complete"]["apex_frame"].to_numpy()
+ y = self.blinking_l[self.blinking_l["blink_type"] == "complete"]["ear_score"].to_numpy()
+ self.scatter_l_comp.setData(x=x,y=y,symbol="o", pen={"color": "#00F", "width": 2})
+ x = self.blinking_r[self.blinking_r["blink_type"] == "complete"]["apex_frame"].to_numpy()
+ y = self.blinking_r[self.blinking_r["blink_type"] == "complete"]["ear_score"].to_numpy()
+ self.scatter_r_comp.setData(x=x,y=y,symbol="o", pen={"color": "#F00", "width": 2})
+
+ # get where the partial blinks are
+ x = self.blinking_l[self.blinking_l["blink_type"] == "partial"]["apex_frame"].to_numpy()
+ y = self.blinking_l[self.blinking_l["blink_type"] == "partial"]["ear_score"].to_numpy()
+ self.scatter_l_part.setData(x=x,y=y, symbol="t", pen={"color": "#00F", "width": 2})
+ x = self.blinking_r[self.blinking_r["blink_type"] == "partial"]["apex_frame"].to_numpy()
+ y = self.blinking_r[self.blinking_r["blink_type"] == "partial"]["ear_score"].to_numpy()
+ self.scatter_r_part.setData(x=x,y=y, symbol="t", pen={"color": "#F00", "width": 2})
+ except Exception as e:
+ logger.error("Error while plotting the blinking intervals", error=e)
+ QMessageBox.critical(None, "Blinking Plotting Error", f"The blinking intervals could not be plotted. {e}")
+ return False
+
return True
def clear_on_new_file(self) -> None:
@@ -687,7 +796,7 @@ def clear_on_new_file(self) -> None:
self.scatter_r_part.clear()
self.table_summary.reset()
-
+
self.disable_column_selection()
self.disable_algorithm()
self.disable_export()
@@ -717,6 +826,8 @@ def highlight_blink(self, index: int) -> None:
frame_idx = min(frame_left, frame_right)
# show 1 second before and after the blink
self.graph.setXRange(frame_idx - self.get_selected_fps(), frame_idx + self.get_selected_fps())
+
+ logger.info("Highlighting blink", index=index, frame_idx=frame_idx)
self.face_preview.set_frame(frame_idx)
# summary of the results
@@ -735,11 +846,11 @@ def compute_summary(self) -> None:
)
self.table_summary.set_data(self.blinking_summary)
logger.info("Summary computed")
-
+
image = blinking.visualize(self.blinking_matched, fps=fps)
self.summary_visual_image.setImage(image)
logger.info("Visual summary computed")
-
+
self.tab_widget_results.setCurrentIndex(1)
# saving of the results
@@ -785,7 +896,7 @@ def save_results(self) -> None:
# TODO give user feedback that saving was successful
logger.info("Saving blinking finished")
-
+
## general widget functions
def shut_down(self) -> None:
"""
@@ -843,7 +954,7 @@ def dropEvent(self, event: QtGui.QDropEvent):
if file.suffix.lower() == ".csv":
self.load_file(file)
return
-
+
logger.info("User dropped invalid file", widget=self)
## enabling for logic flow
@@ -871,4 +982,4 @@ def enable_export(self) -> None:
def disable_export(self) -> None:
self.btn_eprt.setEnabled(False)
self.btn_summ.setEnabled(False)
- self.format_export.setEnabled(False)
\ No newline at end of file
+ self.format_export.setEnabled(False)
diff --git a/frontend/ui_facial_feature_extraction.py b/frontend/ui_facial_feature_extraction.py
index 1636647..8257d9f 100644
--- a/frontend/ui_facial_feature_extraction.py
+++ b/frontend/ui_facial_feature_extraction.py
@@ -159,7 +159,7 @@ def __init__(self, parent):
self.la_current_file.setWordWrap(True)
self.pb_anal = self.parent().progress_bar # type: ignore # TODO: fix this as JeFaPaTo cannot be imported from here...
- self.skip_frame = QtWidgets.QSpinBox()
+ self.update_delay = QtWidgets.QSpinBox()
self.auto_save = QtWidgets.QCheckBox("Auto-Save")
self.auto_save.setToolTip("Save the extracted data automatically after the analysis is finished.")
@@ -167,6 +167,22 @@ def __init__(self, parent):
self.use_bbox = QtWidgets.QCheckBox("Use Bounding Box")
self.use_bbox.setToolTip("Use the bounding box to extract the landmarks.")
+ self.rotate_group = QtWidgets.QGroupBox("Rotate")
+ self.rotate_group.setLayout(QtWidgets.QVBoxLayout())
+
+ self.rotate_none = QtWidgets.QRadioButton("None")
+ self.rotate_90 = QtWidgets.QRadioButton("90")
+ self.rotate_m90 = QtWidgets.QRadioButton("-90")
+
+ self.rotate_none.setChecked(True)
+ self.rotate_group.layout().addWidget(self.rotate_none)
+ self.rotate_group.layout().addWidget(self.rotate_90)
+ self.rotate_group.layout().addWidget(self.rotate_m90)
+ self.current_rotation = "None"
+ self.rotate_none.toggled.connect(self.set_rotation)
+ self.rotate_90.toggled.connect(self.set_rotation)
+ self.rotate_m90.toggled.connect(self.set_rotation)
+
self.add_handler("auto_save", self.auto_save, default=True)
self.add_handler("use_bbox", self.use_bbox, default=True)
self.add_handler("auto_find_face", self.widget_frame.cb_auto_find, default=True)
@@ -191,9 +207,11 @@ def __init__(self, parent):
self.flayout_se.addRow(self.button_start)
self.flayout_se.addRow(self.bt_pause_resume)
self.flayout_se.addRow(self.button_stop)
+ self.flayout_se.addRow(self.rotate_group)
+
self.flayout_se.addRow(self.feature_group)
self.flayout_se.addRow(self.blends_shape_group)
- self.flayout_se.addRow("Graph Update Delay:", self.skip_frame)
+ self.flayout_se.addRow("Update Delay:", self.update_delay)
self.flayout_se.addRow(self.bt_reset_graph)
self.flayout_se.addRow(self.auto_save)
self.flayout_se.addRow(self.use_bbox)
@@ -215,8 +233,7 @@ def __init__(self, parent):
self.button_stop.clicked.connect(self.stop)
self.bt_pause_resume.clicked.connect(self.ea.toggle_pause)
- self.skip_frame.setRange(1, 20)
- self.skip_frame.setValue(1)
+ self.update_delay.setRange(1, 30)
# disable analyse button and check box
self.button_start.setDisabled(True)
@@ -231,6 +248,9 @@ def __init__(self, parent):
self.jefapato_signal_thread = JeFaPaToGUISignalThread(self)
self.ea.register_hooks(self.jefapato_signal_thread)
+ self.update_delay.valueChanged.connect(self.jefapato_signal_thread.set_update_interval)
+ self.update_delay.setValue(5)
+
self.jefapato_signal_thread.sig_updated_display.connect(self.sig_updated_display)
self.jefapato_signal_thread.sig_updated_feature.connect(self.sig_updated_feature)
self.jefapato_signal_thread.sig_processed_percentage.connect(self.sig_processed_percentage)
@@ -239,6 +259,15 @@ def __init__(self, parent):
self.jefapato_signal_thread.sig_resumed.connect(self.sig_resumed)
self.jefapato_signal_thread.sig_finished.connect(self.sig_finished)
self.jefapato_signal_thread.start()
+
+ def set_rotation(self):
+ if self.rotate_none.isChecked():
+ self.current_rotation = "None"
+ elif self.rotate_90.isChecked():
+ self.current_rotation = "90"
+ elif self.rotate_m90.isChecked():
+ self.current_rotation = "-90"
+ self.set_resource(self.video_resource)
def setup_graph(self) -> None:
logger.info("Setup graph for all features to plot", features=len(self.used_features_classes))
@@ -285,7 +314,7 @@ def start(self) -> None:
self.ea.set_features(self.used_features_classes)
rect = self.widget_frame.get_roi_rect() if self.use_bbox.isChecked() else None
- self.ea.clean_start(rect)
+ self.ea.clean_start(rect, self.current_rotation)
def stop(self) -> None:
self.ea.stop()
@@ -362,7 +391,7 @@ def sig_updated_feature(self, feature_data: dict[str, Any]) -> None:
self.plot_data[feature_name][:-1] = self.plot_data[feature_name][1:]
self.plot_data[feature_name][-1] = feature_value
- if self.update_count % self.skip_frame.value() == 0:
+ if self.update_count % self.update_delay.value() == 0:
self.plot_item[feature_name].setData(self.plot_data[feature_name])
def load_video(self):
@@ -371,7 +400,7 @@ def load_video(self):
parent=self,
caption="Select video file",
directory=".",
- filter="Video Files (*.mp4 *.flv *.ts *.mts *.avi *.mov)",
+ filter="Video Files (*.mp4 *.flv *.ts *.mts *.avi *.mov *.wmv)",
)
if fileName == "":
@@ -404,7 +433,7 @@ def set_resource(self, resource: Path | int) -> bool:
else:
self.la_current_file.setText("File: Live Webcam Feed")
- success, frame = self.ea.prepare_video_resource(self.video_resource)
+ success, frame = self.ea.prepare_video_resource(self.video_resource, self.current_rotation)
if success:
logger.info("Image was set", parent=self)
self.widget_frame.set_selection_image(frame)
@@ -454,7 +483,7 @@ def dropEvent(self, event: QtGui.QDropEvent):
file = files[0]
file = Path(file)
- if file.suffix.lower() not in [".mp4", ".flv", ".ts", ".mts", ".avi", ".mov"]:
+ if file.suffix.lower() not in [".mp4", ".flv", ".ts", ".mts", ".avi", ".mov", ".wmv"]:
logger.info("User dropped invalid file", widget=self)
return
self.set_resource(Path(file))
\ No newline at end of file
diff --git a/src/jefapato/blinking/__init__.py b/src/jefapato/blinking/__init__.py
index 182839c..848fed9 100644
--- a/src/jefapato/blinking/__init__.py
+++ b/src/jefapato/blinking/__init__.py
@@ -1,7 +1,61 @@
-__all__ = ["peaks", "smooth", "match", "summarize", "visualize", "load_ear_score", "save_results"]
+__all__ = ["peaks", "smooth", "match", "summarize", "visualize", "load_ear_score", "save_results", "HELP_DESCRIPTION"]
from jefapato.blinking.peaks import peaks
from jefapato.blinking.smooth import smooth
from jefapato.blinking.match import match
from jefapato.blinking.summary import summarize, visualize
-from jefapato.blinking.io import load_ear_score, save_results
\ No newline at end of file
+from jefapato.blinking.io import load_ear_score, save_results
+
+
+HELP_DESCRIPTION = """
+Recommended Extracton Settings for Eye Blinking
+
+
+Here we give some recommended settings for the extraction of eye blinking from EAR scores.
+These settings are based on the analysis of the EAR scores of a dataset of internal dataset, not yet published.
+
+
+
+The dataset was recorded at 30 and 240 FPS.
+The settings are divided into two groups, one for each FPS.
+These should be a good starting point for the extraction of eye blinking from EAR scores depending on the FPS of the video.
+
+
+
+The settings are the following:
+
+
+
+@30 FPS
+
+ - Minimum Distance: 10 Frames
+ - Minimum Prominence: 0.1 EAR Score
+ - Minimum Internal Width: 4 Frames
+ - Maximum Internal Width: 20 Frames
+ - Maximum Matching Distance: 15 Frames
+ - Partial Threshold Left: 0.18 EAR Score
+ - Partial Threshold Right: 0.18 EAR Score
+
+Smoothing
+
+ - Window Size: 7
+ - Polynomial Degree: 3
+
+
+
+@240 FPS
+
+ - Minimum Distance: 50 Frames
+ - Minimum Prominence: 0.1 EAR Score
+ - Minimum Internal Width: 20 Frames
+ - Maximum Internal Width: 100 Frames
+ - Maximum Matching Distance: 30 Frames
+ - Partial Threshold Left: 0.18 EAR Score
+ - Partial Threshold Right: 0.18 EAR Score
+
+Smoothing
+
+ - Window Size: 7
+ - Polynomial Degree: 3
+
+"""
\ No newline at end of file
diff --git a/src/jefapato/blinking/peaks.py b/src/jefapato/blinking/peaks.py
index 5cf2d74..d843b61 100644
--- a/src/jefapato/blinking/peaks.py
+++ b/src/jefapato/blinking/peaks.py
@@ -15,11 +15,20 @@ def otsu_thresholding(values: np.ndarray) -> float:
"""
# first remove all nans from the values
values = values[~np.isnan(values)]
+
+ # check that there are enough values for the calculation
+ if len(values) < 6:
+ return np.nan
+
th_range = np.sort(np.unique(values))[3:-3] # remove the first and last 3 values to avoid errors in the calculation
res = []
for th in th_range:
r = np.nansum([np.mean(cls) * np.var(values, where=cls) for cls in [values>=th, values th:
df.loc[index, 'blink_type'] = "complete"
else:
df.loc[index, 'blink_type'] = "partial"
-
return df, th
diff --git a/src/jefapato/blinking/smooth.py b/src/jefapato/blinking/smooth.py
index 1997b23..d1469f7 100644
--- a/src/jefapato/blinking/smooth.py
+++ b/src/jefapato/blinking/smooth.py
@@ -5,8 +5,12 @@
def smooth(time_series: np.ndarray, smooth_size:int=91, smooth_poly:int=4) -> np.ndarray:
- return signal.savgol_filter(
+ sig = signal.savgol_filter(
time_series,
window_length=smooth_size,
polyorder=smooth_poly,
)
+ # check all values to be 0 or 1
+ sig[sig < 0] = 0
+ sig[sig > 1] = 1
+ return sig
diff --git a/src/jefapato/blinking/summary.py b/src/jefapato/blinking/summary.py
index b3f2349..c52ff6b 100644
--- a/src/jefapato/blinking/summary.py
+++ b/src/jefapato/blinking/summary.py
@@ -132,6 +132,7 @@ def summarize(
partial_times_l = pd.to_datetime(partial_l["minute"], unit='m', errors="ignore")
partial_group_l = partial_l.groupby(partial_times_l.dt.minute)
+ i = 1
for i, row in enumerate(partial_group_l.count()["minute"], start=1):
statistics[f"Partial_Blinks_min{i:02d}_left"] = row
while i <= math.ceil(length_l_min):
@@ -141,9 +142,11 @@ def summarize(
partial_r["minute"] = partial_r["apex_frame_og"] / fps / 60
partial_times_r = pd.to_datetime(partial_r["minute"], unit='m', errors="ignore")
partial_group_r = partial_r.groupby(partial_times_r.dt.minute)
-
+
+ i = 1
for i, row in enumerate(partial_group_r.count()["minute"], start=1):
statistics[f"Partial_Blinks_min{i:02d}_right"] = row
+
while i <= math.ceil(length_r_min):
statistics[f"Partial_Blinks_min{i:02d}_right"] = 0
i += 1
diff --git a/src/jefapato/facial_features/features/ear_feature.py b/src/jefapato/facial_features/features/ear_feature.py
index aece25d..99d0c1c 100644
--- a/src/jefapato/facial_features/features/ear_feature.py
+++ b/src/jefapato/facial_features/features/ear_feature.py
@@ -12,7 +12,7 @@
logger = structlog.get_logger()
-def ear_score(eye: np.ndarray) -> float:
+def ear_score(eye: np.ndarray) -> tuple[float, bool]:
"""
Compute the EAR Score for eye landmarks
@@ -35,6 +35,7 @@ def ear_score(eye: np.ndarray) -> float:
Returns:
float: The computed EAR score, which should be between 0 and 1
+ bool: A flag indicating if the EAR score is valid
"""
if eye is None:
raise ValueError("eye must not be None")
@@ -43,22 +44,31 @@ def ear_score(eye: np.ndarray) -> float:
raise TypeError(f"eye must be a numpy array, but got {type(eye)}")
if eye.shape != (6, 2) and eye.shape != (6, 3): # allow for 3D landmarks
- raise ValueError(f"eye must be a 6x2 array, but got {eye.shape}")
+ raise ValueError(f"eye must be a 6x2 or 6x3 array, but got {eye.shape}")
# check that no value is negative
if np.any(eye < 0):
- raise ValueError(f"eye must not contain negative values, but got {eye}")
-
+ # This can be the case if parts of the face are not inside the image
+ # but the predictor tries to estimate the rough location.
+ # Thus we just log a warning and continue
+ logger.warning(f"Eye landmarks must not contain negative values, but got {eye}")
+
# dont forget the 0-index
A = distance.euclidean(eye[1], eye[5])
B = distance.euclidean(eye[2], eye[4])
C = distance.euclidean(eye[0], eye[3])
ratio = (A + B) / (2.0 * C)
- if ratio > 1.002: # allow for some rounding errors
- raise ValueError(f"EAR score must be between 0 and 1, but got {ratio}, check your landmarks order")
-
- return ratio
+ compute_valid = True
+ if ratio > 1.0:
+ logger.warning(f"EAR score must be between 0 and 1, but got {ratio}")
+ ratio = 1.0
+ compute_valid = False
+ if ratio < 0.0:
+ logger.warning(f"EAR score must be between 0 and 1, but got {ratio}")
+ ratio = 0.0
+ compute_valid = False
+ return ratio, compute_valid
@dataclasses.dataclass
@@ -158,8 +168,13 @@ def compute(self, features: np.ndarray, valid: bool) -> EAR_Data:
return EAR_Data(1.0, 1.0, False, lm_l, lm_r)
ear_valid = not (np.allclose(np.zeros_like(lm_l), lm_l) and np.allclose(np.zeros_like(lm_r), lm_r))
- ear_l = ear_score(lm_l) if ear_valid else 1.0
- ear_r = ear_score(lm_r) if ear_valid else 1.0
+ ear_l, ear_l_c = ear_score(lm_l)
+ ear_r, ear_r_c = ear_score(lm_r)
+
+ if not ear_l_c or not ear_r_c:
+ logger.warning(f"EAR score computation is not valid for left: {ear_l} and right: {ear_r}")
+
+ ear_valid = ear_valid and ear_l_c and ear_r_c
return EAR_Data(ear_l, ear_r, ear_valid, lm_l, lm_r)
@@ -192,6 +207,11 @@ def compute(self, features: np.ndarray, valid: bool) -> EAR_Data:
return EAR_Data(1.0, 1.0, False, lm_l, lm_r)
ear_valid = not (np.allclose(np.zeros_like(lm_l), lm_l) and np.allclose(np.zeros_like(lm_r), lm_r))
- ear_l = ear_score(lm_l) if ear_valid else 1.0
- ear_r = ear_score(lm_r) if ear_valid else 1.0
+ ear_l, ear_l_c = ear_score(lm_l)
+ ear_r, ear_r_c = ear_score(lm_r)
+
+ if not ear_l_c or not ear_r_c:
+ logger.warning(f"EAR score computation is not valid for left: {ear_l} and right: {ear_r}")
+
+ ear_valid = ear_valid and ear_l_c and ear_r_c
return EAR_Data(ear_l, ear_r, ear_valid, lm_l, lm_r)
\ No newline at end of file
diff --git a/src/jefapato/facial_features/landmark_analyser.py b/src/jefapato/facial_features/landmark_analyser.py
index c18882e..b044c4b 100644
--- a/src/jefapato/facial_features/landmark_analyser.py
+++ b/src/jefapato/facial_features/landmark_analyser.py
@@ -43,7 +43,7 @@ def __init__(self, max_ram_size: int = 4<<28):
self.pm = pluggy.PluginManager("analyser")
- def analysis_setup(self, bbox_slice: tuple[int, int, int, int] | None = None) -> bool:
+ def analysis_setup(self, bbox_slice: tuple[int, int, int, int] | None = None, rotation:str="None") -> bool:
"""
Sets up the analysis by initializing necessary components and calculating available resources.
@@ -73,7 +73,7 @@ def analysis_setup(self, bbox_slice: tuple[int, int, int, int] | None = None) ->
if bbox_slice is not None:
logger.info("Bounding box slice", bbox=bbox_slice)
- self.loader = VideoDataLoader(self.resource_interface.read, data_amount=self.data_amount, queue_maxsize=items_to_place)
+ self.loader = VideoDataLoader(self.resource_interface.read, data_amount=self.data_amount, queue_maxsize=items_to_place, rotation=rotation)
self.extractor = MediapipeLandmarkExtractor(data_queue=self.loader.data_queue, data_amount=self.data_amount, bbox_slice=bbox_slice)
self.extractor.register(self)
return True
@@ -200,7 +200,7 @@ def toggle_pause(self) -> None:
self.extractor.toggle_pause()
- def clean_start(self, bbox_slice: tuple[int, int, int, int] | None = None) -> None:
+ def clean_start(self, bbox_slice: tuple[int, int, int, int] | None = None, rotation:str = "None") -> None:
"""
Starts the landmark analysis process.
@@ -217,7 +217,7 @@ def clean_start(self, bbox_slice: tuple[int, int, int, int] | None = None) -> No
for m_name in self.feature_classes:
self.feature_data[m_name].clear()
- self.analysis_setup(bbox_slice=bbox_slice)
+ self.analysis_setup(bbox_slice=bbox_slice, rotation=rotation)
self.analysis_start()
def get_header(self) -> list[str]:
@@ -247,7 +247,7 @@ def __next__(self):
return row
- def prepare_video_resource(self, value: Path) -> tuple[bool, np.ndarray]:
+ def prepare_video_resource(self, value: Path, rotation: str = "None") -> tuple[bool, np.ndarray]:
self.video_resource = value
if not isinstance(self.video_resource, Path):
@@ -259,14 +259,23 @@ def prepare_video_resource(self, value: Path) -> tuple[bool, np.ndarray]:
if not self.video_resource.is_file():
raise ValueError(f"File {self.video_resource} is not a file.")
- if self.video_resource.suffix.lower() not in [".mp4", ".flv", ".ts", ".mts", ".avi", ".mov"]:
+ if self.video_resource.suffix.lower() not in [".mp4", ".flv", ".ts", ".mts", ".avi", ".mov", ".wmv"]:
raise ValueError(f"File {self.video_resource} is not a video file.")
self.resource_interface = cv2.VideoCapture(str(self.video_resource.absolute()))
self.data_amount = self.resource_interface.get(cv2.CAP_PROP_FRAME_COUNT)
success, image = self.resource_interface.read()
- return success, cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
+
+ if not success:
+ return success, None
+
+ image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
+ if rotation == "90":
+ image = cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE)
+ elif rotation == "-90":
+ image = cv2.rotate(image, cv2.ROTATE_90_COUNTERCLOCKWISE)
+ return success, image
def get_fps(self) -> float:
"""
diff --git a/src/jefapato/facial_features/mediapipe_landmark_extractor.py b/src/jefapato/facial_features/mediapipe_landmark_extractor.py
index 736bdea..6c5c459 100644
--- a/src/jefapato/facial_features/mediapipe_landmark_extractor.py
+++ b/src/jefapato/facial_features/mediapipe_landmark_extractor.py
@@ -29,6 +29,7 @@ def __init__(
self.stopped = False
self.paused = False
self.sleep_duration = sleep_duration
+ self.processing_per_second: int = 0
self.pm = pluggy.PluginManager("Extractor")
diff --git a/src/jefapato/facial_features/video_data_loader.py b/src/jefapato/facial_features/video_data_loader.py
index 54ba9b5..3bcb2e6 100644
--- a/src/jefapato/facial_features/video_data_loader.py
+++ b/src/jefapato/facial_features/video_data_loader.py
@@ -18,7 +18,8 @@ def __init__(
self,
next_item_func: Callable,
data_amount: int | None = None,
- queue_maxsize: int = (1 << 10)
+ queue_maxsize: int = (1 << 10),
+ rotation: str = "None",
) -> None:
super().__init__(daemon=True)
assert data_amount is not None, "data_amount must be set"
@@ -28,9 +29,14 @@ def __init__(
self.data_queue: queue.Queue[InputQueueItem] = queue.Queue(maxsize=queue_maxsize)
self.stopped = False
self.data_amount = data_amount
-
- self.processing_per_second: int = 0
+ self.processing_per_second: float = 0
+ if rotation == "None":
+ self.rotation_fc = lambda x: x
+ elif rotation == "90":
+ self.rotation_fc = lambda x: cv2.rotate(x, cv2.ROTATE_90_CLOCKWISE)
+ elif rotation == "-90":
+ self.rotation_fc = lambda x: cv2.rotate(x, cv2.ROTATE_90_COUNTERCLOCKWISE)
def run(self):
logger.info("Loader Thread", state="starting", object=self)
@@ -66,6 +72,7 @@ def run(self):
self.stopped = True
break
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
+ frame = self.rotation_fc(frame)
self.data_queue.put(InputQueueItem(frame=frame, timestamp=c_time))
processed_p_sec += 1
else:
diff --git a/tests/files/blinking/blinking_30FPS.csv b/tests/files/blinking/blinking_30FPS.csv
new file mode 100644
index 0000000..e975fde
--- /dev/null
+++ b/tests/files/blinking/blinking_30FPS.csv
@@ -0,0 +1,251 @@
+frame,EAR2D6_l,EAR2D6_r,EAR2D6_valid,BS_Valid
+0, 0.30839515, 0.31717056,True,True
+1, 0.30697849, 0.31643425,True,True
+2, 0.31780323, 0.32533049,True,True
+3, 0.31657635, 0.31336477,True,True
+4, 0.31764210, 0.31694362,True,True
+5, 0.31386926, 0.31409277,True,True
+6, 0.31484655, 0.31612779,True,True
+7, 0.30915708, 0.31312242,True,True
+8, 0.30693714, 0.31124881,True,True
+9, 0.30799023, 0.31312242,True,True
+10, 0.30571419, 0.30799125,True,True
+11, 0.30042486, 0.30502849,True,True
+12, 0.28607607, 0.30721214,True,True
+13, 0.30121833, 0.30183604,True,True
+14, 0.29187137, 0.30210629,True,True
+15, 0.29767902, 0.29821654,True,True
+16, 0.29061937, 0.30378166,True,True
+17, 0.29875644, 0.29564100,True,True
+18, 0.29875644, 0.30551011,True,True
+19, 0.30571419, 0.29564100,True,True
+20, 0.29262141, 0.29620622,True,True
+21, 0.29262141, 0.29330723,True,True
+22, 0.27219442, 0.27695657,True,True
+23, 0.01769842, 0.01282979,True,True
+24, 0.01231288, 0.02070684,True,True
+25, 0.02101940, 0.01370297,True,True
+26, 0.04426898, 0.02246624,True,True
+27, 0.03302003, 0.00803064,True,True
+28, 0.07497124, 0.02872804,True,True
+29, 0.19807905, 0.19991081,True,True
+30, 0.23124061, 0.24272208,True,True
+31, 0.25739383, 0.26800041,True,True
+32, 0.26600419, 0.27675620,True,True
+33, 0.26620216, 0.28076742,True,True
+34, 0.27219442, 0.28631641,True,True
+35, 0.27817795, 0.28247069,True,True
+36, 0.27817795, 0.28490235,True,True
+37, 0.27819434, 0.28490235,True,True
+38, 0.28417787, 0.29053216,True,True
+39, 0.28076650, 0.29130211,True,True
+40, 0.29126256, 0.29442629,True,True
+41, 0.29036380, 0.29442629,True,True
+42, 0.28054342, 0.28490235,True,True
+43, 0.28688787, 0.29672592,True,True
+44, 0.28076650, 0.29109611,True,True
+45, 0.28670108, 0.28816167,True,True
+46, 0.28076650, 0.28816167,True,True
+47, 0.28417787, 0.29109611,True,True
+48, 0.28784117, 0.29340709,True,True
+49, 0.28790582, 0.29821654,True,True
+50, 0.28435252, 0.29672592,True,True
+51, 0.28076650, 0.29055364,True,True
+52, 0.06502978, 0.03658265,True,True
+53, 0.02024917, 0.02625834,True,True
+54, 0.02000166, 0.01876873,True,True
+55, 0.00874105, 0.02432521,True,True
+56, 0.01492190, 0.02768382,True,True
+57, 0.00863546, 0.02092892,True,True
+58, 0.01492190, 0.03351722,True,True
+59, 0.01236170, 0.01641662,True,True
+60, 0.01233816, 0.01856745,True,True
+61, 0.01831858, 0.00802237,True,True
+62, 0.04230399, 0.00000000,True,True
+63, 0.06181197, 0.02005528,True,True
+64, 0.20705129, 0.22071539,True,True
+65, 0.24511024, 0.24825420,True,True
+66, 0.26281608, 0.27651996,True,True
+67, 0.27138363, 0.28679968,True,True
+68, 0.27138363, 0.29316770,True,True
+69, 0.29029085, 0.30401200,True,True
+70, 0.29152860, 0.30015060,True,True
+71, 0.29287058, 0.30957440,True,True
+72, 0.27435362, 0.29465200,True,True
+73, 0.27774988, 0.29391477,True,True
+74, 0.29281205, 0.29593631,True,True
+75, 0.28205807, 0.30210629,True,True
+76, 0.28360660, 0.29316770,True,True
+77, 0.28491334, 0.30566975,True,True
+78, 0.29736310, 0.29793630,True,True
+79, 0.28449054, 0.30401200,True,True
+80, 0.28346620, 0.30158417,True,True
+81, 0.28915019, 0.29647832,True,True
+82, 0.28346620, 0.28974773,True,True
+83, 0.29029085, 0.29873282,True,True
+84, 0.29520791, 0.29873282,True,True
+85, 0.29047551, 0.30129435,True,True
+86, 0.28481250, 0.29235676,True,True
+87, 0.29038721, 0.30075286,True,True
+88, 0.29399576, 0.29478969,True,True
+89, 0.28474855, 0.29793630,True,True
+90, 0.29544620, 0.29760003,True,True
+91, 0.29047551, 0.29761966,True,True
+92, 0.29734401, 0.30129435,True,True
+93, 0.30882459, 0.30856107,True,True
+94, 0.30317851, 0.30566975,True,True
+95, 0.29734401, 0.30210629,True,True
+96, 0.29985247, 0.30129435,True,True
+97, 0.29991155, 0.30691690,True,True
+98, 0.29411627, 0.30639529,True,True
+99, 0.29736310, 0.30210629,True,True
+100, 0.30554130, 0.32070147,True,True
+101, 0.30754054, 0.31882648,True,True
+102, 0.31910433, 0.32414189,True,True
+103, 0.28094941, 0.27651996,True,True
+104, 0.01744879, 0.02406710,True,True
+105, 0.02247274, 0.03177595,True,True
+106, 0.00860217, 0.03313757,True,True
+107, 0.03164379, 0.01356214,True,True
+108, 0.06768018, 0.01817901,True,True
+109, 0.20271529, 0.22393133,True,True
+110, 0.24316228, 0.25774618,True,True
+111, 0.26001681, 0.28631641,True,True
+112, 0.28056569, 0.28220608,True,True
+113, 0.28056569, 0.29362676,True,True
+114, 0.27485479, 0.29931613,True,True
+115, 0.28094941, 0.29305686,True,True
+116, 0.26910210, 0.28466462,True,True
+117, 0.27036253, 0.28789544,True,True
+118, 0.27151763, 0.27901948,True,True
+119, 0.27870788, 0.29593631,True,True
+120, 0.28456170, 0.29593631,True,True
+121, 0.28913736, 0.29388577,True,True
+122, 0.28790582, 0.30129435,True,True
+123, 0.29387780, 0.30158417,True,True
+124, 0.29047551, 0.30639529,True,True
+125, 0.29152860, 0.30639529,True,True
+126, 0.29387249, 0.30034817,True,True
+127, 0.29174260, 0.30349620,True,True
+128, 0.29174260, 0.30202917,True,True
+129, 0.29274450, 0.30152513,True,True
+130, 0.29876218, 0.30924539,True,True
+131, 0.28607607, 0.30349620,True,True
+132, 0.28933412, 0.30017115,True,True
+133, 0.29876218, 0.31084737,True,True
+134, 0.28156328, 0.30535200,True,True
+135, 0.29876218, 0.31084737,True,True
+136, 0.30084331, 0.30034817,True,True
+137, 0.28824583, 0.30265839,True,True
+138, 0.28947251, 0.29738223,True,True
+139, 0.28476367, 0.29465200,True,True
+140, 0.29399576, 0.30616180,True,True
+141, 0.28122135, 0.29793630,True,True
+142, 0.08696232, 0.07316529,True,True
+143, 0.00872440, 0.02460670,True,True
+144, 0.01941004, 0.02893588,True,True
+145, 0.02526354, 0.03793540,True,True
+146, 0.02328699, 0.04282244,True,True
+147, 0.01221239, 0.01796818,True,True
+148, 0.03546387, 0.00549417,True,True
+149, 0.11005832, 0.05299722,True,True
+150, 0.22507869, 0.22884677,True,True
+151, 0.24808096, 0.25126705,True,True
+152, 0.26451688, 0.28204309,True,True
+153, 0.26857695, 0.28416769,True,True
+154, 0.27301256, 0.28416769,True,True
+155, 0.27997872, 0.28442911,True,True
+156, 0.28101880, 0.28939994,True,True
+157, 0.27989908, 0.28838177,True,True
+158, 0.27870788, 0.29340709,True,True
+159, 0.29038721, 0.29316770,True,True
+160, 0.27761239, 0.28227340,True,True
+161, 0.26704718, 0.28760540,True,True
+162, 0.26704718, 0.28281947,True,True
+163, 0.26590579, 0.28760540,True,True
+164, 0.28326359, 0.28204309,True,True
+165, 0.27880359, 0.27729200,True,True
+166, 0.27286259, 0.28416769,True,True
+167, 0.26590579, 0.28416769,True,True
+168, 0.28248591, 0.28733513,True,True
+169, 0.27448633, 0.27867187,True,True
+170, 0.27566412, 0.28389907,True,True
+171, 0.27556948, 0.28442911,True,True
+172, 0.27870788, 0.28389907,True,True
+173, 0.27884592, 0.28416769,True,True
+174, 0.26715126, 0.28913396,True,True
+175, 0.27424381, 0.29465200,True,True
+176, 0.26278444, 0.28389907,True,True
+177, 0.27884592, 0.28122140,True,True
+178, 0.26965958, 0.28706944,True,True
+179, 0.27884592, 0.29031120,True,True
+180, 0.27556948, 0.28706944,True,True
+181, 0.28467151, 0.28132200,True,True
+182, 0.27435362, 0.28939994,True,True
+183, 0.25727224, 0.26536923,True,True
+184, 0.02088370, 0.01338259,True,True
+185, 0.01360123, 0.01368535,True,True
+186, 0.01218968, 0.02069220,True,True
+187, 0.01489348, 0.02813706,True,True
+188, 0.01208685, 0.01339907,True,True
+189, 0.06587889, 0.02260906,True,True
+190, 0.07325627, 0.03493840,True,True
+191, 0.21407690, 0.22462453,True,True
+192, 0.24230951, 0.24911082,True,True
+193, 0.26417941, 0.27670971,True,True
+194, 0.26573676, 0.27592677,True,True
+195, 0.27774988, 0.29235676,True,True
+196, 0.27448633, 0.28363814,True,True
+197, 0.26603749, 0.28363814,True,True
+198, 0.27894167, 0.28387229,True,True
+199, 0.27190170, 0.28493478,True,True
+200, 0.27448633, 0.28733513,True,True
+201, 0.27774988, 0.28883339,True,True
+202, 0.28933412, 0.29235676,True,True
+203, 0.28607607, 0.28915618,True,True
+204, 0.28593776, 0.29492306,True,True
+205, 0.28028817, 0.28966629,True,True
+206, 0.27566412, 0.28957076,True,True
+207, 0.27661347, 0.29143903,True,True
+208, 0.26603749, 0.28915618,True,True
+209, 0.27904043, 0.28913396,True,True
+210, 0.28499447, 0.29465200,True,True
+211, 0.27566412, 0.29813491,True,True
+212, 0.27674727, 0.29465200,True,True
+213, 0.27566412, 0.28363814,True,True
+214, 0.28607607, 0.29465200,True,True
+215, 0.27129853, 0.29194358,True,True
+216, 0.28810647, 0.29543364,True,True
+217, 0.28476367, 0.28671125,True,True
+218, 0.28132988, 0.29170131,True,True
+219, 0.28217403, 0.29220632,True,True
+220, 0.28364877, 0.30042672,True,True
+221, 0.28476367, 0.30304016,True,True
+222, 0.28378281, 0.29687768,True,True
+223, 0.28396498, 0.30566975,True,True
+224, 0.28387867, 0.30017115,True,True
+225, 0.29422187, 0.30233665,True,True
+226, 0.28378281, 0.30233665,True,True
+227, 0.28607607, 0.30616180,True,True
+228, 0.07306278, 0.04001991,True,True
+229, 0.01190308, 0.02002629,True,True
+230, 0.01767767, 0.01979643,True,True
+231, 0.02384842, 0.01097841,True,True
+232, 0.03500224, 0.01201562,True,True
+233, 0.14034599, 0.10153823,True,True
+234, 0.20675459, 0.22546911,True,True
+235, 0.24530257, 0.25126705,True,True
+236, 0.24239267, 0.26500531,True,True
+237, 0.26391243, 0.27287946,True,True
+238, 0.25075540, 0.28025274,True,True
+239, 0.27674727, 0.28389907,True,True
+240, 0.26921031, 0.29143903,True,True
+241, 0.27909436, 0.29714485,True,True
+242, 0.27323818, 0.28154177,True,True
+243, 0.27372611, 0.28974508,True,True
+244, 0.26667730, 0.28667322,True,True
+245, 0.27129853, 0.28688769,True,True
+246, 0.26921031, 0.28736231,True,True
+247, 0.27690214, 0.28432221,True,True
+248, 0.27806570, 0.28974508,True,True
+249, 0.26818388, 0.28227222,True,True
diff --git a/tests/files/test_1min.csv b/tests/files/test_1min.csv
new file mode 100644
index 0000000..dca5fc2
--- /dev/null
+++ b/tests/files/test_1min.csv
@@ -0,0 +1,1770 @@
+frame,EAR2D6_l,EAR2D6_r,EAR2D6_valid,BS_Valid
+0, 0.30799545, 0.28032574,True,True
+1, 0.32456826, 0.28984380,True,True
+2, 0.32122495, 0.28862193,True,True
+3, 0.32450826, 0.29079934,True,True
+4, 0.32450826, 0.29915607,True,True
+5, 0.32450826, 0.28957659,True,True
+6, 0.31844433, 0.28984380,True,True
+7, 0.31380176, 0.28984380,True,True
+8, 0.31305424, 0.30500184,True,True
+9, 0.31761871, 0.28957659,True,True
+10, 0.29833142, 0.28006730,True,True
+11, 0.29833142, 0.28581396,True,True
+12, 0.30799545, 0.29551837,True,True
+13, 0.29827408, 0.28984380,True,True
+14, 0.31173415, 0.28581396,True,True
+15, 0.30799545, 0.29454412,True,True
+16, 0.30950795, 0.29551837,True,True
+17, 0.31575879, 0.29116053,True,True
+18, 0.30956744, 0.28020945,True,True
+19, 0.30805465, 0.29016782,True,True
+20, 0.31510811, 0.29523517,True,True
+21, 0.32251440, 0.29523517,True,True
+22, 0.32251440, 0.29909700,True,True
+23, 0.32137794, 0.29079934,True,True
+24, 0.29845428, 0.28707951,True,True
+25, 0.28708921, 0.27577628,True,True
+26, 0.30805465, 0.27681827,True,True
+27, 0.31510811, 0.28581396,True,True
+28, 0.31179407, 0.29551837,True,True
+29, 0.31155460, 0.28581396,True,True
+30, 0.29630323, 0.28581396,True,True
+31, 0.29635801, 0.27577628,True,True
+32, 0.29988468, 0.28547138,True,True
+33, 0.29652923, 0.28581396,True,True
+34, 0.29988468, 0.28581396,True,True
+35, 0.30228543, 0.28574522,True,True
+36, 0.29839692, 0.27577628,True,True
+37, 0.28873105, 0.28155289,True,True
+38, 0.30805465, 0.28554006,True,True
+39, 0.29833142, 0.28574522,True,True
+40, 0.28873105, 0.29080448,True,True
+41, 0.31767977, 0.29016782,True,True
+42, 0.29827408, 0.28574522,True,True
+43, 0.29833142, 0.30111890,True,True
+44, 0.29630323, 0.29523517,True,True
+45, 0.30799545, 0.29551837,True,True
+46, 0.31913122, 0.28581396,True,True
+47, 0.31504986, 0.28554006,True,True
+48, 0.31173415, 0.28984380,True,True
+49, 0.30799545, 0.29712804,True,True
+50, 0.30574150, 0.28183707,True,True
+51, 0.30950795, 0.28286004,True,True
+52, 0.31995240, 0.29237810,True,True
+53, 0.30799545, 0.28984380,True,True
+54, 0.31971245, 0.28032574,True,True
+55, 0.31510811, 0.28957659,True,True
+56, 0.32944320, 0.28032574,True,True
+57, 0.29839692, 0.27604081,True,True
+58, 0.31028128, 0.28957659,True,True
+59, 0.31761871, 0.30162897,True,True
+60, 0.30050028, 0.28984380,True,True
+61, 0.32245478, 0.30529441,True,True
+62, 0.32128670, 0.28957659,True,True
+63, 0.31299637, 0.28862193,True,True
+64, 0.30805465, 0.28539579,True,True
+65, 0.30799545, 0.28888826,True,True
+66, 0.30799545, 0.29649261,True,True
+67, 0.30799545, 0.28554006,True,True
+68, 0.29630323, 0.27999994,True,True
+69, 0.30781805, 0.27176321,True,True
+70, 0.31915174, 0.28984380,True,True
+71, 0.30361422, 0.28521419,True,True
+72, 0.31767977, 0.29551837,True,True
+73, 0.33093234, 0.29551837,True,True
+74, 0.30799545, 0.29523517,True,True
+75, 0.31778727, 0.29523517,True,True
+76, 0.30956744, 0.29551837,True,True
+77, 0.30799545, 0.28574522,True,True
+78, 0.32122495, 0.27604081,True,True
+79, 0.30799545, 0.28574522,True,True
+80, 0.32128670, 0.29523517,True,True
+81, 0.30579803, 0.28449807,True,True
+82, 0.33193005, 0.29551837,True,True
+83, 0.32105663, 0.29551837,True,True
+84, 0.33093234, 0.27999994,True,True
+85, 0.31179407, 0.29523517,True,True
+86, 0.31504986, 0.29943212,True,True
+87, 0.32122495, 0.29142256,True,True
+88, 0.31761871, 0.29519218,True,True
+89, 0.32122495, 0.29523517,True,True
+90, 0.30574150, 0.29523517,True,True
+91, 0.30574150, 0.28201377,True,True
+92, 0.32122495, 0.28006730,True,True
+93, 0.32122495, 0.28984380,True,True
+94, 0.30799545, 0.29551837,True,True
+95, 0.31761871, 0.29079934,True,True
+96, 0.31913122, 0.29551837,True,True
+97, 0.31995240, 0.28554006,True,True
+98, 0.31761871, 0.29551837,True,True
+99, 0.31299637, 0.28888826,True,True
+100, 0.32122495, 0.28032574,True,True
+101, 0.31504986, 0.28581396,True,True
+102, 0.31299637, 0.29551837,True,True
+103, 0.30574150, 0.29551837,True,True
+104, 0.32251440, 0.29943212,True,True
+105, 0.30355810, 0.28984380,True,True
+106, 0.31299637, 0.28984380,True,True
+107, 0.30574150, 0.28102196,True,True
+108, 0.31504986, 0.28984380,True,True
+109, 0.29630323, 0.28025831,True,True
+110, 0.30557210, 0.29237810,True,True
+111, 0.32944320, 0.28984380,True,True
+112, 0.31977390, 0.28984380,True,True
+113, 0.30574150, 0.28554006,True,True
+114, 0.32450826, 0.29943212,True,True
+115, 0.31299637, 0.30591493,True,True
+116, 0.31761871, 0.29523517,True,True
+117, 0.30805465, 0.29523517,True,True
+118, 0.30799545, 0.29523517,True,True
+119, 0.30361422, 0.28984380,True,True
+120, 0.30950795, 0.28957659,True,True
+121, 0.31767977, 0.28984380,True,True
+122, 0.31761871, 0.30867649,True,True
+123, 0.30799545, 0.29551837,True,True
+124, 0.31504986, 0.30101088,True,True
+125, 0.31504986, 0.28957659,True,True
+126, 0.31767977, 0.30078653,True,True
+127, 0.31761871, 0.28957659,True,True
+128, 0.32122495, 0.29523517,True,True
+129, 0.31305424, 0.29077900,True,True
+130, 0.31971245, 0.29909700,True,True
+131, 0.32122495, 0.28957659,True,True
+132, 0.31299637, 0.29909700,True,True
+133, 0.31504986, 0.30494162,True,True
+134, 0.31504986, 0.30494162,True,True
+135, 0.30805465, 0.30500184,True,True
+136, 0.31356643, 0.29909700,True,True
+137, 0.30805465, 0.28920373,True,True
+138, 0.31844433, 0.30005166,True,True
+139, 0.30055805, 0.29484005,True,True
+140, 0.29259427, 0.29484005,True,True
+141, 0.29827408, 0.27577628,True,True
+142, 0.30579803, 0.29523517,True,True
+143, 0.31305424, 0.30500184,True,True
+144, 0.30574150, 0.30529441,True,True
+145, 0.30574150, 0.30529441,True,True
+146, 0.30574150, 0.29915607,True,True
+147, 0.29254018, 0.28957659,True,True
+148, 0.29271841, 0.28515792,True,True
+149, 0.30579803, 0.29490929,True,True
+150, 0.29635801, 0.29523517,True,True
+151, 0.30566809, 0.29523517,True,True
+152, 0.31157054, 0.28581396,True,True
+153, 0.30211088, 0.28581396,True,True
+154, 0.30216895, 0.28957659,True,True
+155, 0.29827408, 0.29915607,True,True
+156, 0.29613906, 0.28925696,True,True
+157, 0.31504986, 0.28984380,True,True
+158, 0.31305424, 0.28952388,True,True
+159, 0.32456826, 0.29915607,True,True
+160, 0.30799545, 0.28957659,True,True
+161, 0.30211088, 0.29877737,True,True
+162, 0.30213052, 0.29484005,True,True
+163, 0.30574150, 0.29523517,True,True
+164, 0.31022165, 0.30500184,True,True
+165, 0.30574150, 0.30500184,True,True
+166, 0.32128670, 0.30453351,True,True
+167, 0.30795653, 0.29523517,True,True
+168, 0.31510811, 0.28984380,True,True
+169, 0.32450826, 0.29913216,True,True
+170, 0.29630323, 0.29909700,True,True
+171, 0.32450826, 0.30867649,True,True
+172, 0.29635801, 0.28957659,True,True
+173, 0.29635801, 0.30494162,True,True
+174, 0.30574150, 0.29909700,True,True
+175, 0.30574150, 0.29551837,True,True
+176, 0.32450826, 0.30867649,True,True
+177, 0.29635801, 0.28957659,True,True
+178, 0.30579803, 0.29909700,True,True
+179, 0.30425807, 0.29352982,True,True
+180, 0.30355810, 0.29915607,True,True
+181, 0.31504986, 0.28957659,True,True
+182, 0.30574150, 0.30867649,True,True
+183, 0.29630323, 0.29877737,True,True
+184, 0.31761871, 0.30867649,True,True
+185, 0.32450826, 0.30837680,True,True
+186, 0.29630323, 0.30867649,True,True
+187, 0.30050028, 0.29523517,True,True
+188, 0.32450826, 0.29885638,True,True
+189, 0.31519991, 0.29915607,True,True
+190, 0.32450826, 0.29915607,True,True
+191, 0.31971245, 0.29871189,True,True
+192, 0.30574150, 0.29885638,True,True
+193, 0.32122495, 0.31015773,True,True
+194, 0.31821784, 0.30867649,True,True
+195, 0.31710334, 0.30494162,True,True
+196, 0.32122495, 0.32404311,True,True
+197, 0.31504986, 0.29915607,True,True
+198, 0.32450826, 0.30867649,True,True
+199, 0.32450826, 0.31797622,True,True
+200, 0.31504986, 0.31428712,True,True
+201, 0.32711001, 0.30867649,True,True
+202, 0.31504986, 0.29915607,True,True
+203, 0.30211088, 0.30453351,True,True
+204, 0.32944320, 0.31825831,True,True
+205, 0.31299637, 0.30827904,True,True
+206, 0.32450826, 0.30837680,True,True
+207, 0.32122495, 0.29523517,True,True
+208, 0.31504986, 0.29352982,True,True
+209, 0.31504986, 0.30867649,True,True
+210, 0.31487530, 0.30867649,True,True
+211, 0.30557210, 0.29915607,True,True
+212, 0.32450826, 0.31825831,True,True
+213, 0.31356643, 0.30837680,True,True
+214, 0.31487530, 0.30500184,True,True
+215, 0.31487530, 0.30778090,True,True
+216, 0.32432846, 0.29915607,True,True
+217, 0.33086875, 0.30867649,True,True
+218, 0.32450826, 0.31756680,True,True
+219, 0.32450826, 0.31825831,True,True
+220, 0.30910765, 0.29885638,True,True
+221, 0.34039463, 0.31736272,True,True
+222, 0.30557210, 0.30896132,True,True
+223, 0.31155460, 0.30867649,True,True
+224, 0.32450826, 0.31825831,True,True
+225, 0.32103993, 0.31756680,True,True
+226, 0.31155460, 0.31825831,True,True
+227, 0.30193687, 0.29885638,True,True
+228, 0.31487530, 0.30827904,True,True
+229, 0.32432846, 0.31756680,True,True
+230, 0.31173415, 0.31470830,True,True
+231, 0.33086875, 0.29915607,True,True
+232, 0.32450826, 0.29915607,True,True
+233, 0.31155460, 0.30073338,True,True
+234, 0.31155460, 0.31015773,True,True
+235, 0.31339269, 0.29909700,True,True
+236, 0.32122495, 0.31015773,True,True
+237, 0.32103993, 0.30867649,True,True
+238, 0.33067817, 0.31855199,True,True
+239, 0.33036128, 0.29915607,True,True
+240, 0.32073228, 0.30867649,True,True
+241, 0.32103993, 0.30827904,True,True
+242, 0.32122495, 0.30073338,True,True
+243, 0.31952830, 0.31015773,True,True
+244, 0.31777583, 0.31825831,True,True
+245, 0.32716092, 0.31015773,True,True
+246, 0.30748811, 0.30287118,True,True
+247, 0.31155460, 0.29440856,True,True
+248, 0.33366604, 0.30975837,True,True
+249, 0.31487530, 0.29915607,True,True
+250, 0.32103993, 0.29915607,True,True
+251, 0.31155460, 0.29915607,True,True
+252, 0.31155460, 0.29877088,True,True
+253, 0.31952830, 0.31428712,True,True
+254, 0.31777583, 0.31470830,True,True
+255, 0.31519991, 0.31784852,True,True
+256, 0.32137794, 0.30827904,True,True
+257, 0.30557210, 0.29871189,True,True
+258, 0.30557210, 0.29440856,True,True
+259, 0.30557210, 0.28532398,True,True
+260, 0.30557210, 0.28471380,True,True
+261, 0.31155460, 0.30019122,True,True
+262, 0.31487530, 0.28920373,True,True
+263, 0.30557210, 0.29310804,True,True
+264, 0.30164752, 0.28102196,True,True
+265, 0.29862313, 0.28102196,True,True
+266, 0.30193687, 0.29210855,True,True
+267, 0.31155460, 0.29015716,True,True
+268, 0.30193687, 0.29115389,True,True
+269, 0.30193687, 0.29077900,True,True
+270, 0.30544225, 0.29347186,True,True
+271, 0.31125603, 0.28270844,True,True
+272, 0.30193687, 0.27970669,True,True
+273, 0.30516066, 0.29115389,True,True
+274, 0.30557210, 0.28006730,True,True
+275, 0.31253455, 0.29440856,True,True
+276, 0.29613906, 0.29115389,True,True
+277, 0.31125603, 0.28984380,True,True
+278, 0.30557210, 0.29053124,True,True
+279, 0.30544225, 0.28581396,True,True
+280, 0.32103993, 0.28957659,True,True
+281, 0.29586604, 0.29210855,True,True
+282, 0.30311021, 0.28567814,True,True
+283, 0.30974585, 0.29210855,True,True
+284, 0.31004297, 0.30287118,True,True
+285, 0.31458501, 0.29467010,True,True
+286, 0.30529039, 0.29210855,True,True
+287, 0.30903324, 0.29115389,True,True
+288, 0.29586604, 0.29115389,True,True
+289, 0.30516066, 0.28201377,True,True
+290, 0.30489730, 0.28032574,True,True
+291, 0.30932968, 0.28413049,True,True
+292, 0.30380915, 0.28506720,True,True
+293, 0.30516066, 0.29237810,True,True
+294, 0.30903324, 0.29551837,True,True
+295, 0.30529039, 0.29142256,True,True
+296, 0.31864175, 0.29937300,True,True
+297, 0.32073228, 0.30057824,True,True
+298, 0.30529039, 0.29523517,True,True
+299, 0.32073228, 0.29915607,True,True
+300, 0.31458501, 0.30073338,True,True
+301, 0.30539196, 0.29684329,True,True
+302, 0.30539196, 0.28753504,True,True
+303, 0.30164752, 0.28128127,True,True
+304, 0.32073228, 0.30085560,True,True
+305, 0.31155460, 0.28850929,True,True
+306, 0.30903324, 0.29210855,True,True
+307, 0.31519196, 0.29152120,True,True
+308, 0.30903324, 0.30181114,True,True
+309, 0.31155460, 0.29915607,True,True
+310, 0.31458501, 0.31015773,True,True
+311, 0.31745904, 0.29909700,True,True
+312, 0.31125603, 0.30032854,True,True
+313, 0.30752306, 0.29210855,True,True
+314, 0.30781805, 0.29523517,True,True
+315, 0.31112377, 0.29937300,True,True
+316, 0.31777583, 0.29684329,True,True
+317, 0.31155460, 0.31015773,True,True
+318, 0.32282280, 0.30085560,True,True
+319, 0.32073228, 0.30494162,True,True
+320, 0.32073228, 0.29937300,True,True
+321, 0.31155460, 0.29684329,True,True
+322, 0.32103993, 0.29909700,True,True
+323, 0.32103993, 0.30772001,True,True
+324, 0.33694503, 0.30500184,True,True
+325, 0.31125603, 0.30057824,True,True
+326, 0.30557210, 0.30019122,True,True
+327, 0.31155460, 0.29115389,True,True
+328, 0.32745058, 0.30469630,True,True
+329, 0.30557210, 0.30057824,True,True
+330, 0.31745904, 0.30500184,True,True
+331, 0.31777583, 0.31652181,True,True
+332, 0.31777583, 0.30500184,True,True
+333, 0.31777583, 0.28554006,True,True
+334, 0.31487530, 0.30827904,True,True
+335, 0.30557210, 0.30867649,True,True
+336, 0.32073228, 0.30867649,True,True
+337, 0.31745904, 0.29937300,True,True
+338, 0.33694503, 0.29915607,True,True
+339, 0.33036128, 0.30867649,True,True
+340, 0.30003939, 0.29523517,True,True
+341, 0.32073228, 0.30896132,True,True
+342, 0.31922209, 0.30660997,True,True
+343, 0.31864175, 0.31470830,True,True
+344, 0.30932968, 0.30867649,True,True
+345, 0.32073228, 0.31440275,True,True
+346, 0.31864175, 0.31501017,True,True
+347, 0.33036128, 0.32478861,True,True
+348, 0.31550649, 0.29915607,True,True
+349, 0.32103993, 0.29915607,True,True
+350, 0.31623402, 0.30500184,True,True
+351, 0.32893792, 0.31470830,True,True
+352, 0.32684739, 0.31501017,True,True
+353, 0.30932968, 0.30494162,True,True
+354, 0.33036128, 0.30867649,True,True
+355, 0.32193479, 0.30500184,True,True
+356, 0.33002832, 0.31379521,True,True
+357, 0.32827075, 0.31501017,True,True
+358, 0.32377444, 0.31501017,True,True
+359, 0.32827075, 0.30867649,True,True
+360, 0.31591876, 0.31470830,True,True
+361, 0.33549331, 0.31652181,True,True
+362, 0.31004297, 0.29909700,True,True
+363, 0.31777583, 0.30111890,True,True
+364, 0.30796606, 0.29523517,True,True
+365, 0.31396467, 0.29523517,True,True
+366, 0.29942474, 0.30674576,True,True
+367, 0.31591876, 0.29712804,True,True
+368, 0.31591876, 0.31132915,True,True
+369, 0.28850929, 0.29523517,True,True
+370, 0.29942474, 0.30469630,True,True
+371, 0.31024988, 0.30111890,True,True
+372, 0.31591876, 0.29523517,True,True
+373, 0.31396467, 0.29484005,True,True
+374, 0.32160066, 0.29523517,True,True
+375, 0.31024988, 0.29523517,True,True
+376, 0.30992788, 0.29523517,True,True
+377, 0.31396467, 0.29484005,True,True
+378, 0.31415292, 0.28554006,True,True
+379, 0.32267714, 0.29484005,True,True
+380, 0.29687029, 0.28554006,True,True
+381, 0.30436250, 0.29523517,True,True
+382, 0.31304436, 0.29484005,True,True
+383, 0.32036156, 0.29523517,True,True
+384, 0.32193479, 0.29523517,True,True
+385, 0.29444679, 0.29386804,True,True
+386, 0.31550649, 0.31025393,True,True
+387, 0.30418012, 0.29523517,True,True
+388, 0.32036156, 0.31108021,True,True
+389, 0.32193479, 0.31058583,True,True
+390, 0.31550649, 0.32022208,True,True
+391, 0.31550649, 0.30069972,True,True
+392, 0.30799545, 0.29484005,True,True
+393, 0.31550649, 0.30500184,True,True
+394, 0.31550649, 0.30453351,True,True
+395, 0.31550649, 0.30428852,True,True
+396, 0.29561716, 0.30500184,True,True
+397, 0.29810228, 0.29484005,True,True
+398, 0.31192515, 0.28515792,True,True
+399, 0.31550649, 0.29386804,True,True
+400, 0.30796606, 0.28515792,True,True
+401, 0.29971195, 0.30500184,True,True
+402, 0.31396467, 0.30500184,True,True
+403, 0.30632425, 0.30469630,True,True
+404, 0.31256547, 0.29484005,True,True
+405, 0.30569671, 0.29523517,True,True
+406, 0.32193479, 0.30500184,True,True
+407, 0.31004297, 0.30500184,True,True
+408, 0.31256547, 0.30459366,True,True
+409, 0.29971195, 0.29523517,True,True
+410, 0.30781805, 0.29523517,True,True
+411, 0.30781805, 0.29484005,True,True
+412, 0.30569671, 0.28547138,True,True
+413, 0.30569671, 0.29523517,True,True
+414, 0.30569671, 0.29523517,True,True
+415, 0.30932968, 0.28006730,True,True
+416, 0.30632425, 0.29426185,True,True
+417, 0.30569671, 0.30078653,True,True
+418, 0.29591216, 0.29523517,True,True
+419, 0.29591216, 0.29523517,True,True
+420, 0.30539196, 0.31108021,True,True
+421, 0.30590524, 0.30078653,True,True
+422, 0.30815071, 0.29523517,True,True
+423, 0.30569671, 0.29523517,True,True
+424, 0.29608958, 0.29484005,True,True
+425, 0.30678600, 0.29523517,True,True
+426, 0.29444679, 0.29523517,True,True
+427, 0.30781805, 0.30500184,True,True
+428, 0.30650791, 0.30078653,True,True
+429, 0.31642362, 0.30453351,True,True
+430, 0.32287859, 0.30453351,True,True
+431, 0.29971195, 0.30459366,True,True
+432, 0.30974585, 0.30837680,True,True
+433, 0.31777583, 0.29451462,True,True
+434, 0.31022165, 0.29484005,True,True
+435, 0.30211088, 0.29644603,True,True
+436, 0.29810228, 0.30078653,True,True
+437, 0.30032720, 0.29523517,True,True
+438, 0.30077292, 0.30036782,True,True
+439, 0.29669240, 0.29523517,True,True
+440, 0.29810228, 0.28957659,True,True
+441, 0.29810228, 0.28957659,True,True
+442, 0.29687029, 0.29484005,True,True
+443, 0.32122495, 0.29451462,True,True
+444, 0.30678600, 0.30036782,True,True
+445, 0.30050028, 0.29484005,True,True
+446, 0.31745904, 0.31470830,True,True
+447, 0.31623402, 0.30453351,True,True
+448, 0.31569566, 0.29523517,True,True
+449, 0.30832874, 0.28515792,True,True
+450, 0.31022165, 0.29484005,True,True
+451, 0.29988468, 0.28515792,True,True
+452, 0.31415292, 0.29082516,True,True
+453, 0.31777583, 0.29490929,True,True
+454, 0.31913122, 0.29915607,True,True
+455, 0.29608958, 0.28920373,True,True
+456, 0.32764691, 0.29484005,True,True
+457, 0.32764691, 0.31398198,True,True
+458, 0.30590524, 0.31337525,True,True
+459, 0.30678600, 0.30459366,True,True
+460, 0.31569566, 0.30362165,True,True
+461, 0.30569671, 0.29123058,True,True
+462, 0.31569566, 0.29484005,True,True
+463, 0.31173415, 0.29523517,True,True
+464, 0.30832874, 0.28515792,True,True
+465, 0.29851309, 0.29484005,True,True
+466, 0.30588000, 0.29484005,True,True
+467, 0.31796637, 0.29877088,True,True
+468, 0.31155460, 0.29484005,True,True
+469, 0.31155460, 0.28920373,True,True
+470, 0.31155460, 0.29523517,True,True
+471, 0.32122495, 0.30827904,True,True
+472, 0.30781805, 0.30500184,True,True
+473, 0.29942474, 0.29915607,True,True
+474, 0.31796637, 0.29915607,True,True
+475, 0.31022165, 0.30453351,True,True
+476, 0.30650791, 0.30459366,True,True
+477, 0.31022165, 0.29915607,True,True
+478, 0.31777583, 0.28920373,True,True
+479, 0.31796637, 0.30500184,True,True
+480, 0.31777583, 0.29077900,True,True
+481, 0.30932968, 0.28920373,True,True
+482, 0.31173415, 0.30453351,True,True
+483, 0.31173415, 0.28920373,True,True
+484, 0.31155460, 0.29484005,True,True
+485, 0.31155460, 0.29115389,True,True
+486, 0.31155460, 0.29484005,True,True
+487, 0.31155460, 0.28920373,True,True
+488, 0.31155460, 0.29523517,True,True
+489, 0.31155460, 0.28920373,True,True
+490, 0.31777583, 0.28554006,True,True
+491, 0.30796606, 0.28920373,True,True
+492, 0.31777583, 0.29484005,True,True
+493, 0.30193687, 0.30459366,True,True
+494, 0.31777583, 0.28920373,True,True
+495, 0.31777583, 0.30019122,True,True
+496, 0.31777583, 0.30500184,True,True
+497, 0.31155460, 0.29877088,True,True
+498, 0.31155460, 0.29484005,True,True
+499, 0.31764080, 0.30500184,True,True
+500, 0.31777583, 0.30500184,True,True
+501, 0.31777583, 0.29915607,True,True
+502, 0.31155460, 0.29523517,True,True
+503, 0.30193687, 0.29523517,True,True
+504, 0.30164752, 0.29210855,True,True
+505, 0.29971195, 0.28957659,True,True
+506, 0.31155460, 0.29877088,True,True
+507, 0.30815071, 0.29523517,True,True
+508, 0.29249359, 0.28957659,True,True
+509, 0.30796606, 0.29523517,True,True
+510, 0.29249359, 0.30034616,True,True
+511, 0.31155460, 0.30073338,True,True
+512, 0.29833421, 0.30500184,True,True
+513, 0.31550649, 0.29909700,True,True
+514, 0.30193687, 0.30073338,True,True
+515, 0.31125603, 0.29871189,True,True
+516, 0.30557210, 0.30827904,True,True
+517, 0.30193687, 0.30500184,True,True
+518, 0.30569671, 0.30453351,True,True
+519, 0.31764080, 0.30494162,True,True
+520, 0.31550649, 0.30494162,True,True
+521, 0.31777583, 0.30604168,True,True
+522, 0.31777583, 0.29877088,True,True
+523, 0.31173415, 0.30500184,True,True
+524, 0.30950795, 0.29484005,True,True
+525, 0.31777583, 0.30453351,True,True
+526, 0.31796637, 0.30500184,True,True
+527, 0.29833421, 0.29915607,True,True
+528, 0.31796637, 0.29523517,True,True
+529, 0.31155460, 0.30453351,True,True
+530, 0.31155460, 0.29523517,True,True
+531, 0.31364713, 0.30827904,True,True
+532, 0.31173415, 0.29077900,True,True
+533, 0.31022165, 0.29871189,True,True
+534, 0.30193687, 0.30453351,True,True
+535, 0.30932968, 0.29484005,True,True
+536, 0.31155460, 0.29484005,True,True
+537, 0.31155460, 0.29523517,True,True
+538, 0.29827408, 0.29077900,True,True
+539, 0.31777583, 0.30500184,True,True
+540, 0.31796637, 0.30453351,True,True
+541, 0.32764691, 0.30917347,True,True
+542, 0.31155460, 0.29053124,True,True
+543, 0.30950795, 0.29484005,True,True
+544, 0.31155460, 0.30073338,True,True
+545, 0.31777583, 0.29484005,True,True
+546, 0.31777583, 0.30453351,True,True
+547, 0.31155460, 0.30827904,True,True
+548, 0.31173415, 0.29877088,True,True
+549, 0.31777583, 0.29915607,True,True
+550, 0.30796606, 0.30500184,True,True
+551, 0.30796606, 0.29115389,True,True
+552, 0.31173415, 0.30660997,True,True
+553, 0.31777583, 0.29915607,True,True
+554, 0.31777583, 0.30500184,True,True
+555, 0.30588000, 0.30111890,True,True
+556, 0.29971195, 0.28957659,True,True
+557, 0.31623402, 0.31157716,True,True
+558, 0.29266216, 0.28957659,True,True
+559, 0.32764691, 0.31428712,True,True
+560, 0.30632425, 0.30500184,True,True
+561, 0.29971195, 0.30428852,True,True
+562, 0.31504986, 0.30975837,True,True
+563, 0.31796637, 0.29523517,True,True
+564, 0.30590524, 0.31058583,True,True
+565, 0.31796637, 0.28920373,True,True
+566, 0.29266216, 0.29523517,True,True
+567, 0.30211088, 0.30034616,True,True
+568, 0.29851309, 0.28957659,True,True
+569, 0.31796637, 0.31428712,True,True
+570, 0.31155460, 0.29877088,True,True
+571, 0.31173415, 0.29966531,True,True
+572, 0.30193687, 0.29877088,True,True
+573, 0.29266216, 0.30500184,True,True
+574, 0.31173415, 0.28920373,True,True
+575, 0.31173415, 0.28920373,True,True
+576, 0.31796637, 0.29523517,True,True
+577, 0.28703614, 0.29077900,True,True
+578, 0.31173415, 0.28888451,True,True
+579, 0.30193687, 0.28920373,True,True
+580, 0.29613906, 0.28920373,True,True
+581, 0.29266216, 0.29484005,True,True
+582, 0.30574150, 0.30034616,True,True
+583, 0.31173415, 0.31428712,True,True
+584, 0.30574150, 0.29484005,True,True
+585, 0.31796637, 0.31428712,True,True
+586, 0.31022165, 0.29484005,True,True
+587, 0.28679421, 0.28006730,True,True
+588, 0.29851309, 0.28515792,True,True
+589, 0.29687029, 0.28088066,True,True
+590, 0.29591216, 0.27540720,True,True
+591, 0.28872267, 0.27102027,True,True
+592, 0.27222218, 0.24654977,True,True
+593, 0.27470122, 0.24680592,True,True
+594, 0.27205234, 0.24654977,True,True
+595, 0.27050253, 0.25123401,True,True
+596, 0.25747070, 0.22109358,True,True
+597, 0.25747070, 0.22109358,True,True
+598, 0.25265509, 0.22095636,True,True
+599, 0.25747070, 0.22109358,True,True
+600, 0.25747070, 0.23146749,True,True
+601, 0.25752050, 0.23146749,True,True
+602, 0.27574627, 0.24680592,True,True
+603, 0.25747070, 0.22660419,True,True
+604, 0.27222218, 0.22660419,True,True
+605, 0.26037704, 0.24654977,True,True
+606, 0.27205234, 0.24680592,True,True
+607, 0.29016612, 0.26231333,True,True
+608, 0.27205234, 0.25183791,True,True
+609, 0.29639357, 0.26144334,True,True
+610, 0.28038855, 0.27139808,True,True
+611, 0.29442873, 0.27691633,True,True
+612, 0.28615839, 0.26170423,True,True
+613, 0.27461839, 0.27131747,True,True
+614, 0.28679421, 0.27166890,True,True
+615, 0.29282021, 0.27883842,True,True
+616, 0.28696617, 0.27749571,True,True
+617, 0.28679421, 0.28127221,True,True
+618, 0.30273738, 0.28127221,True,True
+619, 0.29608958, 0.28091616,True,True
+620, 0.28696617, 0.28088066,True,True
+621, 0.29833421, 0.29123058,True,True
+622, 0.29669240, 0.28554006,True,True
+623, 0.29608958, 0.29123058,True,True
+624, 0.27896556, 0.27540720,True,True
+625, 0.30423720, 0.27749571,True,True
+626, 0.30588000, 0.29082516,True,True
+627, 0.28867556, 0.28515792,True,True
+628, 0.30588000, 0.28554006,True,True
+629, 0.29444679, 0.29484005,True,True
+630, 0.29266216, 0.28515792,True,True
+631, 0.30588000, 0.28515792,True,True
+632, 0.30569671, 0.29123058,True,True
+633, 0.30632425, 0.28554006,True,True
+634, 0.28867556, 0.28515792,True,True
+635, 0.29827408, 0.28515792,True,True
+636, 0.30588000, 0.29523517,True,True
+637, 0.29028616, 0.29484005,True,True
+638, 0.31777583, 0.30494162,True,True
+639, 0.31777583, 0.30494162,True,True
+640, 0.31761871, 0.31428712,True,True
+641, 0.29827408, 0.31428712,True,True
+642, 0.30799545, 0.30453351,True,True
+643, 0.30588000, 0.29523517,True,True
+644, 0.29827408, 0.30111890,True,True
+645, 0.30569671, 0.29484005,True,True
+646, 0.31022165, 0.30459366,True,True
+647, 0.31155460, 0.29871189,True,True
+648, 0.31796637, 0.29523517,True,True
+649, 0.29971195, 0.29484005,True,True
+650, 0.31777583, 0.30500184,True,True
+651, 0.30588000, 0.30111890,True,True
+652, 0.31971245, 0.31076858,True,True
+653, 0.31173415, 0.30500184,True,True
+654, 0.31796637, 0.29915607,True,True
+655, 0.30799545, 0.30459366,True,True
+656, 0.30799545, 0.29523517,True,True
+657, 0.31796637, 0.30459366,True,True
+658, 0.31155460, 0.30459366,True,True
+659, 0.30211088, 0.29877088,True,True
+660, 0.31173415, 0.30500184,True,True
+661, 0.31022165, 0.29490929,True,True
+662, 0.32122495, 0.29877088,True,True
+663, 0.30796606, 0.31428712,True,True
+664, 0.31173415, 0.31428712,True,True
+665, 0.31504986, 0.30459366,True,True
+666, 0.32122495, 0.29877088,True,True
+667, 0.31022165, 0.31428712,True,True
+668, 0.31155460, 0.29877088,True,True
+669, 0.33086875, 0.29877088,True,True
+670, 0.31173415, 0.31428712,True,True
+671, 0.31364713, 0.30019122,True,True
+672, 0.32103993, 0.31428712,True,True
+673, 0.32103993, 0.29909700,True,True
+674, 0.32745058, 0.30494162,True,True
+675, 0.31913122, 0.30459366,True,True
+676, 0.32122495, 0.30005166,True,True
+677, 0.31364713, 0.30975837,True,True
+678, 0.31142221, 0.30073338,True,True
+679, 0.32103993, 0.29871189,True,True
+680, 0.32122495, 0.30019122,True,True
+681, 0.31155460, 0.30837680,True,True
+682, 0.31142221, 0.29877737,True,True
+683, 0.31142221, 0.29877737,True,True
+684, 0.31155460, 0.31470830,True,True
+685, 0.30557210, 0.30453351,True,True
+686, 0.30529039, 0.29915607,True,True
+687, 0.30557210, 0.30500184,True,True
+688, 0.31777583, 0.29523517,True,True
+689, 0.30193687, 0.29523517,True,True
+690, 0.29827408, 0.29684329,True,True
+691, 0.31155460, 0.29115389,True,True
+692, 0.31155460, 0.29115389,True,True
+693, 0.30557210, 0.29523517,True,True
+694, 0.31155460, 0.30500184,True,True
+695, 0.31155460, 0.29523517,True,True
+696, 0.31155460, 0.30073338,True,True
+697, 0.31155460, 0.29915607,True,True
+698, 0.30557210, 0.30827904,True,True
+699, 0.29630323, 0.29523517,True,True
+700, 0.31155460, 0.29915607,True,True
+701, 0.31155460, 0.30867649,True,True
+702, 0.31155460, 0.29915607,True,True
+703, 0.31777583, 0.31428712,True,True
+704, 0.31436826, 0.30459366,True,True
+705, 0.31155460, 0.29115389,True,True
+706, 0.30557210, 0.30005166,True,True
+707, 0.32387770, 0.30837680,True,True
+708, 0.33067817, 0.30249571,True,True
+709, 0.31155460, 0.30019122,True,True
+710, 0.31155460, 0.28984380,True,True
+711, 0.30557210, 0.30005166,True,True
+712, 0.30557210, 0.30827904,True,True
+713, 0.32103993, 0.28957659,True,True
+714, 0.30950795, 0.29871189,True,True
+715, 0.31436826, 0.29347186,True,True
+716, 0.31155460, 0.29909700,True,True
+717, 0.33067817, 0.29909700,True,True
+718, 0.32103993, 0.29915607,True,True
+719, 0.31777583, 0.29523517,True,True
+720, 0.31155460, 0.30494162,True,True
+721, 0.31155460, 0.30005166,True,True
+722, 0.31173415, 0.29115389,True,True
+723, 0.31155460, 0.30432456,True,True
+724, 0.30574150, 0.29115389,True,True
+725, 0.32122495, 0.30975837,True,True
+726, 0.31004297, 0.28984380,True,True
+727, 0.30799545, 0.29173243,True,True
+728, 0.31155460, 0.30005166,True,True
+729, 0.30557210, 0.30957207,True,True
+730, 0.31642362, 0.29523517,True,True
+731, 0.31777583, 0.29523517,True,True
+732, 0.31173415, 0.30827904,True,True
+733, 0.31504986, 0.31825831,True,True
+734, 0.32450826, 0.30287118,True,True
+735, 0.30799545, 0.29523517,True,True
+736, 0.30557210, 0.30249571,True,True
+737, 0.30799545, 0.30500184,True,True
+738, 0.31155460, 0.31015773,True,True
+739, 0.29827408, 0.29649261,True,True
+740, 0.31299637, 0.30867649,True,True
+741, 0.31299637, 0.29915607,True,True
+742, 0.31913122, 0.30073338,True,True
+743, 0.30557210, 0.31797622,True,True
+744, 0.29810228, 0.30494162,True,True
+745, 0.30799545, 0.29915607,True,True
+746, 0.29988468, 0.29915607,True,True
+747, 0.30574150, 0.29915607,True,True
+748, 0.31155460, 0.29915607,True,True
+749, 0.31510811, 0.30867649,True,True
+750, 0.30338990, 0.30867649,True,True
+751, 0.31305424, 0.29915607,True,True
+752, 0.30574150, 0.29915607,True,True
+753, 0.30557210, 0.29943212,True,True
+754, 0.31504986, 0.29915607,True,True
+755, 0.31510811, 0.30867649,True,True
+756, 0.32122495, 0.30073338,True,True
+757, 0.32122495, 0.31470830,True,True
+758, 0.31504986, 0.31470830,True,True
+759, 0.32450826, 0.32598754,True,True
+760, 0.31504986, 0.32750583,True,True
+761, 0.31525818, 0.30500184,True,True
+762, 0.31022165, 0.29915607,True,True
+763, 0.30574150, 0.31826964,True,True
+764, 0.31299637, 0.31825831,True,True
+765, 0.32450826, 0.31855199,True,True
+766, 0.30211088, 0.29943212,True,True
+767, 0.31525818, 0.32478861,True,True
+768, 0.31510811, 0.29915607,True,True
+769, 0.31504986, 0.31855199,True,True
+770, 0.31510811, 0.32404311,True,True
+771, 0.31510811, 0.31470830,True,True
+772, 0.31385978, 0.29915607,True,True
+773, 0.32128670, 0.30827904,True,True
+774, 0.31356643, 0.32447736,True,True
+775, 0.31305424, 0.31973955,True,True
+776, 0.31305424, 0.29915607,True,True
+777, 0.31519991, 0.30867649,True,True
+778, 0.31504986, 0.29915607,True,True
+779, 0.31504986, 0.29885638,True,True
+780, 0.32450826, 0.30896132,True,True
+781, 0.31299637, 0.29142256,True,True
+782, 0.32251440, 0.29684329,True,True
+783, 0.30799545, 0.30494162,True,True
+784, 0.30799545, 0.30500184,True,True
+785, 0.30338990, 0.30867649,True,True
+786, 0.31519991, 0.30896132,True,True
+787, 0.32456826, 0.31470830,True,True
+788, 0.31510811, 0.30500184,True,True
+789, 0.31305424, 0.29885638,True,True
+790, 0.32456826, 0.30867649,True,True
+791, 0.32456826, 0.29943212,True,True
+792, 0.31510811, 0.31470830,True,True
+793, 0.31510811, 0.31470830,True,True
+794, 0.31510811, 0.31101879,True,True
+795, 0.31767977, 0.30494162,True,True
+796, 0.31977390, 0.30500184,True,True
+797, 0.32316986, 0.30896132,True,True
+798, 0.31977390, 0.30523413,True,True
+799, 0.31299637, 0.31621848,True,True
+800, 0.31510811, 0.30674576,True,True
+801, 0.31305424, 0.29909700,True,True
+802, 0.31510811, 0.29551837,True,True
+803, 0.31510811, 0.30500184,True,True
+804, 0.31510811, 0.31470830,True,True
+805, 0.31510811, 0.30494162,True,True
+806, 0.32456826, 0.32447736,True,True
+807, 0.31504986, 0.29943212,True,True
+808, 0.31305424, 0.30867649,True,True
+809, 0.31504986, 0.31825831,True,True
+810, 0.31504986, 0.31825831,True,True
+811, 0.31510811, 0.31470830,True,True
+812, 0.31510811, 0.32404311,True,True
+813, 0.31362440, 0.31470830,True,True
+814, 0.29833142, 0.30500184,True,True
+815, 0.31504986, 0.31470830,True,True
+816, 0.29477808, 0.31501017,True,True
+817, 0.30361422, 0.30494162,True,True
+818, 0.30361422, 0.29551837,True,True
+819, 0.31362440, 0.30494162,True,True
+820, 0.31767977, 0.29551837,True,True
+821, 0.30361422, 0.30645180,True,True
+822, 0.30361422, 0.30742512,True,True
+823, 0.31504986, 0.31501017,True,True
+824, 0.31510811, 0.31470830,True,True
+825, 0.30425807, 0.31470830,True,True
+826, 0.30361422, 0.31470830,True,True
+827, 0.31504986, 0.31470830,True,True
+828, 0.30579803, 0.31621848,True,True
+829, 0.30579803, 0.30500184,True,True
+830, 0.30579803, 0.31470830,True,True
+831, 0.30579803, 0.30896132,True,True
+832, 0.31362440, 0.30500184,True,True
+833, 0.30425807, 0.31470830,True,True
+834, 0.30579803, 0.31621848,True,True
+835, 0.31510811, 0.31501017,True,True
+836, 0.30805465, 0.31470830,True,True
+837, 0.31510811, 0.29551837,True,True
+838, 0.31504986, 0.30660997,True,True
+839, 0.30574150, 0.31108021,True,True
+840, 0.31510811, 0.31108021,True,True
+841, 0.31510811, 0.30500184,True,True
+842, 0.31510811, 0.31132915,True,True
+843, 0.31510811, 0.31470830,True,True
+844, 0.31510811, 0.29551837,True,True
+845, 0.30579803, 0.30500184,True,True
+846, 0.31504986, 0.31501017,True,True
+847, 0.31510811, 0.31621848,True,True
+848, 0.31305424, 0.30500184,True,True
+849, 0.30431433, 0.30500184,True,True
+850, 0.31977390, 0.30500184,True,True
+851, 0.30425807, 0.31470830,True,True
+852, 0.30361422, 0.31470830,True,True
+853, 0.31022165, 0.31470830,True,True
+854, 0.31971245, 0.30867649,True,True
+855, 0.31510811, 0.31470830,True,True
+856, 0.33245288, 0.30660997,True,True
+857, 0.31356643, 0.31470830,True,True
+858, 0.31362440, 0.31470830,True,True
+859, 0.31510811, 0.30500184,True,True
+860, 0.32450826, 0.31621848,True,True
+861, 0.31701589, 0.30867649,True,True
+862, 0.30916267, 0.30867649,True,True
+863, 0.31362440, 0.31470830,True,True
+864, 0.31510811, 0.31621848,True,True
+865, 0.31510811, 0.31272039,True,True
+866, 0.32456826, 0.30867649,True,True
+867, 0.31510811, 0.31501017,True,True
+868, 0.31977390, 0.31105331,True,True
+869, 0.31510811, 0.30162897,True,True
+870, 0.31510811, 0.31470830,True,True
+871, 0.31305424, 0.30660997,True,True
+872, 0.31504986, 0.30867649,True,True
+873, 0.31510811, 0.30867649,True,True
+874, 0.31510811, 0.30867649,True,True
+875, 0.31305424, 0.30500184,True,True
+876, 0.31510811, 0.30500184,True,True
+877, 0.31510811, 0.30523413,True,True
+878, 0.31510811, 0.30523413,True,True
+879, 0.31362440, 0.30500184,True,True
+880, 0.31362440, 0.30500184,True,True
+881, 0.31977390, 0.29523517,True,True
+882, 0.31510811, 0.31470830,True,True
+883, 0.31510811, 0.29523517,True,True
+884, 0.31510811, 0.30500184,True,True
+885, 0.31305424, 0.30500184,True,True
+886, 0.30579803, 0.30500184,True,True
+887, 0.31510811, 0.31621848,True,True
+888, 0.31504986, 0.29237810,True,True
+889, 0.31362440, 0.29523517,True,True
+890, 0.31510811, 0.31621848,True,True
+891, 0.30361422, 0.29523517,True,True
+892, 0.31305424, 0.31470830,True,True
+893, 0.31305424, 0.30500184,True,True
+894, 0.31305424, 0.29523517,True,True
+895, 0.31028128, 0.29523517,True,True
+896, 0.31385978, 0.30523413,True,True
+897, 0.31305424, 0.30500184,True,True
+898, 0.30574150, 0.30275907,True,True
+899, 0.31022165, 0.30500184,True,True
+900, 0.31161836, 0.30078653,True,True
+901, 0.31022165, 0.29551837,True,True
+902, 0.31510811, 0.29523517,True,True
+903, 0.31525818, 0.29684329,True,True
+904, 0.30579803, 0.29523517,True,True
+905, 0.30361422, 0.30141938,True,True
+906, 0.30355810, 0.29523517,True,True
+907, 0.31307438, 0.29523517,True,True
+908, 0.33093234, 0.31743577,True,True
+909, 0.30799545, 0.29551837,True,True
+910, 0.32950652, 0.31470830,True,True
+911, 0.32245478, 0.30500184,True,True
+912, 0.30574150, 0.30111890,True,True
+913, 0.30574150, 0.30111890,True,True
+914, 0.31519991, 0.30111890,True,True
+915, 0.31305424, 0.30141938,True,True
+916, 0.30213052, 0.31108021,True,True
+917, 0.31525818, 0.30660997,True,True
+918, 0.31173415, 0.30211161,True,True
+919, 0.31767977, 0.30500184,True,True
+920, 0.31510811, 0.29053124,True,True
+921, 0.31510811, 0.29551837,True,True
+922, 0.31510811, 0.30141938,True,True
+923, 0.32456826, 0.29523517,True,True
+924, 0.32456826, 0.29781661,True,True
+925, 0.30579803, 0.30275907,True,True
+926, 0.30574150, 0.30500184,True,True
+927, 0.30574150, 0.30500184,True,True
+928, 0.32128670, 0.31470830,True,True
+929, 0.30579803, 0.29620848,True,True
+930, 0.30579803, 0.29523517,True,True
+931, 0.32456826, 0.31470830,True,True
+932, 0.32456826, 0.30867649,True,True
+933, 0.33086875, 0.30111890,True,True
+934, 0.31519991, 0.29712804,True,True
+935, 0.30574150, 0.30141938,True,True
+936, 0.31977390, 0.29551837,True,True
+937, 0.32450826, 0.31134034,True,True
+938, 0.31701589, 0.30867649,True,True
+939, 0.32950652, 0.30896132,True,True
+940, 0.32456826, 0.30867649,True,True
+941, 0.31356643, 0.30867649,True,True
+942, 0.32316986, 0.30896132,True,True
+943, 0.32316986, 0.30896132,True,True
+944, 0.31299637, 0.30896132,True,True
+945, 0.31179407, 0.30141938,True,True
+946, 0.31151294, 0.30529441,True,True
+947, 0.31305424, 0.30896132,True,True
+948, 0.31299637, 0.30896132,True,True
+949, 0.31299637, 0.31501017,True,True
+950, 0.31305424, 0.30896132,True,True
+951, 0.31362440, 0.30896132,True,True
+952, 0.31510811, 0.30896132,True,True
+953, 0.32311012, 0.30690408,True,True
+954, 0.31305424, 0.30500184,True,True
+955, 0.31305424, 0.31470830,True,True
+956, 0.30574150, 0.30529441,True,True
+957, 0.31510811, 0.31470830,True,True
+958, 0.30805465, 0.31272039,True,True
+959, 0.31519991, 0.30896132,True,True
+960, 0.31301650, 0.30529441,True,True
+961, 0.32105663, 0.30529441,True,True
+962, 0.31179407, 0.30674576,True,True
+963, 0.30799545, 0.30500184,True,True
+964, 0.31179407, 0.29649261,True,True
+965, 0.30211088, 0.29551837,True,True
+966, 0.29994232, 0.30211161,True,True
+967, 0.31028128, 0.31108021,True,True
+968, 0.30805465, 0.28725949,True,True
+969, 0.30799545, 0.29237810,True,True
+970, 0.29833142, 0.29649261,True,True
+971, 0.30799545, 0.29810228,True,True
+972, 0.29833142, 0.28753504,True,True
+973, 0.30795653, 0.28725949,True,True
+974, 0.30805465, 0.29551837,True,True
+975, 0.31767977, 0.29712804,True,True
+976, 0.29833142, 0.28984380,True,True
+977, 0.30799545, 0.30896132,True,True
+978, 0.31767977, 0.31470830,True,True
+979, 0.30956744, 0.31652181,True,True
+980, 0.31767977, 0.31855199,True,True
+981, 0.31977390, 0.30896132,True,True
+982, 0.29833142, 0.29937300,True,True
+983, 0.31022165, 0.29523517,True,True
+984, 0.31179407, 0.30500184,True,True
+985, 0.29833142, 0.29551837,True,True
+986, 0.30361422, 0.29551837,True,True
+987, 0.30566809, 0.29551837,True,True
+988, 0.29833142, 0.29649261,True,True
+989, 0.29833142, 0.29649261,True,True
+990, 0.31305424, 0.29237810,True,True
+991, 0.30821233, 0.29551837,True,True
+992, 0.29994232, 0.29551837,True,True
+993, 0.30650791, 0.29551837,True,True
+994, 0.30594117, 0.30111890,True,True
+995, 0.32143972, 0.31501017,True,True
+996, 0.31510811, 0.31501017,True,True
+997, 0.31307438, 0.30896132,True,True
+998, 0.29833142, 0.29551837,True,True
+999, 0.30425807, 0.30073338,True,True
+1000, 0.29827408, 0.29142256,True,True
+1001, 0.29994232, 0.29810228,True,True
+1002, 0.30216895, 0.29712804,True,True
+1003, 0.31022165, 0.30752306,True,True
+1004, 0.30207467, 0.30500184,True,True
+1005, 0.30574150, 0.30375178,True,True
+1006, 0.29833142, 0.29237810,True,True
+1007, 0.31173415, 0.30500184,True,True
+1008, 0.30799545, 0.30500184,True,True
+1009, 0.30799545, 0.31501017,True,True
+1010, 0.30795653, 0.30500184,True,True
+1011, 0.30431433, 0.30500184,True,True
+1012, 0.31173415, 0.30211161,True,True
+1013, 0.30805465, 0.29237810,True,True
+1014, 0.30799545, 0.30500184,True,True
+1015, 0.30574150, 0.30591493,True,True
+1016, 0.30574150, 0.30073338,True,True
+1017, 0.30956744, 0.29620848,True,True
+1018, 0.31761871, 0.30101088,True,True
+1019, 0.30799545, 0.30500184,True,True
+1020, 0.30574150, 0.30162897,True,True
+1021, 0.30207467, 0.30162897,True,True
+1022, 0.30574150, 0.30500184,True,True
+1023, 0.30799545, 0.30190730,True,True
+1024, 0.30579803, 0.30101088,True,True
+1025, 0.31022165, 0.30985774,True,True
+1026, 0.30795653, 0.29551837,True,True
+1027, 0.31504986, 0.29943212,True,True
+1028, 0.29833142, 0.29237810,True,True
+1029, 0.30355810, 0.29237810,True,True
+1030, 0.30361422, 0.29237810,True,True
+1031, 0.30355810, 0.28984380,True,True
+1032, 0.30574150, 0.30181114,True,True
+1033, 0.30805465, 0.29237810,True,True
+1034, 0.30799545, 0.29079934,True,True
+1035, 0.30361422, 0.31134034,True,True
+1036, 0.30566809, 0.29810228,True,True
+1037, 0.30361422, 0.29079934,True,True
+1038, 0.31305424, 0.28984380,True,True
+1039, 0.30203429, 0.28984380,True,True
+1040, 0.30799545, 0.30190730,True,True
+1041, 0.30355810, 0.28532043,True,True
+1042, 0.30203429, 0.28032574,True,True
+1043, 0.30361422, 0.29237810,True,True
+1044, 0.30805465, 0.29810228,True,True
+1045, 0.30799545, 0.29551837,True,True
+1046, 0.30361422, 0.29810228,True,True
+1047, 0.31173415, 0.28984380,True,True
+1048, 0.29833142, 0.29551837,True,True
+1049, 0.29450567, 0.29576036,True,True
+1050, 0.30950795, 0.29649261,True,True
+1051, 0.30203429, 0.28984380,True,True
+1052, 0.28873105, 0.29551837,True,True
+1053, 0.31179407, 0.29666349,True,True
+1054, 0.30423720, 0.29158412,True,True
+1055, 0.30355810, 0.29551837,True,True
+1056, 0.30361422, 0.28984380,True,True
+1057, 0.28916477, 0.30032854,True,True
+1058, 0.29259427, 0.28984380,True,True
+1059, 0.29994232, 0.29712804,True,True
+1060, 0.29259427, 0.28984380,True,True
+1061, 0.30799545, 0.29237810,True,True
+1062, 0.30799545, 0.29237810,True,True
+1063, 0.30650791, 0.29551837,True,True
+1064, 0.30211088, 0.29649261,True,True
+1065, 0.30213052, 0.28984380,True,True
+1066, 0.29833142, 0.28984380,True,True
+1067, 0.29259427, 0.28984380,True,True
+1068, 0.30594117, 0.29827408,True,True
+1069, 0.30594117, 0.28770075,True,True
+1070, 0.30429804, 0.29142256,True,True
+1071, 0.30805465, 0.29649261,True,True
+1072, 0.30429804, 0.29810228,True,True
+1073, 0.29450567, 0.29810228,True,True
+1074, 0.31575879, 0.29827408,True,True
+1075, 0.31575879, 0.29827408,True,True
+1076, 0.30429804, 0.29810228,True,True
+1077, 0.30805465, 0.29079934,True,True
+1078, 0.29988468, 0.29649261,True,True
+1079, 0.29614880, 0.29237810,True,True
+1080, 0.31802995, 0.30207467,True,True
+1081, 0.31575879, 0.29649261,True,True
+1082, 0.29833142, 0.29237810,True,True
+1083, 0.31648690, 0.28984380,True,True
+1084, 0.31421574, 0.29810228,True,True
+1085, 0.31575879, 0.30547036,True,True
+1086, 0.31173415, 0.29649261,True,True
+1087, 0.31173415, 0.30620838,True,True
+1088, 0.31575879, 0.28984380,True,True
+1089, 0.30950795, 0.28984380,True,True
+1090, 0.30799545, 0.29943212,True,True
+1091, 0.30950795, 0.29551837,True,True
+1092, 0.31802995, 0.29649261,True,True
+1093, 0.30594117, 0.29551837,True,True
+1094, 0.30805465, 0.29649261,True,True
+1095, 0.30799545, 0.30529441,True,True
+1096, 0.30799545, 0.30638485,True,True
+1097, 0.31569566, 0.30547036,True,True
+1098, 0.29994232, 0.28984380,True,True
+1099, 0.30805465, 0.29810228,True,True
+1100, 0.30950795, 0.30547036,True,True
+1101, 0.30956744, 0.29810228,True,True
+1102, 0.30594117, 0.28984380,True,True
+1103, 0.31575879, 0.28984380,True,True
+1104, 0.30805465, 0.28984380,True,True
+1105, 0.30805465, 0.29943212,True,True
+1106, 0.29833142, 0.30547036,True,True
+1107, 0.30799545, 0.29551837,True,True
+1108, 0.30799545, 0.29568868,True,True
+1109, 0.31415292, 0.29568868,True,True
+1110, 0.31421574, 0.30638485,True,True
+1111, 0.31415292, 0.30799545,True,True
+1112, 0.31415292, 0.30620838,True,True
+1113, 0.31421574, 0.29810228,True,True
+1114, 0.30429804, 0.30781805,True,True
+1115, 0.30805465, 0.29142256,True,True
+1116, 0.30805465, 0.30913260,True,True
+1117, 0.30799545, 0.29237810,True,True
+1118, 0.30799545, 0.29237810,True,True
+1119, 0.30805465, 0.28867556,True,True
+1120, 0.29833142, 0.30190730,True,True
+1121, 0.31767977, 0.30032854,True,True
+1122, 0.30355810, 0.30547443,True,True
+1123, 0.30574150, 0.30073338,True,True
+1124, 0.30431433, 0.29237810,True,True
+1125, 0.30805465, 0.29237810,True,True
+1126, 0.30579803, 0.29810228,True,True
+1127, 0.31510811, 0.30401976,True,True
+1128, 0.31305424, 0.30459491,True,True
+1129, 0.30805465, 0.29237810,True,True
+1130, 0.29833142, 0.28984380,True,True
+1131, 0.28873105, 0.28984380,True,True
+1132, 0.30799545, 0.29915607,True,True
+1133, 0.30799545, 0.30985774,True,True
+1134, 0.30805465, 0.29142256,True,True
+1135, 0.31977390, 0.30896132,True,True
+1136, 0.30355810, 0.28984380,True,True
+1137, 0.30431433, 0.29551837,True,True
+1138, 0.31022165, 0.29712804,True,True
+1139, 0.31767977, 0.29523517,True,True
+1140, 0.31362440, 0.29551837,True,True
+1141, 0.30799545, 0.29551837,True,True
+1142, 0.30799545, 0.28032574,True,True
+1143, 0.30799545, 0.27074025,True,True
+1144, 0.30805465, 0.28201377,True,True
+1145, 0.30083074, 0.28296931,True,True
+1146, 0.29833142, 0.29079934,True,True
+1147, 0.30805465, 0.29551837,True,True
+1148, 0.30574150, 0.30772001,True,True
+1149, 0.31173415, 0.30500184,True,True
+1150, 0.30799545, 0.30660997,True,True
+1151, 0.30799545, 0.29684329,True,True
+1152, 0.30579803, 0.30275907,True,True
+1153, 0.30579803, 0.29684329,True,True
+1154, 0.30805465, 0.28581396,True,True
+1155, 0.30805465, 0.29523517,True,True
+1156, 0.31767977, 0.29915607,True,True
+1157, 0.30805465, 0.29280071,True,True
+1158, 0.31179407, 0.29712804,True,True
+1159, 0.30799545, 0.27604081,True,True
+1160, 0.30805465, 0.28574522,True,True
+1161, 0.30805465, 0.27604081,True,True
+1162, 0.30805465, 0.29551837,True,True
+1163, 0.31028128, 0.29551837,True,True
+1164, 0.31028128, 0.29523517,True,True
+1165, 0.31778727, 0.29551837,True,True
+1166, 0.29833142, 0.29551837,True,True
+1167, 0.31179407, 0.29551837,True,True
+1168, 0.29994232, 0.29551837,True,True
+1169, 0.30216895, 0.29551837,True,True
+1170, 0.31173415, 0.28984380,True,True
+1171, 0.30216895, 0.28581396,True,True
+1172, 0.31179407, 0.29523517,True,True
+1173, 0.30216895, 0.29551837,True,True
+1174, 0.32128670, 0.29551837,True,True
+1175, 0.32128670, 0.31501017,True,True
+1176, 0.31510811, 0.30529441,True,True
+1177, 0.31510811, 0.30529441,True,True
+1178, 0.31179407, 0.30500184,True,True
+1179, 0.33093234, 0.30500184,True,True
+1180, 0.31179407, 0.30547036,True,True
+1181, 0.30431433, 0.28957659,True,True
+1182, 0.31179407, 0.28957659,True,True
+1183, 0.31179407, 0.29943212,True,True
+1184, 0.31767977, 0.28581396,True,True
+1185, 0.31028128, 0.29943212,True,True
+1186, 0.31179407, 0.29915607,True,True
+1187, 0.32128670, 0.30500184,True,True
+1188, 0.32128670, 0.30500184,True,True
+1189, 0.31510811, 0.30529441,True,True
+1190, 0.30805465, 0.30529441,True,True
+1191, 0.30579803, 0.29551837,True,True
+1192, 0.30805465, 0.30660997,True,True
+1193, 0.31028128, 0.29684329,True,True
+1194, 0.31179407, 0.30690408,True,True
+1195, 0.31802995, 0.30529441,True,True
+1196, 0.32122495, 0.29568868,True,True
+1197, 0.31028128, 0.29523517,True,True
+1198, 0.31767977, 0.31501017,True,True
+1199, 0.31179407, 0.30529441,True,True
+1200, 0.31977390, 0.30529441,True,True
+1201, 0.32128670, 0.29943212,True,True
+1202, 0.32128670, 0.31501017,True,True
+1203, 0.31802995, 0.30690408,True,True
+1204, 0.32128670, 0.30690408,True,True
+1205, 0.30211088, 0.30529441,True,True
+1206, 0.32128670, 0.29551837,True,True
+1207, 0.31977390, 0.30529441,True,True
+1208, 0.32128670, 0.29551837,True,True
+1209, 0.31767977, 0.28581396,True,True
+1210, 0.31767977, 0.30529441,True,True
+1211, 0.32137794, 0.30529441,True,True
+1212, 0.31977390, 0.30500184,True,True
+1213, 0.32128670, 0.31501017,True,True
+1214, 0.32128670, 0.31232286,True,True
+1215, 0.30805465, 0.30141938,True,True
+1216, 0.31362440, 0.31501017,True,True
+1217, 0.31919256, 0.29649261,True,True
+1218, 0.32456826, 0.31501017,True,True
+1219, 0.31179407, 0.29649261,True,True
+1220, 0.32456826, 0.29551837,True,True
+1221, 0.32128670, 0.31501017,True,True
+1222, 0.32128670, 0.30529441,True,True
+1223, 0.31510811, 0.30529441,True,True
+1224, 0.32128670, 0.30523413,True,True
+1225, 0.31519991, 0.29551837,True,True
+1226, 0.31510811, 0.31501017,True,True
+1227, 0.33086875, 0.29551837,True,True
+1228, 0.31767977, 0.31139064,True,True
+1229, 0.32771243, 0.30529441,True,True
+1230, 0.32456826, 0.29551837,True,True
+1231, 0.30956744, 0.29551837,True,True
+1232, 0.31157054, 0.30529441,True,True
+1233, 0.32128670, 0.31501017,True,True
+1234, 0.32741239, 0.29551837,True,True
+1235, 0.31919256, 0.29551837,True,True
+1236, 0.31179407, 0.29551837,True,True
+1237, 0.32105663, 0.29943212,True,True
+1238, 0.31179407, 0.30523413,True,True
+1239, 0.30799545, 0.29551837,True,True
+1240, 0.31642362, 0.29142256,True,True
+1241, 0.30950795, 0.29523517,True,True
+1242, 0.32450826, 0.30101088,True,True
+1243, 0.32128670, 0.29551837,True,True
+1244, 0.31519991, 0.30529441,True,True
+1245, 0.31179407, 0.29551837,True,True
+1246, 0.31179407, 0.29551837,True,True
+1247, 0.31173415, 0.29551837,True,True
+1248, 0.31173415, 0.29551837,True,True
+1249, 0.31173415, 0.31061603,True,True
+1250, 0.31421574, 0.29620848,True,True
+1251, 0.30950795, 0.30547036,True,True
+1252, 0.31173415, 0.29551837,True,True
+1253, 0.30956744, 0.29551837,True,True
+1254, 0.31362440, 0.30529441,True,True
+1255, 0.31179407, 0.30500184,True,True
+1256, 0.31913122, 0.29237810,True,True
+1257, 0.31173415, 0.29551837,True,True
+1258, 0.30799545, 0.29551837,True,True
+1259, 0.31761871, 0.29551837,True,True
+1260, 0.30805465, 0.30500184,True,True
+1261, 0.30799545, 0.29523517,True,True
+1262, 0.30799545, 0.29568868,True,True
+1263, 0.30574150, 0.29551837,True,True
+1264, 0.31761871, 0.29568868,True,True
+1265, 0.30805465, 0.29551837,True,True
+1266, 0.30805465, 0.29551837,True,True
+1267, 0.30805465, 0.30529441,True,True
+1268, 0.31767977, 0.29959812,True,True
+1269, 0.32128670, 0.31501017,True,True
+1270, 0.30956744, 0.30529441,True,True
+1271, 0.30956744, 0.30529441,True,True
+1272, 0.30956744, 0.29523517,True,True
+1273, 0.30431433, 0.30500184,True,True
+1274, 0.30805465, 0.28574522,True,True
+1275, 0.30805465, 0.28678821,True,True
+1276, 0.30805465, 0.29152120,True,True
+1277, 0.29988468, 0.30498857,True,True
+1278, 0.31510811, 0.31501017,True,True
+1279, 0.30799545, 0.30111890,True,True
+1280, 0.30805465, 0.30529441,True,True
+1281, 0.30805465, 0.30529441,True,True
+1282, 0.32128670, 0.31501017,True,True
+1283, 0.31362440, 0.30529441,True,True
+1284, 0.31510811, 0.29551837,True,True
+1285, 0.31767977, 0.29551837,True,True
+1286, 0.30805465, 0.28548777,True,True
+1287, 0.32128670, 0.30529441,True,True
+1288, 0.31510811, 0.29943212,True,True
+1289, 0.31510811, 0.30896132,True,True
+1290, 0.31504986, 0.30896132,True,True
+1291, 0.31519991, 0.30896132,True,True
+1292, 0.32450826, 0.30101088,True,True
+1293, 0.32741239, 0.30660997,True,True
+1294, 0.31767977, 0.30111890,True,True
+1295, 0.31157054, 0.32284223,True,True
+1296, 0.32456826, 0.30500184,True,True
+1297, 0.31510811, 0.31501017,True,True
+1298, 0.31305424, 0.30896132,True,True
+1299, 0.31510811, 0.30500184,True,True
+1300, 0.31519991, 0.29551837,True,True
+1301, 0.31179407, 0.29551837,True,True
+1302, 0.31179407, 0.29551837,True,True
+1303, 0.32111599, 0.29551837,True,True
+1304, 0.30799545, 0.29551837,True,True
+1305, 0.32111599, 0.31652181,True,True
+1306, 0.32456826, 0.30896132,True,True
+1307, 0.31510811, 0.30896132,True,True
+1308, 0.32741239, 0.29551837,True,True
+1309, 0.31362440, 0.31134034,True,True
+1310, 0.32950652, 0.31743577,True,True
+1311, 0.32741239, 0.29142256,True,True
+1312, 0.30431433, 0.30896132,True,True
+1313, 0.31971245, 0.31501017,True,True
+1314, 0.32944320, 0.31652181,True,True
+1315, 0.33093234, 0.31272039,True,True
+1316, 0.32741239, 0.30690408,True,True
+1317, 0.31305424, 0.30494162,True,True
+1318, 0.31356643, 0.31621848,True,True
+1319, 0.31767977, 0.30500184,True,True
+1320, 0.32245478, 0.30896132,True,True
+1321, 0.32741239, 0.31501017,True,True
+1322, 0.32741239, 0.30500184,True,True
+1323, 0.31772620, 0.29523517,True,True
+1324, 0.31995240, 0.29523517,True,True
+1325, 0.31022165, 0.31501017,True,True
+1326, 0.32456826, 0.30896132,True,True
+1327, 0.32111599, 0.31743577,True,True
+1328, 0.30805465, 0.29551837,True,True
+1329, 0.31772620, 0.30500184,True,True
+1330, 0.31510811, 0.29712804,True,True
+1331, 0.32111599, 0.29810228,True,True
+1332, 0.30805465, 0.31501017,True,True
+1333, 0.32450826, 0.30032854,True,True
+1334, 0.31977390, 0.31501017,True,True
+1335, 0.31157054, 0.29523517,True,True
+1336, 0.31767977, 0.29551837,True,True
+1337, 0.31977390, 0.30500184,True,True
+1338, 0.30805465, 0.30306120,True,True
+1339, 0.32128670, 0.30867649,True,True
+1340, 0.33086875, 0.31134034,True,True
+1341, 0.31772620, 0.31044393,True,True
+1342, 0.32251440, 0.31652181,True,True
+1343, 0.31977390, 0.31652181,True,True
+1344, 0.31510811, 0.31061603,True,True
+1345, 0.31305424, 0.29649261,True,True
+1346, 0.32105663, 0.31044393,True,True
+1347, 0.32944320, 0.31501017,True,True
+1348, 0.31022165, 0.30690408,True,True
+1349, 0.30425807, 0.29559001,True,True
+1350, 0.31767977, 0.30111890,True,True
+1351, 0.31995240, 0.31501017,True,True
+1352, 0.31767977, 0.29551837,True,True
+1353, 0.31362440, 0.30660997,True,True
+1354, 0.30579803, 0.30500184,True,True
+1355, 0.31977390, 0.31501017,True,True
+1356, 0.32741239, 0.30500184,True,True
+1357, 0.32450826, 0.28984380,True,True
+1358, 0.31995240, 0.30529441,True,True
+1359, 0.31995240, 0.30500184,True,True
+1360, 0.32311012, 0.30529441,True,True
+1361, 0.32311012, 0.30500184,True,True
+1362, 0.31971245, 0.29551837,True,True
+1363, 0.32137794, 0.30500184,True,True
+1364, 0.32450826, 0.31501017,True,True
+1365, 0.32450826, 0.30529441,True,True
+1366, 0.32122495, 0.30529441,True,True
+1367, 0.31510811, 0.31652181,True,True
+1368, 0.32001390, 0.31470830,True,True
+1369, 0.32137794, 0.31501017,True,True
+1370, 0.32128670, 0.31470830,True,True
+1371, 0.31173415, 0.31652181,True,True
+1372, 0.32128670, 0.31670422,True,True
+1373, 0.31510811, 0.31519172,True,True
+1374, 0.31519991, 0.30529441,True,True
+1375, 0.31767977, 0.31044393,True,True
+1376, 0.32122495, 0.31501017,True,True
+1377, 0.31519991, 0.30896132,True,True
+1378, 0.31504986, 0.31501017,True,True
+1379, 0.31504986, 0.30459491,True,True
+1380, 0.31173415, 0.30073338,True,True
+1381, 0.31356643, 0.31044393,True,True
+1382, 0.31356643, 0.30896132,True,True
+1383, 0.31977390, 0.31470830,True,True
+1384, 0.30788310, 0.30867649,True,True
+1385, 0.32122495, 0.29551837,True,True
+1386, 0.31173415, 0.31501017,True,True
+1387, 0.30055805, 0.28678821,True,True
+1388, 0.31519991, 0.30867649,True,True
+1389, 0.31356643, 0.30985774,True,True
+1390, 0.31519991, 0.30985774,True,True
+1391, 0.32137794, 0.30896132,True,True
+1392, 0.30574150, 0.30896132,True,True
+1393, 0.32245478, 0.30190730,True,True
+1394, 0.32450826, 0.31002951,True,True
+1395, 0.32137794, 0.31501017,True,True
+1396, 0.31519991, 0.30896132,True,True
+1397, 0.31510811, 0.30867649,True,True
+1398, 0.31510811, 0.30896132,True,True
+1399, 0.31179407, 0.30500184,True,True
+1400, 0.30574150, 0.30896132,True,True
+1401, 0.30216895, 0.29551837,True,True
+1402, 0.31761871, 0.29237810,True,True
+1403, 0.31525818, 0.30896132,True,True
+1404, 0.31519991, 0.30896132,True,True
+1405, 0.32245478, 0.30867649,True,True
+1406, 0.30950795, 0.29551837,True,True
+1407, 0.32245478, 0.30896132,True,True
+1408, 0.31504986, 0.30896132,True,True
+1409, 0.31157054, 0.30690408,True,True
+1410, 0.31305424, 0.28957659,True,True
+1411, 0.31305424, 0.30500184,True,True
+1412, 0.32456826, 0.28984380,True,True
+1413, 0.32105663, 0.31621848,True,True
+1414, 0.31305424, 0.30500184,True,True
+1415, 0.32245478, 0.30500184,True,True
+1416, 0.31504986, 0.30896132,True,True
+1417, 0.32944320, 0.30500184,True,True
+1418, 0.30216895, 0.30660997,True,True
+1419, 0.32450826, 0.31470830,True,True
+1420, 0.31977390, 0.30500184,True,True
+1421, 0.31305424, 0.31105331,True,True
+1422, 0.31504986, 0.31501017,True,True
+1423, 0.31305424, 0.30660997,True,True
+1424, 0.31157054, 0.31501017,True,True
+1425, 0.30799545, 0.29781661,True,True
+1426, 0.31157054, 0.30752306,True,True
+1427, 0.31504986, 0.28984380,True,True
+1428, 0.30574150, 0.29237810,True,True
+1429, 0.33086875, 0.31470830,True,True
+1430, 0.31767977, 0.30896132,True,True
+1431, 0.31299637, 0.30896132,True,True
+1432, 0.32311012, 0.31044393,True,True
+1433, 0.32311012, 0.30459491,True,True
+1434, 0.32450826, 0.30867649,True,True
+1435, 0.31179407, 0.29915607,True,True
+1436, 0.31356643, 0.31015773,True,True
+1437, 0.31299637, 0.30985774,True,True
+1438, 0.32316986, 0.31470830,True,True
+1439, 0.31504986, 0.31044393,True,True
+1440, 0.31173415, 0.30032854,True,True
+1441, 0.31356643, 0.31855199,True,True
+1442, 0.31761871, 0.30690408,True,True
+1443, 0.31971245, 0.30459491,True,True
+1444, 0.31504986, 0.30896132,True,True
+1445, 0.31173415, 0.30896132,True,True
+1446, 0.31510811, 0.31470830,True,True
+1447, 0.31299637, 0.29237810,True,True
+1448, 0.31971245, 0.32003460,True,True
+1449, 0.31504986, 0.30529441,True,True
+1450, 0.30910765, 0.30867649,True,True
+1451, 0.31362440, 0.31652181,True,True
+1452, 0.31157054, 0.29684329,True,True
+1453, 0.32128670, 0.29712804,True,True
+1454, 0.31173415, 0.30500184,True,True
+1455, 0.31510811, 0.29943212,True,True
+1456, 0.31510811, 0.30896132,True,True
+1457, 0.31504986, 0.30896132,True,True
+1458, 0.32450826, 0.30896132,True,True
+1459, 0.31504986, 0.30005166,True,True
+1460, 0.31504986, 0.29523517,True,True
+1461, 0.31504986, 0.30867649,True,True
+1462, 0.30925487, 0.30896132,True,True
+1463, 0.31487530, 0.30896132,True,True
+1464, 0.32122495, 0.29915607,True,True
+1465, 0.31504986, 0.29943212,True,True
+1466, 0.31504986, 0.30896132,True,True
+1467, 0.32122495, 0.30896132,True,True
+1468, 0.31504986, 0.30896132,True,True
+1469, 0.30950795, 0.30867649,True,True
+1470, 0.31362440, 0.30837680,True,True
+1471, 0.30574150, 0.30896132,True,True
+1472, 0.31504986, 0.30896132,True,True
+1473, 0.30799545, 0.29551837,True,True
+1474, 0.31173415, 0.30896132,True,True
+1475, 0.31299637, 0.30896132,True,True
+1476, 0.31504986, 0.30985774,True,True
+1477, 0.30211088, 0.28984380,True,True
+1478, 0.30574150, 0.28984380,True,True
+1479, 0.31504986, 0.30896132,True,True
+1480, 0.31173415, 0.30752306,True,True
+1481, 0.31173415, 0.30500184,True,True
+1482, 0.31155460, 0.29943212,True,True
+1483, 0.31519991, 0.30896132,True,True
+1484, 0.31971245, 0.31044393,True,True
+1485, 0.32122495, 0.30500184,True,True
+1486, 0.31971245, 0.30432456,True,True
+1487, 0.30574150, 0.31044393,True,True
+1488, 0.30338990, 0.30314023,True,True
+1489, 0.31761871, 0.31134034,True,True
+1490, 0.30355810, 0.30287118,True,True
+1491, 0.29630323, 0.28984380,True,True
+1492, 0.30211088, 0.28984380,True,True
+1493, 0.29630323, 0.29142256,True,True
+1494, 0.31155460, 0.30314023,True,True
+1495, 0.31022165, 0.30432456,True,True
+1496, 0.31761871, 0.30459491,True,True
+1497, 0.31519991, 0.29943212,True,True
+1498, 0.30355810, 0.30896132,True,True
+1499, 0.31642362, 0.29490929,True,True
+1500, 0.32122495, 0.30500184,True,True
+1501, 0.31971245, 0.31470830,True,True
+1502, 0.32122495, 0.31134034,True,True
+1503, 0.30574150, 0.29142256,True,True
+1504, 0.31151294, 0.30896132,True,True
+1505, 0.30355810, 0.30073338,True,True
+1506, 0.32122495, 0.30475746,True,True
+1507, 0.30207467, 0.30500184,True,True
+1508, 0.31299637, 0.30896132,True,True
+1509, 0.31971245, 0.31044393,True,True
+1510, 0.31504986, 0.29943212,True,True
+1511, 0.32122495, 0.30432456,True,True
+1512, 0.30207467, 0.30867649,True,True
+1513, 0.31487530, 0.30459491,True,True
+1514, 0.32122495, 0.30896132,True,True
+1515, 0.31510811, 0.30500184,True,True
+1516, 0.32122495, 0.30867649,True,True
+1517, 0.31356643, 0.30867649,True,True
+1518, 0.31504986, 0.30867649,True,True
+1519, 0.32122495, 0.29915607,True,True
+1520, 0.32122495, 0.29943212,True,True
+1521, 0.32122495, 0.30867649,True,True
+1522, 0.31971245, 0.30867649,True,True
+1523, 0.30338990, 0.30896132,True,True
+1524, 0.30207467, 0.29915607,True,True
+1525, 0.30574150, 0.29915607,True,True
+1526, 0.30799545, 0.30896132,True,True
+1527, 0.30557210, 0.31044393,True,True
+1528, 0.30211088, 0.30896132,True,True
+1529, 0.30557210, 0.30896132,True,True
+1530, 0.31510811, 0.30867649,True,True
+1531, 0.31977390, 0.30500184,True,True
+1532, 0.32456826, 0.31825831,True,True
+1533, 0.30557210, 0.30459491,True,True
+1534, 0.30557210, 0.30896132,True,True
+1535, 0.30574150, 0.30867649,True,True
+1536, 0.31173415, 0.31470830,True,True
+1537, 0.30574150, 0.30459491,True,True
+1538, 0.31504986, 0.30896132,True,True
+1539, 0.31971245, 0.30896132,True,True
+1540, 0.31504986, 0.30896132,True,True
+1541, 0.31173415, 0.29943212,True,True
+1542, 0.31179407, 0.28984380,True,True
+1543, 0.30574150, 0.29915607,True,True
+1544, 0.30557210, 0.30896132,True,True
+1545, 0.31761871, 0.29943212,True,True
+1546, 0.31971245, 0.30500184,True,True
+1547, 0.31028128, 0.29937300,True,True
+1548, 0.30361422, 0.29943212,True,True
+1549, 0.31504986, 0.31470830,True,True
+1550, 0.32122495, 0.30867649,True,True
+1551, 0.30425807, 0.32003460,True,True
+1552, 0.31022165, 0.30896132,True,True
+1553, 0.30557210, 0.30432456,True,True
+1554, 0.31504986, 0.30073338,True,True
+1555, 0.32122495, 0.29915607,True,True
+1556, 0.29254018, 0.29079934,True,True
+1557, 0.30799545, 0.30896132,True,True
+1558, 0.30574150, 0.30867649,True,True
+1559, 0.29833142, 0.29712804,True,True
+1560, 0.30815071, 0.31044393,True,True
+1561, 0.31519991, 0.31855199,True,True
+1562, 0.30050028, 0.30867649,True,True
+1563, 0.30574150, 0.29943212,True,True
+1564, 0.30207467, 0.30101088,True,True
+1565, 0.29827408, 0.30500184,True,True
+1566, 0.29613906, 0.28984380,True,True
+1567, 0.29827408, 0.30101088,True,True
+1568, 0.30594117, 0.30523413,True,True
+1569, 0.29630323, 0.29237810,True,True
+1570, 0.31022165, 0.31652181,True,True
+1571, 0.29827408, 0.28984380,True,True
+1572, 0.30815071, 0.30500184,True,True
+1573, 0.30574150, 0.30867649,True,True
+1574, 0.29833142, 0.28984380,True,True
+1575, 0.29988468, 0.29551837,True,True
+1576, 0.29833142, 0.29551837,True,True
+1577, 0.29630323, 0.30500184,True,True
+1578, 0.29472359, 0.29142256,True,True
+1579, 0.31362440, 0.29810228,True,True
+1580, 0.29833142, 0.29237810,True,True
+1581, 0.29411982, 0.28984380,True,True
+1582, 0.29259427, 0.28984380,True,True
+1583, 0.29833142, 0.29551837,True,True
+1584, 0.29833142, 0.30752306,True,True
+1585, 0.32122495, 0.30896132,True,True
+1586, 0.29971195, 0.28581396,True,True
+1587, 0.30557210, 0.30459491,True,True
+1588, 0.29827408, 0.28984380,True,True
+1589, 0.30050028, 0.30529441,True,True
+1590, 0.31022165, 0.30896132,True,True
+1591, 0.31151294, 0.31470830,True,True
+1592, 0.30193687, 0.30867649,True,True
+1593, 0.30050028, 0.29142256,True,True
+1594, 0.30650791, 0.29237810,True,True
+1595, 0.31772620, 0.30529441,True,True
+1596, 0.31173415, 0.29915607,True,True
+1597, 0.31504986, 0.31470830,True,True
+1598, 0.31767977, 0.29237810,True,True
+1599, 0.30574150, 0.29551837,True,True
+1600, 0.29472359, 0.28984380,True,True
+1601, 0.31173415, 0.31470830,True,True
+1602, 0.31173415, 0.30896132,True,True
+1603, 0.30656921, 0.29551837,True,True
+1604, 0.29254018, 0.28438290,True,True
+1605, 0.30799545, 0.30867649,True,True
+1606, 0.31362440, 0.30073338,True,True
+1607, 0.31179407, 0.31044393,True,True
+1608, 0.29254018, 0.29142256,True,True
+1609, 0.31155460, 0.30896132,True,True
+1610, 0.31510811, 0.28296931,True,True
+1611, 0.30799545, 0.30867649,True,True
+1612, 0.30190730, 0.29943212,True,True
+1613, 0.31301650, 0.30101088,True,True
+1614, 0.29827408, 0.29237810,True,True
+1615, 0.29827408, 0.29551837,True,True
+1616, 0.29827408, 0.30867649,True,True
+1617, 0.29810228, 0.29915607,True,True
+1618, 0.29827408, 0.29551837,True,True
+1619, 0.31648690, 0.29237810,True,True
+1620, 0.29827408, 0.29551837,True,True
+1621, 0.31151294, 0.30500184,True,True
+1622, 0.31510811, 0.30494162,True,True
+1623, 0.30799545, 0.28984380,True,True
+1624, 0.29254018, 0.28984380,True,True
+1625, 0.30795653, 0.30494162,True,True
+1626, 0.31510811, 0.31470830,True,True
+1627, 0.31767977, 0.30500184,True,True
+1628, 0.29635801, 0.29237810,True,True
+1629, 0.30050028, 0.29551837,True,True
+1630, 0.29827408, 0.28984380,True,True
+1631, 0.31362440, 0.31470830,True,True
+1632, 0.30799545, 0.30896132,True,True
+1633, 0.30190730, 0.30459491,True,True
+1634, 0.29259427, 0.29551837,True,True
+1635, 0.29630323, 0.28593191,True,True
+1636, 0.29827408, 0.28984380,True,True
+1637, 0.30077292, 0.30500184,True,True
+1638, 0.31028128, 0.31470830,True,True
+1639, 0.30216895, 0.29937300,True,True
+1640, 0.30781805, 0.30896132,True,True
+1641, 0.32122495, 0.29943212,True,True
+1642, 0.31155460, 0.29915607,True,True
+1643, 0.30193687, 0.30985774,True,True
+1644, 0.30579803, 0.30896132,True,True
+1645, 0.32128670, 0.30867649,True,True
+1646, 0.31767977, 0.30500184,True,True
+1647, 0.30050028, 0.29915607,True,True
+1648, 0.31915174, 0.31507285,True,True
+1649, 0.31022165, 0.30867649,True,True
+1650, 0.32137794, 0.30896132,True,True
+1651, 0.31504986, 0.31939614,True,True
+1652, 0.31173415, 0.31015773,True,True
+1653, 0.31022165, 0.30896132,True,True
+1654, 0.30355810, 0.30867649,True,True
+1655, 0.31995240, 0.29379057,True,True
+1656, 0.30799545, 0.30957207,True,True
+1657, 0.31022165, 0.29943212,True,True
+1658, 0.29254018, 0.28984380,True,True
+1659, 0.29411982, 0.28984380,True,True
+1660, 0.30574150, 0.29943212,True,True
+1661, 0.29827408, 0.29551837,True,True
+1662, 0.31022165, 0.30867649,True,True
+1663, 0.30050028, 0.29551837,True,True
+1664, 0.30207467, 0.30529441,True,True
+1665, 0.29411982, 0.28984380,True,True
+1666, 0.31173415, 0.30957207,True,True
+1667, 0.31155460, 0.30896132,True,True
+1668, 0.30050028, 0.29551837,True,True
+1669, 0.32137794, 0.30867649,True,True
+1670, 0.30050028, 0.29551837,True,True
+1671, 0.29827408, 0.29551837,True,True
+1672, 0.29810228, 0.29551837,True,True
+1673, 0.31022165, 0.29142256,True,True
+1674, 0.30574150, 0.30867649,True,True
+1675, 0.29833142, 0.30529441,True,True
+1676, 0.30193687, 0.29551837,True,True
+1677, 0.30557210, 0.28984380,True,True
+1678, 0.31173415, 0.30752306,True,True
+1679, 0.31173415, 0.30500184,True,True
+1680, 0.30805465, 0.30529441,True,True
+1681, 0.30211088, 0.28823281,True,True
+1682, 0.30050028, 0.30500184,True,True
+1683, 0.32122495, 0.28984380,True,True
+1684, 0.30211088, 0.29110264,True,True
+1685, 0.30832874, 0.29551837,True,True
+1686, 0.31022165, 0.29142256,True,True
+1687, 0.32122495, 0.29551837,True,True
+1688, 0.31173415, 0.30529441,True,True
+1689, 0.30799545, 0.29551837,True,True
+1690, 0.29827408, 0.30500184,True,True
+1691, 0.30799545, 0.29913216,True,True
+1692, 0.29827408, 0.29551837,True,True
+1693, 0.30799545, 0.29551837,True,True
+1694, 0.30211088, 0.29559001,True,True
+1695, 0.30815071, 0.28581396,True,True
+1696, 0.30211088, 0.29142256,True,True
+1697, 0.31044357, 0.30529441,True,True
+1698, 0.30228543, 0.28175378,True,True
+1699, 0.30678600, 0.29551837,True,True
+1700, 0.28629917, 0.29551837,True,True
+1701, 0.29591216, 0.28574522,True,True
+1702, 0.29034726, 0.28728941,True,True
+1703, 0.28303909, 0.25687327,True,True
+1704, 0.27345918, 0.24189515,True,True
+1705, 0.23517912, 0.20494745,True,True
+1706, 0.21935835, 0.15486091,True,True
+1707, 0.19576213, 0.13950747,True,True
+1708, 0.17314200, 0.08754263,True,True
+1709, 0.10371662, 0.04376881,True,True
+1710, 0.06000068, 0.02229275,True,True
+1711, 0.04856429, 0.03152671,True,True
+1712, 0.04124562, 0.02231941,True,True
+1713, 0.03545467, 0.02723225,True,True
+1714, 0.01900715, 0.02231941,True,True
+1715, 0.02294366, 0.02937513,True,True
+1716, 0.02294366, 0.03099224,True,True
+1717, 0.02688017, 0.03099224,True,True
+1718, 0.03018699, 0.02937513,True,True
+1719, 0.02294366, 0.03156442,True,True
+1720, 0.00968549, 0.02191482,True,True
+1721, 0.03469072, 0.02723225,True,True
+1722, 0.03075421, 0.02614882,True,True
+1723, 0.03204813, 0.03159143,True,True
+1724, 0.03949763, 0.04212254,True,True
+1725, 0.03961367, 0.03438158,True,True
+1726, 0.04951709, 0.03922323,True,True
+1727, 0.06299380, 0.04215995,True,True
+1728, 0.09133056, 0.05750731,True,True
+1729, 0.10125397, 0.06928630,True,True
+1730, 0.12566668, 0.06496725,True,True
+1731, 0.13628169, 0.08350729,True,True
+1732, 0.15085274, 0.09849424,True,True
+1733, 0.16457867, 0.10090950,True,True
+1734, 0.16813670, 0.13041148,True,True
+1735, 0.18829323, 0.15196716,True,True
+1736, 0.19859985, 0.17333748,True,True
+1737, 0.20898823, 0.17333748,True,True
+1738, 0.20898823, 0.16519316,True,True
+1739, 0.20898823, 0.20500627,True,True
+1740, 0.22648205, 0.15620764,True,True
+1741, 0.24822311, 0.20505075,True,True
+1742, 0.22953975, 0.21498277,True,True
+1743, 0.24001783, 0.21091578,True,True
+1744, 0.24531412, 0.22269145,True,True
+1745, 0.25558643, 0.22380904,True,True
+1746, 0.26730115, 0.23146749,True,True
+1747, 0.25719226, 0.24189515,True,True
+1748, 0.26730115, 0.25210279,True,True
+1749, 0.25196325, 0.25712942,True,True
+1750, 0.28041434, 0.26720305,True,True
+1751, 0.26921606, 0.25402642,True,True
+1752, 0.27845024, 0.27461839,True,True
+1753, 0.27441611, 0.26374794,True,True
+1754, 0.28986496, 0.26374794,True,True
+1755, 0.28826200, 0.26170423,True,True
+1756, 0.28986496, 0.27371859,True,True
+1757, 0.28986496, 0.27720404,True,True
+1758, 0.30273738, 0.28347821,True,True
+1759, 0.29669240, 0.27792197,True,True
+1760, 0.30194124, 0.28155289,True,True
+1761, 0.28986496, 0.28330834,True,True
+1762, 0.31391459, 0.28753504,True,True
+1763, 0.30539196, 0.30141938,True,True
+1764, 0.29833421, 0.29152120,True,True
+1765, 0.30765904, 0.30690408,True,True
+1766, 0.29803680, 0.29523517,True,True
+1767, 0.30765904, 0.30500184,True,True
+1768, 0.31155460, 0.29551837,True,True
diff --git a/tests/test_earfeature.py b/tests/test_earfeature.py
index b31e519..07b0a74 100644
--- a/tests/test_earfeature.py
+++ b/tests/test_earfeature.py
@@ -28,28 +28,30 @@ def test_ear_score_inputs():
with pytest.raises(ValueError):
features.ear_score(input_data)
- # Test case 5: Invalid input range
- input_data = np.array([[-2, 2], [1,4], [4,4], [5,2], [4, 0], [1, 0]])
- with pytest.raises(ValueError):
- features.ear_score(input_data)
+ # TEST DEPRIECATED
+ # Reason: negative values are possible (but rare) and should not raise an error
+ # # Test case 5: Invalid input range
+ # input_data = np.array([[-2, 2], [1,4], [4,4], [5,2], [4, 0], [1, 0]])
+ # with pytest.raises(ValueError):
+ # features.ear_score(input_data)
- # Test case 6: Out of range
+ # Test case 6: Out of range, thus not valid output
input_data = np.array([[0, 2], [1,10], [4,10], [5,2], [4, 0], [1, 0]])
- with pytest.raises(ValueError):
- features.ear_score(input_data)
-
+ score, valid = features.ear_score(input_data)
+ assert not valid
+
def test_ear_score():
# Test case 1: Valid input of sphere
input_data = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
expected_output = 1.0
- assert features.ear_score(input_data) == approx(expected_output)
+ assert features.ear_score(input_data)[0] == approx(expected_output)
# Test case 2: Valid input
input_data = np.array([[0, 2], [1,4], [4,4], [5,2], [4, 0], [1, 0]])
expected_output = (4 + 4) / 10
- assert features.ear_score(input_data) == approx(expected_output)
+ assert features.ear_score(input_data)[0] == approx(expected_output)
# Test case 3: Valid input
input_data = np.array([[0, 2], [1,3], [4,3], [5,2], [4, 1], [1, 1]])
expected_output = (2 + 2) / 10
- assert features.ear_score(input_data) == approx(expected_output)
+ assert features.ear_score(input_data)[0] == approx(expected_output)
|