diff --git a/.github/workflows/pin_requirements.yml b/.github/workflows/pin_requirements.yml index 9394002..0487066 100644 --- a/.github/workflows/pin_requirements.yml +++ b/.github/workflows/pin_requirements.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - python-version: ["3.9", "3.10"] + python-version: ["3.10"] steps: - name: Checkout code uses: actions/checkout@v3 diff --git a/.github/workflows/pypi_main.yml b/.github/workflows/pypi_main.yml index 8fe54fe..5019915 100644 --- a/.github/workflows/pypi_main.yml +++ b/.github/workflows/pypi_main.yml @@ -11,10 +11,10 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 0 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: 3.9 + python-version: "3.10" - name: Install Hatch run: pip install hatch - name: Build diff --git a/.github/workflows/pypi_test.yml b/.github/workflows/pypi_test.yml index 24ad77f..6344faf 100644 --- a/.github/workflows/pypi_test.yml +++ b/.github/workflows/pypi_test.yml @@ -11,10 +11,10 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 0 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: 3.9 + python-version: "3.10" - name: Install Hatch run: pip install hatch - name: Build diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index afba137..4b6c68a 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -7,7 +7,7 @@ jobs: fail-fast: false matrix: os: [ "ubuntu-latest", "macos-latest" , "windows-latest"] - python-version: ["3.9", "3.10" ] + python-version: ["3.10" ] defaults: run: shell: bash diff --git a/dont_fret/config/config.py b/dont_fret/config/config.py index 3a1d49b..93dc0ce 100644 --- a/dont_fret/config/config.py +++ b/dont_fret/config/config.py @@ -28,6 +28,7 @@ class BurstFilterItem: name: str min: Optional[float] = field(default=None) max: Optional[float] = field(default=None) + active: bool = field(default=True) def as_expr(self) -> list[pl.Expr]: expr = [] diff --git a/dont_fret/models.py b/dont_fret/models.py index 7a78841..418d1d4 100644 --- a/dont_fret/models.py +++ b/dont_fret/models.py @@ -73,6 +73,11 @@ def cps(self) -> float: """Average count rate (counts per second / Hz)""" return len(self) / float(self.photon_times.max()) # type: ignore + @property + def duration(self) -> Optional[float]: + """user-specified duration in seconds, obtained from metadata""" + return self.metadata.get("acquisition_duration") + def __getitem__(self, key): # TODO sort when slicing backwards? return self.__class__(self.data[key], metadata=self.metadata, cfg=self.cfg) @@ -132,7 +137,7 @@ def nanotimes_unit(self) -> Optional[float]: def tau_mean(self) -> float: """Mean of the nanotimes (in seconds). Sometimes referred to as 'fast lifetime' as it is fast to compute""" if self.nanotimes is not None and self.nanotimes_unit is not None: - return self.nanotimes.mean() * self.nanotimes_unit + return self.nanotimes.mean() * self.nanotimes_unit # type: ignore else: return np.nan @@ -365,10 +370,16 @@ def __init__( self.metadata: dict = metadata or {} self.cfg = cfg + # number of photons per stream per burst agg = [(pl.col("stream") == stream).sum().alias(f"n_{stream}") for stream in cfg.streams] + + # mean nanotimes per stream per burst agg.extend( [ - pl.when(pl.col("stream") == k).then(pl.col("nanotimes")).mean().alias(f"tau_{k}") + pl.when(pl.col("stream") == k) + .then(pl.col("nanotimes")) + .mean() + .alias(f"nanotimes_{k}") for k in cfg.streams ] ) @@ -387,6 +398,8 @@ def __init__( photon_data["burst_index"].unique_counts().alias("n_photons"), ] + # TODO These should move somewhere else; possibly some second step conversion + # from raw stamps to times t_unit = self.metadata.get("timestamps_unit", None) if t_unit is not None: columns.extend( @@ -397,6 +410,14 @@ def __init__( ), ] ) + nanotimes_unit = self.metadata.get("nanotimes_unit", None) + if nanotimes_unit is not None: + columns.extend( + [ + pl.col(f"nanotimes_{stream}").mul(nanotimes_unit).alias(f"tau_{stream}") + for stream in cfg.streams + ] + ) self.burst_data = ( self.photon_data.group_by("burst_index", maintain_order=True) diff --git a/dont_fret/process.py b/dont_fret/process.py index 2ae17e0..421fe29 100644 --- a/dont_fret/process.py +++ b/dont_fret/process.py @@ -41,7 +41,7 @@ def search_and_save( def write_dataframe(df: pl.DataFrame, path: Path) -> None: - """Write a dataframe to disk. Writier used depends on path suffix.""" + """Write a dataframe to disk. Writer used depends on path suffix.""" if path.suffix == ".pq": df.write_parquet(path) elif path.suffix == ".csv": diff --git a/dont_fret/tmp.py b/dont_fret/tmp.py index 1458dbe..82646c8 100644 --- a/dont_fret/tmp.py +++ b/dont_fret/tmp.py @@ -1,51 +1,53 @@ +import uuid +from dataclasses import replace +from functools import reduce +from itertools import chain +from operator import and_ from pathlib import Path +from typing import Callable, Dict, List, Optional, Type, TypedDict, Union +import altair as alt +import numpy as np import solara import solara.lab import yaml import dont_fret.web.state as state -from dont_fret.config.config import cfg -from dont_fret.web.dev import load_burst_items, load_file_items +from dont_fret.config.config import BurstFilterItem, cfg +from dont_fret.web.bursts import BurstPage +from dont_fret.web.bursts.components import BurstFigure, BurstFigureSelection +from dont_fret.web.components import RegexSelectDialog from dont_fret.web.home import HomePage from dont_fret.web.main import Page as MainPage -from dont_fret.web.models import FRETNode +from dont_fret.web.models import BurstNode, ListStore, PhotonNode +from dont_fret.web.trace import TracePage +from dont_fret.web.utils import ( + find_index, + find_object, + get_bursts, + make_selector_nodes, + wrap_callback, +) data = yaml.safe_load(Path("default_testing.yaml").read_text()) cfg.update(data) +style = """ +.vega-embed { + overflow: visible; + width: 100% !important; +} +""" -# TODO default burst searches from config -DCBS_TEST = {"DD + DA": {"L": 50, "M": 35, "T": 0.0005}, "AA": {"L": 50, "M": 35, "T": 0.0005}} -APBS_TEST = {"DD + DA + AA": {"L": 50, "M": 35, "T": 0.0005}} +my_selection = ListStore([]) -pth = "ds2" -photon_file_items = load_file_items(pth) -# burst_items = load_burst_items(pth, suffix=".csv") +values = ["a", "b1", "c1", "d3"] -fret_nodes = [ - FRETNode( - name="FRET NOT", - photons=photon_file_items, - # bursts=burst_items, - ), -] - -# %% +state.disable_burst_page.set(False) +state.disable_trace_page.set(False) @solara.component def Page(): - def preload(): - # state.FRET_NODES.set([]) - if len(state.fret_nodes.value) == 0: - state.fret_nodes.extend(fret_nodes) - - solara.use_effect(preload, dependencies=[]) - nodes = state.fret_nodes.value - - if len(nodes) != 0: - with solara.Column(style={"height": "100%"}): - MainPage() - else: - solara.Text("Loading fret nodes...") + solara.Style(style) + MainPage() diff --git a/dont_fret/web/bursts/components.py b/dont_fret/web/bursts/components.py index 0eac72c..d37ee82 100644 --- a/dont_fret/web/bursts/components.py +++ b/dont_fret/web/bursts/components.py @@ -1,9 +1,10 @@ from __future__ import annotations -import re -from typing import Callable, Literal, Optional, cast +import uuid +from dataclasses import dataclass, field, replace +from typing import Callable, Literal, Optional, TypeVar, cast -import numpy as np +import altair as alt import plotly.express as px import plotly.graph_objects as go import polars as pl @@ -11,377 +12,265 @@ import solara.lab from plotly.subplots import make_subplots from solara.alias import rv -from solara.toestand import Ref -from dont_fret.web.bursts.methods import create_histogram -from dont_fret.web.components import RangeInputField +import dont_fret.web.state as state +from dont_fret.web.components import FigureFromTask, RangeInputField, RegexSelectDialog from dont_fret.web.methods import chain_filters -from dont_fret.web.models import BinnedImage, BurstFilterItem, BurstItem, BurstPlotSettings -from dont_fret.web.reactive import ReactiveFRETNodes -from dont_fret.web.utils import not_none +from dont_fret.web.models import ( + BinnedImage, + BurstFilterItem, + BurstNode, + BurstPlotSettings, + FRETNode, + FRETStore, + ListStore, + use_liststore, +) +from dont_fret.web.utils import ( + NestedSelectors, + find_index, + find_object, + get_bursts, + make_selector_nodes, +) N_STEP = 1000 # number slider steps CMAP = px.colors.sequential.Viridis WRATIO = 3.5 +DEFAULT_FIELD = "n_photons" +# TODO this is hardcoded but it depends on cfg settings what fields burst item dataframes have +# -> deduce from selection +FIELD_OPTIONS = [ + "burst_index", + "n_DD", + "n_DA", + "n_AA", + "n_AD", + "nanotimes_DD", + "nanotimes_DA", + "nanotimes_AA", + "nanotimes_AD", + "timestamps_mean", + "timestamps_min", + "timestamps_max", + "E_app", + "S_app", + "n_photons", + "time_mean", + "time_length", + "tau_DD", + "tau_DA", + "tau_AA", + "tau_AD", +] + + +def fd_bin_width(data: pl.Series) -> float: + """ + Calculate bin width using the Freedman-Diaconis rule: + bin width = 2 * IQR * n^(-1/3) + where IQR is the interquartile range and n is the number of observations + """ + q75, q25 = data.quantile(0.75), data.quantile(0.25) + assert q75 is not None + assert q25 is not None + iqr = q75 - q25 + n = len(data) + return 2 * iqr * (n ** (-1 / 3)) + + +def make_chart(df: pl.DataFrame, field: str, opacity: float = 1.0): + chart = ( + alt.Chart(df.select(pl.col(field))) + .mark_rect(opacity=opacity) + .transform_bin( + as_=["x", "x2"], + field=field, + bin=alt.Bin(step=fd_bin_width(df[field])), + ) + .encode( + x=alt.X("x:Q", scale={"zero": False}, title=field), + x2="x2:Q", + y=alt.Y("count():Q", title="count"), + tooltip=[ + alt.Tooltip("bin_center:Q", title="Bin center", format=".3g"), + alt.Tooltip("count():Q", title="Count", format=","), + ], + ) + .transform_calculate( + bin_center="(datum.x + datum.x2) / 2" # Calculate bin center + ) + # .add_params(selection) # Add the selection to the chart + .properties(width="container") + ) + return chart -@solara.component -def FigurePlotlyShapes( - fig: go.Figure, - shapes: dict, - dependencies=None, -): - from plotly.graph_objs._figurewidget import FigureWidget - - fig_element = FigureWidget.element() # type: ignore - - def update_data(): - fig_widget: FigureWidget = solara.get_widget(fig_element) # type: ignore - fig_widget.layout = fig.layout - length = len(fig_widget.data) # type: ignore - fig_widget.add_traces(fig.data) - data = list(fig_widget.data) - fig_widget.data = data[length:] +def make_overlay_chart( + df: pl.DataFrame, field: str, filters: list[BurstFilterItem] +) -> alt.LayerChart | alt.Chart: + f = chain_filters(filters) + df_f = df.filter(f) - def update_shapes(): - if shapes: - fig_widget: FigureWidget = solara.get_widget(fig_element) # type: ignore - fig_widget.update_shapes(**shapes) + base_chart = make_chart(df, field, opacity=0.5) + selection = alt.selection_interval(name="range", encodings=["x"]) - solara.use_effect(update_data, dependencies or fig) - solara.use_effect(update_shapes, shapes) + if len(df_f) > 0: + filtered_chart = make_chart(df_f, field).add_params(selection) + chart = base_chart + filtered_chart + else: + chart = base_chart.add_params(selection) - return fig_element + return chart @solara.component -def EditFilterDialog( - filter_item: solara.Reactive[BurstFilterItem], # should be a reactive - data: np.ndarray, - on_close: Callable[[], None], -): - def bin_data(): - data_f = data[~np.isnan(data)] - counts, binspace = np.histogram(data_f, bins="fd") - xbins = {"start": binspace[0], "end": binspace[-1], "size": binspace[1] - binspace[0]} - arange = 2 * binspace[0] - 0.05 * binspace[-1], 1.05 * binspace[-1] - binspace[0] - - return data_f, xbins, arange +def SelectionChart(chart: alt.Chart | alt.LayerChart, on_selection): + jchart = alt.JupyterChart.element(chart=chart, embed_options={"actions": False}) # type: ignore - data_f, xbins, arange = solara.use_memo(bin_data, []) - - xr_default = ( - not_none(filter_item.value.min, arange[0]), - not_none(filter_item.value.max, arange[1]), - ) + def bind(): + widget = cast(alt.JupyterChart, solara.get_widget(jchart)) + widget.selections.observe(on_selection, "range") - xrange, set_xrange = solara.use_state(xr_default) - shapes, set_shapes = solara.use_state({}) + solara.use_effect(bind, [chart]) - def make_figure(): - return create_histogram(data_f, xbins, arange, xrange) - fig = solara.use_memo(make_figure, []) - - show_slider, set_show_slider = solara.use_state(True) +@solara.component +def FilterItemCard(filter_item: BurstFilterItem): + text_style = { + "fontWeight": "bold", + "fontSize": "16px", + "padding": "8px 0", + } + with solara.Card(title=None): + with solara.Row(style={"align-items": "end"}, justify="space-between"): + solara.Text(filter_item.name, style=text_style) + with solara.Row(style={"align-items": "end"}, gap="1px"): + + def on_checkbox(value: bool, filter_item=filter_item): + idx = state.filters.index(filter_item) + state.filters.update(idx, active=value) + + solara.Checkbox(label="", style="marginBottom: -16px", on_value=on_checkbox) + + def on_delete(filter_item=filter_item): + state.filters.remove(filter_item) - def update_xmin(value): - set_xrange((value, xrange[1])) - d = {"patch": dict(x0=arange[0], x1=value), "selector": 0} - set_shapes(d) + solara.IconButton( + icon_name="delete", + on_click=on_delete, + ) - def update_xmax(value): - set_xrange((xrange[0], value)) - d = {"patch": dict(x0=value, x1=arange[1]), "selector": 1} - set_shapes(d) + with solara.Row(): - def on_slider(value: tuple[float, float]): - if value[0] != xrange[0]: - d = {"patch": dict(x0=arange[0], x1=value[0]), "selector": 0} - elif value[1] != xrange[1]: - d = {"patch": dict(x0=value[1], x1=arange[1]), "selector": 1} - else: - return - set_shapes(d) - set_xrange(value) + def on_vmin(value, filter_item=filter_item): + idx = state.filters.index(filter_item) + state.filters.update(idx, min=value) - with solara.Card(f"Filter: {filter_item.value.name}"): - FigurePlotlyShapes(fig, shapes=shapes) - step = (arange[1] - arange[0]) / N_STEP - with solara.Row(): - with solara.Tooltip( - "Disable slider to prevent threshold value rounding." # type: ignore - ): - rv.Switch(v_model=show_slider, on_v_model=set_show_slider) - if show_slider: - solara.SliderRangeFloat( - label="", - min=arange[0], - max=arange[1], - value=xrange, - step=step, - on_value=on_slider, - ) - with solara.Row(): - RangeInputField( - label="Min", - value=xrange[0], - vtype=float, - on_value=update_xmin, - vmin=arange[0], - ) RangeInputField( - label="Max", - value=xrange[1], + label="Lower bound", + value=filter_item.min, + on_value=on_vmin, + vmax=filter_item.max, vtype=float, - on_value=update_xmax, - vmax=arange[1], + allow_none=True, ) - def on_save(): - new_filter = BurstFilterItem( - filter_item.value.name, - min=xrange[0], - max=xrange[1], - ) - filter_item.set(new_filter) - on_close() - - with solara.CardActions(): - rv.Spacer() - solara.Button("Save", icon_name="mdi-content-save", on_click=on_save) - solara.Button("Cancel", icon_name="mdi-window-close", on_click=on_close) + def on_vmax(value, filter_item=filter_item): + idx = state.filters.index(filter_item) + state.filters.update(idx, max=value) - -@solara.component -def FilterListItem( - filter_item: solara.Reactive[BurstFilterItem], data: np.ndarray, on_delete: Callable[[], None] -): - edit, set_edit = solara.use_state(False) - with rv.ListItem(): - rv.ListItemAvatar(children=[rv.Icon(children=["mdi-filter"])]) - rv.ListItemTitle(children=[filter_item.value.name]) - - # TODO multi line - def fmt(v): - if v is None: - return "None" - else: - return f"{v:.5g}" - - rv.ListItemSubtitle( - children=[f"{fmt(filter_item.value.min)} - {fmt(filter_item.value.max)}"] - ) - - solara.IconButton( - color="secondary", - small=True, - rounded=True, - icon_name="mdi-delete", - on_click=on_delete, - ) - - solara.IconButton( - color="secondary", - small=True, - rounded=True, - icon_name="mdi-pencil", - on_click=lambda: set_edit(True), - ) - - with rv.Dialog(v_model=edit, max_width=750, on_v_model=set_edit): - if edit: - EditFilterDialog( - filter_item, - data, - on_close=lambda: set_edit(False), + RangeInputField( + label="Upper bound", + value=filter_item.max, + on_value=on_vmax, + vmin=filter_item.min, + vtype=float, + allow_none=True, ) -DTYPES = { - "E_app": float, - "S_app": float, - "n_photons": int, - "time_length": float, - "time_mean": float, - "time_min": float, - "time_max": float, - "n_DD": int, - "n_DA": int, - "n_AA": int, - "n_AD": int, - "tau_DD": float, - "tau_DA": float, - "tau_AA": float, - "tau_AD": float, -} - - @solara.component -def BurstFilters(filters: solara.Reactive[list[BurstFilterItem]], dataframe: pl.DataFrame): - f_names = [f.name for f in filters.value] - attrs = [k for k in DTYPES if k not in f_names] - new_filter_name, set_new_filter_name = solara.use_state(attrs[0]) - - with solara.Card(title="Global filters"): - with rv.List(dense=False): - for idx, flt in enumerate(filters.value): - - def on_delete(idx=idx): - new_filters = filters.value.copy() - del new_filters[idx] - filters.set(new_filters) - - arr = dataframe[flt.name].to_numpy() - FilterListItem(Ref(filters.fields[idx]), arr, on_delete) - - def add_filter(): - item = BurstFilterItem(name=new_filter_name) - new_filters = filters.value.copy() - new_filters.append(item) - filters.set(new_filters) - - solara.Select( - label="Filter attribute", - value=new_filter_name, - values=attrs, - on_value=set_new_filter_name, - ) - solara.Button("Add filter", on_click=lambda: add_filter(), block=True) - - -def generate_figure( - df: pl.DataFrame, - plot_settings: BurstPlotSettings, - binned_image: BinnedImage, - dark: bool = False, -) -> go.Figure: - fig = make_subplots( - rows=2, - cols=2, - shared_yaxes="rows", # type: ignore - shared_xaxes="columns", # type: ignore - horizontal_spacing=0.02, - vertical_spacing=0.02, - column_widths=[WRATIO, 1], - row_heights=[1, WRATIO], +def FilterEditDialog(): + field = solara.use_reactive(DEFAULT_FIELD) + chart_selection = solara.use_reactive(None) + existing_filter_fields = [f.name for f in state.filters] + + burst_node_choice = use_liststore([]) + selector_nodes = make_selector_nodes(state.fret_nodes.items, attr="bursts") + selectors = NestedSelectors( + nodes=selector_nodes, selection=burst_node_choice, labels=["Measurement", "Bursts"] ) - - if sum([plot_settings.z_min is None, plot_settings.z_max is None]) == 1: - raise ValueError("z_min and z_max must be both None or both not None") - - hist2d = go.Heatmap( - x=binned_image.x, - y=binned_image.y, - z=binned_image.img_data.T, - zmin=plot_settings.z_min, - zmax=plot_settings.z_max, - colorscale=CMAP, - colorbar={"title": "Counts"}, + levels = list(selectors) + burst_node = get_bursts(state.fret_nodes.items, burst_node_choice.items) + + def make_chart(): + new_chart = make_overlay_chart(burst_node.df, field.value, state.filters.items) + return new_chart + + def on_download(): + f = chain_filters(state.filters.items) + df_f = burst_node.df.filter(f) + return df_f.write_csv() + + # note: cant be 100% sure but you could get some panicking threads when using + # vegafusion in a use_task hook with prefer_threaded=True + task_chart = solara.lab.use_task( # type: ignore + make_chart, + dependencies=[field.value, state.filters.items, burst_node_choice.items], + prefer_threaded=False, ) - fig.add_trace(hist2d, row=2, col=1) - fig.update_xaxes(row=2, col=1, range=plot_settings.x_range, title=plot_settings.x_name) - fig.update_yaxes(row=2, col=1, range=plot_settings.y_range, title=plot_settings.y_name) - - if dark: - hist_settings = { - "marker_color": "#adadad", - } - else: - hist_settings = { - "marker_color": "#330C73", - } - - histx = go.Histogram( - x=df[plot_settings.x_name], - xbins=plot_settings.xbins, - name=plot_settings.x_name, - **hist_settings, - ) - fig.add_trace(histx, row=1, col=1) - fig.update_yaxes(row=1, col=1, title="counts") - - histy = go.Histogram( - y=df[plot_settings.y_name], - ybins=plot_settings.ybins, - name=plot_settings.y_name, - **hist_settings, - ) - fig.add_trace( - histy, - row=2, - col=2, - ) - fig.update_xaxes(row=2, col=2, title="counts") - fig.update_layout( - width=700, - height=700, - showlegend=False, - margin=dict(l=20, r=20, t=20, b=20), - template="plotly_dark" if dark else "plotly_white", - ) + def filter_from_selection(): + """adds or edits a filter based on the current selection in the chart""" + try: + vmin, vmax = chart_selection.value["new"].value["x"] # type: ignore + except (KeyError, TypeError): + vmin, vmax = None, None + + if field.value in existing_filter_fields: + current_item_idx = find_index(state.filters.items, name=field.value) + current_item = state.filters.items[current_item_idx] + new_item = replace(current_item, min=vmin, max=vmax) + state.filters.set_item(current_item_idx, new_item) + else: + filter_item = BurstFilterItem(name=field.value, min=vmin, max=vmax) + state.filters.append(filter_item) - return fig + with solara.ColumnsResponsive([8, 4]): + with solara.Card("Histogram"): + with solara.Row(style={"align-items": "center"}): + for level in levels: + solara.Select(**level) + with solara.FileDownload( + on_download, filename=f"{burst_node.name}_filtered_bursts.csv" + ): + with solara.Tooltip("Download filtered data as .csv"): + solara.IconButton("mdi-file-download", on_click=on_download) -@solara.component -def FileFilterDialog( - burst_item: solara.Reactive[BurstItem], - on_close: Callable[[], None], -): - all_files = sorted(burst_item.value.df["filename"].unique()) - local_selected_files = solara.use_reactive(cast(list[str], burst_item.value.selected_files)) - error, set_error = solara.use_state("") - regex, set_regex = solara.use_state("") + with solara.Row(style={"align-items": "center"}): - def on_input(value: str): - try: - pattern = re.compile(value) - set_error("") - except Exception: - set_error("Invalid regex") - set_regex(value) - return - new_selected = [f for f in all_files if pattern.search(f)] - local_selected_files.set(new_selected) + def on_field(value): + chart_selection.set(None) + field.set(value) - def on_save(): - if not local_selected_files.value: - return - burst_item.update(selected_files=local_selected_files.value) - # selected_files.set(local_selected_files.value) - on_close() - - with solara.Card("File Filter"): - with solara.Row(style="align-items: center;"): - solara.InputText( - label="regex", value=regex, on_value=on_input, continuous_update=True, error=error - ) - solara.Button(label="Select All", on_click=lambda: local_selected_files.set(all_files)) - solara.Button(label="Select None", on_click=lambda: local_selected_files.set([])) - with solara.v.List(nav=True): - with solara.v.ListItemGroup( - v_model=local_selected_files.value, - on_v_model=local_selected_files.set, - multiple=True, - ): - for filename in all_files: - with solara.v.ListItem(value=filename): - with solara.v.ListItemAction(): - solara.Checkbox(value=filename in local_selected_files.value) - solara.v.ListItemTitle(children=[filename]) - - with solara.CardActions(): - solara.v.Spacer() - solara.Button( - "Save", - icon_name="mdi-content-save", - on_click=on_save, - disabled=not local_selected_files.value, - ) - solara.Button("Close", icon_name="mdi-window-close", on_click=on_close) + solara.Select( + label="Field", value=field.value, values=FIELD_OPTIONS, on_value=on_field + ) + with solara.Tooltip("Add or edit filter"): + solara.IconButton("mdi-filter-plus", on_click=filter_from_selection) + if task_chart.latest is None: + solara.Text("loading...") + else: + chart = task_chart.value if task_chart.finished else task_chart.latest + assert chart is not None + with solara.Div(style="opacity: 0.3" if task_chart.pending else None): + SelectionChart(chart, on_selection=chart_selection.set) + with solara.Column(): + for filter_item in state.filters: + FilterItemCard(filter_item) @solara.component @@ -434,8 +323,11 @@ def rebin(): # only *some* of copy's attributes should trigger the redraw (specifically not z_min, z_max) redraw_attrs = ["x_name", "y_name", "x_min", "x_max", "y_min", "y_max", "nbinsx", "nbinsy"] + + # TODO use_task bin_result = solara.use_thread( - rebin, dependencies=[getattr(copy.value, attr) for attr in redraw_attrs] + rebin, # type: ignore + dependencies=[getattr(copy.value, attr) for attr in redraw_attrs], ) disabled = bin_result.state == solara.ResultState.RUNNING with solara.Card("Plot Settings"): @@ -460,7 +352,6 @@ def rebin(): on_value=lambda val: copy.update(x_min=val), vtype=float, vmax=copy.value.x_max, - enable_restore=False, ) RangeInputField( @@ -469,7 +360,6 @@ def rebin(): on_value=lambda val: copy.update(x_max=val), vtype=float, vmin=copy.value.x_min, - enable_restore=False, ) solara.IconButton( icon_name="mdi-auto-fix", @@ -483,7 +373,6 @@ def rebin(): on_value=lambda val: copy.update(y_min=val), vtype=float, vmax=copy.value.y_max, - enable_restore=False, ) RangeInputField( @@ -492,7 +381,6 @@ def rebin(): on_value=lambda val: copy.update(y_max=val), vtype=float, vmin=copy.value.y_min, - enable_restore=False, ) solara.IconButton( @@ -509,7 +397,6 @@ def rebin(): on_value=lambda val: copy.update(z_min=val), vtype=float, vmax=copy.value.z_max, - enable_restore=False, disabled=disabled, ) RangeInputField( @@ -518,7 +405,6 @@ def rebin(): on_value=lambda val: copy.update(z_max=val), vtype=float, vmin=copy.value.z_min, - enable_restore=False, disabled=disabled, ) @@ -546,103 +432,288 @@ def rebin(): solara.Button("Close", icon_name="mdi-window-close", on_click=on_close) -# burst item model could have plotsettings instance as child to keep the state +@solara.component_vue("select_count.vue") +def SelectCount(label, value, on_value, items, item_name="item"): + pass + + +T = TypeVar("T") + + +@dataclass +class BurstFigureSelection: + fret_store: FRETStore + + # TODO make sure it can not be None -> always some uuid + # maybe we should make a class which solves the interdependent select for n states + # and it should also be able to deal with deletions in the tree + # and it takes the full tree as input + fret_id: solara.Reactive[uuid.UUID | None] = field( + default_factory=lambda: solara.reactive(None) + ) + burst_id: solara.Reactive[uuid.UUID | None] = field( + default_factory=lambda: solara.reactive(None) + ) + + # keys are tuple of (fret_id, burst_id) + # values are hex values of the photon item uuids + selection_store: solara.Reactive[dict[tuple[uuid.UUID, uuid.UUID], list[str]]] = field( + default_factory=lambda: solara.reactive({}) + ) + + def __post_init__(self): + self.fret_store._reactive.subscribe(self.on_fret_store) + self.reset() + + def on_fret_store(self, new_value: list[FRETNode]): + options = [fret_node.id for fret_node in new_value] + if self.fret_id.value not in options: + self.reset() + + def reset(self): + if self.has_bursts: + fret_node = self.fret_nodes_with_bursts[0] + self.set_fret_id(fret_node.id.hex) + else: + self.fret_id.set(None) + self.burst_id.set(None) + + @property + def is_set(self) -> bool: + return bool(self.fret_id.value) and bool(self.burst_id.value) + + @property + def fret_nodes_with_bursts(self) -> list[FRETNode]: + return [node for node in self.fret_store if node.bursts] + + @property + def has_bursts(self) -> bool: + return bool(self.fret_nodes_with_bursts) + + @property + def fret_values(self) -> list[dict]: + return [ + {"text": node.name.value, "value": node.id.hex} for node in self.fret_nodes_with_bursts + ] + + @property + def burst_values(self) -> list[dict]: + return [{"text": node.name, "value": node.id.hex} for node in self.fret_node.bursts] + + @property + def fret_node(self) -> FRETNode: + return find_object(self.fret_nodes_with_bursts, id=self.fret_id.value) + + @property + def burst_node(self) -> BurstNode: + return find_object(self.fret_node.bursts.items, id=self.burst_id.value) + + @property + def selected_files_values(self) -> list[dict]: + return [{"text": node.name, "value": node.id.hex} for node in self.burst_node.photon_nodes] + + @property + def selected_files(self) -> list[str]: + assert self.fret_id.value is not None + assert self.burst_id.value is not None + stored = self.selection_store.value.get((self.fret_id.value, self.burst_id.value), []) + + if stored: + return stored + + return [item["value"] for item in self.selected_files_values] + + def set_fret_id(self, value: str): + self.fret_id.set(uuid.UUID(value)) + + # set the first burst node as the default value + burst_node = self.fret_node.bursts[0] + self.burst_id.set(burst_node.id) + + def set_burst_id(self, value: str): + self.burst_id.set(uuid.UUID(value)) + + def set_selected_files(self, values: list[str]): + new_value = self.selection_store.value.copy() + assert self.fret_id.value is not None + assert self.burst_id.value is not None + new_value[(self.fret_id.value, self.burst_id.value)] = values + self.selection_store.value = new_value + + +def generate_figure( + df: pl.DataFrame, + plot_settings: BurstPlotSettings, + binned_image: BinnedImage, + dark: bool = False, +) -> go.Figure: + fig = make_subplots( + rows=2, + cols=2, + shared_yaxes="rows", # type: ignore + shared_xaxes="columns", # type: ignore + horizontal_spacing=0.02, + vertical_spacing=0.02, + column_widths=[WRATIO, 1], + row_heights=[1, WRATIO], + ) + + if sum([plot_settings.z_min is None, plot_settings.z_max is None]) == 1: + raise ValueError("z_min and z_max must be both None or both not None") + + hist2d = go.Heatmap( + x=binned_image.x, + y=binned_image.y, + z=binned_image.img_data.T, + zmin=plot_settings.z_min, + zmax=plot_settings.z_max, + colorscale=CMAP, + colorbar={"title": "Counts"}, + ) + + fig.add_trace(hist2d, row=2, col=1) + fig.update_xaxes(row=2, col=1, range=plot_settings.x_range, title=plot_settings.x_name) + fig.update_yaxes(row=2, col=1, range=plot_settings.y_range, title=plot_settings.y_name) + + if dark: + hist_settings = { + "marker_color": "#adadad", + } + else: + hist_settings = { + "marker_color": "#330C73", + } + + histx = go.Histogram( + x=df[plot_settings.x_name], + xbins=plot_settings.xbins, + name=plot_settings.x_name, + **hist_settings, + ) + fig.add_trace(histx, row=1, col=1) + fig.update_yaxes(row=1, col=1, title="counts") + + histy = go.Histogram( + y=df[plot_settings.y_name], + ybins=plot_settings.ybins, + name=plot_settings.y_name, + **hist_settings, + ) + fig.add_trace( + histy, + row=2, + col=2, + ) + fig.update_xaxes(row=2, col=2, title="counts") + fig.update_layout( + width=700, + height=700, + showlegend=False, + margin=dict(l=20, r=20, t=20, b=20), + template="plotly_dark" if dark else "plotly_white", + ) + + return fig + + @solara.component def BurstFigure( - fret_nodes: ReactiveFRETNodes, - global_filters: solara.Reactive[list[BurstFilterItem]], - node_idx: Optional[solara.Reactive[int]] = None, - burst_idx: Optional[solara.Reactive[int]] = None, + fret_nodes: list[FRETNode], + selection: ListStore[str] | list[str] | None = None, + file_selection: dict[uuid.UUID, ListStore[str]] | None = None, ): - node_idx = solara.use_reactive(node_idx if node_idx is not None else 0) - burst_idx = solara.use_reactive(burst_idx if burst_idx is not None else 0) + settings_dialog = solara.use_reactive(False) + file_filter_dialog = solara.use_reactive(False) + plot_settings = solara.use_reactive( + BurstPlotSettings() + ) # -> these reset to default, move to global state? pass as kwarg? - figure, set_figure = solara.use_state(cast(Optional[go.Figure], None)) - edit_filter, set_edit_filter = solara.use_state(False) - edit_settings, set_edit_settings = solara.use_state(False) - plot_settings = solara.use_reactive(BurstPlotSettings()) + selection = use_liststore(selection if selection is not None else []) + file_selection = {} if file_selection is None else file_selection dark_effective = solara.lab.use_dark_effective() - node_ref = Ref(fret_nodes.fields[node_idx.value]) - burst_ref = Ref(fret_nodes.fields[node_idx.value].bursts[burst_idx.value]) - - has_bursts = (node for node in fret_nodes.value if node.bursts) - node_values = [{"text": node.name, "value": i} for i, node in enumerate(has_bursts)] - - burst_item_values = [ - {"text": burst_item.name, "value": i} for i, burst_item in enumerate(node_ref.value.bursts) - ] + labels = ["Measurement", "Bursts"] # TODO move elsewhere + selector_nodes = make_selector_nodes(fret_nodes, "bursts") + # making the levels populates the selection + levels = list(NestedSelectors(nodes=selector_nodes, selection=selection, labels=labels)) + burst_node = get_bursts(fret_nodes, selection.items) + filenames = sorted(burst_node.df["filename"].unique()) + if burst_node.id in file_selection: + file_store = file_selection[burst_node.id] + else: + file_store = ListStore(filenames) + file_selection[burst_node.id] = file_store - file_filter = pl.col("filename").is_in(burst_ref.value.selected_files) - f_expr = chain_filters(global_filters.value) & file_filter + file_filter = pl.col("filename").is_in(file_store.items) + f_expr = chain_filters(state.filters.items) & file_filter - # this is triggered twice ? + # this is triggered twice ? -> known plotly bug, use .key(...) def redraw(): - filtered_df = burst_ref.value.df.filter(f_expr) + filtered_df = burst_node.df.filter(f_expr) img = BinnedImage.from_settings(filtered_df, plot_settings.value) figure = generate_figure( filtered_df, plot_settings.value, binned_image=img, dark=dark_effective ) - set_figure(figure) + return figure - # does hashability matter in speed? - fig_result = solara.use_thread( + figure_task = solara.lab.use_task( # type: ignore redraw, - dependencies=[ - node_idx.value, - burst_idx.value, - plot_settings.value, - global_filters.value, - burst_ref.value.selected_files, - dark_effective, - ], - intrusive_cancel=False, # is much faster + dependencies=[burst_node.id, plot_settings.value, file_store.items, state.filters.items], ) - def on_fret_node(value: int): - node_idx.set(value) - burst_idx.set(0) - with solara.Card(): with solara.Row(): - solara.Select( - label="Measurement", - value=node_idx.value, - on_value=on_fret_node, # type: ignore - values=node_values, # type: ignore - ) + for level in levels: + solara.Select(**level) - solara.Select( - label="Burst item", - value=burst_idx.value, - on_value=burst_idx.set, - values=burst_item_values, # type: ignore + solara.IconButton( + icon_name="mdi-file-star", on_click=lambda: file_filter_dialog.set(True) ) + solara.IconButton(icon_name="mdi-settings", on_click=lambda: settings_dialog.set(True)) + + FigureFromTask(figure_task) + + with solara.v.Dialog( + v_model=settings_dialog.value, max_width=750, on_v_model=settings_dialog.set + ): + PlotSettingsEditDialog( + plot_settings, + burst_node.df.filter(f_expr), # = filtered dataframe by global filter + on_close=lambda: settings_dialog.set(False), + duration=burst_node.duration, + ) - solara.IconButton(icon_name="mdi-file-star", on_click=lambda: set_edit_filter(True)) - solara.IconButton(icon_name="mdi-settings", on_click=lambda: set_edit_settings(True)) - - solara.ProgressLinear(fig_result.state == solara.ResultState.RUNNING) - if figure is not None: - with solara.Div( - style="opacity: 0.3" if fig_result.state == solara.ResultState.RUNNING else None - ): - solara.FigurePlotly(figure) - - # dedent this and figure will flicker/be removed when opening the dialog - if edit_settings: - with rv.Dialog(v_model=edit_settings, max_width=750, on_v_model=set_edit_settings): - PlotSettingsEditDialog( - plot_settings, - burst_ref.value.df.filter(f_expr), # = filtered dataframe by global filter - on_close=lambda: set_edit_settings(False), - duration=burst_ref.value.duration, - ) + with solara.v.Dialog( + v_model=file_filter_dialog.value, max_width=750, on_v_model=file_filter_dialog.set + ): + RegexSelectDialog( + title="File Filter", + value=file_store.items, + on_value=file_store.set, + values=filenames, + on_close=lambda: file_filter_dialog.set(False), + ) - if edit_filter: - with rv.Dialog(v_model=edit_filter, max_width=750, on_v_model=set_edit_filter): - FileFilterDialog( - burst_item=burst_ref, - on_close=lambda: set_edit_filter(False), - ) + +@solara.component +def FilterListItem(filter_item): + with rv.ListItem(): + rv.ListItemTitle(children=[filter_item.name]) + + def fmt(v): + if v is None: + return "None" + else: + return f"{v:.3g}" + + rv.ListItemSubtitle(children=[f"{fmt(filter_item.min)} - {fmt(filter_item.max)}"]) + + def on_check(value: bool, filter_item=filter_item): + idx = state.filters.index(filter_item) + state.filters.update(idx, active=value) + + solara.Checkbox( + value=filter_item.active, + on_value=on_check, + ) diff --git a/dont_fret/web/bursts/methods.py b/dont_fret/web/bursts/methods.py deleted file mode 100644 index 838f3c5..0000000 --- a/dont_fret/web/bursts/methods.py +++ /dev/null @@ -1,54 +0,0 @@ -from typing import Optional - -import plotly.graph_objs as go - - -def create_histogram( - data, xbins, arange: tuple[float, float], xrange: tuple[Optional[float], Optional[float]] -) -> go.Figure: - hist_trace = go.Histogram(x=data, xbins=xbins) - - layout = go.Layout( - modebar_remove=[ - "lasso2d", - "select2d", - "zoom2d", - "pan2d", - "zoomIn2d", - "zoomOut2d", - "autoScale2d", - "resetScale2d", - ], - xaxis=dict( - range=arange, - type="linear", - ), - yaxis=dict( - type="linear", - ), - ) - - # Create a figure with the histogram trace and layout - fig = go.Figure(data=[hist_trace], layout=layout) - fig.update_layout(dragmode=False, selectdirection="h") - - fig.add_vrect( - editable=False, - x0=arange[0], - x1=xrange[0] if xrange[0] is not None else arange[0], - fillcolor="gray", - opacity=0.5, - layer="above", - line_width=0, - ) - fig.add_vrect( - editable=False, - x0=xrange[1] if xrange[1] is not None else arange[1], - x1=arange[1], - fillcolor="gray", - opacity=0.5, - layer="above", - line_width=0, - ) - - return fig diff --git a/dont_fret/web/bursts/page.py b/dont_fret/web/bursts/page.py index d6d2fd1..e016acc 100644 --- a/dont_fret/web/bursts/page.py +++ b/dont_fret/web/bursts/page.py @@ -1,91 +1,40 @@ from __future__ import annotations -import polars as pl import solara import dont_fret.web.state as state -from dont_fret.web.bursts.components import BurstFigure, BurstFilters -from dont_fret.web.methods import chain_filters +from dont_fret.web.bursts.components import BurstFigure, FilterEditDialog, FilterListItem @solara.component def BurstPage(): - solara.Title(f"{state.APP_TITLE} / Plot 2D") - # sidebar selected node and burst for filters - has_bursts = [node for node in state.fret_nodes.value if node.bursts] - fret_node, set_fret_node = solara.use_state(has_bursts[0]) - burst_item, set_burst_item = solara.use_state(fret_node.bursts[0]) - - def on_fret_node(node_id: str): - new_node = state.fret_nodes.get_node(node_id) - set_fret_node(new_node) - set_burst_item(new_node.bursts[0]) - - def on_burst_item(item_name: str): - new_item = state.fret_nodes.get_item(fret_node.id, "bursts", item_name) - set_burst_item(new_item) - - def get_dataframe() -> tuple[pl.DataFrame, pl.DataFrame]: - return burst_item.df.filter(chain_filters(state.filters.value)), burst_item.df - - filtered_df, original_df = solara.use_memo( - get_dataframe, - dependencies=[ - burst_item, - state.filters.value, - ], # TODO do they need id's for faster hashing? - ) + open_filter_dialog = solara.use_reactive(False) + solara.Title(f"{state.APP_TITLE} / Bursts") with solara.Sidebar(): - with solara.Card("Burst plot settings", margin=0, elevation=0): - solara.Select( - label="Measurement", - value=fret_node.id, - on_value=on_fret_node, # type: ignore - values=[ - {"text": fret_node.name, "value": fret_node.id} - for fret_node in state.fret_nodes.value - if fret_node.bursts # type: ignore - ], - ) - - # check what happens if fret node is changed; should make sure to select a new burst item - solara.Select( - label="Burst item", - value=burst_item.name, - on_value=on_burst_item, - values=[ph.name for ph in fret_node.bursts], - ) - solara.Info(f"Number of bursts: {len(original_df)}", dense=True) - solara.Info(f"After filtering: {len(filtered_df)}", dense=True) - items = list(filtered_df.columns) - try: - items.remove("filename") - except ValueError: + with solara.Card("Filters"): + solara.Button("Edit filters", on_click=lambda: open_filter_dialog.set(True), block=True) + with solara.v.List(dense=False): + for filter_item in state.filters.items: + FilterListItem(filter_item) + + with solara.v.Dialog( + v_model=open_filter_dialog.value, max_width=1200, on_v_model=open_filter_dialog.set + ): + with solara.Card(style={"width": "1190px"}): + # only place the dialog if its open otherwise altair chart won't show + if open_filter_dialog.value: + FilterEditDialog() + else: pass - BurstFilters(state.filters, original_df) - with solara.Card(): - solara.FileDownload( - filtered_df.write_csv, - filename=f"{burst_item.name}{'_filtered' if state.filters.value else ''}_bursts.csv", - children=[ - solara.Button( - "Download bursts csv", - block=True, - ) - ], - ) - with solara.GridFixed(columns=2): BurstFigure( - state.fret_nodes, - state.filters, - node_idx=state.burst_figure_selection[0][0], - burst_idx=state.burst_figure_selection[0][1], + state.fret_nodes.items, + state.burst_figure_selection[0], + state.burst_figure_file_selection[0], ) BurstFigure( - state.fret_nodes, - state.filters, - node_idx=state.burst_figure_selection[1][0], - burst_idx=state.burst_figure_selection[1][1], + state.fret_nodes.items, + state.burst_figure_selection[1], + state.burst_figure_file_selection[1], ) diff --git a/dont_fret/web/bursts/select_count.vue b/dont_fret/web/bursts/select_count.vue new file mode 100644 index 0000000..d0db0dc --- /dev/null +++ b/dont_fret/web/bursts/select_count.vue @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/dont_fret/web/components.py b/dont_fret/web/components.py index 7e6d3f1..16ce3b0 100644 --- a/dont_fret/web/components.py +++ b/dont_fret/web/components.py @@ -1,5 +1,6 @@ from __future__ import annotations +import re from typing import Callable, Optional, Type import solara @@ -8,8 +9,6 @@ import dont_fret.web.state as state -# from dont_fret.web.methods import burst_search, combine_bursts, get_dataframe - @solara.component def Snackbar(): @@ -34,60 +33,164 @@ def Snackbar(): @solara.component def RangeInputField( label: str, - value: float | int, + value: float | int | None, on_value: Callable[[float | int | None], None], vtype: Type[float] | Type[int], vmin: Optional[float | int] = None, vmax: Optional[float | int] = None, disabled: bool = False, - enable_restore: bool = True, + allow_none: bool = False, ): """Input field for a float value with a range slider.""" if vmin is not None and vmax is not None and vmin >= vmax: raise ValueError("vmin must be smaller than vmax") - error, set_error = solara.use_state(False) - message, set_message = solara.use_state("") + error = solara.use_reactive(False) + message = solara.use_reactive("") - def inputtext_cb(new_value: str): + def inputtext_cb(new_value: str) -> None: + if not new_value: + if allow_none: + on_value(None) + error.set(False) + message.set("") + return + else: + message.set("Input required") + error.set(True) try: value = vtype(new_value) except ValueError: if vtype == int: - set_message("Input must be an integer") + message.set("Input must be an integer") else: - set_message("Input must be a number") - set_error(True) + message.set("Input must be a number") + error.set(True) return if vmin is not None and value < vmin: - set_message(f"Input must be >= {vmin}") - set_error(True) + message.set(f"Input must be >= {vmin}") + error.set(True) return if vmax is not None and value > vmax: - set_message(f"Input must be <= {vmax}") - set_error(True) + message.set(f"Input must be <= {vmax}") + error.set(True) return - set_error(False) - set_message("") + error.set(False) + message.set("") on_value(value) - text_field = solara.InputText( + solara.InputText( label=label, value=str(value), - error=error, - message=message, + error=error.value, + message=message.value, disabled=disabled, on_value=inputtext_cb, ) - # TODO restore to external component - if enable_restore: - with solara.Row(): - (text_field,) # type: ignore - solara.IconButton( - icon_name="mdi-restore", on_click=lambda *args: on_value(vmin or vmax) - ) + +@solara.component +def EditableTitle(initial: str | solara.Reactive[str], edit: bool | solara.Reactive[bool] = False): + title = solara.use_reactive(initial) + edit_mode = solara.use_reactive(edit) + + def on_edit(value: str): + edit_mode.set(False) + title.set(value) + + def handle(*args): + if edit_mode.value: + return + edit_mode.set(True) + + if edit_mode.value: + children = [solara.InputText(label="", value=title.value, on_value=on_edit)] + + else: + children = [solara.Text(title.value)] + + div = solara.Div(children=children) + solara.v.use_event(div, "dblclick", handle) # type: ignore + + +@solara.component +def FigureFromTask(task: solara.lab.Task): # type: ignore + solara.ProgressLinear(task.pending) + if task.latest is None: + solara.Text("loading...") else: - text_field # type: ignore + figure = task.value if task.finished else task.latest + with solara.Div(style="opacity: 0.3" if task.pending else None): + solara.FigurePlotly(figure) + + +@solara.component +def RegexSelectDialog( + title: str, + value: list[str], + on_value: Callable[[list[str]], None], + values: list[str], + on_close: Callable[[], None], + sort: bool = True, +): + """ + select string by checkboxes or regex + """ + local_selection = solara.use_reactive(value) + error = solara.use_reactive("") + regex = solara.use_reactive("") + + def on_input(value: str): + try: + pattern = re.compile(value) + regex.set(value) + error.set("") + except Exception: + error.set("Invalid regex") + return + new_selected = [f for f in values if pattern.search(f)] + local_selection.set(new_selected) + + def on_save(): + if not local_selection.value: + return + if sort: + on_value(sorted(local_selection.value)) + else: + on_value(local_selection.value) + on_close() + + with solara.Card(title): + with solara.Row(style="align-items: center;"): + solara.InputText( + label="regex", + value=regex.value, + on_value=on_input, + continuous_update=True, + error=error.value, + ) + solara.Button(label="Select All", on_click=lambda: local_selection.set(values)) + solara.Button(label="Select None", on_click=lambda: local_selection.set([])) + with solara.v.List(nav=True): + with solara.v.ListItemGroup( + v_model=local_selection.value, + on_v_model=local_selection.set, + multiple=True, + ): + for v in values: + with solara.v.ListItem(value=v): + with solara.v.ListItemAction(): + solara.Checkbox(value=v in local_selection.value) + solara.v.ListItemTitle(children=[v]) + + with solara.CardActions(): + solara.v.Spacer() + solara.Button( + "Save", + icon_name="mdi-content-save", + on_click=on_save, + disabled=not local_selection.value, + ) + solara.Button("Close", icon_name="mdi-window-close", on_click=on_close) diff --git a/dont_fret/web/datamanager.py b/dont_fret/web/datamanager.py new file mode 100644 index 0000000..34d44a1 --- /dev/null +++ b/dont_fret/web/datamanager.py @@ -0,0 +1,166 @@ +from __future__ import annotations + +import asyncio +import dataclasses +import json +import uuid +from concurrent.futures import ThreadPoolExecutor +from typing import ( + Callable, + Dict, + Optional, +) + +import numpy as np +import polars as pl + +from dont_fret.config.config import BurstColor +from dont_fret.fileIO import PhotonFile +from dont_fret.models import Bursts, PhotonData +from dont_fret.web.methods import get_duration, get_info, make_burst_dataframe +from dont_fret.web.models import BurstNode, PhotonNode + + +class ThreadedDataManager: + def __init__(self) -> None: + self.photon_cache: Dict[uuid.UUID, asyncio.Future[PhotonData]] = {} + self.burst_cache: Dict[tuple[uuid.UUID, str], asyncio.Future[Bursts]] = {} + self.executor = ThreadPoolExecutor(max_workers=4) # todo config wokers + self.running_jobs = {} + + # todo allow passing loop to init + @property + def loop(self) -> asyncio.AbstractEventLoop: + return asyncio.get_running_loop() + + def run(self, func, *args): + # TODO typing + return self.loop.run_in_executor(self.executor, func, *args) + + async def get_photons(self, node: PhotonNode) -> PhotonData: + if node.id not in self.photon_cache: + future = self.loop.create_future() + self.photon_cache[node.id] = future + + try: + photons = await self.run(PhotonData.from_file, PhotonFile(node.file_path)) + future.set_result(photons) + except Exception as e: + self.photon_cache.pop(node.id) + future.set_exception(e) + raise + + return await self.photon_cache[node.id] + + async def get_info(self, node: PhotonNode) -> dict: + if node.info is not None: + return node.info + else: + photons = await self.get_photons(node) + info = get_info(photons) + node.info = info + return info + + @staticmethod + def burst_key(node: PhotonNode, burst_colors: list[BurstColor]) -> tuple[uuid.UUID, str]: + s = json.dumps([dataclasses.asdict(c) for c in burst_colors]) + return (node.id, s) + + async def get_bursts( + self, + photon_node: PhotonNode, + burst_colors: list[BurstColor], + ) -> Bursts: + key = self.burst_key(photon_node, burst_colors) + + if key not in self.burst_cache: + future = self.loop.create_future() + self.burst_cache[key] = future + + try: + bursts = await self.search(photon_node, burst_colors) + future.set_result(bursts) + except Exception as e: + self.burst_cache.pop(key) + future.set_exception(e) + raise + + return await self.burst_cache[key] + + async def search(self, node: PhotonNode, colors: list[BurstColor]) -> Bursts: + photon_data = await self.get_photons(node) + bursts = photon_data.burst_search(colors) + + return bursts + + async def get_bursts_batch( + self, + photon_nodes: list[PhotonNode], + burst_colors: list[BurstColor], + on_progress: Optional[Callable[[float | bool], None]] = None, + ) -> list[Bursts]: + on_progress = on_progress or (lambda _: None) + + tasks = [] + for ph_node in photon_nodes: + task = asyncio.create_task(self.get_bursts(ph_node, burst_colors)) + tasks.append(task) + + for i, f in enumerate(asyncio.as_completed(tasks)): + await f + progress = (i + 1) * (100 / len(tasks)) + on_progress(progress) + + results = await asyncio.gather(*tasks) + + return results + + async def get_dataframe( + self, + photon_nodes: list[PhotonNode], + burst_colors: list[BurstColor], + on_progress: Optional[Callable[[float | bool], None]] = None, + ) -> pl.DataFrame: + on_progress = on_progress or (lambda _: None) + on_progress(True) + raise DeprecationWarning("USe get burst node instead") + results = await self.get_bursts_batch(photon_nodes, burst_colors, on_progress) + on_progress(True) + + names = [ph_node.name for ph_node in photon_nodes] + lens = [len(burst) for burst in results] + + dtype = pl.Enum(categories=names) + filenames = pl.Series(name="filename", values=np.repeat(names, lens), dtype=dtype) + + df = pl.concat([b.burst_data for b in results], how="vertical_relaxed").with_columns( + filenames + ) + + return df + + async def get_burst_node( + self, + photon_nodes: list[PhotonNode], + burst_colors: list[BurstColor], + name: str = "", + on_progress: Optional[Callable[[float | bool], None]] = None, + ) -> BurstNode: + bursts = await self.get_bursts_batch(photon_nodes, burst_colors, on_progress=on_progress) + bursts_df = make_burst_dataframe(bursts, names=[ph_node.name for ph_node in photon_nodes]) + # burst_df = await self.get_dataframe(photon_nodes, burst_colors, on_progress=on_progress) + info_list = [await self.get_info(node) for node in photon_nodes] + + duration = get_duration(info_list) + uu_id = uuid.uuid4() + + node = BurstNode( + name=name or f"burst_node-{id}", + df=bursts_df, + colors=burst_colors, + photon_nodes=photon_nodes, + duration=duration, + id=uu_id, + ) + + return node diff --git a/dont_fret/web/home/burst_settings.py b/dont_fret/web/home/burst_settings.py index f283604..f4a9f1c 100644 --- a/dont_fret/web/home/burst_settings.py +++ b/dont_fret/web/home/burst_settings.py @@ -5,15 +5,17 @@ from solara.alias import rv from dont_fret.config import cfg -from dont_fret.web.reactive import BurstSettingsReactive +from dont_fret.config.config import BurstColor +from dont_fret.web.models import BurstSettingsStore, ListStore, use_liststore @solara.component -def BurstColorSettingForm( - burst_settings: BurstSettingsReactive, settings_name: str, color_idx: int -): - burst_color = burst_settings.get_color(settings_name, color_idx) - setter = partial(burst_settings.update_color, settings_name, color_idx) +def BurstColorSettingForm(color_store: ListStore[BurstColor], color_idx: int): + burst_color = color_store[color_idx] + # burst_color = burst_settings.get_color(settings_name, color_idx) + + setter = partial(color_store.update, color_idx) + # setter = partial(burst_settings.update_color, settings_name, color_idx) with solara.ColumnsResponsive([8, 4]): with solara.Card("Search Thresholds"): with solara.Column(): @@ -63,8 +65,9 @@ def on_value(val, stream: str = stream): @solara.component -def BurstSettingsDialog(burst_settings: BurstSettingsReactive, settings_name, on_close): - tab, set_tab = solara.use_state(0) +def BurstSettingsDialog(colors: list[BurstColor], settings_name, on_value, on_close): + tab, set_tab = solara.use_state(0) # active tab number + color_store = use_liststore(colors) title = f"Editing burst search settings: '{settings_name}'" with solara.Card(title): @@ -73,14 +76,17 @@ def on_tab_change(val): set_tab(val) def on_tab_remove(*args): - burst_settings.remove_color(settings_name) + color_store.pop(len(color_store) - 1) + # burst_settings.remove_color(settings_name) def on_tab_add(*args): - burst_settings.add_color(settings_name) + color_store.append(BurstColor()) + # burst_settings.add_color(settings_name) try: - n_tabs = len(burst_settings.value[settings_name]) + n_tabs = len(color_store) # This can happen if the settings are reset while a new set was added and is selected + # update: not sure how we can get here atm except KeyError: return @@ -97,14 +103,18 @@ def on_tab_add(*args): with rv.TabsItems(v_model=tab): for i in range(n_tabs): with rv.TabItem(): - BurstColorSettingForm(burst_settings, settings_name, i) + BurstColorSettingForm(color_store, i) + + def save_close(): + on_value(color_store.items) + on_close(False) with solara.CardActions(): # todo align center with rv.Layout(row=True): solara.Button( label="Save & close", - on_click=lambda *args: on_close(False), + on_click=save_close, text=True, classes=["centered"], ) diff --git a/dont_fret/web/home/info_cards.py b/dont_fret/web/home/info_cards.py index 5ca9a5d..e2d9d2d 100644 --- a/dont_fret/web/home/info_cards.py +++ b/dont_fret/web/home/info_cards.py @@ -1,5 +1,6 @@ """Solara components for the home page.""" +from dataclasses import asdict from datetime import datetime from pathlib import Path from typing import Callable @@ -11,52 +12,46 @@ from solara.alias import rv import dont_fret.web.state as state +from dont_fret.config.config import BurstColor +from dont_fret.web.components import EditableTitle from dont_fret.web.home.burst_settings import BurstSettingsDialog from dont_fret.web.home.methods import task_burst_search from dont_fret.web.methods import format_size -from dont_fret.web.models import BurstItem, FRETNode, PhotonFileItem -from dont_fret.web.reactive import ( - BurstSettingsReactive, - ReactiveFRETNodes, +from dont_fret.web.models import ( + BurstNode, + BurstSettingsStore, + ListStore, + PhotonNode, ) +from dont_fret.web.utils import has_photons @solara.component def FRETNodeInfoCard( - fret_node: FRETNode, - on_name: Callable[[str], None], - on_description: Callable[[str], None], + name: solara.Reactive[str], + description: solara.Reactive[str], on_delete: Callable[[], None], ): - title = solara.use_reactive(fret_node.name) - editing, set_editing = solara.use_state(False) - - def update_title(value): - title.set(value) - on_name(value) - set_editing(False) - - title_elem = ( - fret_node.name - if not editing - else solara.InputText(label="", value=title, on_value=update_title, continuous_update=False) - ) - with solara.Card(title_elem): # type: ignore - rv.Textarea(label="Description", v_model=fret_node.description, on_v_model=on_description) + edit = solara.use_reactive(False) + + with solara.Card(EditableTitle(name, edit)): # type: ignore + rv.Textarea(label="Description", v_model=description.value, on_v_model=description.set) with solara.CardActions(): rv.Spacer() - solara.IconButton("edit", on_click=lambda: set_editing(True)) + solara.IconButton("edit", on_click=lambda: edit.set(not edit.value)) solara.IconButton("delete", on_click=lambda *args: on_delete()) @solara.component def PhotonInfoCard( - fret_nodes: ReactiveFRETNodes, - measurement_id: str, + name: str, + photon_store: ListStore[PhotonNode], + burst_store: ListStore[BurstNode], filebrowser_folder: solara.Reactive[Path], - burst_settings: BurstSettingsReactive, - open_: solara.Reactive[list[str]], + burst_settings: BurstSettingsStore, + # open_: solara.Reactive[list[str]], ): + # todo reactives bs_name, set_bs_name = solara.use_state(next(iter(burst_settings.value.keys()))) add_new, set_add_new = solara.use_state(False) show_settings_dialog, set_show_settings_dialog = solara.use_state(False) @@ -65,12 +60,14 @@ def PhotonInfoCard( # open the current node so that users can see the files they're adding def open_node(): - ph_node_id = f"{measurement_id}:photons" + # Todo attach to callable + pass + # ph_node_id = f"{node_idx}:photons" - if ph_node_id not in open_.value: - new_open = open_.value.copy() - new_open.append(ph_node_id) - open_.value = new_open + # if ph_node_id not in open_.value: + # new_open = open_.value.copy() + # new_open.append(ph_node_id) + # open_.value = new_open def filebrowser_filter(pth: Path) -> bool: """Return True if the path is a ptu file or a folder.""" @@ -96,31 +93,45 @@ def add_all_files(*ignore): def add_files(files: list[Path]): open_node() - current_names = [ph.name for ph in fret_nodes.get_node(measurement_id).photons] - to_add = [PhotonFileItem(file_path=pth) for pth in files if pth.name not in current_names] - fret_nodes.add_photon_files(measurement_id, to_add) + current_names = [ph.name for ph in photon_store.items] + to_add = [PhotonNode(file_path=pth) for pth in files if pth.name not in current_names] + # TODO sort ? + + photon_store.extend(to_add) + state.disable_trace_page.set(not has_photons(state.fret_nodes.items)) def remove_all_files(*ignore): - fret_nodes.remove_all_photon_files(measurement_id) + photon_store.set([]) + state.disable_trace_page.set(not has_photons(state.fret_nodes.items)) def confirm_burst_search(): - if not state.fret_nodes.get_node(measurement_id).photons: + # TODO needs to be passed as callable as well + + if not photon_store.items: state.snackbar.warning("No photon files selected", timeout=0) return - if bs_name in [b.name for b in fret_node.bursts]: + if bs_name in {node.name for node in burst_store.items}: open_confirmation_dialog.value = True else: do_burst_search() def do_burst_search(): # open the bursts node if not open already - bursts_node_id = f"{measurement_id}:bursts:" - if bursts_node_id not in open_.value: - new_open = open_.value.copy() - new_open.append(bursts_node_id) - open_.value = new_open - - task_burst_search(bs_name, measurement_id) + # bursts_node_id = f"{measurement_id}:bursts:" + # if bursts_node_id not in open_.value: + # new_open = open_.value.copy() + # new_open.append(bursts_node_id) + # open_.value = new_open + + # remove the burst node if its already in the store + try: + names = [node.name for node in burst_store.items] + idx = names.index(bs_name) + burst_store.pop(idx) + except ValueError: + pass + + task_burst_search(bs_name, photon_store.items, burst_store) def on_new_settings(new_name): if new_name in burst_settings.settings_names: @@ -129,8 +140,7 @@ def on_new_settings(new_name): burst_settings.add_settings(new_name) set_bs_name(new_name) - fret_node = fret_nodes.get_node(measurement_id) - with solara.Card(f"{fret_node.name} / Photons"): + with solara.Card(f"{name} / Photons"): with solara.Columns([3, 1], gutters=False, gutters_dense=True): with solara.Card(margin=0): solara.Text("Click files to add") @@ -142,6 +152,7 @@ def on_new_settings(new_name): ) with solara.Card("Burst Search", margin=0): + # TODO the settings need to move to a component with solara.Column(): if add_new: solara.InputText( @@ -220,15 +231,21 @@ def reset(): persistent=False, max_width=800, ): - BurstSettingsDialog(burst_settings, bs_name, on_close=set_show_settings_dialog) + def on_value(value: list[BurstColor], name=bs_name): + burst_settings[name] = value -@solara.component + BurstSettingsDialog( + burst_settings[bs_name], bs_name, on_value=on_value, on_close=set_show_settings_dialog + ) + + +@solara.component # type: ignore def BurstInfoCard( - fret_nodes: ReactiveFRETNodes, - measurement_id: str, + name: str, + burst_store: ListStore[BurstNode], filebrowser_folder: solara.Reactive[Path], - open_: solara.Reactive[list[str]], + # open_: solara.Reactive[list[str]], ): # TODO different file types for bursts def filebrowser_filter(pth: Path) -> bool: @@ -244,24 +261,23 @@ def add_single_file(burst_pth: Path): if burst_pth.is_dir(): return - bursts_node_id = f"{measurement_id}:bursts" - + state.snackbar.warning("Not implemented") # open the leaf we are adding to - if bursts_node_id not in open_.value: - new_open = open_.value.copy() - new_open.append(bursts_node_id) - open_.value = new_open + # if bursts_node_id not in open_.value: + # new_open = open_.value.copy() + # new_open.append(bursts_node_id) + # open_.value = new_open # check if the item already exists: - if burst_pth.stem in [b.name for b in fret_nodes.get_node(measurement_id).bursts]: + if burst_pth.stem in [b.name for b in burst_store.items]: state.snackbar.warning(f"Burst result name {burst_pth.stem!r} already exists.") return - # TODO check already added - fret_nodes.add_burst_items(measurement_id, [BurstItem.from_path(burst_pth)]) + # TODO via dataloader object + raise NotImplementedError("TODO via dataloader object") + # burst_store.extend([BurstNode.from_path(burst_pth)]) - fret_node = fret_nodes.get_node(measurement_id) - with solara.Card(f"{fret_node.name} / Bursts"): + with solara.Card(f"{name} / Bursts"): solara.Text("Click files to add") solara.FileBrowser( directory=filebrowser_folder.value, @@ -273,22 +289,22 @@ def add_single_file(burst_pth: Path): @solara.component -def PhotonFileInfoCard(ph_file_item: PhotonFileItem, node_name: str, on_delete: Callable[[], None]): +def PhotonNodeInfoCard(node_name: str, photon_node: PhotonNode, on_delete: Callable[[], None]): # prevent flicker by setting `loaded` to `True` if we find ourselves in this component # with the photon loading future already completed loaded, set_loaded = solara.use_state(False) - def load_info(): - if ph_file_item.photons is not None: + async def load_info(): + if photon_node.id in state.data_manager.photon_cache: set_loaded(True) else: set_loaded(False) - info = ph_file_item.get_info() + info = await state.data_manager.get_info(photon_node) return info - result = solara.lab.use_task(load_info, dependencies=[ph_file_item], prefer_threaded=True) + result = solara.lab.use_task(load_info, dependencies=[photon_node], prefer_threaded=False) # type: ignore - with solara.Card(f"{node_name} / Photon file / {ph_file_item.name}"): + with solara.Card(f"{node_name} / Photon file / {photon_node.name}"): solara.ProgressLinear(result.pending and not loaded) if result.pending and not loaded: @@ -317,7 +333,7 @@ def load_info(): # TODO humanize file size { "property": "File size", - "value": format_size(ph_file_item.size), + "value": format_size(photon_node.size), }, { "property": "Number of photons", @@ -377,8 +393,8 @@ def load_info(): solara.IconButton("delete", on_click=lambda *args: on_delete()) -@solara.component -def BurstItemInfoCard(burst_item: BurstItem, node_name: str, on_delete: Callable[[], None]): +@solara.component # type: ignore +def BurstItemInfoCard(node_name: str, burst_node: BurstNode, on_delete: Callable[[], None]): headers = [ {"text": "Filename", "value": "filename"}, {"text": "Number of bursts", "value": "bursts"}, @@ -389,11 +405,11 @@ def BurstItemInfoCard(burst_item: BurstItem, node_name: str, on_delete: Callable {"text": "In-burst countrate (kHz)", "value": "burst_cps"}, ] - filenames = burst_item.df["filename"].unique().sort() + filenames = burst_node.df["filename"].unique().sort() items = [] for fname in filenames: item = {"filename": fname} - df = burst_item.df.filter(pl.col("filename") == fname) + df = burst_node.df.filter(pl.col("filename") == fname) item["bursts"] = len(df) @@ -415,8 +431,8 @@ def BurstItemInfoCard(burst_item: BurstItem, node_name: str, on_delete: Callable burst_cps = df["n_photons"] / df["time_length"] item["burst_cps"] = f"{burst_cps.mean()*1e-3:.2f} ± {burst_cps.std()*1e-3:.2f}" # type: ignore - with solara.Card(f"{node_name} / Bursts / {burst_item.name}"): - solara.Text(f"Total number of bursts: {len(burst_item.df)}", style="font-weight: bold;") + with solara.Card(f"{node_name} / Bursts / {burst_node.name}"): + solara.Text(f"Total number of bursts: {len(burst_node.df)}", style="font-weight: bold;") solara.HTML(tag="br") solara.Text("Bursts statistics per file:") @@ -429,8 +445,8 @@ def BurstItemInfoCard(burst_item: BurstItem, node_name: str, on_delete: Callable with solara.CardActions(): solara.FileDownload( - burst_item.df.write_csv, - filename=f"{burst_item.name}_bursts.csv", + burst_node.df.write_csv, + filename=f"{burst_node.name}_bursts.csv", children=[ solara.Button( "Download burst data.csv", @@ -439,8 +455,8 @@ def BurstItemInfoCard(burst_item: BurstItem, node_name: str, on_delete: Callable ], ) solara.FileDownload( - lambda: yaml.dump(burst_item.search_spec), - filename=f"{burst_item.name}_setttings.yaml", + lambda: yaml.dump(yaml.dump([asdict(c) for c in burst_node.colors])), + filename=f"{burst_node.name}_setttings.yaml", children=[ solara.Button( "Download settings", diff --git a/dont_fret/web/home/methods.py b/dont_fret/web/home/methods.py index 9d912b8..e164d0e 100644 --- a/dont_fret/web/home/methods.py +++ b/dont_fret/web/home/methods.py @@ -1,50 +1,32 @@ -import asyncio -from concurrent.futures import ThreadPoolExecutor - -import polars as pl import solara import solara.lab import dont_fret.web.state as state -from dont_fret.web.methods import burst_search -from dont_fret.web.models import BurstItem +from dont_fret.web.models import PhotonNode +from dont_fret.web.utils import has_bursts -@solara.lab.task(prefer_threaded=False) -async def task_burst_search(name: str, measurement_id: str) -> None: +@solara.lab.task(prefer_threaded=False) # type: ignore +async def task_burst_search(name: str, photon_nodes: list[PhotonNode], burst_store) -> None: # name: name of burst search settings as well as its output name - task_burst_search.progress = True - photon_file_items = state.fret_nodes.get_node(measurement_id).photons - burst_colors = list(state.burst_settings.value[name]) - categories = [item.name for item in photon_file_items] - dtype = pl.Enum(categories) + def on_progress(progress: float | bool) -> None: + task_burst_search.progress = progress - loop = asyncio.get_running_loop() - with ThreadPoolExecutor(max_workers=4) as executor: - futures = [] - for f in photon_file_items: - fut = loop.run_in_executor(executor, burst_search, f, burst_colors, dtype) - futures.append(fut) + burst_colors = list(state.burst_settings.value[name]) - results = [] - for i, f in enumerate(asyncio.as_completed(futures)): - results.append(await f) - task_burst_search.progress = (i + 1) * (100 / len(futures)) + try: + burst_node = await state.data_manager.get_burst_node( + photon_nodes, burst_colors, name, on_progress + ) + except ValueError: + state.snackbar.warning("No bursts found", timeout=0) + task_burst_search.progress = False + return - task_burst_search.progress = True + burst_store.append(burst_node) + state.disable_burst_page.set(not has_bursts(state.fret_nodes.items)) - df = pl.concat( - results, how="vertical_relaxed" - ) # this should be very short such that the UI remains responsive - if len(df) == 0: - state.snackbar.warning("No bursts found", timeout=0) - else: - metadata = {fi.name: fi.get_info() for fi in photon_file_items} - burst_item = BurstItem(name=name, df=df, metadata=metadata) - state.fret_nodes.add_burst_items(measurement_id, [burst_item]) - state.snackbar.success( - f"Burst search completed, found {len(burst_item.df)} bursts", timeout=0 - ) + state.snackbar.success(f"Burst search completed, found {len(burst_node.df)} bursts", timeout=0) task_burst_search.progress = False diff --git a/dont_fret/web/home/page.py b/dont_fret/web/home/page.py index db6c08c..a2ff8f3 100644 --- a/dont_fret/web/home/page.py +++ b/dont_fret/web/home/page.py @@ -1,4 +1,7 @@ -from typing import cast +from __future__ import annotations + +from dataclasses import dataclass +from typing import Literal, Optional, cast import solara import solara.lab @@ -9,10 +12,12 @@ BurstInfoCard, BurstItemInfoCard, FRETNodeInfoCard, - PhotonFileInfoCard, PhotonInfoCard, + PhotonNodeInfoCard, ) from dont_fret.web.methods import to_treeview +from dont_fret.web.models import BurstNode, FRETNode, PhotonNode +from dont_fret.web.utils import has_bursts, has_photons welcome_text = """# Don't FRET! @@ -35,16 +40,65 @@ def FRETTreeView(items, value, active, open_): active_id = solara.Reactive(cast(list[str], [])) -@solara.component +# TODO there are now 3 selection classes +# perhaps they can be generalized +@dataclass +class TreeSelection: + f_idx: Optional[int] = None + node_type: Literal["bursts", "photons", None] = None + d_idx: Optional[int] = None + + @classmethod + def from_string(cls, input_string: str) -> TreeSelection: + parts = input_string.split(":") + + def parse_node_type(nt: str) -> Literal["bursts", "photons", None]: + if nt in ("bursts", "photons"): + return nt + elif nt.lower() == "none": + return None + else: + raise ValueError(f"Invalid node_type: {nt}. Must be 'bursts', 'photons', or None.") + + if not input_string: + return cls() + elif len(parts) == 1: + return cls(f_idx=int(parts[0])) + elif len(parts) == 2: + f_idx, node_type = parts + return cls(f_idx=int(f_idx), node_type=parse_node_type(node_type)) + elif len(parts) == 3: + f_idx, node_type, d_idx = parts + return cls(f_idx=int(f_idx), node_type=parse_node_type(node_type), d_idx=int(d_idx)) + else: + raise ValueError("Invalid input string format") + + @property + def fret_node(self) -> FRETNode: + assert self.f_idx is not None + return state.fret_nodes.items[self.f_idx] + + @property + def data_node(self) -> PhotonNode | BurstNode: + assert self.d_idx is not None + if self.node_type == "photons": + return self.fret_node.photons.items[self.d_idx] + elif self.node_type == "bursts": + return self.fret_node.bursts.items[self.d_idx] + else: + raise ValueError(f"Invalid node_type: {self.node_type}") + + +@solara.component # type: ignore def HomePage(): - if len(state.fret_nodes.value) == 0: - state.fret_nodes.add_node() + if len(state.fret_nodes) == 0: + state.fret_nodes.new_node() with solara.Columns([4, 8], style={"height": "100%"}): with solara.Card("FRET Measurements"): with solara.Column(): FRETTreeView( - items=to_treeview(state.fret_nodes.value), + items=to_treeview(state.fret_nodes.items), active=active_id.value, on_active=active_id.set, # type: ignore open_=open_.value, @@ -57,63 +111,64 @@ def HomePage(): solara.Button( "Add new measurement", text=True, - on_click=lambda *args: state.fret_nodes.add_node(), + on_click=lambda *args: state.fret_nodes.new_node(), ) - split = active_id.value[0].split(":") if active_id.value else [] - if len(split) == 0: - with solara.Card(): - solara.Markdown(welcome_text, style="font-size: 18px") - elif len(split) == 1: - - def on_delete_node(node_id=split[0]): - # set the active id to the parent node before deleting - active_id.set([]) - state.fret_nodes.remove_node(node_id) - - def on_name(value: str, node_id=split[0]): - idx = state.fret_nodes.node_idx(node_id) - ref = solara.toestand.Ref(state.fret_nodes.fields[idx]) - ref.update(name=value) - - def on_description(value: str, node_id=split[0]): - idx = state.fret_nodes.node_idx(node_id) - ref = solara.toestand.Ref(state.fret_nodes.fields[idx]) - ref.update(description=value) - - fret_node = state.fret_nodes.get_node(split[0]) - FRETNodeInfoCard( - fret_node, on_name=on_name, on_description=on_description, on_delete=on_delete_node - ) - elif len(split) == 2: - node_id, dtype = split - if dtype == "photons": + selection = TreeSelection.from_string(active_id.value[0] if active_id.value else "") + # TODO this selection suses indices while later we use uuid's + match selection: + case TreeSelection(f_idx=None, node_type=None, d_idx=None): + with solara.Card(): + solara.Markdown(welcome_text, style="font-size: 18px") + case TreeSelection(f_idx=int(), node_type=None, d_idx=None): + node = selection.fret_node + + def on_delete(idx=selection.f_idx): + # set the active id to the parent node before deleting + active_id.set([]) + state.fret_nodes.pop(idx) # type: ignore + + FRETNodeInfoCard(name=node.name, description=node.description, on_delete=on_delete) + case TreeSelection(f_idx=int(), node_type="photons", d_idx=None): + # TODO open_ callable PhotonInfoCard( - state.fret_nodes, node_id, state.filebrowser_folder, state.burst_settings, open_ + selection.fret_node.name.value, + selection.fret_node.photons, + selection.fret_node.bursts, + state.filebrowser_folder, + state.burst_settings, ) - elif dtype == "bursts": - BurstInfoCard(state.fret_nodes, node_id, state.filebrowser_folder, open_) - elif len(split) == 3: - node_id, dtype, file_item_id = split - fret_node = state.fret_nodes.get_node(node_id) + case TreeSelection(f_idx=int(), node_type="bursts", d_idx=None): + # TODO open_ + BurstInfoCard( + selection.fret_node.name.value, + selection.fret_node.bursts, + state.filebrowser_folder, + # open_ + ) + case TreeSelection(f_idx=int(), node_type="photons", d_idx=int()): + photon_node = selection.data_node + assert isinstance(photon_node, PhotonNode) + fret_node = selection.fret_node - if dtype not in ["photons", "bursts"]: - raise ValueError(f"Invalid dtype {dtype}") + def delete_photon(p_node_idx=selection.d_idx): + # set the active id to the parent node before deleting + active_id.set([f"{selection.f_idx}:{selection.node_type}"]) + fret_node.photons.pop(p_node_idx) # type: ignore + state.disable_trace_page.set(not has_photons(state.fret_nodes.items)) - item = state.fret_nodes.get_item(node_id, dtype, file_item_id) # type: ignore - if dtype == "photons": + PhotonNodeInfoCard(fret_node.name.value, photon_node, delete_photon) - def on_delete(item_id=file_item_id): - # set the active id to the parent node before deleting - active_id.set([f"{node_id}:{dtype}"]) - state.fret_nodes.remove_item(node_id, "photons", item_id) + case TreeSelection(f_idx=int(), node_type="bursts", d_idx=int()): + burst_node = selection.data_node + assert isinstance(burst_node, BurstNode) - PhotonFileInfoCard(item, fret_node.name, on_delete) - elif dtype == "bursts": + fret_node = selection.fret_node - def on_delete(item_id=file_item_id): + def delete_burst(b_node_idx=selection.d_idx): # set the active id to the parent node before deleting - active_id.set([f"{node_id}:{dtype}"]) - state.fret_nodes.remove_item(node_id, "bursts", item_id) + active_id.set([f"{selection.f_idx}:{selection.node_type}"]) + fret_node.bursts.pop(b_node_idx) # type: ignore + state.disable_burst_page.set(not has_bursts(state.fret_nodes.items)) - BurstItemInfoCard(item, fret_node.name, on_delete) + BurstItemInfoCard(fret_node.name.value, burst_node, delete_burst) diff --git a/dont_fret/web/main.py b/dont_fret/web/main.py index ea24d1d..7a8a3db 100644 --- a/dont_fret/web/main.py +++ b/dont_fret/web/main.py @@ -3,6 +3,7 @@ import sys from pathlib import Path +import altair as alt import solara import solara.lab import solara.server.settings @@ -13,54 +14,51 @@ from dont_fret.web.bursts import BurstPage from dont_fret.web.components import Snackbar from dont_fret.web.home import HomePage -from dont_fret.web.models import BurstColorList, FRETNode +from dont_fret.web.models import BurstColorList +from dont_fret.web.state import disable_burst_page, disable_trace_page from dont_fret.web.trace import TracePage +# config option? +alt.data_transformers.enable("vegafusion") -def disable_bursts(nodes: list[FRETNode]) -> bool: - return not bool([ph for node in nodes for ph in node.bursts]) +parser = argparse.ArgumentParser(description="Process config argument") +parser.add_argument("--config", help="Configuration file") -def disable_trace(nodes: list[FRETNode]) -> bool: - return not bool([b for node in nodes for b in node.photons]) +if "--" in sys.argv: + extra_args = sys.argv[sys.argv.index("--") + 1 :] + parsed = parser.parse_args(extra_args) + + data = yaml.safe_load(Path(parsed.config).read_text()) + cfg.update(data) -pages = [ +SCRIPT_PATH = Path(__file__).parent +PAGES = [ { "name": "home", "main": HomePage, "sidebar": None, - "disabled": lambda x: False, + "disabled": solara.Reactive(False), # always false "show": lambda: True, }, { "name": "bursts", "main": BurstPage, "sidebar": None, - "disabled": disable_bursts, + "disabled": disable_burst_page, "show": lambda: True, }, { "name": "trace", "main": TracePage, "sidebar": None, - "disabled": disable_trace, + "disabled": disable_trace_page, "show": lambda: True, }, ] -parser = argparse.ArgumentParser(description="Process config argument") -parser.add_argument("--config", help="Configuration file") - -if "--" in sys.argv: - extra_args = sys.argv[sys.argv.index("--") + 1 :] - parsed = parser.parse_args(extra_args) - - data = yaml.safe_load(Path(parsed.config).read_text()) - cfg.update(data) - - @solara.component def Page(): tab_selection = solara.use_reactive(0) @@ -68,8 +66,11 @@ def Page(): login_failed = solara.use_reactive(False) password = solara.use_reactive("") + solara.Style(SCRIPT_PATH / "style.css") + def initialize(): - state.burst_settings.set({k: BurstColorList(v) for k, v in cfg.burst_search.items()}) + # TODO burst settings as listStore + state.burst_settings.set({k: BurstColorList(v) for k, v in cfg.burst_search.items()}) # type: ignore default_filters = copy.deepcopy(cfg.web.burst_filters) state.filters.set(default_filters) @@ -91,6 +92,8 @@ def authorize(value: str): else: login_failed.set(True) + # has_photons = [node for node in state.fr-- + # it is important we do not interrupt the height 100% chain # to ensure independent scrolling for both columns with solara.Column(style={"height": "100%"}): @@ -100,16 +103,14 @@ def authorize(value: str): with solara.lab.Tabs( value=tab_selection.value, on_value=tab_selection.set, align="center" ): - for page in pages: + for page in PAGES: if page["show"](): - solara.lab.Tab( - page["name"], disabled=page["disabled"](state.fret_nodes.value) - ) + solara.lab.Tab(page["name"], disabled=page["disabled"].value) solara.Title(state.APP_TITLE) if authorized.value: - pages[tab_selection.value]["main"]() - sidebar = pages[tab_selection.value]["sidebar"] + PAGES[tab_selection.value]["main"]() + sidebar = PAGES[tab_selection.value]["sidebar"] if sidebar is not None: sidebar() else: diff --git a/dont_fret/web/methods.py b/dont_fret/web/methods.py index 201eb82..ce221c0 100644 --- a/dont_fret/web/methods.py +++ b/dont_fret/web/methods.py @@ -2,108 +2,74 @@ import itertools import math -from concurrent.futures import ThreadPoolExecutor from functools import reduce from operator import and_ -from pathlib import Path from typing import Literal, Optional, TypedDict, Union +import numpy as np import polars as pl -from dont_fret import BinnedPhotonData from dont_fret.config.config import BurstColor -from dont_fret.formatting import TRACE_COLORS -from dont_fret.web.models import ( - BurstFilterItem, - BurstItem, - FRETNode, - PhotonData, - PhotonFileItem, - TraceSettings, -) - - -def batch_burst_search( - photon_file_items: list[PhotonFileItem], burst_colors: str, max_workers: int = 4 -) -> BurstItem: - """ - Search all photon file items in batch threaded. - """ - dtype = pl.Enum([item.name for item in photon_file_items]) - - futures = [] - with ThreadPoolExecutor(max_workers=max_workers) as executor: - for f in photon_file_items: - fut = executor.submit(burst_search, f, burst_colors, dtype) - futures.append(fut) - - df = pl.concat([f.result() for f in futures], how="vertical_relaxed") - metadata = {fi.name: fi.get_info() for fi in photon_file_items} +from dont_fret.fileIO import PhotonFile +from dont_fret.models import Bursts, PhotonData +from dont_fret.web.models import BurstFilterItem, BurstNode, FRETNode, PhotonNode - return BurstItem(name=burst_colors, df=df, metadata=metadata) - -def burst_search( - ph_file_item: PhotonFileItem, burst_colors: str | list[BurstColor], dtype: pl.Enum +def make_burst_dataframe( + bursts: list[Bursts], names: Optional[list[str]], name_column="filename" ) -> pl.DataFrame: - photons = ph_file_item.get_photons() - bursts = photons.burst_search(burst_colors) + """Convert a list of `Bursts` objects into a `polars.DataFrame`.""" - t_unit = photons.timestamps_unit - with_columns = [ - # (pl.col("timestamps_mean") * t_unit).alias("time_mean"), - # ((pl.col("timestamps_max") - pl.col("timestamps_min")) * t_unit).alias("time_length"), - pl.lit(ph_file_item.name).alias("filename").cast(dtype), - ] + concat = pl.concat([b.burst_data for b in bursts], how="vertical_relaxed") + if names: + lens = [len(burst) for burst in bursts] + dtype = pl.Enum(categories=names) + series = pl.Series(name=name_column, values=np.repeat(names, lens), dtype=dtype) - drop_columns = ["timestamps_mean", "timestamps_min", "timestamps_max"] - df = bursts.burst_data.with_columns(with_columns).drop(drop_columns) + return concat.with_columns(series) + else: + return concat + + +def make_burst_nodes( + photon_nodes: list[PhotonNode], burst_settings: dict[str, list[BurstColor]] +) -> list[BurstNode]: + photons = [PhotonData.from_file(PhotonFile(node.file_path)) for node in photon_nodes] + burst_nodes = [] + # todo tqdm? + for name, burst_colors in burst_settings.items(): + bursts = [photons.burst_search(burst_colors) for photons in photons] + infos = [get_info(photons) for photons in photons] + duration = get_duration(infos) + df = make_burst_dataframe(bursts, names=[node.name for node in photon_nodes]) + node = BurstNode( + name=name, df=df, colors=burst_colors, photon_nodes=photon_nodes, duration=duration + ) + burst_nodes.append(node) - return df + return burst_nodes def chain_filters(filters: list[BurstFilterItem]) -> Union[pl.Expr, Literal[True]]: """Chain a list of `BurstFilterItem` objects into a single `pl.Expr` object.""" - f_exprs = list(itertools.chain(*(f.as_expr() for f in filters))) + f_exprs = list(itertools.chain(*(f.as_expr() for f in filters if f.active))) if f_exprs: return reduce(and_, f_exprs) else: return True -# todo move to `dev` -def create_file_items(pth: Path) -> list[PhotonFileItem]: - """Return a list of `PhotonFileItem` objects from a directory containing ptu files.""" - return [PhotonFileItem(file_path=ptu_pth) for ptu_pth in pth.glob("*.ptu")] - - -# move to `dev` ? -def gen_fileitems(n: Optional[int] = None, directory: str = "ds2") -> list[PhotonFileItem]: - """Returns a list of the first `n` FileItem objects generated from - the data in `TEST_FILE_DIR`""" - - # root = Path(__file__).parent.parent.parent.parent - root = Path(*Path(__file__).parts[:5]) - - test_dir = root / "tests" / "test_data" / "input" / directory - - file_items = create_file_items(test_dir) - if n is None: - return file_items - else: - return file_items[:n] - - def get_duration(metadata: list[dict]) -> Optional[float]: """try to find the acquisition duraction of the photon files, and return as float only if they are all equal, otherwise returns `None` """ - durations = [m.get("acquisition_duration", None) for m in metadata] - if len(set(durations)) == 1: - return durations[0] - else: + durations = {m.get("acquisition_duration", None) for m in metadata} + if None in durations: return None + elif len(durations) != 1: + return None + return durations.pop() def format_size(size_in_bytes: int) -> str: @@ -122,57 +88,38 @@ class BurstResult(TypedDict): metadata: dict -def generate_traces( - photons: PhotonData, trace_settings: TraceSettings -) -> dict[str, BinnedPhotonData]: - t_bin = trace_settings.t_bin * 1e-3 - bounds = (trace_settings.t_min, trace_settings.t_max) - - traces = {} - for stream in TRACE_COLORS: - stream_data = PhotonData( - photons.data.filter(pl.col("stream") == stream), - metadata=photons.metadata, - cfg=photons.cfg, - ) - - traces[stream] = BinnedPhotonData(stream_data, binning_time=t_bin, bounds=bounds) - - return traces - - def to_treeview(nodes: list[FRETNode]) -> list[dict]: items = [] - for fret_node in nodes: + for node_idx, fret_node in enumerate(nodes): item = { - "name": fret_node.name, - "id": fret_node.id, + "name": fret_node.name.value, + "id": str(node_idx), "icon": "mdi-ruler", "children": [ { "name": "Photons", - "id": f"{fret_node.id}:photons", + "id": f"{node_idx}:photons", "icon": "mdi-lightbulb", "children": [ { "name": photon_file.name, - "id": f"{fret_node.id}:photons:{photon_file.name}", + "id": f"{node_idx}:photons:{ph_idx}", "icon": "mdi-file-star", } - for photon_file in fret_node.photons + for ph_idx, photon_file in enumerate(fret_node.photons.items) ], }, { "name": "Bursts", - "id": f"{fret_node.id}:bursts", + "id": f"{node_idx}:bursts", "icon": "mdi-flash", "children": [ { "name": burst_item.name, - "id": f"{fret_node.id}:bursts:{burst_item.name}", + "id": f"{node_idx}:bursts:{b_idx}", "icon": "mdi-file-chart", } - for burst_item in fret_node.bursts + for b_idx, burst_item in enumerate(fret_node.bursts.items) ], }, ], @@ -180,3 +127,20 @@ def to_treeview(nodes: list[FRETNode]) -> list[dict]: items.append(item) return items + + +def get_info(photons: PhotonData) -> dict: + info = {} + info["creation_time"] = photons.metadata["creation_time"] + info["number_of_photons"] = len(photons) + info["acquisition_duration"] = photons.metadata["acquisition_duration"] + info["power_diode"] = photons.metadata["tags"]["UsrPowerDiode"]["value"] + + info["cps"] = photons.cps + t_max = photons.photon_times.max() + counts = photons.data["stream"].value_counts(sort=True) + info["stream_cps"] = {k: v / t_max for k, v in counts.iter_rows()} + + if comment := photons.comment: + info["comment"] = comment + return info diff --git a/dont_fret/web/models.py b/dont_fret/web/models.py index 08ca15b..e8b4a13 100644 --- a/dont_fret/web/models.py +++ b/dont_fret/web/models.py @@ -2,17 +2,33 @@ import dataclasses import uuid +import warnings from collections import UserList -from dataclasses import dataclass, field, make_dataclass +from dataclasses import dataclass, field, make_dataclass, replace from pathlib import Path -from typing import Optional, Tuple, TypedDict +from typing import ( + Callable, + ContextManager, + Dict, + Generic, + List, + Optional, + Tuple, + TypedDict, + TypeVar, +) import numpy as np import polars as pl +import solara +from solara import Reactive +from solara.toestand import merge_state +from dont_fret import cfg from dont_fret.config.config import BurstColor, BurstFilterItem -from dont_fret.fileIO import PhotonFile -from dont_fret.models import PhotonData + +T = TypeVar("T") +R = TypeVar("R") BURST_SCHEMA = { "E_app": pl.Float64, @@ -33,29 +49,10 @@ } -# refactor: move to methods -def get_info(photons: PhotonData) -> dict: - info = {} - info["creation_time"] = photons.metadata["creation_time"] - info["number_of_photons"] = len(photons) - info["acquisition_duration"] = photons.metadata["acquisition_duration"] - info["power_diode"] = photons.metadata["tags"]["UsrPowerDiode"]["value"] - - info["cps"] = photons.cps - t_max = photons.photon_times.max() - counts = photons.data["stream"].value_counts(sort=True) - info["stream_cps"] = {k: v / t_max for k, v in counts.iter_rows()} - - if comment := photons.comment: - info["comment"] = comment - return info - - @dataclasses.dataclass -class PhotonFileItem: +class PhotonNode: file_path: Path info: Optional[dict] = None - photons: Optional[PhotonData] = None id: uuid.UUID = dataclasses.field(default_factory=lambda: uuid.uuid4()) @property @@ -66,32 +63,21 @@ def name(self) -> str: def size(self) -> int: return self.file_path.stat().st_size - def get_info(self) -> dict: - if self.info is None: - self.get_photons() - assert self.info is not None - return self.info - else: - return self.info - - def get_photons(self) -> PhotonData: - """read the file if it hasn't been read yet, otherwise checks for cached rsult""" + def __eq__(self, value: object) -> bool: + if not isinstance(value, PhotonNode): + return False + return self.id == value.id - if self.photons is not None: - return self.photons - # todo cachhe - # elif self.id in CHACHE: - # return CHACHE[self.id] - else: - self.photons = PhotonData.from_file(PhotonFile(self.file_path)) - self.info = get_info(self.photons) - return self.photons - def to_cache(self): - pass +@dataclasses.dataclass +class BurstNode: + name: str + df: pl.DataFrame + colors: list[BurstColor] = dataclasses.field(default_factory=list) + id: uuid.UUID = dataclasses.field(default_factory=lambda: uuid.uuid4()) - def from_cache(self): - pass + photon_nodes: list[PhotonNode] = dataclasses.field(default_factory=list) + duration: Optional[float] = None # move to config ? @@ -102,6 +88,7 @@ class SearchParams(TypedDict): # todo maybe don't use this class anymore with the new config settings +# todo remove class BurstColorList(UserList[BurstColor]): @classmethod def from_dict(cls, search_spec: dict[str, SearchParams]) -> BurstColorList: @@ -128,49 +115,6 @@ def to_dict(self) -> dict[str, SearchParams]: return spec -@dataclasses.dataclass -class BurstItem: - name: str - - df: pl.DataFrame - - selected_files: list[str] = dataclasses.field(default_factory=list) - - search_spec: Optional[dict[str, SearchParams]] = None - """Burst search settings used to generate the bursts""" - - metadata: dict = field(default_factory=dict) - - id: uuid.UUID = dataclasses.field(default_factory=lambda: uuid.uuid4()) - - def __post_init__(self): - if not self.selected_files: - self.selected_files = list(self.df["filename"].unique()) - - @property - def duration(self) -> Optional[float]: - durations = [m.get("acquisition_duration", None) for m in self.metadata.values()] - if len(set(durations)) == 1: - return durations[0] - else: - return None - - @classmethod - def from_path(cls, path: Path) -> BurstItem: - # todo add support for hdf5 files - if path.suffix == ".csv": - df = pl.read_csv(path) - elif path.suffix == ".pq": - df = pl.read_parquet(path) - else: - raise ValueError(f"Unsupported file type: {path.suffix}") - - # convert the filename column to Enum dtype - df = df.with_columns(pl.col("filename").cast(pl.Enum(df["filename"].unique().sort()))) - - return cls(name=path.stem, df=df) - - @dataclasses.dataclass class BurstPlotSettings: # = burst plot settings @@ -262,13 +206,8 @@ class TCSPCSettings: log_y: bool = True -@dataclasses.dataclass -class FRETNode: - name: str # displayed name - id: str = dataclasses.field(default_factory=lambda: uuid.uuid4().hex) # unique id - description: str = "" # description of the node - photons: list[PhotonFileItem] = dataclasses.field(default_factory=list) - bursts: list[BurstItem] = dataclasses.field(default_factory=list) +def reactive_factory(factory: Callable[[], T]) -> solara.Reactive[T]: + return solara.reactive(factory()) @dataclass @@ -279,3 +218,306 @@ class SnackbarMessage: btn_color: str = "text-primary-color" show: bool = False + + +class Snackbar: + def __init__(self, value: SnackbarMessage = SnackbarMessage(), default_timeout: int = 5000): + self.default_timeout = default_timeout + self.message = solara.Reactive(value) + + @property + def value(self) -> SnackbarMessage: + return self.message.value + + def update(self, **kwargs): + self.message.update(**kwargs) + + def set_message(self, msg: str, timeout: Optional[int] = None, **kwargs): + timeout = timeout if timeout is not None else self.default_timeout + self.message.update(message=msg, timeout=timeout, show=True, **kwargs) + + def info(self, msg: str, timeout: Optional[int] = None): + self.set_message(msg, color="primary", btn_color="text-primary-color", timeout=timeout) + + def secondary(self, msg: str, timeout: Optional[int] = None): + self.set_message(msg, color="secondary", btn_color="text-secondary-color", timeout=timeout) + + def warning(self, msg: str, timeout: Optional[int] = None): + self.set_message(msg, color="warning", btn_color="text-warning-color", timeout=timeout) + + def error(self, msg: str, timeout: Optional[int] = None): + self.set_message(msg, color="error", btn_color="text-error-color", timeout=timeout) + + def success(self, msg: str, timeout: Optional[int] = None): + self.set_message(msg, color="success", btn_color="text-success-color", timeout=timeout) + + +class _NoDefault: + """Sentinel class to distinguish between no default and None as default""" + + pass + + +NO_DEFAULT = _NoDefault() + + +class Store(Generic[T]): + def __init__(self, initial_value: T): + self._reactive = solara.reactive(initial_value) + + def subscribe(self, listener: Callable[[T], None], scope: Optional[ContextManager] = None): + return self._reactive.subscribe(listener, scope=scope) + + def subscribe_change( + self, listener: Callable[[T, T], None], scope: Optional[ContextManager] = None + ): + return self._reactive.subscribe_change(listener, scope=scope) + + +class ListStore(Store[list[T]]): + """baseclass for reactive list""" + + def __init__(self, items: Optional[list[T]] = None): + super().__init__(items if items is not None else []) + # self._reactive = solara.reactive(items if items is not None else []) + + def __len__(self): + return len(self.items) + + def __getitem__(self, idx: int) -> T: + return self.items[idx] + + def __iter__(self): + return iter(self.items) + + @property # TODO perhaps refactor to value + def items(self): + return self._reactive.value + + def get_item(self, idx: int, default: R = NO_DEFAULT) -> T | R: + try: + return self._reactive.value[idx] + except IndexError: + if default is NO_DEFAULT: + raise IndexError(f"Index {idx} is out of range") + return default + + def set(self, items: list[T]) -> None: + self._reactive.value = items + + def set_item(self, idx: int, item: T) -> None: + new_items = self._reactive.value.copy() + if idx == len(new_items): + new_items.append(item) + elif idx < len(new_items): + new_items[idx] = item + else: + raise IndexError(f"Index {idx} is out of range") + self._reactive.value = new_items + + def append(self, item: T) -> None: + self._reactive.value = [*self._reactive.value, item] + + def extend(self, items: list[T]) -> None: + new_value = self.items.copy() + new_value.extend(items) + self._reactive.value = new_value + + def insert(self, idx: int, item: T) -> None: + new_value = self.items.copy() + new_value.insert(idx, item) + self._reactive.value = new_value + + def remove(self, item: T) -> None: + self._reactive.value = [it for it in self.items if it != item] + + def pop(self, idx: int) -> T: + item = self.items[idx] + self._reactive.value = self.items[:idx] + self.items[idx + 1 :] + return item + + def clear(self) -> None: + self._reactive.value = [] + + def index(self, item: T) -> int: + return self.items.index(item) + + def update(self, idx: int, **kwargs): + new_value = self.items.copy() + updated_item = merge_state(new_value[idx], **kwargs) + new_value[idx] = updated_item + self._reactive.value = new_value + + def count(self, item: T) -> int: + return self.items.count(item) + + +def use_liststore(value: list[T] | ListStore[T]) -> ListStore[T]: + """use_reactive for liststore""" + + def make_liststore(): + if not isinstance(value, ListStore): + return ListStore(value) + + # dependencies = [value] if not isinstance(value, ListStore) else [] + + store = solara.use_memo(make_liststore, value) # type ignore + if isinstance(value, ListStore): + warnings.warn("look at use_reactive to implement all cases properly") + # raise ValueError("look at use_reactive to implement all cases properly") + store = value + assert store is not None + + return store + + +solara.use_reactive +K = TypeVar("K") +V = TypeVar("V") + + +class DictStore(Store[dict[K, V]]): + # todo maybe require values to be a dict + def __init__(self, values: Optional[dict] = None): + super().__init__(values if values is not None else {}) + + @property + def value(self): + return self._reactive.value + + def set(self, items: dict[K, V]) -> None: + self._reactive.value = items + + def __len__(self) -> int: + return len(self._reactive.value) + + def __getitem__(self, key): + return self._reactive.value[key] + + def __setitem__(self, key, value): + new_value = self._reactive.value.copy() + new_value[key] = value + self._reactive.value = new_value + + def items(self): + return self._reactive.value.items() + + def keys(self): + return self._reactive.value.keys() + + def values(self): + return self._reactive.value.values() + + def pop(self, key) -> V: + new_value = self._reactive.value.copy() + item = new_value.pop(key) + self.set(new_value) + return item + + def popitem(self) -> tuple[K, V]: + new_value = self._reactive.value.copy() + item = new_value.popitem() + self.set(new_value) + return item + + +@dataclasses.dataclass +class FRETNode: + name: solara.Reactive[str] # displayed name + id: uuid.UUID = dataclasses.field(default_factory=lambda: uuid.uuid4()) + description: solara.Reactive[str] = dataclasses.field( + default_factory=lambda: solara.reactive("") + ) + photons: ListStore[PhotonNode] = dataclasses.field(default_factory=lambda: ListStore([])) + bursts: ListStore[BurstNode] = dataclasses.field(default_factory=lambda: ListStore([])) + + +class FRETStore(ListStore[FRETNode]): + def __init__(self, nodes: list[FRETNode]): + super().__init__(nodes) + + def new_node(self, name: solara.Optional[str] = None) -> None: + name = name or self.get_default_name() + node = FRETNode(name=solara.Reactive(name)) + self.append(node) + + def get_node(self, node_id: uuid.UUID) -> FRETNode: + for node in self.items: + if node.id == node_id: + return node + + raise ValueError(f"Node with id {node_id} not found.") + + def get_default_name(self) -> str: + num_dic = { + 1: "TOO", + 2: "THREE", + 3: "FOUR", + 4: "FIVE", + 5: "SIX", + 6: "SEVEN", + 7: "EIGHT", + 8: "NINE", + 9: "TEN", + } + + if len(self) == 0: + return "FRET NOT" + else: + return f"FRET {num_dic.get(len(self), len(self) + 1)}" + + +@dataclass +class SelectorNode: + value: str + text: Optional[str] = None + children: list[SelectorNode] = field(default_factory=list) + + def __post_init__(self): + if self.text is None: + self.text = self.value + + @property + def record(self) -> dict: + return {"text": self.text, "value": self.value} + + +class BurstSettingsStore(DictStore[str, list[BurstColor]]): + """TODO most of these methods are now unused""" + + def reset(self) -> None: + self.set({k: v for k, v in cfg.burst_search.items()}) + + def add_settings(self, setting_name: str): + """Adds a new burst settings name with default settings.""" + new_value = self.value.copy() + new_value[setting_name] = [BurstColor()] + self.set(new_value) + + def remove_settings(self, setting_name: str): + self.pop(setting_name) + + def remove_color(self, setting_name: str): + """Removes the last color from the list of colors for a given burst settings name.""" + new_colors = self.value[setting_name].copy() + if len(new_colors) == 1: + return + new_colors.pop() + self[setting_name] = new_colors + + def update_color(self, settings_name: str, color_idx: int, **kwargs): + new_colors = self.value[settings_name].copy() + new_colors[color_idx] = replace(new_colors[color_idx], **kwargs) + self[settings_name] = new_colors + + def get_color(self, settings_name: str, color_idx: int) -> BurstColor: + return self.value[settings_name][color_idx] + + def add_color(self, settings_name: str): + colors = self.value[settings_name] + colors.append(BurstColor()) + self[settings_name] = colors + + @property + def settings_names(self) -> list[str]: + return list(self.keys()) diff --git a/dont_fret/web/reactive.py b/dont_fret/web/reactive.py deleted file mode 100644 index aea50ee..0000000 --- a/dont_fret/web/reactive.py +++ /dev/null @@ -1,243 +0,0 @@ -import dataclasses -import uuid -from typing import Dict, List, Literal, Optional, TypeVar, Union, overload - -import solara -from solara import Reactive -from solara.lab import Ref - -from dont_fret import cfg -from dont_fret.config.config import BurstColor -from dont_fret.web.models import ( - BurstColorList, - BurstItem, - FRETNode, - PhotonFileItem, - SnackbarMessage, -) - -S = TypeVar("S") - - -class ReactiveFRETNodes(solara.Reactive[list[FRETNode]]): - def add_node(self, name: Optional[str] = None) -> None: - name = name or self.default_name() - node = FRETNode(name=name, id=uuid.uuid4().hex) # todo uuid as UUID type - self.append(node) - - def append(self, item: FRETNode) -> None: - new_value = self.value.copy() - new_value.append(item) - self.value = new_value - - def extend(self, items: list[FRETNode]) -> None: - new_value = self.value.copy() - new_value.extend(items) - self.value = new_value - - def default_name(self) -> str: - num_dic = { - 1: "TWO", - 2: "THREE", - 3: "FOUR", - 4: "FIVE", - 5: "SIX", - 6: "SEVEN", - 7: "EIGHT", - 8: "NINE", - 9: "TEN", - } - - if len(self.value) == 0: - return "FRET NOT" - else: - return f"FRET {num_dic.get(len(self.value), len(self.value) + 1)}" - - def remove_node(self, node_id: str) -> None: - self.value = [node for node in self.value if node.id != node_id] - - def node_idx(self, node_id: str) -> int: - return [node.id for node in self.value].index(node_id) - - def get_node(self, node_id: str) -> FRETNode: - for node in self.value: - if node.id == node_id: - return node - - raise ValueError(f"Node with id {node_id} not found.") - - def remove_all_photon_files(self, node_id: str) -> None: - idx = self.node_idx(node_id) - ref = Ref(self.fields[idx].photons) - ref.value = [] - - def add_photon_files(self, node_id: str, photon_files: list[PhotonFileItem]) -> None: - idx = self.node_idx(node_id) - ref = Ref(self.fields[idx].photons) - ref.value = ref.value + photon_files - - def add_burst_items(self, node_id: str, burst_items: list[BurstItem]) -> None: - """ - adds a burst item. If the item already exists, it will be replaced - """ - - idx = self.node_idx(node_id) - ref = Ref(self.fields[idx].bursts) - new_names = [item.name for item in burst_items] - previous_items = [item for item in ref.value if item.name not in new_names] - ref.value = previous_items + burst_items - - @overload - def get_item( - self, node_id: str, item_type: Literal["photons"], item_name: str - ) -> PhotonFileItem: - ... - - @overload - def get_item(self, node_id: str, item_type: Literal["bursts"], item_name: str) -> BurstItem: - ... - - # overload for type checking - def get_item( - self, node_id: str, item_type: Literal["photons", "bursts"], item_name: str - ) -> Union[PhotonFileItem, BurstItem]: - idx = self.node_idx(node_id) - ref = Ref(getattr(self.fields[idx], item_type)) - for item in ref.value: - if item.name == item_name: - return item - - raise ValueError(f"Item with name {item_name} not found.") - - def remove_item( - self, node_id: str, item_type: Literal["photons", "bursts"], item_name: str - ) -> None: - idx = self.node_idx(node_id) - ref = Ref(getattr(self.fields[idx], item_type)) - ref.value = [item for item in ref.value if item.name != item_name] - - -class ReactiveList(solara.Reactive[list[S]]): - def add_item(self, item: S) -> None: - self.value = self.value + [item] - - def remove_item(self, idx: int) -> None: - new_items = self.value.copy() - del new_items[idx] - self.value = new_items - - # self.value = [item for i, item in enumerate(self.value) if i != idx] - - -class PhotonFileReactiveList(ReactiveList[PhotonFileItem]): - def __init__(self, *args, **kwargs): - raise DeprecationWarning("deprecated in favour of ReactiveFRETNodes") - - def add_file_items(self, file_items: list[PhotonFileItem]) -> None: - new_items = self.value + [f for f in file_items if f.file_info["name"] not in self.names] - if new_items: - self.value = new_items - - def remove_file_item(self, idx: int) -> None: - new_items = self.value.copy() - del new_items[idx] - self.value = new_items - - def remove_all(self) -> None: - self.value = [] - - def select_index(self, idx: list[int]) -> None: - self.value = [dataclasses.replace(f, selected=i in idx) for i, f in enumerate(self.value)] - - def select_none(self) -> None: - self.value = [dataclasses.replace(f, selected=False) for f in self.value] - - def select_all(self) -> None: - self.value = [dataclasses.replace(f, selected=True) for f in self.value] - - @property - def names(self) -> list[str]: - """Returns names of all files""" - return [item.file_info["name"] for item in self.value] - - @property - def selected(self) -> list[int]: - """Returns indices of selected files""" - return [i for i, f in enumerate(self.value) if f.selected] - - -class BurstItemsReactiveList(ReactiveList[BurstItem]): - @property - def names(self) -> list[str]: - """Returns names of all files""" - return [item.name for item in self.value] - - -class BurstSettingsReactive(Reactive[Dict[str, List[BurstColor]]]): - def reset(self) -> None: - self.value = {k: BurstColorList(v) for k, v in cfg.burst_search.items()} - - def add_settings(self, setting_name: str): - """Adds a new burst settings name with default settings.""" - new_value = self.value.copy() - new_value[setting_name] = [BurstColor()] - self.value = new_value - - def remove_settings(self, setting_name: str): - """Removes a burst settings name.""" - new_value = self.value.copy() - new_value.pop(setting_name) - self.value = new_value - - def remove_color(self, setting_name: str): - """Removes the last color from the list of colors for a given burst settings name.""" - colors_ref = Ref(self.fields[setting_name]) - new_colors = colors_ref.get().copy() - if len(new_colors) == 1: - return - new_colors.pop() - colors_ref.set(new_colors) # isnt this a copy? - - def update_color(self, settings_name: str, color_idx: int, **kwargs): - # calling update / setter is fine because there are no listeners attached - Ref(self.fields[settings_name][color_idx]).update(**kwargs) - - def get_color(self, settings_name: str, color_idx: int) -> BurstColor: - # this is not allowed because it creates a listener with a too high idx - # return Ref(self.fields[setting_name][color_idx]).get() - - # do this instead - return self.value[settings_name][color_idx] - - def add_color(self, settings_name: str): - colors_ref = Ref(self.fields[settings_name]) - colors_ref.set(colors_ref.get().copy() + [BurstColor()]) - - @property - def settings_names(self) -> List[str]: - return list(self.value.keys()) - - -class SnackbarReactive(solara.Reactive[SnackbarMessage]): - def __init__(self, value: SnackbarMessage = SnackbarMessage(), default_timeout: int = 5000): - self.default_timeout = default_timeout - super().__init__(value) - - def set_message(self, msg: str, timeout: Optional[int] = None, **kwargs): - timeout = timeout if timeout is not None else self.default_timeout - self.update(message=msg, timeout=timeout, show=True, **kwargs) - - def info(self, msg: str, timeout: Optional[int] = None): - self.set_message(msg, color="primary", btn_color="text-primary-color", timeout=timeout) - - def secondary(self, msg: str, timeout: Optional[int] = None): - self.set_message(msg, color="secondary", btn_color="text-secondary-color", timeout=timeout) - - def warning(self, msg: str, timeout: Optional[int] = None): - self.set_message(msg, color="warning", btn_color="text-warning-color", timeout=timeout) - - def error(self, msg: str, timeout: Optional[int] = None): - self.set_message(msg, color="error", btn_color="text-error-color", timeout=timeout) - - def success(self, msg: str, timeout: Optional[int] = None): - self.set_message(msg, color="success", btn_color="text-success-color", timeout=timeout) diff --git a/dont_fret/web/state.py b/dont_fret/web/state.py index b917c39..382ea49 100644 --- a/dont_fret/web/state.py +++ b/dont_fret/web/state.py @@ -4,20 +4,42 @@ import solara from dont_fret.config import cfg -from dont_fret.web.models import BurstColorList -from dont_fret.web.reactive import BurstSettingsReactive, ReactiveFRETNodes, SnackbarReactive +from dont_fret.web.datamanager import ThreadedDataManager +from dont_fret.web.models import ( + BurstColorList, + BurstSettingsStore, + FRETStore, + ListStore, + Snackbar, +) APP_TITLE = "Don't FRET!" -fret_nodes = ReactiveFRETNodes([]) filebrowser_folder = solara.Reactive[Path](cfg.web.default_dir) -burst_settings = BurstSettingsReactive({k: BurstColorList(v) for k, v in cfg.burst_search.items()}) -filters = solara.Reactive(copy.deepcopy(cfg.web.burst_filters)) -snackbar = SnackbarReactive() +# TODO as liststore +burst_settings = BurstSettingsStore( + {k: BurstColorList(v) for k, v in cfg.burst_search.items()} # type ignore +) + +filters = ListStore(copy.deepcopy(cfg.web.burst_filters)) +snackbar = Snackbar() + +fret_nodes = FRETStore([]) -# selections for burst figures (node, burst) burst_figure_selection = [ - (solara.Reactive(0), solara.Reactive(0)), - (solara.Reactive(0), solara.Reactive(0)), + ListStore[str](), + ListStore[str](), ] + +burst_figure_file_selection = [{}, {}] + +trace_selection = ListStore[str]() + +# cfg set to dask manager +data_manager = ThreadedDataManager() + +# maybe check this via subscribe on the liststores ? +# -> make sure we can use the classes in different contexts +disable_trace_page = solara.Reactive(True) +disable_burst_page = solara.Reactive(True) diff --git a/dont_fret/web/style.css b/dont_fret/web/style.css new file mode 100644 index 0000000..19821c7 --- /dev/null +++ b/dont_fret/web/style.css @@ -0,0 +1,4 @@ +.vega-embed { + overflow: visible; + width: 100% !important; +} \ No newline at end of file diff --git a/dont_fret/web/trace/methods.py b/dont_fret/web/trace/methods.py deleted file mode 100644 index 97a5cd9..0000000 --- a/dont_fret/web/trace/methods.py +++ /dev/null @@ -1,40 +0,0 @@ -import plotly.graph_objects as go -import polars as pl -import solara -import solara.lab - -from dont_fret import PhotonData -from dont_fret.formatting import TRACE_COLORS -from dont_fret.web.models import TCSPCSettings - -# TODO move fret node / photon file reactives to module level -TCSPC_SETTINGS = solara.Reactive(TCSPCSettings()) -MAX_DATAPOINTS = 100_000 - - -def create_tcspc_histogram( - photons: PhotonData, settings: TCSPCSettings, dark: bool = False -) -> go.Figure: - if photons.nanotimes_unit is None: - raise ValueError("Provided photon data does not have TCSPC information.") - fig = go.Figure() - for stream in TRACE_COLORS: - x, y = ( - photons.data.filter(pl.col("stream") == stream)["nanotimes"] - .value_counts() - .sort(pl.col("nanotimes")) - ) - - line = dict(color=TRACE_COLORS[stream]) - fig.add_trace(go.Scatter(x=x, y=y, mode="lines", line=line, name=stream)) - - fig.update_layout( - xaxis_title="Time (ns)", - yaxis_title="Photons per bin", - template="plotly_dark" if dark else "plotly_white", - ) - - if settings.log_y: - fig.update_yaxes(type="log") - - return fig diff --git a/dont_fret/web/trace/page.py b/dont_fret/web/trace/page.py index bab5f1e..f7cfc78 100644 --- a/dont_fret/web/trace/page.py +++ b/dont_fret/web/trace/page.py @@ -1,48 +1,35 @@ from io import BytesIO -from typing import Optional, cast import pandas as pd import plotly.graph_objects as go +import polars as pl import solara import solara.lab -from solara.alias import rv import dont_fret.web.state as state from dont_fret import BinnedPhotonData, PhotonData from dont_fret.formatting import TRACE_COLORS, TRACE_SIGNS -from dont_fret.web.methods import generate_traces -from dont_fret.web.models import TCSPCSettings, TraceSettings -from dont_fret.web.trace.methods import create_tcspc_histogram +from dont_fret.web.components import FigureFromTask +from dont_fret.web.models import ( + PhotonNode, + TCSPCSettings, + TraceSettings, +) +from dont_fret.web.utils import ( + NestedSelectors, + get_photons, + make_selector_nodes, +) # TODO move fret node / photon file reactives to module level TCSPC_SETTINGS = solara.Reactive(TCSPCSettings()) MAX_DATAPOINTS = 100_000 -@solara.component -def TCSPCFigure(photons: PhotonData, title: str): - settings = TCSPC_SETTINGS.value # not really need in the global state - figure, set_figure = solara.use_state(cast(Optional[go.Figure], None)) - dark_effective = solara.lab.use_dark_effective() - - def redraw(): - fig = create_tcspc_histogram(photons, settings, dark=dark_effective) - fig.update_layout(title=title) - set_figure(fig) - - fig_result = solara.use_thread(redraw, dependencies=[photons, settings, dark_effective]) - # TODO style="opacity: 0.3" if fig_result.state == solara.ResultState.RUNNING else None - with solara.Card(): - solara.ProgressLinear(fig_result.state == solara.ResultState.RUNNING) - if figure: - solara.FigurePlotly(figure) - else: - solara.SpinnerSolara(size="100px") - - def to_csv(traces: dict[str, BinnedPhotonData], name: str) -> BytesIO: """Return a CSV string for the traces.""" # TODO this name does not do anything + # TODO not used, saving data needs to be reimplemented df = pd.DataFrame( index=next(iter(traces.values())).time, data={tr_name: trace.photons for tr_name, trace in traces.items()}, @@ -59,152 +46,102 @@ def to_csv(traces: dict[str, BinnedPhotonData], name: str) -> BytesIO: def TracePage(): solara.Title(f"{state.APP_TITLE} / Trace") - # photons, set_photons = solara.use_state(cast(Optional[ChannelPhotonData], None)) + selector_nodes = make_selector_nodes(state.fret_nodes.items) + labels = ["Measurement", "Photons"] # TODO move elsewhere TRACE_SETTINGS: solara.Reactive[TraceSettings] = solara.use_reactive(TraceSettings()) - # only fret nodes with photon file items added are shown - nodes_with_photons = [node for node in state.fret_nodes.value if node.photons] - fret_node, set_fret_node = solara.use_state(nodes_with_photons[0]) - - photon_file, set_photon_file = solara.use_state(fret_node.photons[0]) - dark_effective = solara.lab.use_dark_effective() - - def on_fret_node(node_id: str): - new_node = state.fret_nodes.get_node(node_id) - set_fret_node(new_node) - set_photon_file(new_node.photons[0]) - - def on_photon_file(photon_file_name: str): - photon_file_item = state.fret_nodes.get_item(fret_node.id, "photons", photon_file_name) - set_photon_file(photon_file_item) + selectors = NestedSelectors( + nodes=selector_nodes, selection=state.trace_selection, labels=labels + ) + with solara.Sidebar(): + for level in selectors: + solara.Select(**level) - def load_photons() -> PhotonData: - photons = photon_file.get_photons() - return photons + photon_node = get_photons(state.fret_nodes.items, state.trace_selection.items) + TraceFigure(photon_node, TRACE_SETTINGS.value) + TCSPCFigure(photon_node) - ph_result = solara.lab.use_task(load_photons, dependencies=[photon_file], prefer_threaded=True) - def traces_memo(): - if ph_result.value is None: - return {} - if TRACE_SETTINGS.value.num_dpts > MAX_DATAPOINTS: - return {} +@solara.component +def TraceFigure(photon_node: PhotonNode, settings: TraceSettings): + dark_effective = solara.lab.use_dark_effective() - return generate_traces(ph_result.value, TRACE_SETTINGS.value) + async def redraw(): + photons = await state.data_manager.get_photons(photon_node) - traces: dict[str, BinnedPhotonData] = solara.use_memo( - traces_memo, dependencies=[ph_result.value, TRACE_SETTINGS.value] - ) - with solara.Sidebar(): - with solara.Card("Controls"): - solara.Select( - label="Measurement", - value=fret_node.id, - on_value=on_fret_node, # type: ignore - values=[ - {"text": fret_node.name, "value": fret_node.id} - for fret_node in state.fret_nodes.value - if fret_node.photons # type: ignore - ], - ) + # also probably it would be nice to make the getting photons etc more functional? + # we might want to move binning to data manager as well such that is is async + t_bin = settings.t_bin * 1e-3 + bounds = (settings.t_min, settings.t_max) - solara.Select( - label="Photon file", - value=photon_file.name, - on_value=on_photon_file, - values=[ph.name for ph in fret_node.photons], + traces = {} + for stream in TRACE_COLORS: + stream_data = PhotonData( + photons.data.filter(pl.col("stream") == stream), + metadata=photons.metadata, + cfg=photons.cfg, ) - solara.ProgressLinear(ph_result.pending) - if ph_result.finished is not None: - solara.Text("Trace settings") - rv.Divider() # noqa - solara.InputFloat( - label="Time start", - # hint="Start time point of the trace in seconds.", - value=TRACE_SETTINGS.value.t_min, - on_value=lambda x: TRACE_SETTINGS.update(t_min=x), - ) - solara.InputFloat( - label="Time end", - # hint="Ending time point of the trace in seconds.", - value=TRACE_SETTINGS.value.t_max, - on_value=lambda x: TRACE_SETTINGS.update(t_max=x), + traces[stream] = BinnedPhotonData(stream_data, binning_time=t_bin, bounds=bounds) + + fig = go.Figure() + for tr in TRACE_COLORS: + line = dict(color=TRACE_COLORS[tr]) + fig.add_trace( + go.Scatter( + x=traces[tr].time, + y=TRACE_SIGNS[tr] * traces[tr].photons, + mode="lines", + line=line, + name=tr, ) - solara.InputFloat( - label="Binning time", - # hint="Binning time in milliseconds.", - value=TRACE_SETTINGS.value.t_bin, - on_value=lambda x: TRACE_SETTINGS.update(t_bin=x), - ) - - solara.Div(style="height: 25px") + ) - solara.Text("TCSPC histogram settings") - rv.Divider() + fig.update_layout( + # title="Time trace", + xaxis_title="Time (s)", + yaxis_title="Photons per bin", + template="plotly_dark" if dark_effective else "plotly_white", + ) - solara.Checkbox( - label="logy", - value=TCSPC_SETTINGS.value.log_y, - on_value=lambda x: TCSPC_SETTINGS.update(log_y=x), - ) - rv.Divider() + return fig - solara.Div(style="height: 25px") + figure_task = solara.lab.use_task(redraw, dependencies=[photon_node, settings, dark_effective]) # type: ignore + FigureFromTask(figure_task) - if TRACE_SETTINGS.value.num_dpts > MAX_DATAPOINTS: - solara.Warning( - "Too many datapoints to plot. Please increase the binning time or reduce the interval." - ) - if ph_result.finished and ph_result.value is not None: - solara.Info(f"Loaded {len(ph_result.value)} photons.") - solara.Info(f"Duration: {ph_result.value.metadata['acquisition_duration']} s") +@solara.component +def TCSPCFigure(photon_node: PhotonNode): + # todo move settings + settings = TCSPC_SETTINGS.value + dark_effective = solara.lab.use_dark_effective() - if traces: + # TODO make binning step also async / threaded + async def redraw(): + photons = await state.data_manager.get_photons(photon_node) + if photons.nanotimes_unit is None: + raise ValueError("Provided photon data does not have TCSPC information.") + fig = go.Figure() + for stream in TRACE_COLORS: + x, y = ( + photons.data.filter(pl.col("stream") == stream)["nanotimes"] + .value_counts() + .sort(pl.col("nanotimes")) + ) - def download_cb(): - return to_csv(traces, "filename.txt") + line = dict(color=TRACE_COLORS[stream]) + fig.add_trace(go.Scatter(x=x, y=y, mode="lines", line=line, name=stream)) - solara.FileDownload( - download_cb, - filename=f"{photon_file.name}_traces.csv", - children=[ - solara.Button( - "Download binned data", - block=True, - ) - ], - ) + fig.update_layout( + xaxis_title="Time (ns)", + yaxis_title="Photons per bin", + template="plotly_dark" if dark_effective else "plotly_white", + ) - with solara.Column(): - # move to component - if traces: # this doesnt work like this? use use_state? - fig = go.Figure() - - for tr in TRACE_COLORS: - line = dict(color=TRACE_COLORS[tr]) - fig.add_trace( - go.Scatter( - x=traces[tr].time, - y=TRACE_SIGNS[tr] * traces[tr].photons, - mode="lines", - line=line, - name=tr, - ) - ) + if settings.log_y: + fig.update_yaxes(type="log") - fig.update_layout( - title=f"Time trace: {fret_node.name}/{photon_file.name}", - xaxis_title="Time (s)", - yaxis_title="Photons per bin", - template="plotly_dark" if dark_effective else "plotly_white", - ) - with solara.Card(): - solara.FigurePlotly(fig, dependencies=[traces, dark_effective]) + return fig - if ph_result.finished: - assert ph_result.value is not None - TCSPCFigure( - ph_result.value, title=f"TCSPC histogram: {fret_node.name}/{photon_file.name}" - ) + figure_task = solara.lab.use_task(redraw, dependencies=[photon_node, settings, dark_effective]) # type: ignore # noqa: SH101 + FigureFromTask(figure_task) diff --git a/dont_fret/web/utils.py b/dont_fret/web/utils.py index 754a13e..541be34 100644 --- a/dont_fret/web/utils.py +++ b/dont_fret/web/utils.py @@ -1,7 +1,40 @@ -from typing import Optional, TypeVar import time +import uuid +from dataclasses import dataclass +from functools import partial +from typing import Any, Callable, Dict, Iterator, List, Literal, Optional, TypeVar + +from dont_fret.web.models import BurstNode, FRETNode, ListStore, PhotonNode, SelectorNode T = TypeVar("T") +V = TypeVar("V") + + +# TODO 1) it should be able not to take any args at all +# and just bind args and return a callable taking no arg +# and 2) you should be able to not give any value for value_arg +# and then the returned wrapper takes a single argument which is passed to the function +# as its only remaining non-wrapped argument +def wrap_callback(fn: Callable[..., Any], value_arg: str, **bound_args: Any) -> Callable[[V], None]: + """ + Wraps a function to create a callback suitable for Solara component props. + + Args: + fn: The base function to wrap (e.g., set_item) + value_arg: Name of the argument that will receive the callback's value + **bound_args: Fixed arguments to bind to the function + + Example: + >>> store = ListStore() + >>> on_value = wrap_callback(store.set_item, 'item', idx=0) + >>> solara.Select(value='current', on_value=on_value, values=['a', 'b']) + """ + pfunc = partial(fn, **bound_args) + + def wrapper(value: V) -> None: + pfunc(**{value_arg: value}) + + return wrapper def not_none(*args: Optional[T]) -> T: @@ -15,3 +48,99 @@ def not_none(*args: Optional[T]) -> T: def some_task(param=3) -> int: time.sleep(param / 2) return param * 2 + + +def find_object(items: list[T], **kwargs) -> T: + for item in items: + if all(getattr(item, key) == value for key, value in kwargs.items()): + return item + raise ValueError("Object not found") + + +def find_index(items: list, **kwargs) -> int: + for i, item in enumerate(items): + if all(getattr(item, key) == value for key, value in kwargs.items()): + return i + raise ValueError("Object not found") + + +def make_selector_nodes( + fret_nodes: list[FRETNode], + attr: Literal["photons", "bursts"] = "photons", + require_children: bool = True, +) -> list[SelectorNode]: + selector_nodes = [] + for fret_node in fret_nodes: + children = [ + SelectorNode(value=n.id.hex, text=n.name) for n in getattr(fret_node, attr).items + ] + + if require_children and not children: + continue + + node = SelectorNode( + value=fret_node.id.hex, + text=fret_node.name.value, + children=children, + ) + + selector_nodes.append(node) + + return selector_nodes + + +def get_photons(fret_nodes: list[FRETNode], choice: list[str]) -> PhotonNode: + assert len(choice) == 2 + fret_node = find_object(fret_nodes, id=uuid.UUID(choice[0])) + photon_node = find_object(fret_node.photons.items, id=uuid.UUID(choice[1])) + return photon_node + + +def get_bursts(fret_nodes: list[FRETNode], choice: list[str]) -> BurstNode: + assert len(choice) == 2 + fret_node = find_object(fret_nodes, id=uuid.UUID(choice[0])) + burst_node = find_object(fret_node.bursts.items, id=uuid.UUID(choice[1])) + return burst_node + + +def has_photons(nodes: list[FRETNode]) -> bool: + return any([n.photons for n in nodes]) + + +def has_bursts(nodes: list[FRETNode]) -> bool: + return any([n.bursts for n in nodes]) + + +@dataclass +class NestedSelectors: + nodes: List[SelectorNode] + selection: ListStore[str] + labels: Optional[List[str]] + + def __iter__(self) -> Iterator[Dict[str, Any]]: + stack = self.nodes + i = 0 + while stack: + records = [node.record for node in stack] + if not records: + break + + on_value = wrap_callback(self.selection.set_item, "item", idx=i) + + val_stored = self.selection.get_item(i, None) + if val_stored in {v["value"] for v in records}: + value = val_stored + else: + value = records[0]["value"] + on_value(value) + + if self.labels: + label = self.labels[i] + else: + label = f"Level {i}" + + yield {"label": label, "value": value, "values": records, "on_value": on_value} + + selected_node = find_object(stack, value=value) + stack = selected_node.children if selected_node else [] + i += 1 diff --git a/pyproject.toml b/pyproject.toml index fdd5894..9d8ad4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,10 +10,9 @@ authors = [ ] license = "MIT" readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.10" classifiers = [ "Development Status :: 4 - Beta", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Intended Audience :: Science/Research", @@ -31,6 +30,9 @@ dependencies = [ "click", "solara>=1.19.0", "plotly", + "altair", + "anywidget", + "vegafusion[embed]" ] dynamic = ["version"] @@ -55,6 +57,7 @@ test = [ "pytest>=7.2.0", "pytest-playwright>=0.3.3", "pytest-asyncio", + "pytest-ipywidgets[solara]", ] diff --git a/templates/01_load_datafile_1.py b/templates/01_load_datafile_1.py index b7111ff..fd9f9bc 100644 --- a/templates/01_load_datafile_1.py +++ b/templates/01_load_datafile_1.py @@ -16,11 +16,6 @@ # %% bursts = photons.burst_search("DCBS") +bursts.burst_data # %% - -# Export to a dataframe, skip the number of photons but include photon count -# and mean life time per burst per photon stream. - -bursts.burst_data.head() -print(bursts.burst_data) diff --git a/templates/05_web_models.py b/templates/05_web_models.py index c00000a..8cd2d90 100644 --- a/templates/05_web_models.py +++ b/templates/05_web_models.py @@ -1,5 +1,4 @@ # %% - """template for creating web models and using them to launch solara parts for interactive use only @@ -9,31 +8,40 @@ from pathlib import Path -import dont_fret.web.state as state +import solara + +from dont_fret.config import cfg from dont_fret.web.bursts.components import BurstFigure -from dont_fret.web.methods import batch_burst_search -from dont_fret.web.models import FRETNode, PhotonFileItem + +# SyncDataManager, +from dont_fret.web.methods import make_burst_nodes +from dont_fret.web.models import FRETNode, ListStore, PhotonNode # %% ROOT = Path(__file__).parent.parent pth = ROOT / "tests" / "test_data" / "input" / "ds2" -photon_file_items = [PhotonFileItem(file_path=ptu_pth) for ptu_pth in pth.glob("*.ptu")] +photon_nodes = [PhotonNode(file_path=ptu_pth) for ptu_pth in pth.glob("*.ptu")] +burst_nodes = make_burst_nodes(photon_nodes, cfg.burst_search) -# %% -burst_settings = ["DCBS", "APBS"] -burst_items = [batch_burst_search(photon_file_items, name) for name in burst_settings] # %% -state.fret_nodes.set([]) -node = FRETNode( - name="FRET NOT", - photons=photon_file_items, - bursts=burst_items, + +node_1 = FRETNode( + name=solara.Reactive("my_node"), + photons=ListStore(photon_nodes), + bursts=ListStore(burst_nodes), ) -state.fret_nodes.append(node) # %% -BurstFigure(state.fret_nodes, state.filters) +node_2 = FRETNode( + name=solara.Reactive("my_node_2"), +) +node_2.photons.extend(photon_nodes[2:]) +fret_nodes = [node_1, node_2] +fret_nodes +# %% + +BurstFigure(fret_nodes) # %% diff --git a/templates/06_preload_web.py b/templates/06_preload_web.py index ffe1726..6cc1651 100644 --- a/templates/06_preload_web.py +++ b/templates/06_preload_web.py @@ -14,13 +14,13 @@ from dont_fret.web.bursts.components import BurstFigure from dont_fret.web.main import Page as MainPage from dont_fret.web.methods import batch_burst_search -from dont_fret.web.models import FRETNode, PhotonFileItem +from dont_fret.web.models import FRETNode, PhotonNode # %% ROOT = Path(__file__).parent.parent pth = ROOT / "tests" / "test_data" / "input" / "ds2" -photon_file_items = [PhotonFileItem(file_path=ptu_pth) for ptu_pth in pth.glob("*.ptu")] +photon_file_items = [PhotonNode(file_path=ptu_pth) for ptu_pth in pth.glob("*.ptu")] # %% diff --git a/tests/test_data/output/web/DCBS_default_bursts.csv b/tests/test_data/output/web/DCBS_default_bursts.csv index 852fb31..102a766 100644 --- a/tests/test_data/output/web/DCBS_default_bursts.csv +++ b/tests/test_data/output/web/DCBS_default_bursts.csv @@ -1,230 +1,711 @@ -,E_app,S_app,n_photons,time_length,time_mean,time_min,time_max,n_DD,n_DA,n_AA,n_AD,tau_DD,tau_DA,tau_AA,tau_AD,filename -0,0.5394736842105263,0.5615763546798029,407,0.0016798499999999999,0.5821335101965601,0.58126295,0.5829428,105,123,178,1,2.6492857496574723e-09,3.726016309910254e-09,2.876685431666296e-08,2.7300000364494093e-08,f4.ptu -1,0.6666666666666666,0.5,126,0.00042964999999999995,0.6517511976190475,0.6515398,0.65196945,21,42,63,0,2.3464286027567528e-09,3.557738142738993e-09,2.9110714674384005e-08,,f4.ptu -2,0.5319148936170213,0.48205128205128206,195,0.00066875,0.8446144617948718,0.8442822999999999,0.8449510499999999,44,50,101,0,3.1789773151711712e-09,4.2075000561761505e-09,2.8527970677918958e-08,,f4.ptu -3,0.3805309734513274,0.46887966804979253,241,0.0007504499999999999,2.5442334163900413,2.5438294,2.54457985,70,43,128,0,2.7935714658696076e-09,3.2552326016015513e-09,2.810332068771957e-08,,f4.ptu -4,0.15,0.5813953488372093,172,0.00062635,2.9248856671511625,2.92461285,2.9252392,85,15,72,0,3.5211765176009833e-09,2.2600000301742365e-09,2.8517361491858714e-08,,f4.ptu -5,0.11888111888111888,0.6559633027522935,218,0.0006665999999999999,2.925925973853211,2.9255554999999998,2.9262221,126,17,75,0,3.1081349621329723e-09,2.947058862876867e-09,2.8762000384013887e-08,,f4.ptu -6,0.5,0.48484848484848486,132,0.00035585,3.1350279803030303,3.1348157,3.13517155,32,32,68,0,2.2718750303327845e-09,4.254687556806171e-09,2.879117685499167e-08,,f4.ptu -7,0.782051282051282,0.5454545454545454,143,0.0004764,3.2864551877622374,3.28621215,3.28668855,17,61,65,0,3.2617647494315826e-09,4.791393506594914e-09,2.972923116615857e-08,,f4.ptu -8,0.37037037037037035,0.574468085106383,94,0.00042395,4.077127779787234,4.0769307999999995,4.07735475,34,20,40,0,3.7433824029206915e-09,3.915000052270856e-09,2.82618753773365e-08,,f4.ptu -9,0.16901408450704225,0.5035460992907801,141,0.000419,4.077845644326241,4.0776496,4.0780686,59,12,70,0,3.604237336257322e-09,4.512500060248337e-09,2.8293214663469214e-08,,f4.ptu -10,0.6911764705882353,0.5271317829457365,129,0.00046919999999999997,4.637728455813953,4.6374898,4.6379589999999995,21,47,61,0,2.5059524144104338e-09,3.582446856341433e-09,2.854631185654397e-08,,f4.ptu -11,0.7027027027027027,0.5311004784688995,209,0.00066225,4.638759683014354,4.6384251,4.63908735,33,78,98,0,2.3568182132850794e-09,3.768910306730605e-09,2.8820153446014802e-08,,f4.ptu -12,0.9418604651162791,0.5584415584415584,154,0.00046215,5.617535639935065,5.6173267,5.61778885,5,81,68,0,2.4400000325774937e-09,3.808642026159466e-09,2.948419157012676e-08,,f4.ptu -13,0.8676470588235294,0.5528455284552846,370,0.0016384499999999998,6.18067671527027,6.17992095,6.181559399999999,27,177,165,1,2.444444477081278e-09,4.015819262656485e-09,2.888742462811272e-08,2.8400000379180668e-08,f4.ptu -14,0.1919191919191919,0.5892857142857143,168,0.00057135,6.445808167559524,6.445531,6.446102349999999,80,19,69,0,2.9609375395327556e-09,4.142105318460931e-09,2.7926449648220407e-08,,f4.ptu -15,0.4925373134328358,0.44370860927152317,151,0.0006914499999999999,6.848385460927152,6.8480377,6.84872915,34,33,84,0,2.9588235689162957e-09,3.2287879218968205e-09,2.869791704982495e-08,,f4.ptu -16,0.07246376811594203,0.5227272727272727,132,0.00050475,7.911861859090909,7.9116329,7.91213765,64,5,63,0,3.441796920952917e-09,2.810000037517524e-09,2.881746070221468e-08,,f4.ptu -17,0.9375,0.5594405594405595,143,0.00050435,9.351014051048951,9.3507822,9.35128655,5,75,63,0,3.5100000468635264e-09,3.1803333757953376e-09,2.8963889275598284e-08,,f4.ptu -18,0.603448275862069,0.464,125,0.00045545,9.416124843199999,9.41589775,9.4163532,23,35,67,0,3.019565257706824e-09,2.9250000390529385e-09,2.8533582470516418e-08,,f4.ptu -19,0.5573770491803278,0.46564885496183206,131,0.00048259999999999997,10.591812293511449,10.5915714,10.592054,27,34,70,0,2.4203704026857807e-09,2.7823529783248667e-09,2.8474286094458202e-08,,f4.ptu -20,0.7092198581560284,0.47315436241610737,298,0.00100585,10.737798576342282,10.737345099999999,10.73835095,41,100,157,0,2.6280488155760192e-09,3.591500047951668e-09,2.881799401533473e-08,,f4.ptu -21,0.684931506849315,0.5214285714285715,140,0.00055145,11.267530855714284,11.2672595,11.26781095,23,50,67,0,2.820652211572789e-09,3.877000051763502e-09,2.9170149643194604e-08,,f4.ptu -22,0.6842105263157895,0.5688622754491018,167,0.0006324999999999999,12.915512495508981,12.91519235,12.91582485,30,65,72,0,2.3883333652210034e-09,3.632692356193952e-09,2.918819483414864e-08,,f4.ptu -23,0.9137931034482759,0.42962962962962964,135,0.00045484999999999997,13.01316205222222,13.01293065,13.0133855,5,53,77,0,2.4850000331783087e-09,3.490566084339904e-09,2.890422116513352e-08,,f4.ptu -24,0.5,0.14285714285714285,14,7.785e-05,13.209333589285714,13.2092961,13.20937395,1,1,12,0,1.875000025033935e-09,2.8000000373840095e-09,2.7860417038643125e-08,,f4.ptu -25,0.07692307692307693,0.5098039215686274,51,0.0002939,13.211191288235295,13.2110265,13.2113204,24,2,25,0,3.043750040638421e-09,2.4500000327110083e-09,2.8557000381276842e-08,,f4.ptu -26,0.3333333333333333,0.5454545454545454,11,7.91e-05,13.211634327272726,13.21159615,13.211675249999999,4,2,5,0,2.918750038969492e-09,1.0112500135016356e-08,2.8335000378312825e-08,,f4.ptu -27,0.5853658536585366,0.48520710059171596,169,0.0005829499999999999,13.819275338461539,13.818995549999999,13.819578499999999,34,48,87,0,2.191911793971043e-09,3.1036458747714492e-09,2.8375287735172555e-08,,f4.ptu -28,0.3835616438356164,0.474025974025974,154,0.0007446,13.820477097077921,13.82005525,13.82079985,45,28,81,0,2.890000038585638e-09,2.9276786105172726e-09,2.8303086797639822e-08,,f4.ptu -29,0.4426229508196721,0.5292841648590022,461,0.00180065,14.382028272125813,14.38117995,14.3829806,136,108,217,0,2.7430147425055272e-09,3.0828704115311044e-09,2.8282258442124773e-08,,f4.ptu -30,0.8767123287671232,0.5289855072463768,138,0.0006378499999999999,14.587557782608696,14.58725675,14.587894599999998,9,64,65,0,2.1444444730758483e-09,3.257031293486031e-09,2.8316154224215047e-08,,f4.ptu -31,0.8865979381443299,0.5449438202247191,178,0.00070595,14.591304641011234,14.5909582,14.59166415,11,86,81,0,2.415909123164937e-09,3.649709351054427e-09,2.8890432484494072e-08,,f4.ptu -32,0.82,0.45454545454545453,110,0.00041224999999999996,14.592095303181818,14.591866399999999,14.592278649999999,9,41,60,0,3.069444485425923e-09,2.9365854050612786e-09,2.8923750386173482e-08,,f4.ptu -33,0.8617021276595744,0.5053763440860215,186,0.00068025,14.611716611021507,14.611367999999999,14.612048249999999,13,81,92,0,3.436538507421171e-09,3.520370417372356e-09,2.877663081899183e-08,,f4.ptu -34,0.8070175438596491,0.5277777777777778,109,0.0005647499999999999,15.581095133027523,15.5808369,15.58140165,11,46,51,1,4.152272782711514e-09,3.751087006604121e-09,2.95544121592996e-08,3.83750005123612e-08,f4.ptu -35,0.84375,0.47761194029850745,134,0.00049955,15.721624518656714,15.7213578,15.721857349999999,10,54,70,0,2.4850000331783087e-09,4.087037091604835e-09,2.940928610694179e-08,,f4.ptu -36,0.5645161290322581,0.4161073825503356,149,0.0005742,16.423194540604026,16.422921249999998,16.42349545,27,35,87,0,2.453703736464162e-09,3.1600000421905252e-09,2.8230172790706332e-08,,f4.ptu -37,0.3548387096774194,0.5344827586206896,116,0.00034155,19.08830083922414,19.08811115,19.088452699999998,40,22,54,0,2.7768750370752575e-09,4.2511364203951215e-09,2.864722260470366e-08,,f4.ptu -38,0.20703125,0.37481698389458273,683,0.0016120499999999999,20.147808349048315,20.1470772,20.14868925,203,53,427,0,3.424507434884639e-09,3.118867966169655e-09,2.873208469274796e-08,,f4.ptu -39,0.5365853658536586,0.4270833333333333,288,0.00100165,21.421523339583334,21.4210335,21.42203515,57,66,165,0,2.7074561764992935e-09,3.3965909544402617e-09,2.8214545831250036e-08,,f4.ptu -40,0.6527777777777778,0.5714285714285714,126,0.00043759999999999996,21.618915067460314,21.6186985,21.6191361,25,47,54,0,2.4990000333652285e-09,3.901595796772742e-09,2.8891204089442642e-08,,f4.ptu -41,0.6307692307692307,0.4744525547445255,138,0.0004298,21.759782247101448,21.75953675,21.759966549999998,24,41,72,1,2.5343750338375354e-09,2.862804916271325e-09,2.820208370987153e-08,3.9850000532054564e-08,f4.ptu -42,0.7647058823529411,0.5112781954887218,133,0.00062205,22.103106266541353,22.1027904,22.10341245,16,52,65,0,2.5609375341921828e-09,3.026442348099646e-09,2.8818077307839515e-08,,f4.ptu -43,0.6111111111111112,0.5228215767634855,241,0.00092895,22.430489224481324,22.43002025,22.4309492,49,77,115,0,2.3357143168994163e-09,3.4314935523088584e-09,2.841739168376069e-08,,f4.ptu -44,0.65,0.4968944099378882,161,0.00047149999999999997,22.617157853416145,22.6169248,22.6173963,28,52,81,0,2.42142860375811e-09,3.2009615811989587e-09,2.8524691738870168e-08,,f4.ptu -45,0.6947368421052632,0.5121293800539084,371,0.00132065,22.677137446495955,22.6764437,22.67776435,58,132,181,0,2.6112069314150756e-09,3.2920454984989756e-09,2.8710359499346508e-08,,f4.ptu -46,0.7023809523809523,0.6131386861313869,137,0.00045155,22.74959053759124,22.74937,22.74982155,25,59,53,0,3.2740000437125883e-09,3.7262712361917344e-09,2.9067453218280794e-08,,f4.ptu -47,0.08823529411764706,0.44933920704845814,227,0.0009239,23.55503067665198,23.55454245,23.55546635,93,9,125,0,3.543010799992439e-09,2.5777778121948023e-09,2.8357000378606556e-08,,f4.ptu -48,0.5478260869565217,0.5665024630541872,203,0.00062345,24.15185354384236,24.1515362,24.152159649999998,52,63,88,0,2.8153846529740316e-09,3.733730208580803e-09,2.863664810961298e-08,,f4.ptu -49,0.7,0.4968944099378882,161,0.000536,24.155670441614905,24.15540785,24.15594385,24,56,81,0,2.6541667021035926e-09,3.5294643328376877e-09,2.918456829089034e-08,,f4.ptu -50,0.18867924528301888,0.53,100,0.00046455,25.3026513765,25.30239765,25.3028622,43,10,47,0,3.0360465521634754e-09,3.895000052003828e-09,2.8594681232843762e-08,,f4.ptu -51,0.5403225806451613,0.49206349206349204,252,0.0008286,25.46154012361111,25.46112835,25.461956949999998,57,67,128,0,2.5859649468070365e-09,3.06082093638873e-09,2.8365625378721712e-08,,f4.ptu -52,0.7972972972972973,0.3978494623655914,186,0.0008005499999999999,26.24204197983871,26.24164745,26.242448,15,59,112,0,2.3716666983318126e-09,3.4733051311193593e-09,2.8539732523903437e-08,,f4.ptu -53,0.3835616438356164,0.49324324324324326,148,0.0005848,26.339037227027024,26.33874385,26.33932865,45,28,75,0,2.626111146173455e-09,3.6785714776856248e-09,2.8414667046043152e-08,,f4.ptu -54,0.5185185185185185,0.5454545454545454,99,0.00044554999999999996,26.767675527272726,26.76743315,26.767878699999997,26,28,45,0,2.7365384980751686e-09,2.6491071782265165e-09,2.8166667042732e-08,,f4.ptu -55,0.6811594202898551,0.45394736842105265,152,0.0005622499999999999,27.335942306907892,27.3356861,27.336248349999998,22,47,83,0,2.327272758345151e-09,3.605851111973063e-09,2.8808735324396898e-08,,f4.ptu -56,0.7454545454545455,0.44715447154471544,123,0.00048435,27.5337966402439,27.533520449999997,27.534004799999998,14,41,68,0,2.7178571791444275e-09,3.5713415110971563e-09,2.8916912150788063e-08,,f4.ptu -57,0.3108108108108108,0.4277456647398844,173,0.0006491,28.835067339595376,28.834718849999998,28.83536795,51,23,99,0,3.603431420659988e-09,3.5434783081800736e-09,2.9111111499786127e-08,,f4.ptu -58,0.5521739130434783,0.39182282793867124,587,0.0017437,28.8372608044293,28.83636245,28.838106149999998,103,127,357,0,3.039805865828479e-09,3.4647638257871173e-09,2.8860434558997588e-08,,f4.ptu -59,0.2876712328767123,0.45625,160,0.00064435,28.8530899484375,28.85276425,28.853408599999998,52,21,87,0,3.046153886824362e-09,3.4511905222688106e-09,2.9333621081301016e-08,,f4.ptu -60,0.35064935064935066,0.4723926380368098,164,0.00052,28.855552888414632,28.855291249999997,28.85581125,50,27,86,1,3.0295000404481633e-09,3.271296339972786e-09,2.858604689329256e-08,4.2100000562095286e-08,f4.ptu -61,0.8125,0.43243243243243246,37,0.00022495,29.263552058108107,29.2634261,29.26365105,3,13,21,0,3.7166667162894886e-09,3.146153888159505e-09,2.8782143241425677e-08,,f4.ptu -62,0.43356643356643354,0.5836734693877551,245,0.0007888,29.366160405714282,29.36578105,29.366569849999998,81,62,102,0,3.0854938683562547e-09,4.264516185969655e-09,2.836446116301989e-08,,f4.ptu -63,0.7962962962962963,0.3624161073825503,149,0.00043575,30.10236235067114,30.102122899999998,30.10255865,11,43,95,0,2.3318182129512936e-09,3.033139575380477e-09,2.8183684586818855e-08,,f4.ptu -64,0.6,0.5,150,0.00055315,30.505348113999997,30.505074949999997,30.5056281,30,45,75,0,2.3808333651208676e-09,3.5133333802413643e-09,2.889066705239844e-08,,f4.ptu -65,0.15730337078651685,0.6137931034482759,145,0.00047335,31.64941631206896,31.649206799999998,31.64968015,75,14,56,0,3.3400000445937825e-09,2.3714286030905386e-09,2.849464323758714e-08,,f4.ptu -66,0.3333333333333333,0.5960264900662252,151,0.0006406,32.15981011059603,32.1595089,32.160149499999996,60,30,61,0,2.845416704657054e-09,3.053333374099706e-09,2.8793443007384507e-08,,f4.ptu -67,0.3333333333333333,0.375,8,7.835e-05,32.41301610625,32.4129789,32.41305725,2,1,5,0,2.875000038385367e-09,2.2000000293731503e-09,3.043000040628407e-08,,f4.ptu -68,0.4410480349344978,0.5204545454545455,440,0.0012304,35.21902380579545,35.21838965,35.219620049999996,128,101,211,0,2.919531288979923e-09,3.9554455973653175e-09,2.8841114129146e-08,,f4.ptu -69,0.5851063829787234,0.618421052631579,152,0.0005434999999999999,35.42218565493421,35.4218681,35.4224116,39,55,58,0,2.913461577360422e-09,3.509090955942298e-09,2.8333621067949584e-08,,f4.ptu -70,0.5555555555555556,0.4090909090909091,154,0.00049155,37.726308175,37.7260492,37.72654075,28,35,91,0,2.973214325410954e-09,3.6764286205141572e-09,2.9238461928836866e-08,,f4.ptu -71,0.7272727272727273,0.4782608695652174,345,0.0008767499999999999,38.102571626231885,38.1021131,38.10298985,45,120,180,0,2.6238889239215626e-09,3.562708380900591e-09,2.8972639275715105e-08,,f4.ptu -72,0.6486486486486487,0.5606060606060606,133,0.00064965,38.36923358684211,38.36893315,38.369582799999996,26,48,58,1,2.633653881316896e-09,3.079687541118238e-09,2.8591810726569197e-08,3.4550000461291974e-08,f4.ptu -73,0.9690721649484536,0.6510067114093959,149,0.00048489999999999997,39.34529019664429,39.345073299999996,39.3455582,3,94,52,0,6.450000086116736e-09,3.3316489806524964e-09,2.9073077311244132e-08,,f4.ptu -74,0.5959595959595959,0.5,198,0.001032,40.23424834191919,40.23369555,40.234727549999995,40,59,99,0,2.7893750372421504e-09,3.3652542822190987e-09,2.865530341289236e-08,,f4.ptu -75,0.9134615384615384,0.45021645021645024,231,0.0006613999999999999,40.369481995021644,40.3691849,40.3698463,9,95,127,0,2.4805555886745245e-09,3.294473728196468e-09,2.9209646059281935e-08,,f4.ptu -76,0.7407407407407407,0.4682080924855491,173,0.0007645,40.37030513236994,40.369862149999996,40.37062665,21,60,92,0,2.726190512589023e-09,3.717916716306178e-09,2.9077717779533514e-08,,f4.ptu -77,0.5,0.45614035087719296,114,0.00041319999999999996,40.48003367982456,40.47982825,40.48024145,26,26,62,0,2.553846187943657e-09,3.502884662153141e-09,2.8756855222654866e-08,,f4.ptu -78,0.9047619047619048,0.5294117647058824,119,0.00044354999999999997,40.494585637394955,40.4943807,40.49482425,6,57,56,0,2.116666694927198e-09,3.604824609533079e-09,2.9059375387984268e-08,,f4.ptu -79,0.42990654205607476,0.45147679324894513,237,0.0007995,40.67092567341772,40.6704563,40.6712558,61,46,130,0,2.3668033102887375e-09,2.872282647044738e-09,2.8382115763557267e-08,,f4.ptu -80,0.5512820512820513,0.5416666666666666,144,0.0006095499999999999,40.855711693055554,40.855415699999995,40.856025249999995,35,43,66,0,3.0878571840844574e-09,3.0988372506762396e-09,2.8303030680916285e-08,,f4.ptu -81,0.46715328467153283,0.556910569105691,246,0.0009835,40.85737670406504,40.8569533,40.8579368,73,64,109,0,3.459589087286358e-09,3.281250043809386e-09,2.8547248087568655e-08,,f4.ptu -82,0.6153846153846154,0.5449101796407185,167,0.00063245,42.454439111077846,42.45412985,42.4547623,35,56,76,0,2.6935714645344645e-09,3.0526786121862016e-09,2.8179934586768793e-08,,f4.ptu -83,0.6689655172413793,0.5846774193548387,248,0.0006495,42.67430638709677,42.6739442,42.674593699999996,48,97,103,0,2.628125035089232e-09,2.998453648281072e-09,2.8450485816747925e-08,,f4.ptu -84,0.5742574257425742,0.5233160621761658,193,0.00065105,42.69856419326425,42.69827385,42.6989249,43,58,92,0,2.845348875198784e-09,2.9745690052319965e-09,2.828097863846112e-08,,f4.ptu -85,0.9,0.5633802816901409,284,0.0007343,42.98488619260563,42.98449565,42.98522995,16,144,124,0,2.4781250330865173e-09,3.880902829593387e-09,2.9253024584118147e-08,,f4.ptu -86,0.7477477477477478,0.4007220216606498,277,0.00092965,42.99480259079422,42.99433275,42.9952624,28,83,166,0,2.554464319820042e-09,3.268072332790071e-09,2.869954857595115e-08,,f4.ptu -87,0.07142857142857142,0.5,28,0.00016319999999999998,43.03175564107143,43.03168785,43.03185105,13,1,14,0,2.2807692612207657e-09,1.7750000236987917e-09,2.8766071812639674e-08,,f4.ptu -88,0.0,0.5454545454545454,22,0.00010879999999999999,43.032139336363635,43.03208275,43.03219155,12,0,10,0,2.620833368325211e-09,,2.7772500370802645e-08,,f4.ptu -89,0.8666666666666667,0.5357142857142857,84,0.00046344999999999996,43.45571499285714,43.4554773,43.455940749999996,6,39,39,0,2.9458333726644264e-09,3.752564152666207e-09,2.9477564496131795e-08,,f4.ptu -90,0.8142857142857143,0.5,140,0.0006619,43.45652058571429,43.45615695,43.45681885,13,57,70,0,2.4730769560960413e-09,3.3557017991893887e-09,2.8982857529819786e-08,,f4.ptu -91,0.5783783783783784,0.4920212765957447,376,0.0015259499999999999,43.69243048430851,43.6916492,43.693175149999995,78,107,191,0,2.6342949069664807e-09,3.896962668852462e-09,2.922002656813966e-08,,f4.ptu -92,0.7590361445783133,0.46368715083798884,179,0.0007042,44.27589455083798,44.275517099999995,44.276221299999996,20,63,96,0,2.241250029923897e-09,2.597222256898858e-09,2.8156771209266542e-08,,f4.ptu -93,0.7454545454545455,0.5238095238095238,105,0.0004893,44.35365143999999,44.35339245,44.35388175,14,41,50,0,2.1928571721349257e-09,3.4073171186632937e-09,2.8722500383486505e-08,,f4.ptu -94,0.7761194029850746,0.4249471458773784,473,0.0012506,44.355893730443974,44.35526945,44.35652005,45,156,272,0,2.642222257499672e-09,3.2004808119617707e-09,2.8379320231845734e-08,,f4.ptu -95,0.5277777777777778,0.4864864864864865,518,0.0018279,44.542024715444015,44.5411262,44.542954099999996,119,133,266,0,2.831932810919601e-09,3.7511278696318e-09,2.8645677074190127e-08,,f4.ptu -96,0.6595744680851063,0.47959183673469385,98,0.00045325,44.549770708163265,44.54953965,44.5499929,16,31,51,0,2.818750037634349e-09,4.6120968357716444e-09,2.936666705875372e-08,,f4.ptu -97,0.6436781609195402,0.58,151,0.0006680999999999999,44.55326150562914,44.552965449999995,44.55363355,31,56,63,1,2.843548425062217e-09,3.5575893332131968e-09,2.898055594248747e-08,3.637500048565834e-08,f4.ptu -98,0.6912751677852349,0.3983957219251337,374,0.00105625,44.915177765106954,44.91464865,44.9157049,46,103,225,0,2.4467391631022534e-09,3.726456360433139e-09,2.8769222606332533e-08,,f4.ptu -99,0.3163841807909605,0.5315315315315315,333,0.00089845,45.50582873453453,45.50531965,45.5062181,121,56,156,0,3.3702479788819336e-09,4.458482202384264e-09,2.895464782248344e-08,,f4.ptu -100,0.4117647058823529,0.5190839694656488,131,0.00045214999999999996,46.45097035267175,46.450738099999995,46.451190249999996,40,28,63,0,2.9443750393116227e-09,3.2687500436424932e-09,2.841785752227623e-08,,f4.ptu -101,0.1111111111111111,0.45918367346938777,196,0.0008277,46.662896001275506,46.662475099999995,46.6633028,80,10,106,0,2.5500000340461515e-09,2.2275000297403144e-09,2.8188915470702004e-08,,f4.ptu -102,0.5145631067961165,0.4735632183908046,435,0.00168575,47.9430433613793,47.942224949999996,47.943910699999996,100,106,229,0,2.5692500343031663e-09,3.4733491029779572e-09,2.8662773308453255e-08,,f4.ptu -103,0.6533333333333333,0.436046511627907,172,0.0007373999999999999,49.202366022965116,49.2019619,49.2026993,26,49,97,0,2.243269260720087e-09,3.342857187489073e-09,2.9130670492028944e-08,,f4.ptu -104,0.5,0.5373134328358209,67,0.0002804,49.60217505074627,49.602036899999995,49.602317299999996,18,18,31,0,2.7555555923461683e-09,2.834722260069823e-09,2.842983908925648e-08,,f4.ptu -105,0.18072289156626506,0.3824884792626728,217,0.000687,49.63986816290322,49.639540249999996,49.640227249999995,68,15,134,0,3.73970593228337e-09,3.290000043926211e-09,2.866660486035216e-08,,f4.ptu -106,0.4731182795698925,0.6480836236933798,287,0.0007833,50.00666215121951,50.006342149999995,50.00712545,98,88,101,0,2.5640306464783783e-09,2.9974432218383405e-09,2.8779950879303057e-08,,f4.ptu -107,0.6778523489932886,0.5033783783783784,296,0.00094285,50.385764453209454,50.3852775,50.386220349999995,48,101,147,0,3.0171875402837736e-09,3.3269802424397517e-09,2.8350170446542578e-08,,f4.ptu -108,0.20930232558139536,0.3805309734513274,113,0.00036304999999999996,50.90522852699115,50.905077649999996,50.9054407,34,9,70,0,4.26102946865555e-09,3.502777824544877e-09,2.8096786089418037e-08,,f4.ptu -109,0.5,0.6666666666666666,6,2.575e-05,50.905624616666664,50.90561525,50.905640999999996,2,2,2,0,4.512500060248337e-09,2.0375000272035426e-09,3.0637500409054497e-08,,f4.ptu -110,0.8950276243093923,0.48655913978494625,372,0.0014762,51.94293650080645,51.9421758,51.943652,19,162,191,0,2.0513158168616874e-09,3.1058642389985987e-09,2.8750262163961875e-08,,f4.ptu -111,0.7,0.42424242424242425,165,0.00064645,52.76915396060606,52.768864799999996,52.76951125,21,49,95,0,2.2511905062470927e-09,3.838265357368787e-09,2.9557368815685826e-08,,f4.ptu -112,0.5531914893617021,0.44976076555023925,209,0.0009620999999999999,52.77216551387559,52.771689249999994,52.77265135,42,52,115,0,2.391071460495656e-09,3.1413461957876234e-09,2.846956559750077e-08,,f4.ptu -113,0.17142857142857143,0.4,175,0.00050395,52.95185815342857,52.951587149999995,52.9520911,58,12,105,0,3.0577586615151114e-09,4.427083392441236e-09,2.9044762292551068e-08,,f4.ptu -114,0.11666666666666667,0.38461538461538464,156,0.00054135,54.27040434903846,54.27014885,54.2706902,53,7,96,0,2.8372641888249354e-09,2.542857176807927e-09,2.8677344132883604e-08,,f4.ptu -115,0.1694915254237288,0.35435435435435436,334,0.0012213,54.550410606137724,54.54973035,54.550951649999995,98,20,215,1,5.057908230795623e-09,5.285000070562318e-09,2.9800930630443235e-08,3.0025000400876745e-08,f4.ptu -116,0.6226415094339622,0.49074074074074076,108,0.00038134999999999997,54.642948249074074,54.642742899999995,54.64312425,20,33,55,0,2.686250035865284e-09,3.910606112818252e-09,2.8306364014294123e-08,,f4.ptu -117,0.14893617021276595,0.4845360824742268,97,0.0003361,54.643468467525764,54.643266149999995,54.64360225,40,7,50,0,3.3156250442683416e-09,4.196428627456902e-09,2.87905003843944e-08,,f4.ptu -118,0.4533762057877814,0.5174708818635607,602,0.00225365,54.650484004817265,54.649338799999995,54.651592449999995,170,141,290,1,3.201029454503032e-09,3.4507092659300652e-09,2.836353486145242e-08,4.640000061950644e-08,f4.ptu -119,0.5116279069767442,0.44559585492227977,193,0.0007350999999999999,54.65273091450777,54.6523295,54.6530646,42,44,107,0,4.558333394193611e-09,3.2897727711959043e-09,2.809556112277952e-08,,f4.ptu -120,0.8585858585858586,0.526595744680851,188,0.0008407499999999999,55.64281142765957,55.642402499999996,55.64324325,14,85,89,0,2.1928571721349257e-09,3.2885294556712825e-09,2.8296629591283667e-08,,f4.ptu -121,0.81,0.4716981132075472,424,0.0017059,55.92719289009434,55.9263444,55.928050299999995,38,162,224,0,2.2789473988482634e-09,3.060956830991613e-09,2.8381473593219025e-08,,f4.ptu -122,0.676056338028169,0.5725806451612904,124,0.0005603499999999999,55.97100817862903,55.970726299999995,55.971286649999996,23,48,53,0,3.4021739584673715e-09,3.230729209801527e-09,2.850613245606938e-08,,f4.ptu -123,0.5818181818181818,0.4700854700854701,117,0.0006104,56.109517774786326,56.109204049999995,56.109814449999995,23,32,62,0,2.3478261183033622e-09,3.853125051444736e-09,2.983427459187867e-08,,f4.ptu -124,0.7222222222222222,0.5,144,0.0007322,56.77475826041666,56.774402599999995,56.7751348,20,52,72,0,2.173750029022675e-09,3.1495192728198223e-09,2.8840625385063642e-08,,f4.ptu -125,0.4939759036144578,0.5460526315789473,152,0.0006464,56.88836104144736,56.8880488,56.8886952,42,41,69,0,2.576190510586308e-09,3.0567073578845903e-09,2.8277898928275077e-08,,f4.ptu -126,0.6931818181818182,0.6153846153846154,143,0.0005092499999999999,57.021123320629364,57.02087805,57.0213873,27,61,55,0,2.3740741057713627e-09,3.407786930744737e-09,2.8627727654948423e-08,,f4.ptu -127,0.7065217391304348,0.6524822695035462,141,0.00049915,57.47610904574468,57.47584525,57.476344399999995,27,65,49,0,2.718518554814634e-09,3.5980769711164027e-09,2.836581670525488e-08,,f4.ptu -128,0.6344827586206897,0.5160142348754448,281,0.0010586,58.29588915409252,58.295342749999996,58.29640135,53,92,136,0,2.4514151270695247e-09,3.1385869984263694e-09,2.8289338612997292e-08,,f4.ptu -129,0.5862068965517241,0.5337423312883436,163,0.0005429,58.74937125460123,58.749095399999995,58.7496383,36,51,76,0,2.970833372998212e-09,3.779902011251417e-09,2.8672368803869808e-08,,f4.ptu -130,0.5702479338842975,0.5761904761904761,210,0.0006611,59.05708218904762,59.056726149999996,59.05738725,52,69,89,0,2.4350961863581746e-09,2.8887681545112197e-09,2.813455093743429e-08,,f4.ptu -131,0.5526315789473685,0.6031746031746031,252,0.0007373,59.07075541507936,59.07040885,59.07114615,68,84,100,0,2.6547794472098123e-09,2.896726229151633e-09,2.8271500377465006e-08,,f4.ptu -0,0.4852941176470588,0.5074626865671642,134,0.0006167999999999999,0.08911167686567165,0.08879234999999999,0.08940914999999999,35,33,66,0,2.3742857459858285e-09,2.7174242787057473e-09,2.8120833708786725e-08,,f5.ptu -1,0.49122807017543857,0.5,115,0.00052085,0.693281542173913,0.6929847499999999,0.6935055999999999,29,28,57,1,3.431034528567844e-09,3.2482143290825975e-09,2.831842143072305e-08,2.7300000364494093e-08,f5.ptu -2,0.0,0.7333333333333333,15,7.465e-05,1.4107530633333332,1.4107178,1.41079245,11,0,4,0,2.875000038385367e-09,,2.7862500372004273e-08,,f5.ptu -3,0.46551724137931033,0.48333333333333334,121,0.0005157499999999999,1.5077220834710743,1.50746955,1.5079852999999999,31,27,62,1,3.26048391449987e-09,3.350000044727297e-09,2.824193586094125e-08,3.065000040922139e-08,f5.ptu -4,0.3333333333333333,0.4015748031496063,127,0.0004764,2.0681050783464565,2.0678719,2.0683483,34,17,76,0,3.018382393240903e-09,3.629411813163727e-09,2.8193092481681306e-08,,f5.ptu -5,0.37209302325581395,0.45989304812834225,187,0.000765,2.0757352112299463,2.07533515,2.07610015,54,32,101,0,3.5472222695827185e-09,3.1054687914624547e-09,2.815717859376043e-08,,f5.ptu -6,0.43243243243243246,0.3425925925925926,432,0.0013327,2.079810994560185,2.07923355,2.08056625,84,64,284,0,3.3255952824966964e-09,3.1664062922760576e-09,2.8369278547784575e-08,,f5.ptu -7,0.7441860465116279,0.49142857142857144,175,0.0005409999999999999,3.2670912902857143,3.2668277999999997,3.2673688,22,64,89,0,2.7840909462625092e-09,3.3109375442057568e-09,2.870196667534718e-08,,f5.ptu -8,0.5957446808510638,0.44339622641509435,106,0.00048475,4.3925374924528295,4.392282,4.39276675,19,28,59,0,2.5828947713274486e-09,3.276785758035496e-09,2.8105508849825055e-08,,f5.ptu -9,0.5471698113207547,0.4608695652173913,115,0.0004453,5.10318447173913,5.1029706,5.1034159,24,29,62,0,2.604166701436021e-09,3.019827626525919e-09,2.8408468121229207e-08,,f5.ptu -10,0.4854368932038835,0.38721804511278196,266,0.0006916499999999999,6.514980245112782,6.51462525,6.515316899999999,53,50,163,0,2.545283052851098e-09,4.1285000551213866e-09,2.8621472774775677e-08,,f5.ptu -11,0.34210526315789475,0.49673202614379086,153,0.000567,7.625833409477123,7.6255498,7.626116799999999,50,26,77,0,3.496500046683282e-09,3.60673081738579e-09,2.834188349528784e-08,,f5.ptu -12,0.58,0.4854368932038835,103,0.0003816,7.974767051941748,7.9745691,7.9749507,21,29,53,0,2.7000000360488663e-09,3.6681034972502954e-09,2.866084943926715e-08,,f5.ptu -13,0.47368421052631576,0.4470588235294118,85,0.00043275,9.144545437647059,9.1443342,9.14476695,20,18,47,0,3.757500050168006e-09,3.533333380508393e-09,2.852393655104816e-08,,f5.ptu -14,0.5161290322580645,0.4492753623188406,138,0.0007314499999999999,9.756791853985508,9.75643475,9.7571662,30,32,76,0,2.4658333662557395e-09,3.1835937925055353e-09,2.8423026695277576e-08,,f5.ptu -15,0.5,0.6187845303867403,181,0.0006030499999999999,11.749963713259667,11.7496668,11.750269849999999,56,56,69,0,2.779464322824114e-09,3.494642903801343e-09,2.8391304726890654e-08,,f5.ptu -16,0.364741641337386,0.5238853503184714,630,0.0028314,11.765248445079365,11.7639173,11.766748699999999,209,120,299,2,2.786722525245013e-09,3.2370833765530308e-09,2.8455267938446998e-08,3.605000048131912e-08,f5.ptu -17,0.4132231404958678,0.491869918699187,246,0.0007993999999999999,11.768057269715447,11.76768775,11.76848715,71,50,125,0,3.0598591957830787e-09,3.000000040054296e-09,2.8657600382619998e-08,,f5.ptu -18,0.5753424657534246,0.4515463917525773,486,0.0017597,13.332430587757202,13.331564949999999,13.33332465,93,126,266,1,2.5422043350173366e-09,2.9976190876415543e-09,2.830404173128294e-08,2.8250000377177953e-08,f5.ptu -19,0.5068493150684932,0.477124183006536,153,0.00057315,14.626009948039215,14.625746099999999,14.62631925,36,37,80,0,2.502777811193445e-09,3.939189241783006e-09,2.8862500385355705e-08,,f5.ptu -20,0.5454545454545454,0.46261682242990654,214,0.0006303,14.628214856542057,14.62787455,14.628504849999999,45,54,115,0,2.5122222557639865e-09,4.3759259843508034e-09,2.9008043865559786e-08,,f5.ptu -21,0.44,0.5,100,0.00045329999999999996,16.768321407,16.76811265,16.76856595,28,22,50,0,2.9776786111848442e-09,3.5193182288061194e-09,2.898700038701796e-08,,f5.ptu -22,0.49606299212598426,0.4980392156862745,255,0.0008707,16.769195165686273,16.76873745,16.76960815,64,63,128,0,2.592968784619846e-09,3.946031798716921e-09,2.846855506759597e-08,,f5.ptu -23,0.47619047619047616,0.5283018867924528,159,0.00065475,16.98523041855346,16.98491335,16.9855681,44,40,75,0,2.52386367006083e-09,3.392500045294733e-09,2.8522667047485113e-08,,f5.ptu -24,0.5,0.4,5,1.365e-05,17.138263369999997,17.138254,17.13826765,1,1,3,0,2.7750000370502237e-09,4.375000058412515e-09,2.8016667040729287e-08,,f5.ptu -25,0.7222222222222222,0.5217391304347826,138,0.0005635,17.209692888043477,17.209417549999998,17.20998105,20,52,66,0,2.5750000343799373e-09,3.175961580865173e-09,2.8412121591463717e-08,,f5.ptu -26,0.5460992907801419,0.5183823529411765,273,0.00120685,19.96056306208791,19.959995749999997,19.9612026,64,77,131,1,2.382812531813959e-09,3.1610390032433576e-09,2.8638359160989054e-08,4.255000056810343e-08,f5.ptu -27,0.696078431372549,0.5425531914893617,188,0.0006849499999999999,20.236021824468086,20.2356917,20.23637665,31,71,86,0,2.3508064829995357e-09,3.6690141334936345e-09,2.8668023638573116e-08,,f5.ptu -28,0.7428571428571429,0.5185185185185185,135,0.0006154,20.23682351962963,20.23649845,20.23711385,18,52,65,0,2.9694444840907797e-09,3.196634658064265e-09,2.887115423162509e-08,,f5.ptu -29,0.6,0.38461538461538464,13,8.329999999999999e-05,20.92415252307692,20.92411705,20.92420035,2,3,8,0,3.587500047898262e-09,3.7083333828448937e-09,2.8946875386482232e-08,,f5.ptu -30,0.38095238095238093,0.43448275862068964,145,0.00053015,20.92473878655172,20.924479899999998,20.925010049999997,39,24,82,0,3.0583333741664625e-09,2.9333333724975335e-09,2.8316463792699482e-08,,f5.ptu -31,0.5576923076923077,0.45414847161572053,229,0.0008036,20.926414966593885,20.9260186,20.9268222,46,58,125,0,2.5657609038217993e-09,3.4250000457286545e-09,2.8537000381009815e-08,,f5.ptu -32,0.7387387387387387,0.44047619047619047,252,0.0007701499999999999,20.94402479484127,20.943616249999998,20.9443864,29,82,141,0,2.2353448574312613e-09,3.1600610178010954e-09,2.8654433006691182e-08,,f5.ptu -33,0.3944954128440367,0.5190476190476191,210,0.0008181,21.739925945,21.73953925,21.74035735,66,43,101,0,2.5670454888191874e-09,2.90465120157195e-09,2.8213861762834066e-08,,f5.ptu -34,0.45,0.49586776859504134,121,0.00041529999999999996,21.742062458264463,21.741843199999998,21.7422585,33,27,61,0,2.508333366823175e-09,2.8212963339646417e-09,2.8159426605476863e-08,,f5.ptu -35,0.6075949367088608,0.4968553459119497,159,0.00064235,22.326253931132076,22.32593085,22.3265732,31,48,80,0,2.766129069189848e-09,4.034895887204971e-09,2.883500038498854e-08,,f5.ptu -36,0.575,0.41237113402061853,97,0.00049055,23.09945217680412,23.0992118,23.099702349999998,17,23,57,0,3.1573529833316537e-09,3.2369565649571354e-09,2.8520175819381675e-08,,f5.ptu -37,0.3684210526315789,0.4253731343283582,134,0.00042409999999999995,24.39973922947761,24.39953575,24.39995985,36,21,77,0,2.8951389275431387e-09,3.990476243754762e-09,2.8638312070674158e-08,,f5.ptu -38,0.47761194029850745,0.47183098591549294,142,0.0005882,24.53823494507042,24.53790625,24.538494449999998,35,32,75,0,2.558571462732021e-09,3.5984375480442934e-09,2.840033371251845e-08,,f5.ptu -39,0.6095238095238096,0.4751131221719457,221,0.0009567,26.266305195475113,26.26582475,26.26678145,41,64,116,0,2.6335366205273382e-09,3.2882812939032634e-09,2.8366164171832353e-08,,f5.ptu -40,0.4782608695652174,0.4726027397260274,146,0.0005207499999999999,27.12029227568493,27.12002085,27.1205416,36,33,77,0,2.4937500332951335e-09,3.0371212526711295e-09,2.7988636737324737e-08,,f5.ptu -41,0.875,0.5106382978723404,141,0.0004696,27.664543893971633,27.66428885,27.664758449999997,9,63,69,0,3.161111153316471e-09,3.651190524939097e-09,2.9059420677839946e-08,,f5.ptu -42,0.48854961832061067,0.5927601809954751,221,0.00071555,27.92877466402715,27.928383049999997,27.9290986,67,64,90,0,2.8134328733842524e-09,3.2546875434547387e-09,2.8460833713326215e-08,,f5.ptu -43,0.46153846153846156,0.37142857142857144,140,0.0004525,28.437483804285716,28.43724335,28.437695849999997,28,24,88,0,2.360714317233202e-09,2.8520833714127296e-09,2.809744355695928e-08,,f5.ptu -44,0.573170731707317,0.44086021505376344,186,0.0006634999999999999,28.75447188575269,28.75417105,28.754834549999998,35,47,104,0,2.7400000365829233e-09,3.779255369607406e-09,2.8304086916361622e-08,,f5.ptu -45,0.5086705202312138,0.4505208333333333,384,0.00111565,29.817958333463544,29.81741615,29.8185318,85,88,211,0,2.725882389335609e-09,3.1823864061257786e-09,2.862582976608207e-08,,f5.ptu -46,0.7432432432432432,0.5138888888888888,144,0.0005059999999999999,30.19215564861111,30.191889999999997,30.192396,19,55,70,0,2.4263158218684744e-09,3.5481818655551267e-09,2.918464324679963e-08,,f5.ptu -47,0.8255813953488372,0.6056338028169014,142,0.00048485,30.19535183028169,30.19509485,30.1955797,15,71,56,0,2.3366666978645126e-09,3.965493010691488e-09,2.9033928959073093e-08,,f5.ptu -48,0.639751552795031,0.5313531353135313,303,0.0007817999999999999,30.965410602970294,30.9649751,30.9657569,58,103,142,0,2.373275893755597e-09,3.346601986429501e-09,2.8993134189916754e-08,,f5.ptu -49,0.5692307692307692,0.4452054794520548,146,0.00056005,31.04872991746575,31.04843845,31.0489985,28,37,81,0,2.4830357474377965e-09,3.1972973399857947e-09,2.850308680031011e-08,,f5.ptu -50,0.29508196721311475,0.5169491525423728,118,0.0006190999999999999,31.27212399618644,31.2717966,31.2724157,43,18,57,0,2.964534923301716e-09,2.9472222615718593e-09,2.843552669544447e-08,,f5.ptu -51,0.7068965517241379,0.4915254237288136,118,0.00046655,33.05308340338983,33.05284165,33.0533082,17,41,60,0,2.627941211557366e-09,3.87804883226531e-09,2.841750037941432e-08,,f5.ptu -52,0.6451612903225806,0.49206349206349204,63,0.00037735,33.062999488888885,33.0628154,33.06319275,11,20,32,0,2.7409091275041523e-09,3.2387500432419503e-09,2.8463281630025563e-08,,f5.ptu -53,0.6091954022988506,0.58,151,0.000714,33.08902509039735,33.08868675,33.089400749999996,34,53,63,1,2.4992647392511157e-09,3.059434003111975e-09,2.8181746408012696e-08,2.772500037016845e-08,f5.ptu -54,0.4426229508196721,0.5,122,0.0005136,33.34201549385246,33.3417639,33.3422775,34,27,61,0,2.7852941548347235e-09,3.3027778218745905e-09,2.843401677307746e-08,,f5.ptu -55,0.7682926829268293,0.5655172413793104,290,0.0010274499999999998,33.34387511431034,33.343328899999996,33.34435635,38,126,126,0,3.034210566826845e-09,3.371230203740909e-09,2.8949008323018644e-08,,f5.ptu -56,0.7101449275362319,0.4423076923076923,156,0.0006541,34.45274865961538,34.4524131,34.4530672,20,49,87,0,3.000000040054296e-09,3.246938818861486e-09,2.8478736012415807e-08,,f5.ptu -57,0.7840909090909091,0.5269461077844312,167,0.0007524999999999999,34.55674930149701,34.55636415,34.55711665,19,69,79,0,2.3250000310420793e-09,3.7246377308886667e-09,2.9003797855596656e-08,,f5.ptu -58,0.691358024691358,0.4764705882352941,170,0.0006083,34.562754489411766,34.56243715,34.56304545,25,56,89,0,3.2570000434856138e-09,3.886160766171525e-09,2.8771629597625597e-08,,f5.ptu -59,0.7352941176470589,0.53125,129,0.0005336,34.58158944612403,34.581311899999996,34.5818455,18,50,60,1,2.715277814030624e-09,3.5775000477647476e-09,2.8927500386223547e-08,4.987500066590267e-08,f5.ptu -60,0.6923076923076923,0.4148936170212766,188,0.00079625,35.48936040718085,35.48899885,35.489795099999995,24,54,110,0,2.6416667019366997e-09,3.1814815239588147e-09,2.876113674763872e-08,,f5.ptu -61,0.5684210526315789,0.4947916666666667,192,0.0005714,35.54255734270833,35.542252,35.542823399999996,41,54,97,0,2.35731710464429e-09,2.8958333719968548e-09,2.8368299347829576e-08,,f5.ptu -62,0.5272727272727272,0.46218487394957986,119,0.00048045,35.78564016260504,35.785396399999996,35.78587685,26,29,64,0,2.796153883486504e-09,2.9163793492826677e-09,2.850273475555232e-08,,f5.ptu -63,0.43478260869565216,0.6571428571428571,35,0.00015635,35.86945125142857,35.86938045,35.8695368,13,10,12,0,2.5307692645586237e-09,3.935000052537885e-09,2.9141667055749647e-08,,f5.ptu -64,0.3790322580645161,0.4217687074829932,294,0.0012322499999999998,36.43600531598639,36.435352699999996,36.43658495,77,47,170,0,2.9941558841321123e-09,3.006914933763641e-09,2.8463088615317102e-08,,f5.ptu -65,0.3627450980392157,0.4722222222222222,216,0.0008685499999999999,36.53979275046296,36.5393408,36.54020935,65,37,114,0,3.0876923489174216e-09,3.2439189622298813e-09,2.8736184594195527e-08,,f5.ptu -66,0.21176470588235294,0.4913294797687861,173,0.0007634499999999999,37.236032522543354,37.23563255,37.236396,67,18,88,0,2.869776157718606e-09,3.359722267079325e-09,2.8331534469175645e-08,,f5.ptu -67,0.32142857142857145,0.45161290322580644,124,0.00055905,37.343197318548384,37.34293435,37.3434934,38,18,68,0,3.0598684619062566e-09,3.881944496273962e-09,2.856360332254147e-08,,f5.ptu -68,0.5652173913043478,0.5411764705882353,85,0.00028155,38.30112031352941,38.30093565,38.301217199999996,20,26,39,0,2.9125000388860456e-09,3.4653846616524624e-09,2.8284615762255505e-08,,f5.ptu -69,0.5935483870967742,0.5326460481099656,291,0.0012402,39.28324331821305,39.2826312,39.283871399999995,63,92,136,0,2.557936542088623e-09,3.771195702524775e-09,2.878327244312143e-08,,f5.ptu -70,0.8115942028985508,0.46621621621621623,148,0.0005518,41.68679008243243,41.68651505,41.68706685,13,56,79,0,2.726923113331405e-09,3.7227679068471386e-09,2.911234216084335e-08,,f5.ptu -71,0.7868852459016393,0.45185185185185184,135,0.0005547,41.68829379555555,41.6879801,41.6885348,13,48,74,0,2.6365384967400254e-09,3.408854212179751e-09,2.8580067949152394e-08,,f5.ptu -72,0.5849056603773585,0.5047619047619047,105,0.00042685,42.68550820047619,42.685332249999995,42.6857591,22,31,52,0,2.3920454864826868e-09,3.2967742375650436e-09,2.833076960902557e-08,,f5.ptu -73,0.21428571428571427,0.3684210526315789,38,0.00015255,43.93478923947368,43.934700799999995,43.93485335,11,3,24,0,3.6704545944603695e-09,2.4583333661556033e-09,2.851458371404385e-08,,f5.ptu -74,0.2838709677419355,0.39948453608247425,388,0.0013503,44.056695406701024,44.056005899999995,44.0573562,111,44,233,0,2.5853603948786233e-09,2.910227311582974e-09,2.844688879182386e-08,,f5.ptu -75,0.31343283582089554,0.4407894736842105,152,0.0007126999999999999,44.16442669078947,44.1640454,44.1647581,46,21,85,0,2.6635869920844392e-09,2.9630952776568024e-09,2.8717941559896227e-08,,f5.ptu -76,0.3010752688172043,0.627318718381113,594,0.0016085499999999998,44.20988538215488,44.20916235,44.2107709,260,112,221,1,3.480480815700171e-09,3.2991071869049477e-09,2.8366403093664222e-08,3.4425000459623045e-08,f5.ptu -77,0.4492753623188406,0.5679012345679012,243,0.00092735,44.21190302983539,44.2114744,44.21240175,76,62,105,0,2.974671092347697e-09,3.020564556457894e-09,2.857738133392991e-08,,f5.ptu -78,0.4050632911392405,0.5231788079470199,151,0.00044524999999999995,44.40955782119205,44.40933885,44.409784099999996,47,32,72,0,3.003723444359328e-09,2.890625038593983e-09,2.795034759539938e-08,,f5.ptu -79,0.5317460317460317,0.4581818181818182,275,0.0011355,44.99130482272727,44.99074175,44.991877249999995,59,67,149,0,2.562711898622653e-09,3.300746312726406e-09,2.8852684948983046e-08,,f5.ptu -80,0.5821596244131455,0.5195121951219512,410,0.00179415,44.99358852670731,44.9927162,44.99451035,89,124,197,0,2.6738764401944608e-09,3.508064562966717e-09,2.8544543528318648e-08,,f5.ptu -81,0.4444444444444444,0.6040268456375839,298,0.0010332,45.66544020704698,45.664881949999995,45.66591515,100,80,118,0,2.7980000373573067e-09,3.099375041381094e-09,2.8337500378346203e-08,,f5.ptu -82,0.6666666666666666,0.2727272727272727,11,7.07e-05,48.31098235909091,48.310942149999995,48.31101285,1,2,8,0,4.575000061082801e-09,1.7875000238656846e-09,2.8106250375258685e-08,,f5.ptu -83,0.23529411764705882,0.288135593220339,295,0.0006483999999999999,48.31344315169491,48.3131257,48.313774099999996,65,20,210,0,2.4900000332450653e-09,2.2837500304913325e-09,2.80436908506139e-08,,f5.ptu -84,0.5932203389830508,0.5190615835777126,341,0.0008273,49.949005867448676,49.9485637,49.949391,72,105,164,0,2.659027813279606e-09,4.1023810071536126e-09,2.9235671122045386e-08,,f5.ptu -85,0.16666666666666666,0.5,24,0.00010059999999999999,51.853378308333326,51.8533042,51.8534048,10,2,12,0,2.9075000388192885e-09,2.8000000373840095e-09,2.8410417045986413e-08,,f5.ptu -86,0.19402985074626866,0.46206896551724136,146,0.00057095,52.08590552739726,52.085634649999996,52.0862056,54,13,78,1,3.850925977341302e-09,3.0634615793631368e-09,2.9145513209647155e-08,2.7275000364160307e-08,f5.ptu -87,0.0873015873015873,0.490272373540856,257,0.0008307999999999999,52.08712855544747,52.08673555,52.087566349999996,115,11,131,0,3.888695704093569e-09,3.1181818598140106e-09,2.9661069098307817e-08,,f5.ptu -88,0.64,0.45454545454545453,110,0.00031895,54.30143566318181,54.301239499999994,54.301558449999995,18,32,60,0,2.7958333706617116e-09,3.1617187922134728e-09,2.805791704128003e-08,,f5.ptu -89,0.5833333333333334,0.42857142857142855,280,0.0009350999999999999,54.414427614642854,54.413981549999995,54.414916649999995,50,70,160,0,2.3200000309753222e-09,3.077142898227121e-09,2.8549844131181297e-08,,f5.ptu -90,0.6666666666666666,0.55,120,0.00053755,54.731234539999996,54.730965749999996,54.7315033,22,44,54,0,2.6920454904881164e-09,3.4426136823274586e-09,2.868842630895749e-08,,f5.ptu -91,0.33962264150943394,0.4690265486725664,113,0.00050175,55.283732448672566,55.283459199999996,55.28396095,35,18,60,0,3.6578571916947737e-09,2.850000038051581e-09,2.8300833711189985e-08,,f5.ptu -92,0.5384615384615384,0.5603448275862069,116,0.00043345,55.37193135043103,55.3717198,55.37215325,30,35,51,0,2.5625000342130444e-09,3.523571475616153e-09,2.905392195653891e-08,,f5.ptu -93,0.47435897435897434,0.4727272727272727,165,0.00068615,57.75650380333333,57.7561866,57.75687275,41,37,87,0,2.5835366198597666e-09,3.609459507650912e-09,2.819051761776308e-08,,f5.ptu -94,0.46875,0.5079365079365079,189,0.00071565,58.027801915079365,58.02743365,58.028149299999995,51,45,93,0,3.081372590160344e-09,3.63222227071759e-09,2.8269892850561825e-08,,f5.ptu -95,0.4444444444444444,0.44751381215469616,181,0.0006277,58.11850843232044,58.11822325,58.118850949999995,45,36,100,0,2.788888926124549e-09,3.59722227025029e-09,2.8413250379357574e-08,,f5.ptu -96,0.3541666666666667,0.46601941747572817,103,0.0005473,58.94836859126214,58.9480965,58.9486438,31,17,55,0,2.7927419727709747e-09,3.6352941661834407e-09,2.8350909469434323e-08,,f5.ptu +burst_index,n_DD,n_DA,n_AA,n_AD,nanotimes_DD,nanotimes_DA,nanotimes_AA,nanotimes_AD,timestamps_mean,timestamps_min,timestamps_max,E_app,S_app,n_photons,time_mean,time_length,tau_DD,tau_DA,tau_AA,tau_AD,filename +0,51,15,87,0,129.52941176470588,127.26666666666667,1152.2643678160919,,613394.9869281045,607291,619992,0.22727272727272727,0.43137254901960786,153,0.030669994706362877,0.0006350550804406436,3.238235337352725e-9,3.1816667091464727e-9,2.880660958001178e-8,,f1.ptu +1,62,11,159,0,116.64516129032258,76.45454545454545,1141.440251572327,,640196.1551724138,633708,648949,0.1506849315068493,0.3146551724137931,232,0.0320100638391314,0.0007620560964487716,2.916129071192563e-9,1.911363661883078e-9,2.853600667030472e-8,,f1.ptu +2,19,55,103,0,122.15789473684211,120.07272727272728,1132.504854368932,,9048155.892655367,9039790,9056519,0.7432432432432432,0.4180790960451977,177,0.45241141392407974,0.0008364566916535332,3.053947409195623e-9,3.001818221896753e-9,2.831262173723734e-8,,f1.ptu +3,48,4,73,0,109.91666666666667,123.5,1165.2739726027398,,10362177.816,10358076,10367801,0.07692307692307693,0.416,125,0.5181130357042856,0.0004862538900311202,2.7479167033552893e-9,3.087500041222546e-9,2.91318497040204e-8,,f1.ptu +4,45,6,58,0,149.62222222222223,161.16666666666666,1140.4655172413793,,10503973.027522936,10499769,10509037,0.11764705882352941,0.46788990825688076,109,0.5252028529989708,0.00046340370722965785,3.740555605497329e-9,4.029166720461811e-9,2.8511638311705677e-8,,f1.ptu +5,22,6,37,0,116.95454545454545,128.83333333333334,1160.054054054054,,17915098.215384614,17911714,17918832,0.21428571428571427,0.4307692307692308,65,0.8957620768658456,0.0003559028472227778,2.923863675401403e-9,3.2208333763360706e-9,2.9001351738560918e-8,,f1.ptu +6,20,51,67,0,101.25,142.94117647058823,1141.4328358208954,,23782648.413043477,23777742,23786173,0.7183098591549296,0.5144927536231884,138,1.189141933787644,0.0004215533724269794,2.531250033795812e-9,3.5735294594764404e-9,2.8535821276516457e-8,,f1.ptu +7,16,43,72,0,116.8125,170.86046511627907,1155.236111111111,,27421687.72519084,27416404,27428102,0.7288135593220338,0.45038167938931295,131,1.3710953550223821,0.0005849046792374339,2.9203125389903536e-9,4.271511684937774e-9,2.8880903163379187e-8,,f1.ptu +8,32,51,77,0,113.125,168.66666666666666,1163.142857142857,,34384718.70625,34376873,34391567,0.6144578313253012,0.51875,160,1.7192496893100142,0.0007347058776470211,2.8281250377595185e-9,4.216666722965204e-9,2.9078571816811997e-8,,f1.ptu +9,22,39,98,1,101.5,116.38461538461539,1146.1020408163265,1125.0,44425075.75625,44416906,44431249,0.639344262295082,0.3836477987421384,160,2.221271557984964,0.0007171557372458979,2.5375000338792586e-9,2.9096154234629164e-9,2.865255140296075e-8,2.8125000375509024e-8,f1.ptu +10,61,8,48,0,175.95081967213116,186.5,1151.0625,,46154947.35042735,46149411,46159782,0.11594202898550725,0.5897435897435898,117,2.307765829648005,0.0005185541484331875,4.398770550533164e-9,4.6625000622510515e-9,2.8776562884208316e-8,,f1.ptu +11,26,79,80,0,117.15384615384616,141.55696202531647,1167.75,,55022169.35135135,55015113,55029374,0.7523809523809524,0.5675675675675675,185,2.7511304766113804,0.0007130557044456355,2.928846192950444e-9,3.5389240978826154e-9,2.9193750389778367e-8,,f1.ptu +12,64,26,102,0,124.640625,125.84615384615384,1129.9117647058824,,61255262.578125,61248241,61263319,0.28888888888888886,0.46875,192,3.0627876312072995,0.0007539060312482499,3.1160156666032706e-9,3.146153888159505e-9,2.8247794494795563e-8,,f1.ptu +13,23,51,54,0,110.65217391304348,139.64705882352942,1154.6296296296296,,77544504.9296875,77540033,77549753,0.6891891891891891,0.578125,128,3.8772562645344912,0.0004860038880311042,2.7663043847602113e-9,3.4911765172004405e-9,2.8865741126139712e-8,,f1.ptu +14,12,61,76,0,119.08333333333333,128.1639344262295,1155.828947368421,,87991554.83221476,87985050,87996912,0.8356164383561644,0.4899328859060403,149,4.399612938514246,0.0005931047448379587,2.9770833730816586e-9,3.2040984034350388e-9,2.8895724070009815e-8,,f1.ptu +15,18,67,76,0,90.33333333333333,157.32835820895522,1159.828947368421,,88010605.40993789,88005408,88016089,0.788235294117647,0.5279503105590062,161,4.400565475020694,0.0005340542724341794,2.258333363485317e-9,3.933209007737852e-9,2.8995724071344958e-8,,f1.ptu +16,40,58,114,0,129.225,164.6206896551724,1143.3245614035088,,97588974.18396227,97579608,97598062,0.5918367346938775,0.46226415094339623,212,4.879487745100074,0.0009227073816590533,3.2306250431334696e-9,4.115517296327359e-9,2.8583114416713223e-8,,f1.ptu +17,24,66,90,0,100.625,120.51515151515152,1161.2,,100031735.68333334,100024959,100037737,0.7333333333333333,0.5,180,5.001626797181044,0.0006389051112408899,2.515625033587196e-9,3.012878828105034e-9,2.9030000387592072e-8,,f1.ptu +18,5,35,36,0,129.2,159.22857142857143,1138.1944444444443,,101349572.7236842,101346248,101353586,0.875,0.5263157894736842,76,5.067519176337621,0.0003669029352234818,3.230000043125125e-9,3.980714338862522e-9,2.845486149102425e-8,,f1.ptu +19,66,79,104,0,121.18181818181819,148.41772151898735,1155.7692307692307,,115148362.35341366,115141386,115155214,0.5448275862068965,0.5823293172690763,249,5.757464177384102,0.00069140553124425,3.0295454949942247e-9,3.7104430875144114e-9,2.8894231155010124e-8,,f1.ptu +20,38,35,68,0,96.63157894736842,109.82857142857142,1132.25,,120128592.27659574,120122971,120132884,0.4794520547945205,0.5177304964539007,141,6.006477665651112,0.0004956539652317218,2.4157895059384593e-9,2.745714322373503e-9,2.830625037792897e-8,,f1.ptu +21,61,62,141,0,109.47540983606558,128.2258064516129,1148.2695035460993,,120779806.15151516,120770393,120789868,0.5040650406504065,0.4659090909090909,264,6.039038619884717,0.0009737577900623205,2.7368852824429767e-9,3.2056452040902755e-9,2.8706737971928537e-8,,f1.ptu +22,59,79,167,0,115.57627118644068,154.86075949367088,1168.502994011976,,121671643.20983607,121656676,121685682,0.572463768115942,0.4524590163934426,305,6.083630829538439,0.0014503116024928199,2.889406818238735e-9,3.871519039032094e-9,2.9212575240329103e-8,,f1.ptu +23,129,293,424,0,114.13953488372093,167.679180887372,1185.7004716981132,,122956741.74940899,122932001,122976648,0.6943127962085308,0.4988179669030733,846,6.147886270560614,0.0022323678589428715,2.8534884101911792e-9,4.19197957815323e-9,2.964251218822281e-8,,f1.ptu +24,50,55,62,0,133.94,144.92727272727274,1172.7903225806451,,123384881.19760479,123378410,123390448,0.5238095238095238,0.6287425149700598,167,6.169293414227553,0.0006019048152385219,3.3485000447072697e-9,3.623181866556484e-9,2.9319758455976883e-8,,f1.ptu +25,25,42,53,0,117.04,165.28571428571428,1139.3396226415093,,125242851.08333333,125238491,125247403,0.6268656716417911,0.5583333333333333,120,6.262192651707879,0.00044560356482851863,2.92600003906629e-9,4.1321429123128815e-9,2.848349094633312e-8,,f1.ptu +26,5,64,79,0,122.6,141.34375,1147.5822784810127,,138173744.05405405,138168430,138179124,0.927536231884058,0.46621621621621623,148,6.9087424726424835,0.0005347042776342211,3.0650000409221387e-9,3.5335937971785365e-9,2.8689557345071987e-8,,f1.ptu +27,17,37,53,0,106.88235294117646,126.0,1145.0188679245282,,190278125.9906542,190274580,190281351,0.6851851851851852,0.5046728971962616,107,9.513982411392,0.00033855270842166735,2.6720588592052232e-9,3.1500000420570107e-9,2.8625472080304244e-8,,f1.ptu +28,18,47,72,0,143.61111111111111,174.36170212765958,1136.8333333333333,,194716778.86861312,194711400,194722223,0.7230769230769231,0.4744525547445255,137,9.735916830765301,0.0005411543292346339,3.590277825713127e-9,4.359042611390949e-9,2.8420833712792155e-8,,f1.ptu +29,17,40,58,0,100.82352941176471,133.85,1129.9310344827586,,195232344.61739132,195226843,195236693,0.7017543859649122,0.4956521739130435,115,9.76169532443216,0.0004925039400315202,2.52058826894758e-9,3.346250044677229e-9,2.8248276239223897e-8,,f1.ptu +30,145,26,151,0,153.70344827586206,98.84615384615384,1125.8807947019868,,201497926.61490682,201485033,201510563,0.15204678362573099,0.531055900621118,322,10.074976930560785,0.0012765102120816966,3.84258625820058e-9,2.4711538791472885e-9,2.8147020243352692e-8,,f1.ptu +31,16,42,47,0,110.0,133.28571428571428,1137.3191489361702,,201612676.56190476,201607890,201617602,0.7241379310344828,0.5523809523809524,105,10.080714473811028,0.0004856038848310786,2.750000036716438e-9,3.3321429016317355e-9,2.8432979103025237e-8,,f1.ptu +32,35,24,76,0,118.82857142857142,150.0,1156.0,,202489180.66666666,202484404,202494515,0.4067796610169492,0.43703703703703706,135,10.12454002965357,0.0005055540444323554,2.9707143253775754e-9,3.75000005006787e-9,2.8900000385856384e-8,,f1.ptu +33,22,26,49,0,107.36363636363636,113.46153846153847,1151.7551020408164,,203073055.48453608,203069545,203077332,0.5416666666666666,0.4948453608247423,97,10.153734004098837,0.00038935311482491856,2.684090944927366e-9,2.8365384994103118e-9,2.8793877935459908e-8,,f1.ptu +34,29,37,95,0,97.86206896551724,135.27027027027026,1126.8105263157895,,204059362.85714287,204051994,204067087,0.5606060606060606,0.40993788819875776,161,10.203049767255282,0.000754656037248298,2.4465517568028998e-9,3.3817568019080517e-9,2.8170263534008088e-8,,f1.ptu +35,80,128,201,0,111.8375,133.5078125,1141.2636815920398,,204087106.6821516,204074282,204099584,0.6153846153846154,0.508557457212714,409,10.204436969603336,0.001265110120880967,2.7959375373297695e-9,3.337695357063012e-9,2.8531592420738605e-8,,f1.ptu +36,42,80,103,0,91.85714285714286,135.5875,1152.2718446601941,,209328071.07555556,209319130,209336820,0.6557377049180327,0.5422222222222223,225,10.466487285676063,0.0008845070760566085,2.296428602089181e-9,3.3896875452571823e-9,2.880679650111683e-8,,f1.ptu +37,26,43,74,1,111.26923076923077,122.20930232558139,1138.9594594594594,1101.0,217643721.2986111,217638067,217650183,0.6231884057971014,0.4825174825174825,144,10.88227312311554,0.0006058048464387714,2.7817308063708585e-9,3.0552325989312645e-9,2.8473986866654978e-8,2.7525000367498165e-8,f1.ptu +38,48,11,71,0,125.85416666666667,127.36363636363636,1122.1830985915492,,221784626.86923078,221779413,221789899,0.1864406779661017,0.45384615384615384,130,11.089320058022002,0.0005243041944335555,3.1463542086750005e-9,3.184090951603082e-9,2.805457783935751e-8,,f1.ptu +39,92,66,104,0,111.80434782608695,148.03030303030303,1131.7884615384614,,223827624.67938933,223816806,223835873,0.4177215189873418,0.6030534351145038,262,11.191470765735591,0.0009533576268610149,2.7951087329708773e-9,3.700757625167989e-9,2.8294711916236452e-8,,f1.ptu +40,38,80,90,0,103.02631578947368,140.525,1175.9555555555555,,230018515.39903846,230009626,230025037,0.6779661016949152,0.5673076923076923,208,11.501017778094148,0.0007705561644493155,2.5756579291255632e-9,3.5131250469052497e-9,2.939888928140615e-8,,f1.ptu +41,34,32,64,0,107.82352941176471,161.9375,1139.359375,,235364180.95384616,235359560,235370611,0.48484848484848486,0.5076923076923077,130,11.76830319411786,0.0005525544204353634,2.6955882712840806e-9,4.048437554052438e-9,2.848398475530198e-8,,f1.ptu +42,29,44,57,0,104.82758620689656,116.3409090909091,1127.982456140351,,240271376.03846154,240266360,240276981,0.6027397260273972,0.5615384615384615,130,12.013664911242365,0.0005310542484339875,2.6206896901623735e-9,2.908522766105671e-9,2.81995617800133e-8,,f1.ptu +43,25,34,159,0,119.76,124.3529411764706,1131.6415094339623,,242946874.4174312,242941487,242953436,0.576271186440678,0.2706422018348624,218,12.147440900398763,0.0005974547796382371,2.9940000399741874e-9,3.1088235709190105e-9,2.8291038113574923e-8,,f1.ptu +44,99,183,285,0,122.28282828282828,140.52459016393442,1148.4701754385965,,244121215.01234567,244098430,244142623,0.648936170212766,0.4973544973544973,567,12.206158399884481,0.002209667677341419,3.0570707478869786e-9,3.513114801003473e-9,2.8711754769307947e-8,,f1.ptu +45,47,42,115,0,96.48936170212765,126.26190476190476,1147.3739130434783,,248184856.72549018,248176228,248194399,0.47191011235955055,0.4362745098039216,204,12.409342111011396,0.0009085572684581476,2.41223407475997e-9,3.1565476611920497e-9,2.8684348209064076e-8,,f1.ptu +46,5,57,91,1,91.0,156.28070175438597,1155.6483516483515,1068.0,266473401.46753246,266466803,266480486,0.9193548387096774,0.40522875816993464,154,13.32377666358993,0.0006841554732437859,2.2750000303745077e-9,3.9070175960239286e-9,2.8891209176947797e-8,2.6700000356483233e-8,f1.ptu +47,45,156,135,0,102.08888888888889,140.80769230769232,1149.0666666666666,,267120849.86607143,267108703,267132063,0.7761194029850746,0.5982142857142857,336,13.35614934249831,0.0011680093440747526,2.5522222562980436e-9,3.520192354691916e-9,2.87266670502088e-8,,f1.ptu +48,49,51,73,0,92.75510204081633,114.58823529411765,1138.6575342465753,,269351431.1965318,269344261,269359799,0.51,0.5780346820809249,173,13.467679301260999,0.000776906215249722,2.318877581980744e-9,2.864705920600867e-9,2.8466438736232097e-8,,f1.ptu +49,66,9,102,0,123.31818181818181,102.0,1143.1568627450981,,270914044.5819209,270909422,270919424,0.12,0.423728813559322,177,13.54581059558081,0.0005001040008320067,3.082954586616403e-9,2.5500000340461515e-9,2.857892195019698e-8,,f1.ptu +50,117,61,175,0,107.48717948717949,121.19672131147541,1152.4857142857143,,283054427.33427763,283041235,283066724,0.34269662921348315,0.5042492917847026,353,14.152834589390595,0.0012744601956815654,2.687179523057181e-9,3.02991807324063e-9,2.8812143241826222e-8,,f1.ptu +51,65,59,132,0,109.04615384615384,120.8135593220339,1133.2954545454545,,283096913.97265625,283088784,283104685,0.47580645161290325,0.484375,256,14.154958938304318,0.0007950563604508836,2.7261538825519035e-9,3.0203390233766978e-9,2.833238674191429e-8,,f1.ptu +52,18,36,51,0,112.5,136.86111111111111,1160.8431372549019,,283417923.26666665,283413616,283423226,0.6666666666666666,0.5142857142857142,105,14.171009531409583,0.0004805038440307522,2.8125000375509024e-9,3.421527823460073e-9,2.90210788188455e-8,,f1.ptu +53,6,41,46,0,143.33333333333334,173.97560975609755,1164.3695652173913,,289457380.39784944,289452204,289462752,0.8723404255319149,0.5053763440860215,93,14.4729848037709,0.0005274042192337539,3.5833333811759647e-9,4.349390301973027e-9,2.910923951908481e-8,,f1.ptu +54,15,50,116,0,98.13333333333334,130.6,1155.594827586207,,289502067.1436464,289497511,289507557,0.7692307692307693,0.35911602209944754,181,14.475219158935593,0.0005023040184321475,2.4533333660888466e-9,3.265000043592425e-9,2.8889871075376318e-8,,f1.ptu +55,42,24,156,0,169.52380952380952,107.0,1151.121794871795,,299326887.4234234,299320987,299332559,0.36363636363636365,0.2972972972972973,222,14.966464102883993,0.0005786046288370307,4.238095294679878e-9,2.6750000357150805e-9,2.877804525602298e-8,,f1.ptu +56,1,1,3,0,94.0,93.0,1219.3333333333333,,299400970.0,299400626,299401411,0.5,0.4,5,14.97016826134609,0.00003925031400251202,2.350000031375865e-9,2.3250000310420793e-9,3.048333374032948e-8,,f1.ptu +57,67,9,67,0,138.7910447761194,89.66666666666667,1132.0597014925372,,301900142.67832166,301895134,301905395,0.11842105263157894,0.5314685314685315,143,15.095127894939242,0.0005130541044328354,3.469776165729465e-9,2.241666696596127e-9,2.8301492915178883e-8,,f1.ptu +58,9,63,63,0,97.0,141.95238095238096,1158.7460317460318,,302495545.67407405,302489602,302501196,0.875,0.5333333333333333,135,15.124898282889966,0.0005797046376371011,2.4250000323772225e-9,3.548809571191213e-9,2.8968651180423766e-8,,f1.ptu +59,22,70,89,0,96.0,148.78571428571428,1142.4719101123596,,306988149.2486188,306982512,306994197,0.7608695652173914,0.5082872928176796,181,15.349530258673008,0.0005842546740373923,2.4000000320434367e-9,3.7196429068054154e-9,2.856179813414989e-8,,f1.ptu +60,37,91,91,0,97.32432432432432,140.57142857142858,1128.89010989011,,308876043.5890411,308867944,308884670,0.7109375,0.5844748858447488,219,15.443925730857902,0.0008363066904535236,2.4331081405935853e-9,3.514285761206461e-9,2.8222253124060235e-8,,f1.ptu +61,46,60,117,0,107.43478260869566,134.96666666666667,1151.008547008547,,312542162.8116592,312534640,312549741,0.5660377358490566,0.47533632286995514,223,15.627233158448227,0.0007550560404483236,2.685869601077596e-9,3.3741667117166233e-9,2.8775214059403986e-8,,f1.ptu +62,35,61,82,0,120.97142857142858,139.11475409836066,1125.7926829268292,,316775083.28651685,316769737,316780310,0.6354166666666666,0.5393258426966292,178,15.838880875372844,0.0005286542292338339,3.0242857546642593e-9,3.477868898893546e-9,2.814481744894434e-8,,f1.ptu +63,18,56,98,0,99.61111111111111,131.30357142857142,1176.234693877551,,331120277.5755814,331113400,331125318,0.7567567567567568,0.43023255813953487,172,16.55614632794969,0.0005959047672381379,2.490277811026552e-9,3.282589329541553e-9,2.9405867739549214e-8,,f1.ptu +64,52,106,192,0,104.1923076923077,127.0377358490566,1138.8177083333333,,338988824.7457143,338974999,339004492,0.6708860759493671,0.4514285714285714,350,16.949576833900387,0.0014746617972943782,2.604807727085605e-9,3.1759434386298073e-9,2.847044308845451e-8,,f1.ptu +65,19,77,145,0,104.63157894736842,128.74025974025975,1148.096551724138,,344853831.746888,344845671,344863199,0.8020833333333334,0.3983402489626556,241,17.24282952998064,0.00087640701125609,2.6157895086087457e-9,3.218506536478164e-9,2.8702414176321774e-8,,f1.ptu +66,3,60,87,0,107.0,138.0,1147.8505747126437,,344878634.9066667,344873605,344883930,0.9523809523809523,0.42,150,17.244069697890918,0.0005162541300330403,2.6750000357150805e-9,3.4500000460624403e-9,2.8696264750952315e-8,,f1.ptu +67,35,30,66,0,101.71428571428571,119.93333333333334,1120.7575757575758,,356512966.2519084,356507847,356518118,0.46153846153846156,0.4961832061068702,131,17.82579091892277,0.0005135541084328674,2.542857176807927e-9,2.9983333733653767e-9,2.8018939768032356e-8,,f1.ptu +68,30,118,101,0,102.3,147.35593220338984,1179.5643564356435,,357550507.8072289,357539531,357560507,0.7972972972972973,0.5943775100401606,249,17.87766841170874,0.0010488083904671237,2.5575000341462873e-9,3.6838983542700634e-9,2.948910930461292e-8,,f1.ptu +69,30,39,76,0,109.7,125.0,1165.6973684210527,,365100402.1034483,365093577,365105589,0.5652173913043478,0.47586206896551725,145,18.255166146501583,0.0006006048048384387,2.742500036616302e-9,3.125000041723225e-9,2.9142434599619547e-8,,f1.ptu +70,26,41,47,0,90.46153846153847,155.5609756097561,1154.1489361702127,,382613446.1754386,382609155,382618676,0.6119402985074627,0.5877192982456141,114,19.13082535537477,0.0004760538084304674,2.2615384917332384e-9,3.889024442167947e-9,2.8853723789493843e-8,,f1.ptu +71,44,59,101,0,102.0,157.35593220338984,1166.6534653465346,,386124258.3480392,386115208,386133642,0.5728155339805825,0.5049019607843137,204,19.306367368340908,0.0009217073736589893,2.5500000340461515e-9,3.9338983576079214e-9,2.9166337023075725e-8,,f1.ptu +72,104,57,111,0,122.6923076923077,170.43859649122808,1140.5405405405406,,389199759.7830882,389190100,389209072,0.35403726708074534,0.5919117647058824,272,19.460143670303772,0.0009486075888607108,3.0673077332606424e-9,4.2609649691706854e-9,2.851351389420975e-8,,f1.ptu +73,40,38,59,0,114.65,129.1315789473684,1139.3050847457628,,394014969.28467155,394010425,394019826,0.48717948717948717,0.5693430656934306,137,19.700906071482148,0.00047005376043008344,2.866250038268542e-9,3.2282895167864974e-9,2.8482627498927927e-8,,f1.ptu +74,26,37,81,0,118.3076923076923,163.45945945945945,1158.5061728395062,,394963982.7777778,394956970,394970419,0.5873015873015873,0.4375,144,19.748357125745894,0.0006724553796430371,2.957692347181735e-9,4.086486541046933e-9,2.8962654707680564e-8,,f1.ptu +75,42,4,39,0,161.14285714285714,125.75,1153.974358974359,,414225971.9764706,414221945,414229678,0.08695652173913043,0.5411764705882353,85,20.711464290537855,0.0003866530932247458,4.0285714823586255e-9,3.1437500419735642e-9,2.8849359359539226e-8,,f1.ptu +76,24,101,124,0,106.16666666666667,147.85148514851485,1159.733870967742,,414355317.5582329,414347718,414361075,0.808,0.5020080321285141,249,20.717931621364617,0.0006678553428427428,2.6541667021035926e-9,3.6962871780635976e-9,2.8993347161296244e-8,,f1.ptu +77,47,9,71,0,127.25531914893617,172.11111111111111,1153.8309859154929,,414920882.6692913,414915915,414925596,0.16071428571428573,0.4409448818897638,127,20.74621010314539,0.0004840538724309794,3.1813830211994225e-9,4.3027778352260224e-9,2.884577503301972e-8,,f1.ptu +78,54,11,57,1,133.2037037037037,121.0909090909091,1186.5087719298247,1393.0,414954229.44715446,414948535,414959590,0.16923076923076924,0.5327868852459017,123,20.747877455377367,0.0005527544220353763,3.330092637054097e-9,3.0272727676911534e-9,2.9662719694285394e-8,3.482500046496362e-8,f1.ptu +79,112,101,203,0,98.92857142857143,131.3960396039604,1141.088669950739,,417742201.9326923,417727136,417759616,0.47417840375586856,0.5120192307692307,416,20.88727719485217,0.0016240129921039367,2.473214318735238e-9,3.284901033957142e-9,2.8527217129647665e-8,,f1.ptu +80,89,42,230,1,99.76404494382022,133.45238095238096,1146.1652173913044,1135.0,417841539.97790056,417831889,417854012,0.32061068702290074,0.3628808864265928,362,20.892244136848124,0.0011061588492707942,2.494101156895327e-9,3.336309568354034e-9,2.8654130817356282e-8,2.8375000378846882e-8,f1.ptu +81,30,97,113,0,97.33333333333333,130.1958762886598,1137.9026548672566,,421267648.1041667,421259923,421274571,0.7637795275590551,0.5291666666666667,240,21.063550913615643,0.000732405859246874,2.4333333658218175e-9,3.2548969506740296e-9,2.844756675149716e-8,,f1.ptu +82,33,25,57,0,134.1818181818182,146.04,1129.877192982456,,433997775.9217391,433993271,434002468,0.43103448275862066,0.5043478260869565,115,21.700062396586127,0.00045985367882943063,3.35454549933344e-9,3.651000048746078e-9,2.8246930201698363e-8,,f1.ptu +83,21,39,80,0,103.42857142857143,120.64102564102564,1167.05,,453578019.37142855,453571256,453583518,0.65,0.42857142857142855,140,22.679082401230637,0.0006131049048392386,2.5857143202372742e-9,3.016025681293902e-9,2.9176250389544715e-8,,f1.ptu +84,5,24,27,0,84.8,112.625,1146.5185185185185,,467111535.73214287,467109120,467114966,0.8275862068965517,0.5178571428571429,56,23.355763632716204,0.0002923023384187073,2.120000028305036e-9,2.8156250375926256e-9,2.8662963345654563e-8,,f1.ptu +85,13,38,52,1,98.07692307692308,149.10526315789474,1131.3076923076924,1164.0,467342965.0192308,467339172,467346006,0.7450980392156863,0.49514563106796117,104,23.367335189643054,0.00034170273362186897,2.451923109659761e-9,3.727631628716588e-9,2.828269268530675e-8,2.910000038852667e-8,f1.ptu +86,27,52,117,0,114.5925925925926,134.32692307692307,1148.948717948718,,467376210.47959185,467369907,467381180,0.6582278481012658,0.4030612244897959,196,23.3689974759594,0.0005636545092360739,2.864814853064195e-9,3.358173121759496e-9,2.8723718332220717e-8,,f1.ptu +87,67,71,218,0,110.97014925373135,121.54929577464789,1136.3623853211009,,479242196.17134833,479228512,479257119,0.5144927536231884,0.38764044943820225,356,23.962301506979472,0.001430361442891543,2.7742537683835436e-9,3.038732434937626e-9,2.840906001232915e-8,,f1.ptu +88,44,8,57,0,144.47727272727272,137.25,1163.877192982456,,479276543.5504587,479270421,479282045,0.15384615384615385,0.47706422018348627,109,23.964018889674055,0.0005812046496371971,3.6119318664062797e-9,3.431250045812101e-9,2.909693021304708e-8,,f1.ptu +89,7,67,75,0,83.71428571428571,133.55223880597015,1143.68,,485428463.76510066,485421433,485436559,0.9054054054054054,0.4966442953020134,149,24.271617361193922,0.0007563060504484036,2.0928571707997825e-9,3.3388060147270946e-9,2.8592000381744143e-8,,f1.ptu +90,6,117,100,0,242.0,144.8803418803419,1169.68,,486402422.9147982,486396175,486409863,0.9512195121951219,0.5515695067264574,223,24.320315708265575,0.0006844054752438019,6.050000080776163e-9,3.622008595367548e-9,2.9242000390422574e-8,,f1.ptu +91,57,56,148,0,196.21052631578948,125.66071428571429,1141.8581081081081,,495472090.3754789,495463669,495480272,0.49557522123893805,0.4329501915708812,261,24.773802709195618,0.00083015664125313,4.905263223387024e-9,3.141517899086619e-9,2.8546453083838724e-8,,f1.ptu +92,22,30,48,0,122.04545454545455,157.93333333333334,1157.3958333333333,,497092385.47,497088755,497095910,0.5769230769230769,0.52,100,24.854818112044896,0.0003577528620228962,3.051136404373403e-9,3.948333386049237e-9,2.8934896219655625e-8,,f1.ptu +93,33,48,71,0,107.42424242424242,148.52083333333334,1154.3098591549297,,498220804.79605263,498216098,498227888,0.5925925925925926,0.5328947368421053,152,24.91123952971887,0.0005895047160377283,2.685606096462747e-9,3.7130208829074785e-9,2.885774686416548e-8,,f1.ptu +94,8,9,33,0,113.75,117.88888888888889,1132.4242424242425,,498231510.4,498229447,498234145,0.5294117647058824,0.34,50,24.911774814198512,0.0002349018792150337,2.8437500379681346e-9,2.9472222615718593e-9,2.831060643859319e-8,,f1.ptu +95,71,126,146,1,108.28169014084507,126.67460317460318,1156.0342465753424,1105.0,504330095.09302324,504319163,504341314,0.6395939086294417,0.5743440233236151,344,25.216706488303068,0.0011075588604708838,2.7070422896640173e-9,3.1668651216472632e-9,2.8900856550251375e-8,2.7625000368833308e-8,f1.ptu +96,115,7,99,0,121.07826086956521,101.57142857142857,1155.7878787878788,,512206225.9004525,512197873,512215091,0.05737704918032787,0.5520361990950227,221,25.610516179152057,0.000860906887255098,3.0269565621533344e-9,2.5392857481888145e-9,2.889469735548255e-8,,f1.ptu +97,6,46,49,0,170.83333333333334,158.58695652173913,1150.0204081632653,,525360123.1881188,525355279,525365251,0.8846153846153846,0.5148514851485149,101,26.26821630513638,0.0004986039888319107,4.2708333903550745e-9,3.9646739659775524e-9,2.8750510587942112e-8,,f1.ptu +98,32,28,87,0,94.28125,164.5,1158.4367816091954,,530957332.72789115,530951647,530961805,0.4666666666666667,0.40816326530612246,147,26.548079021026723,0.0005079040632325058,2.3570312814697424e-9,4.112500054907764e-9,2.8960919926899632e-8,,f1.ptu +99,44,43,84,1,98.97727272727273,132.37209302325581,1126.0833333333333,1104.0,539262783.005814,539256055,539269061,0.4942528735632184,0.5087719298245614,172,26.963354857129556,0.0006503052024416195,2.4744318512190263e-9,3.3093023697653203e-9,2.8152083709203957e-8,2.7600000368499522e-8,f1.ptu +100,22,5,13,0,112.36363636363636,155.6,1140.3846153846155,,550473832.125,550471904,550476211,0.18518518518518517,0.675,40,27.52391179754438,0.0002153517228137825,2.809090946596295e-9,3.8900000519370705e-9,2.8509615765259577e-8,,f1.ptu +101,83,9,53,0,119.63855421686748,77.77777777777777,1142.377358490566,,552291029.6137931,552285709,552295668,0.09782608695652174,0.6344827586206897,145,27.614772398868848,0.0004979539836318691,2.9909638953553372e-9,1.944444470405562e-9,2.8559434343573488e-8,,f1.ptu +102,17,47,79,0,112.58823529411765,141.85106382978722,1137.1518987341772,,562144623.0559441,562139132,562151156,0.734375,0.44755244755244755,143,28.107456012445304,0.0006012048096384771,2.8147059199332954e-9,3.5462766430925514e-9,2.8428797847919583e-8,,f1.ptu +103,27,46,73,0,98.11111111111111,134.84782608695653,1168.958904109589,,562366611.3904109,562362265,562370946,0.6301369863013698,0.5,146,28.118555517964687,0.0004340534724277794,2.4527778105258733e-9,3.3711956971842027e-9,2.9223972992921606e-8,,f1.ptu +104,120,14,178,0,121.09166666666667,110.28571428571429,1125.9325842696628,,584408879.4647436,584397733,584420173,0.1044776119402985,0.42948717948717946,312,29.220677738659088,0.0011220089760718085,3.0272917070853453e-9,2.7571428939546625e-9,2.8148314982561877e-8,,f1.ptu +105,3,82,68,0,87.0,141.4390243902439,1157.1764705882354,,608952032.1895425,608947104,608957498,0.9647058823529412,0.5555555555555556,153,30.447845192238663,0.000519704157633261,2.1750000290393645e-9,3.535975656966435e-9,2.8929412150954956e-8,,f1.ptu +106,40,50,69,0,99.025,127.3,1127.623188405797,,618054931.1257862,618048875,618061454,0.5555555555555556,0.5660377358490566,159,30.90299378023955,0.0006289550316402531,2.475625033053139e-9,3.1825000424909323e-9,2.8190580086529533e-8,,f1.ptu +107,21,55,108,0,116.38095238095238,101.67272727272727,1139.5277777777778,,620121312.1902174,620113917,620128599,0.7236842105263158,0.41304347826086957,184,31.006313660020147,0.0007341058728469827,2.909523848370119e-9,2.541818215755094e-9,2.8488194824802636e-8,,f1.ptu +108,22,35,53,0,138.04545454545453,152.42857142857142,1156.8490566037735,,658187239.1727272,658183096,658192250,0.6140350877192983,0.5181818181818182,110,32.909625235638245,0.000457703661629293,3.4511364097139755e-9,3.810714336592778e-9,2.8921226801234125e-8,,f1.ptu +109,23,44,98,0,113.73913043478261,142.02272727272728,1138.6632653061224,,661772623.339394,661765535,661779346,0.6567164179104478,0.40606060606060607,165,33.088895878136725,0.0006905555244441956,2.8434782988340716e-9,3.5505682292233517e-9,2.8466582012722688e-8,,f1.ptu +110,40,56,93,0,95.975,123.08928571428571,1131.0752688172042,,663153793.1798942,663144990,663161958,0.5833333333333334,0.5079365079365079,189,33.15795492263409,0.000848406787254298,2.399375032035092e-9,3.0772321839425983e-9,2.8276882097966968e-8,,f1.ptu +111,33,41,62,0,89.72727272727273,126.09756097560975,1141.5645161290322,,663178607.3970588,663172244,663186048,0.5540540540540541,0.5441176470588235,136,33.15919564341809,0.0006902055216441731,2.2431818481315076e-9,3.152439066479819e-9,2.8539113284263828e-8,,f1.ptu +112,42,50,88,0,98.07142857142857,133.8,1130.5454545454545,,673097248.8277777,673090757,673102980,0.5434782608695652,0.5111111111111111,180,33.655131682442345,0.0006111548892391139,2.4517857470205643e-9,3.34500004466054e-9,2.826363674099638e-8,,f1.ptu +113,32,60,77,0,97.65625,132.13333333333333,1127.3766233766235,,673965944.0591716,673957469,673973231,0.6521739130434783,0.5443786982248521,169,33.69856679149291,0.0007881063048504387,2.4414062825962694e-9,3.3033333774375634e-9,2.8184415960717894e-8,,f1.ptu +114,14,25,41,0,99.14285714285714,124.16,1155.8292682926829,,677007493.2375,677003879,677011887,0.6410256410256411,0.4875,80,33.85064546703873,0.0004004032032256258,2.4785714616639064e-9,3.1040000414428447e-9,2.8895732093116466e-8,,f1.ptu +115,7,99,104,0,88.57142857142857,161.4949494949495,1183.625,,677148624.3047619,677139451,677157184,0.9339622641509434,0.5047619047619047,210,33.85770207685471,0.000886657093256746,2.214285743849599e-9,4.037373791278458e-9,2.9590625395077216e-8,,f1.ptu +116,18,34,48,0,126.38888888888889,139.58823529411765,1165.1666666666667,,682493963.22,682488330,682499753,0.6538461538461539,0.52,100,34.124971160769284,0.0005711545692365539,3.1597222644090386e-9,3.489705928945512e-9,2.9129167055582755e-8,,f1.ptu +117,59,69,182,0,89.33898305084746,106.46376811594203,1148.5604395604396,,690710378.4064516,690698139,690721900,0.5390625,0.4129032258064516,310,34.535795206684234,0.0011880595044760358,2.2334746060912703e-9,2.6615942384346446e-9,2.8714011372384154e-8,,f1.ptu +118,30,36,67,0,94.16666666666667,115.19444444444444,1129.1791044776119,,697612839.5639098,697607681,697618824,0.5454545454545454,0.49624060150375937,133,34.880921025563694,0.0005571544572356579,2.354166698098163e-9,2.879861149561381e-9,2.8229477988844246e-8,,f1.ptu +119,146,138,236,0,104.10958904109589,109.5,1132.2033898305085,,697808343.6326923,697790003,697828835,0.4859154929577465,0.5461538461538461,520,34.890696307205076,0.0019416155329242634,2.6027397607776997e-9,2.737500036549545e-9,2.8305085123676126e-8,,f1.ptu +120,31,80,126,0,86.61290322580645,156.4,1141.095238095238,,703657251.7510549,703650538,703664077,0.7207207207207207,0.46835443037974683,237,35.18314405270517,0.0006769554156433251,2.1653226095553184e-9,3.910000052204099e-9,2.8527381333262337e-8,,f1.ptu +121,91,84,210,0,107.67032967032966,128.53571428571428,1125.5238095238096,,709741371.8597403,709724626,709757385,0.48,0.45454545454545453,385,35.487352491806945,0.0016379631037048295,2.691758277697069e-9,3.213392900046253e-9,2.8138095613779106e-8,,f1.ptu +122,43,43,76,0,101.88372093023256,123.34883720930233,1124.0526315789473,,709773429.8641975,709768004,709780212,0.5,0.5308641975308642,162,35.488955404853115,0.0006104048832390659,2.547093057263153e-9,3.0837209714046484e-9,2.8101316164666487e-8,,f1.ptu +123,34,26,62,1,129.1764705882353,123.88461538461539,1151.6935483870968,1481.0,715230881.4796748,715225874,715236543,0.43333333333333335,0.4918032786885246,123,35.76183016862509,0.000533454267634141,3.229411807823154e-9,3.09711542596631e-9,2.8792339094096373e-8,3.702500049433677e-8,f1.ptu +124,41,187,230,0,95.65853658536585,149.54545454545453,1155.2217391304348,,720954156.4563318,720935815,720973232,0.8201754385964912,0.4978165938864629,458,36.047996206786244,0.0018708649669197353,2.3914634465636074e-9,3.738636413552513e-9,2.8880543863857482e-8,,f1.ptu +125,20,64,87,0,93.65,138.25,1166.6091954022988,,720982357.0233918,720973673,720990186,0.7619047619047619,0.49122807017543857,171,36.049406246419565,0.000825656605252842,2.3412500312590403e-9,3.4562500461458867e-9,2.9165230274455054e-8,,f1.ptu +126,29,23,57,0,91.89655172413794,119.56521739130434,1134.122807017544,,731787830.7614679,731783699,731791928,0.4423076923076923,0.47706422018348627,109,36.58968425554744,0.000411453291626333,2.297413823777212e-9,2.9891304746917802e-9,2.8353070553992686e-8,,f1.ptu +127,60,89,166,0,104.16666666666667,120.12359550561797,1124.3313253012047,,731847794.3555555,731833757,731859944,0.5973154362416108,0.473015873015873,315,36.59268245923745,0.001309360474883799,2.604166701436021e-9,3.0030899277359998e-9,2.810828350781595e-8,,f1.ptu +128,58,82,199,0,92.15517241379311,120.35365853658537,1146.497487437186,,735918192.9056047,735906681,735932553,0.5857142857142857,0.41297935103244837,339,36.796204014912355,0.001293610348882791,2.3038793411049157e-9,3.0088415035869763e-9,2.866243756861423e-8,,f1.ptu +129,14,5,19,0,112.57142857142857,97.6,1134.4736842105262,,745980581.7894737,745978161,745982381,0.2631578947368421,0.5,38,37.29932748409355,0.0002110016880135041,2.8142857518604583e-9,2.4400000325774937e-9,2.836184248393436e-8,,f1.ptu +130,9,3,12,0,90.0,109.33333333333333,1123.8333333333333,,756067978.0,756066807,756069501,0.25,0.5,24,37.80370132961063,0.00013470107760862087,2.250000030040722e-9,2.733333369827247e-9,2.809583370845294e-8,,f1.ptu +131,39,44,63,0,101.76923076923077,105.72727272727273,1125.5238095238096,,763174991.5136986,763168069,763180525,0.5301204819277109,0.5684931506849316,146,38.15905484812371,0.0006228049824398595,2.5442308031998935e-9,2.6431818534720804e-9,2.8138095613779106e-8,,f1.ptu +132,59,82,147,0,107.96610169491525,134.390243902439,1134.9591836734694,,765722014.5694444,765710031,765731551,0.5815602836879432,0.4895833333333333,288,38.28640701972838,0.0010760086080688646,2.6991525784104327e-9,3.3597561424185303e-9,2.8373979970669992e-8,,f1.ptu +133,20,64,88,0,92.25,152.359375,1168.6136363636363,,817266095.3313954,817259744,817270815,0.7619047619047619,0.4883720930232558,172,40.863631675623175,0.0005535544284354275,2.30625003079174e-9,3.808984425855396e-9,2.921534129915754e-8,,f1.ptu +134,42,88,108,0,127.61904761904762,116.6590909090909,1135.8796296296296,,820972974.1806723,820963730,820983076,0.676923076923077,0.5462184873949579,238,41.04897710085042,0.0009673077384619077,3.190476233073616e-9,2.9164773116664203e-9,2.8396991119881228e-8,,f1.ptu +135,25,40,56,0,109.24,113.475,1145.107142857143,,820996015.6942148,820991508,820999653,0.6153846153846154,0.5371900826446281,121,41.050129185744225,0.0004072532580260642,2.7310000364627606e-9,2.8368750378763433e-9,2.8627678953649074e-8,,f1.ptu +136,54,99,193,0,101.01851851851852,124.88888888888889,1137.823834196891,,843428774.2283237,843415924,843441983,0.6470588235294118,0.4421965317919075,346,42.17177608562487,0.0013029604236833895,2.52546299668151e-9,3.12222226390836e-9,2.8445596234711714e-8,,f1.ptu +137,33,45,55,0,100.66666666666667,131.33333333333334,1156.8181818181818,,888406987.593985,888400242,888412473,0.5769230769230769,0.5864661654135338,133,44.42070474533721,0.0006115548924391395,2.5166667002677707e-9,3.283333377170535e-9,2.8920454931584024e-8,,f1.ptu +138,16,7,26,0,136.375,115.0,1142.576923076923,,895353067.3265306,895350851,895355182,0.30434782608695654,0.46938775510204084,49,44.76801151041861,0.0002165517324138593,3.4093750455200383e-9,2.875000038385367e-9,2.8564423458299027e-8,,f1.ptu +139,40,71,95,0,109.5,154.83098591549296,1157.9263157894736,,906367144.1213592,906358428,906374968,0.6396396396396397,0.5388349514563107,206,45.31871975582601,0.0008270066160529284,2.737500036549545e-9,3.8707746995677085e-9,2.89481582812362e-8,,f1.ptu +140,11,49,59,0,89.36363636363636,147.30612244897958,1167.6440677966102,,925529954.9663866,925525537,925533955,0.8166666666666667,0.5042016806722689,119,46.27686796326303,0.0004209033672269378,2.2340909389192217e-9,3.682653110393181e-9,2.9191102084658262e-8,,f1.ptu +141,42,69,105,0,132.85714285714286,108.81159420289855,1119.5619047619048,,929259621.962963,929249069,929269570,0.6216216216216216,0.5138888888888888,216,46.46335280497059,0.0010250582004656037,3.321428615774399e-9,2.7202898913922286e-9,2.7989047992741486e-8,,f1.ptu +142,45,41,93,1,132.35555555555555,118.48780487804878,1148.3870967741937,1091.0,929556079.1333333,929548771,929563963,0.47674418604651164,0.48044692737430167,180,46.478175782072924,0.0007596060768486147,3.3088889330672938e-9,2.962195161500766e-9,2.8709677802670146e-8,2.7275000364160307e-8,f1.ptu +143,66,14,120,0,126.28787878787878,132.0,1131.125,,934639909.28,934633767,934645675,0.175,0.4,200,46.73236932295458,0.0005954047632381059,3.15719701185007e-9,3.3000000440597255e-9,2.8278125377553462e-8,,f1.ptu +144,24,57,92,0,118.25,127.98245614035088,1132.3369565217392,,938761386.0520232,938752910,938769397,0.7037037037037037,0.4682080924855491,173,46.93844481015964,0.0008243565948527588,2.9562500394701707e-9,3.199561446227498e-9,2.830842429100148e-8,,f1.ptu +145,34,64,68,0,105.67647058823529,134.171875,1134.1323529411766,,938814434.313253,938809324,938819328,0.6530612244897959,0.5903614457831325,166,46.941097244440606,0.0005002040016320131,2.6419117999791875e-9,3.3542969197846665e-9,2.8353309202086687e-8,,f1.ptu +146,18,48,54,0,124.11111111111111,140.47916666666666,1153.3703703703704,,973408483.6583333,973404099,973411733,0.7272727272727273,0.55,120,48.670813549425056,0.000381703053624429,3.102777819204304e-9,3.5119792135566174e-9,2.8834259644237912e-8,,f1.ptu +147,31,37,84,0,98.6774193548387,111.02702702702703,1117.952380952381,,977371300.2894737,977365381,977377078,0.5441176470588235,0.4473684210526316,152,48.86895596612141,0.0005848546788374307,2.4669355168080888e-9,2.7756757127349207e-9,2.794880989696615e-8,,f1.ptu +148,23,29,60,1,100.0,122.62068965517241,1125.0333333333333,1330.0,979270673.0884956,979265611,979275191,0.5576923076923077,0.4642857142857143,113,48.963925365827706,0.0004790038320306562,2.50000003337858e-9,3.0655172823083553e-9,2.8125833708853484e-8,3.325000044393511e-8,f1.ptu +149,77,61,147,1,108.72727272727273,114.70491803278688,1130.639455782313,1809.0,984767095.8321679,984755236,984777551,0.4420289855072464,0.4842105263157895,286,49.238748701598006,0.0011157589260714085,2.718181854473438e-9,2.867622989106545e-9,2.826598677194922e-8,4.522500060381851e-8,f1.ptu +150,115,100,193,0,117.9304347826087,161.74,1144.9430051813472,,990952529.9901961,990937071,990967943,0.46511627906976744,0.5269607843137255,408,49.54802288369287,0.0015436123488987911,2.9482609089287217e-9,4.043500053986515e-9,2.8623575511699395e-8,,f1.ptu +151,13,58,108,0,92.46153846153847,149.0344827586207,1178.75,,996640550.9776536,996632809,996646634,0.8169014084507042,0.39664804469273746,179,49.83242620829235,0.0006912555300442404,2.31153849240081e-9,3.725862118711111e-9,2.946875039345001e-8,,f1.ptu +152,30,46,82,1,101.66666666666667,144.06521739130434,1160.3292682926829,1747.0,996838945.6415094,996832783,996846501,0.6052631578947368,0.4810126582278481,159,49.842346020843635,0.0006859054872438979,2.5416667006015565e-9,3.6016304828695323e-9,2.9008232094618502e-8,4.367500058312379e-8,f1.ptu +153,44,37,90,0,94.75,123.16216216216216,1120.9555555555555,,1000051147.9415205,1000045138,1000058053,0.4567901234567901,0.47368421052631576,171,50.002957420735385,0.0006457551660413283,2.3687500316262045e-9,3.079054095163835e-9,2.8023889263047932e-8,,f1.ptu +154,37,44,97,0,103.83783783783784,116.29545454545455,1129.2061855670104,,1000137743.8876405,1000129713,1000146923,0.5432098765432098,0.4550561797752809,178,50.007287252680044,0.0008605068840550725,2.5959459806055415e-9,2.9073864024541348e-9,2.8230155016088248e-8,,f1.ptu +155,29,29,76,0,113.65517241379311,133.0,1147.842105263158,,1000503610.9477612,1000498069,1000509548,0.5,0.43283582089552236,134,50.025580752034074,0.0005739545916367331,2.8413793482813103e-9,3.3250000443935113e-9,2.869605301471234e-8,,f1.ptu +156,36,61,81,0,102.16666666666667,105.8688524590164,1135.567901234568,,1010351305.511236,1010343618,1010358343,0.6288659793814433,0.5449438202247191,178,50.51796941931715,0.0007362558900471203,2.5541667007684494e-9,2.6467213468129295e-9,2.8389197909900636e-8,,f1.ptu +157,32,33,57,0,107.53125,118.03030303030303,1127.4736842105262,,1020111748.6557378,1020105327,1020116152,0.5076923076923077,0.5327868852459017,122,51.005995480750734,0.0005412543300346403,2.688281285892404e-9,2.950757615154415e-9,2.818684248159786e-8,,f1.ptu +158,36,12,68,1,122.94444444444444,98.16666666666667,1145.014705882353,1480.0,1034180639.2393162,1034175409,1034185273,0.25,0.41379310344827586,117,51.70944563753091,0.000493203945631565,3.0736111521482208e-9,2.4541666994333062e-9,2.8625368029248473e-8,3.700000049400298e-8,f1.ptu +159,37,44,85,0,101.05405405405405,121.75,1168.0,,1046123591.6325301,1046116784,1046129515,0.5432098765432098,0.4879518072289157,166,52.306598034410776,0.0006365550924407395,2.5263513850817593e-9,3.043750040638421e-9,2.9200000389861813e-8,,f1.ptu +160,40,26,70,0,105.825,132.19230769230768,1132.8142857142857,,1058624552.875,1058618982,1058629854,0.3939393939393939,0.4852941176470588,136,52.931651096958774,0.0005436043488347906,2.645625035322882e-9,3.304807736431607e-9,2.8320357520974463e-8,,f1.ptu +161,38,41,88,0,91.28947368421052,136.73170731707316,1130.715909090909,,1058641514.8443114,1058633168,1058648645,0.5189873417721519,0.47305389221556887,167,52.932499202209186,0.0007738561908495268,2.282236872576393e-9,3.418292728565931e-9,2.826789810468964e-8,,f1.ptu +162,41,39,110,0,92.1951219512195,144.53846153846155,1123.8727272727272,,1058663445.3,1058655468,1058669172,0.4875,0.42105263157894735,190,52.93359573376586,0.0006852054816438531,2.30487807955391e-9,3.6134615867064244e-9,2.8096818556950935e-8,,f1.ptu +163,14,44,49,0,96.42857142857143,164.6590909090909,1150.8775510204082,,1059395882.1401869,1059392451,1059400448,0.7586206896551724,0.5420560747663551,107,52.97021786875229,0.0003998531988255906,2.4107143179007737e-9,4.116477327688139e-9,2.877193915965679e-8,,f1.ptu +164,158,63,252,0,115.27215189873418,132.22222222222223,1139.765873015873,,1062788031.9238901,1062770281,1062805203,0.2850678733031674,0.46723044397463004,473,53.13982671480822,0.0017461139689117513,2.8818038359445616e-9,3.305555599689456e-9,2.849414720583449e-8,,f1.ptu +165,21,27,49,0,176.71428571428572,140.77777777777777,1135.2448979591836,,1064775655.1649485,1064770837,1064780694,0.5625,0.4948453608247423,97,53.2392086719168,0.0004928539428315427,4.417857201841862e-9,3.5194444914340673e-9,2.8381122827908214e-8,,f1.ptu +166,85,105,155,0,96.31764705882352,116.52380952380952,1132.3354838709677,,1076219471.078261,1076208162,1076229795,0.5526315789473685,0.5507246376811594,345,53.8114040451454,0.0010816586532692261,2.407941208620051e-9,2.9130952769892308e-9,2.8308387474731697e-8,,f1.ptu +167,21,26,55,0,127.38095238095238,136.34615384615384,1132.1818181818182,,1080127051.8921568,1080124073,1080131153,0.5531914893617021,0.46078431372549017,102,54.00678464888503,0.0003540028320226562,3.1845238520417626e-9,3.408653891664256e-9,2.830454583245167e-8,,f1.ptu +168,102,8,83,0,114.94117647058823,92.125,1191.1084337349398,,1110996153.5803108,1110987775,1111004261,0.07272727272727272,0.5699481865284974,193,55.550252081032184,0.0008243065944527556,2.873529450130438e-9,2.3031250307500167e-9,2.9777711240948575e-8,,f1.ptu +169,106,107,224,0,102.93396226415095,129.26168224299064,1132.299107142857,,1145550515.771167,1145538643,1145564325,0.5023474178403756,0.4874141876430206,437,57.27798401243045,0.001284110272882183,2.5733490909616685e-9,3.23154209922048e-9,2.830747805651679e-8,,f1.ptu +170,23,85,121,0,106.52173913043478,141.31764705882352,1144.1239669421489,,1147986676.3100436,1147978190,1147993237,0.7870370370370371,0.47161572052401746,229,57.399793013846285,0.0007523560188481507,2.6630435138163132e-9,3.532941223640412e-9,2.8603099555446054e-8,,f1.ptu +171,11,2,22,0,110.0,95.5,1121.1363636363637,,1155012346.8857143,1155010457,1155014753,0.15384615384615385,0.37142857142857144,35,57.751079352920534,0.0002148017184137473,2.750000036716438e-9,2.387500031876544e-9,2.8028409465128492e-8,,f1.ptu +172,24,36,72,0,100.54166666666667,119.58333333333333,1123.638888888889,,1172453433.810606,1172447911,1172458185,0.6,0.45454545454545453,132,58.623140675655705,0.000513704109632877,2.5135417002260475e-9,2.9895833732485515e-9,2.8090972597276926e-8,,f1.ptu +173,45,92,98,0,107.8,129.82608695652175,1132.9285714285713,,1189563664.0680852,1189555275,1189571561,0.6715328467153284,0.5829787234042553,235,59.47865903267652,0.0008143065144521156,2.6950000359821092e-9,3.2456522172471477e-9,2.8323214663869752e-8,,f1.ptu +174,43,47,145,0,103.32558139534883,121.97872340425532,1142.6758620689654,,1197370795.493617,1197362421,1197379050,0.5222222222222223,0.3829787234042553,235,59.86901872683067,0.0008314566516532132,2.5831395693723326e-9,3.0494681258211484e-9,2.8566896933133112e-8,,f1.ptu +0,22,50,56,0,131.13636363636363,139.6,1142.3214285714287,,30453104.9609375,30449259,30456533,0.6944444444444444,0.5625,128,1.522655248046875,0.0003637,3.2784091346805466e-9,3.4900000465964973e-9,2.8558036095576387e-8,,f2.ptu +1,19,51,58,0,124.63157894736842,125.25490196078431,1132.344827586207,,37881404.109375,37875876,37886597,0.7285714285714285,0.546875,128,1.89407020546875,0.0005360499999999999,3.1157895152844617e-9,3.1313725908279154e-9,2.83086210676158e-8,,f2.ptu +2,6,56,74,0,84.83333333333333,126.21428571428571,1148.445945945946,,48914883.90441176,48908879,48920634,0.9032258064516129,0.45588235294117646,136,2.445744195220588,0.00058775,2.120833361649495e-9,3.155357184985679e-9,2.87111490319836e-8,,f2.ptu +3,86,147,191,1,119.51162790697674,155.31972789115648,1145.3560209424083,1124.0,84943401.80705883,84924114,84961698,0.630901287553648,0.5495283018867925,425,4.247170090352941,0.0018792,2.9877907375657027e-9,3.882993249122431e-9,2.8633900905863784e-8,2.8100000375175238e-8,f2.ptu +4,15,41,61,0,132.8,147.1951219512195,1161.7704918032787,,87016316.94017094,87011748,87020551,0.7321428571428571,0.47863247863247865,117,4.350815847008547,0.00044015,3.320000044326754e-9,3.679878097912129e-9,2.904426268286446e-8,,f2.ptu +5,2,12,14,0,103.5,149.83333333333334,1151.0,,118353580.14285715,118352097,118355842,0.8571428571428571,0.5,28,5.9176790071428576,0.00018725,2.58750003454683e-9,3.745833383345573e-9,2.8775000384187455e-8,,f2.ptu +6,30,140,179,0,137.3,186.80714285714285,1183.1787709497207,,118406231.5816619,118395250,118420124,0.8235294117647058,0.4871060171919771,349,5.920311579083094,0.0012437,3.4325000458287903e-9,4.670178633782143e-9,2.957946966867129e-8,,f2.ptu +7,57,50,133,0,97.17543859649123,120.06,1134.1278195488721,,135234194.23333332,135224938,135243073,0.4672897196261682,0.44583333333333336,240,6.761709711666666,0.00090675,2.4293859973480623e-9,3.0015000400743232e-9,2.8353195867277563e-8,,f2.ptu +8,43,78,106,0,116.04651162790698,139.83333333333334,1142.0,,158696088.4889868,158688074,158702832,0.6446280991735537,0.5330396475770925,227,7.934804424449339,0.0007379,2.901162829432352e-9,3.4958333800077144e-9,2.8550000381183382e-8,,f2.ptu +9,32,85,83,0,98.5625,158.28235294117647,1160.3253012048192,,188875871.04,188869376,188883035,0.7264957264957265,0.585,200,9.443793551999999,0.00068295,2.464062532898763e-9,3.9570588763618135e-9,2.9008132917420588e-8,,f2.ptu +10,75,7,84,0,137.61333333333334,208.28571428571428,1141.7738095238096,,192320014.30120483,192311519,192327395,0.08536585365853659,0.4939759036144578,166,9.616000715060242,0.0007938,3.44033337926671e-9,5.207142926665671e-9,2.8544345619203125e-8,,f2.ptu +11,2,1,2,0,90.0,105.0,1183.0,,193331913.8,193331352,193332387,0.3333333333333333,0.6,5,9.66659569,0.00005175,2.250000030040722e-9,2.625000035047509e-9,2.95750003948686e-8,,f2.ptu +12,43,46,75,0,96.23255813953489,124.91304347826087,1120.2,,193338883.77439025,193332565,193346194,0.5168539325842697,0.5426829268292683,164,9.666944188719512,0.00068145,2.4058139856094334e-9,3.122826128650722e-9,2.8005000373906854e-8,,f2.ptu +13,1,0,2,0,116.0,,1134.0,,193813745.33333334,193813328,193813970,0.0,0.3333333333333333,3,9.690687266666666,0.0000321,2.9000000387191527e-9,,2.8350000378513096e-8,,f2.ptu +14,35,49,91,1,94.14285714285714,122.59183673469387,1127.4725274725274,1111.0,204237796.6590909,204230279,204245367,0.5833333333333334,0.48,176,10.211889832954546,0.0007544,2.3535714599949774e-9,3.064795959286761e-9,2.8186813563147505e-8,2.7775000370836023e-8,f2.ptu +15,56,54,130,0,115.78571428571429,129.7962962962963,1148.5615384615385,,205753439.26666668,205745888,205761426,0.4909090909090909,0.4583333333333333,240,10.287671963333334,0.0007769,2.8946428957904844e-9,3.244907450731568e-9,2.8714038844911994e-8,,f2.ptu +16,23,4,28,0,127.0,92.0,1119.357142857143,,238034249.47272727,238031553,238036855,0.14814814814814814,0.4909090909090909,55,11.901712473636364,0.0002651,3.1750000423907965e-9,2.3000000307082935e-9,2.798392894505409e-8,,f2.ptu +17,25,5,21,0,153.72,96.0,1146.7619047619048,,238040716.84313726,238037822,238043539,0.16666666666666666,0.5882352941176471,51,11.902035842156863,0.00028585,3.843000051309553e-9,2.4000000320434367e-9,2.8669048001820458e-8,,f2.ptu +18,36,54,94,0,96.30555555555556,119.9074074074074,1141.7021276595744,,238059209.5271739,238053084,238064765,0.6,0.4891304347826087,184,11.902960476358695,0.00058405,2.4076389210343157e-9,2.9976852252085748e-9,2.8542553572573318e-8,,f2.ptu +19,13,79,72,0,89.53846153846153,131.0,1147.9722222222222,,243636920.9207317,243632161,243641353,0.8586956521739131,0.5609756097560976,164,12.181846046036584,0.0004596,2.2384615683482054e-9,3.2750000437259397e-9,2.869930593873238e-8,,f2.ptu +20,23,31,50,0,101.26086956521739,127.6774193548387,1148.96,,309406446.41346157,309400805,309412633,0.5740740740740741,0.5192307692307693,104,15.470322320673077,0.0005914,2.531521772929875e-9,3.191935526487877e-9,2.872400038350653e-8,,f2.ptu +21,29,25,53,0,93.0,115.36,1136.9245283018868,,309620704.2803738,309616722,309625700,0.46296296296296297,0.5046728971962616,107,15.48103521401869,0.00044889999999999996,2.3250000310420793e-9,2.8840000385055296e-9,2.842311358703643e-8,,f2.ptu +22,23,40,70,0,95.17391304347827,132.625,1153.0142857142857,,344328424.83458644,344323666,344332565,0.6349206349206349,0.47368421052631576,133,17.21642124172932,0.00044495,2.379347857854657e-9,3.3156250442683416e-9,2.8825357527716938e-8,,f2.ptu +23,56,82,115,0,114.64285714285714,151.4878048780488,1133.7652173913043,,357844929.7786561,357837269,357853785,0.5942028985507246,0.5454545454545454,253,17.892246488932805,0.0008258,2.8660714668375863e-9,3.787195172515698e-9,2.8344130813217338e-8,,f2.ptu +24,66,103,232,0,103.56060606060606,162.05825242718447,1168.9353448275863,,381384820.3291771,381373428,381395500,0.6094674556213018,0.42144638403990026,401,19.069241016458854,0.0011036,2.5890151860822113e-9,4.051456364772355e-9,2.9223384010863674e-8,,f2.ptu +25,46,11,115,0,108.6086956521739,92.63636363636364,1142.304347826087,,394734919.30813956,394728339,394740837,0.19298245614035087,0.3313953488372093,172,19.73674596540698,0.0006249,2.715217427556388e-9,2.3159091218297937e-9,2.8557609076937145e-8,,f2.ptu +26,87,75,155,0,126.82758620689656,121.34666666666666,1140.2645161290322,,402095205.6940063,402085239,402107790,0.46296296296296297,0.5110410094637224,317,20.104760284700316,0.00112755,3.170689697505661e-9,3.0336667071704608e-9,2.850661328382991e-8,,f2.ptu +27,57,122,274,0,123.6842105263158,180.13934426229508,1170.434306569343,,414191765.6777042,414174766,414206192,0.6815642458100558,0.39514348785871967,453,20.70958828388521,0.0015712999999999999,3.0921053044419278e-9,4.503483666685332e-9,2.926085805490793e-8,,f2.ptu +28,137,186,235,3,99.43065693430657,163.5,1160.672340425532,1117.0,414245666.4634581,414227635,414267539,0.5758513931888545,0.578853046594982,561,20.712283323172905,0.0019952,2.4857664565462055e-9,4.087500054573978e-9,2.9016808898054244e-8,2.7925000372838737e-8,f2.ptu +29,36,18,65,0,146.69444444444446,120.88888888888889,1123.8461538461538,,422117992.07563025,422113153,422123156,0.3333333333333333,0.453781512605042,119,21.105899603781513,0.00050015,3.667361160075634e-9,3.0222222625732167e-9,2.809615422127773e-8,,f2.ptu +30,38,31,64,0,111.57894736842105,135.19354838709677,1153.09375,,424979821.16541356,424974510,424986544,0.4492753623188406,0.518796992481203,133,21.248991058270676,0.0006016999999999999,2.7894737214539944e-9,3.379838754803106e-9,2.882734413488632e-8,,f2.ptu +31,40,16,60,0,112.75,159.8125,1150.45,,432092731.63793105,432087155,432097484,0.2857142857142857,0.4827586206896552,116,21.60463658189655,0.00051645,2.818750037634349e-9,3.995312553343143e-9,2.8761250384003874e-8,,f2.ptu +32,123,201,303,0,115.01626016260163,141.84577114427861,1153.03300330033,,436453002.09728867,436427290,436479149,0.6203703703703703,0.5167464114832536,627,21.822650104864433,0.0025929499999999997,2.875406542455835e-9,3.5461443259530693e-9,2.882582546737429e-8,,f2.ptu +33,23,41,74,0,95.3913043478261,146.41463414634146,1141.1216216216217,,436844433.04347825,436838841,436851606,0.640625,0.463768115942029,138,21.84222165217391,0.0006382499999999999,2.384782640535915e-9,3.660365902529662e-9,2.8528040921430735e-8,,f2.ptu +34,43,21,103,0,195.62790697674419,135.38095238095238,1143.7864077669904,,438834527.7005988,438828995,438840681,0.328125,0.38323353293413176,167,21.941726385029938,0.0005842999999999999,4.890697739716422e-9,3.384523854712049e-9,2.859466057595442e-8,,f2.ptu +35,69,33,122,0,129.92753623188406,144.15151515151516,1142.9426229508197,,462562540.75,462552492,462572436,0.3235294117647059,0.45535714285714285,224,23.1281270375,0.0009972,3.248188449165068e-9,3.6037879269036075e-9,2.857356595526851e-8,,f2.ptu +36,7,93,135,0,144.0,123.90322580645162,1155.6444444444444,,467109571.7574468,467099752,467122057,0.93,0.425531914893617,235,23.35547858787234,0.00111525,3.600000048065155e-9,3.0975806865184278e-9,2.8891111496848814e-8,,f2.ptu +37,7,48,67,0,91.57142857142857,137.04166666666666,1156.686567164179,,467143342.06557375,467139228,467147937,0.8727272727272727,0.45081967213114754,122,23.357167103278687,0.00043545,2.2892857448509566e-9,3.4260417124092287e-9,2.8917164565190026e-8,,f2.ptu +38,27,4,20,0,122.77777777777777,268.0,1144.5,,467641319.25490195,467638744,467643388,0.12903225806451613,0.6078431372549019,51,23.382065962745095,0.00023219999999999998,3.069444485425923e-9,6.700000089454594e-9,2.8612500382017847e-8,,f2.ptu +39,8,53,51,0,111.875,191.83018867924528,1177.549019607843,,473985141.7410714,473978659,473991648,0.8688524590163934,0.5446428571428571,112,23.69925708705357,0.00064945,2.7968750373422863e-9,4.7957547810113246e-9,2.943872588324522e-8,,f2.ptu +40,48,103,130,0,103.91666666666667,150.5242718446602,1144.4,,474036059.33096087,474028945,474042982,0.6821192052980133,0.5373665480427047,281,23.701802966548044,0.00070185,2.5979167013525746e-9,3.763106846359369e-9,2.861000038198447e-8,,f2.ptu +41,51,72,89,0,100.37254901960785,147.13888888888889,1161.4943820224719,,489361816.4386792,489355237,489367380,0.5853658536585366,0.5801886792452831,212,24.46809082193396,0.00060715,2.5093137589931277e-9,3.678472271335094e-9,2.9037359938252128e-8,,f2.ptu +42,17,84,110,0,105.52941176470588,143.86904761904762,1141.8272727272727,,511904904.6445498,511897775,511912674,0.8316831683168316,0.4786729857819905,211,25.595245232227487,0.00074495,2.638235329341866e-9,3.5967262384976353e-9,2.8545682199307545e-8,,f2.ptu +43,59,43,94,0,107.66101694915254,131.13953488372093,1136.1808510638298,,511957063.02040815,511949720,511964485,0.4215686274509804,0.5204081632653061,196,25.597853151020406,0.00073825,2.691525459664532e-9,3.278488415865538e-9,2.8404521655836777e-8,,f2.ptu +44,36,90,217,0,130.91666666666666,167.65555555555557,1171.5668202764978,,513453117.1895044,513442289,513463890,0.7142857142857143,0.3673469387755102,343,25.672655859475217,0.00108005,3.2729167103647907e-9,4.191388944849933e-9,2.928917089796481e-8,,f2.ptu +45,14,75,69,0,107.85714285714286,164.04,1154.5797101449275,,520531998.4683544,520524423,520538776,0.8426966292134831,0.5632911392405063,158,26.02659992341772,0.00071765,2.696428607429754e-9,4.101000054754222e-9,2.88644931390055e-8,,f2.ptu +46,26,90,98,0,101.1923076923077,154.4111111111111,1150.6632653061224,,525232510.87383175,525224286,525240103,0.7758620689655172,0.5420560747663551,214,26.261625543691586,0.00079085,2.5298077260842477e-9,3.8602778293180135e-9,2.8766582016728118e-8,,f2.ptu +47,61,15,120,0,112.36065573770492,119.06666666666666,1156.35,,534831129.17346936,534823678,534838424,0.19736842105263158,0.3877551020408163,196,26.741556458673468,0.0007373,2.809016430947014e-9,2.9766667064094292e-9,2.8908750385973208e-8,,f2.ptu +48,18,35,65,0,114.22222222222223,148.31428571428572,1144.8,,539534278.8898305,539528999,539537938,0.660377358490566,0.4491525423728814,118,26.97671394449152,0.00044695,2.8555555936813115e-9,3.7078571923623453e-9,2.862000038211798e-8,,f2.ptu +49,15,60,57,0,88.86666666666666,128.8,1143.122807017544,,540308861.9848485,540302667,540315113,0.8,0.5681818181818182,132,27.015443099242425,0.0006223,2.2216666963290978e-9,3.220000042991611e-9,2.8578070556996758e-8,,f2.ptu +50,168,34,188,0,172.79761904761904,213.3235294117647,1171.3510638297873,,548924256.3769231,548911079,548939864,0.16831683168316833,0.517948717948718,390,27.446212818846153,0.00143925,4.319940533867867e-9,5.333088306498482e-9,2.9283776986725033e-8,,f2.ptu +51,51,51,95,0,105.0,114.56862745098039,1137.9157894736843,,550188308.5532995,550180257,550197273,0.5,0.5177664974619289,197,27.509415427664976,0.0008508,2.625000035047509e-9,2.8642157245158906e-9,2.844789511666224e-8,,f2.ptu +52,47,20,54,0,102.91489361702128,136.05,1171.851851851852,,583326931.0578512,583321689,583332480,0.29850746268656714,0.5537190082644629,121,29.16634655289256,0.00053955,2.572872374777062e-9,3.401250045411558e-9,2.9296296687443805e-8,,f2.ptu +53,22,67,84,0,98.04545454545455,130.92537313432837,1142.7738095238096,,597076632.751445,597069246,597082568,0.7528089887640449,0.5144508670520231,173,29.853831637572252,0.0006661,2.451136396362544e-9,3.2731343720592393e-9,2.856934561953691e-8,,f2.ptu +54,88,17,99,0,130.0909090909091,112.3529411764706,1146.8080808080808,,613069250.2794118,613060245,613078710,0.1619047619047619,0.5147058823529411,204,30.653462513970588,0.0009232499999999999,3.2522727706952256e-9,2.808823566913581e-9,2.867020240299027e-8,,f2.ptu +55,12,47,32,0,113.16666666666667,143.72340425531914,1148.625,,615783486.7692307,615780746,615786464,0.7966101694915254,0.6483516483516484,91,30.789174338461535,0.0002859,2.829166704440093e-9,3.5930851543558096e-9,2.8715625383394713e-8,,f2.ptu +56,24,37,66,1,109.75,166.0,1133.4242424242425,1831.0,624163781.8984375,624158941,624168877,0.6065573770491803,0.48031496062992124,128,31.208189094921874,0.0004967999999999999,2.7437500366329914e-9,4.150000055408443e-9,2.8335606438926977e-8,4.57750006111618e-8,f2.ptu +57,33,54,103,0,106.54545454545455,138.85185185185185,1138.1844660194174,,628673824.0,628665639,628681766,0.6206896551724138,0.45789473684210524,190,31.4336912,0.00080635,2.6636363991997232e-9,3.4712963426430725e-9,2.8454612030395246e-8,,f2.ptu +58,55,58,104,0,115.14545454545454,137.0,1138.826923076923,,638102631.640553,638093668,638110305,0.5132743362831859,0.5207373271889401,217,31.90513158202765,0.00083185,2.8786364020702813e-9,3.4250000457286545e-9,2.847067345704733e-8,,f2.ptu +59,21,42,68,0,103.95238095238095,128.5952380952381,1129.1911764705883,,642810988.167939,642806505,642815257,0.6666666666666666,0.48091603053435117,131,32.14054940839694,0.00043759999999999996,2.5988095585073523e-9,3.2148809953042167e-9,2.8229779788672686e-8,,f2.ptu +60,62,65,84,0,131.11290322580646,152.5076923076923,1169.797619047619,,644089606.113744,644082850,644096886,0.5118110236220472,0.6018957345971564,211,32.2044803056872,0.0007017999999999999,3.277822624408787e-9,3.812692358597209e-9,2.924494086665231e-8,,f2.ptu +61,79,28,71,0,109.60759493670886,153.75,1162.8732394366198,,644106415.4494382,644097651,644114462,0.2616822429906542,0.601123595505618,178,32.20532077247191,0.0008405499999999999,2.74018991000318e-9,3.843750051319567e-9,2.9071831374066068e-8,,f2.ptu +62,145,41,84,1,145.94482758620688,132.8048780487805,1127.7857142857142,1307.0,656054379.1217712,656048744,656062282,0.22043010752688172,0.6888888888888889,271,32.80271895608856,0.0006768999999999999,3.648620738369483e-9,3.320121995547895e-9,2.819464323358171e-8,3.267500043625804e-8,f2.ptu +63,29,25,52,0,115.55172413793103,127.08,1120.7884615384614,,662075583.8301886,662069243,662082324,0.46296296296296297,0.5094339622641509,106,33.10377919150943,0.00065405,2.8887931420178002e-9,3.1770000424174993e-9,2.801971191256481e-8,,f2.ptu +64,44,151,136,0,117.0909090909091,136.2980132450331,1160.2794117647059,,664918039.1933535,664904954,664931624,0.7743589743589744,0.5891238670694864,331,33.24590195966768,0.0013334999999999998,2.92727276635601e-9,3.407450376620169e-9,2.9006985681402435e-8,,f2.ptu +65,32,22,56,0,102.53125,116.5,1126.732142857143,,667395273.6,667391507,667399940,0.4074074074074074,0.4909090909090909,110,33.36976368,0.00042165,2.563281284223475e-9,2.9125000388860456e-9,2.816830394751576e-8,,f2.ptu +66,38,58,102,0,98.92105263157895,128.0,1124.5098039215686,,670630649.4090909,670622759,670637033,0.6041666666666666,0.48484848484848486,198,33.53153247045454,0.0007137,2.4730263488079163e-9,3.2000000427245823e-9,2.811274547338462e-8,,f2.ptu +67,40,35,115,0,93.075,144.0857142857143,1137.2,,684363715.0842105,684359384,684369854,0.4666666666666667,0.39473684210526316,190,34.21818575421052,0.0005235,2.326875031067113e-9,3.6021429052366226e-9,2.8430000379581213e-8,,f2.ptu +68,45,72,100,1,94.44444444444444,119.33333333333333,1127.31,1152.0,686125432.1238532,686119424,686132721,0.6153846153846154,0.5391705069124424,218,34.30627160619266,0.0006648499999999999,2.3611111426353255e-9,2.983333373165105e-9,2.8182750376280068e-8,2.880000038452124e-8,f2.ptu +69,54,10,52,0,121.5925925925926,77.6,1140.9038461538462,,693730388.6810344,693725050,693735507,0.15625,0.5517241379310345,116,34.68651943405172,0.0005228499999999999,3.0398148554006957e-9,1.9400000259017778e-9,2.8522596534663657e-8,,f2.ptu +70,37,39,83,0,113.83783783783784,133.5897435897436,1131.8915662650602,,695017658.4591194,695011374,695024657,0.5131578947368421,0.4779874213836478,159,34.750882922955974,0.00066415,2.8459459839433995e-9,3.3397436343339493e-9,2.8297289534435836e-8,,f2.ptu +71,35,24,53,0,96.2,121.79166666666667,1144.8301886792453,,697137477.1785715,697132954,697141601,0.4067796610169492,0.5267857142857143,112,34.85687385892857,0.00043234999999999997,2.4050000321101938e-9,3.0447917073189957e-9,2.8620755099109194e-8,,f2.ptu +72,56,48,78,0,98.51785714285714,138.72916666666666,1131.2692307692307,,697166600.3791208,697160733,697172262,0.46153846153846156,0.5714285714285714,182,34.85833001895604,0.0005764499999999999,2.4629464614552903e-9,3.4682292129724923e-9,2.8281731146832372e-8,,f2.ptu +73,46,44,68,0,124.82608695652173,121.86363636363636,1133.014705882353,,703162972.278481,703157647,703167436,0.4888888888888889,0.569620253164557,158,35.15814861392405,0.00048945,3.1206522155782187e-9,3.04659094976726e-9,2.8325368025243043e-8,,f2.ptu +74,33,70,155,0,109.27272727272727,158.55714285714285,1156.8,,704848496.1240311,704839679,704856059,0.6796116504854369,0.3992248062015504,258,35.242424806201555,0.000819,2.7318182182918664e-9,3.963928624352694e-9,2.892000038612341e-8,,f2.ptu +75,45,61,91,0,92.46666666666667,133.44262295081967,1144.0,,721708504.751269,721698607,721717297,0.5754716981132075,0.5380710659898477,197,36.08542523756345,0.0009345,2.311666697530727e-9,3.336065618311744e-9,2.8600000381850954e-8,,f2.ptu +76,39,116,197,0,105.51282051282051,142.0948275862069,1157.5532994923858,,735404523.5227273,735392344,735415842,0.7483870967741936,0.4403409090909091,352,36.77022617613636,0.0011749,2.637820548039194e-9,3.5523707370844077e-9,2.89388328736845e-8,,f2.ptu +77,21,32,51,0,96.47619047619048,112.09375,1121.5294117647059,,738464122.4615384,738459413,738469097,0.6037735849056604,0.5096153846153846,104,36.92320612307692,0.00048419999999999995,2.4119047941071444e-9,2.802343787415302e-9,2.8038235668468236e-8,,f2.ptu +78,52,38,86,0,99.3076923076923,124.07894736842105,1124.1976744186047,,767657420.7784091,767650792,767663233,0.4222222222222222,0.5113636363636364,176,38.382871038920456,0.00062205,2.482692340839805e-9,3.101973725626317e-9,2.8104942235706337e-8,,f2.ptu +79,43,49,116,0,98.46511627906976,134.42857142857142,1130.2241379310344,,787873108.3317307,787866010,787880715,0.532608695652174,0.4423076923076923,208,39.39365541658653,0.00073525,2.4616279398430014e-9,3.3607143305846336e-9,2.8255603825528628e-8,,f2.ptu +80,18,4,22,0,110.0,160.25,1141.0,,787901451.4090909,787899478,787903437,0.18181818181818182,0.5,44,39.395072570454545,0.00019795,2.750000036716438e-9,4.006250053489174e-9,2.8525000380849597e-8,,f2.ptu +81,25,64,89,0,101.56,149.03125,1191.426966292135,,788149760.1235955,788143987,788154611,0.7191011235955056,0.5,178,39.40748800617977,0.0005312,2.539000033899286e-9,3.725781299744515e-9,2.9785674554984776e-8,,f2.ptu +82,76,54,70,0,130.92105263157896,130.09259259259258,1136.6285714285714,,789364854.87,789357069,789371208,0.4153846153846154,0.65,200,39.4682427435,0.0007069499999999999,3.2730263594890623e-9,3.2523148582378746e-9,2.8415714665104762e-8,,f2.ptu +83,39,7,29,0,107.46153846153847,122.42857142857143,1146.8275862068965,,789382590.8666667,789379229,789385579,0.15217391304347827,0.6133333333333333,75,39.46912954333333,0.00031749999999999997,2.686538497407597e-9,3.0607143265792044e-9,2.8670690037967176e-8,,f2.ptu +84,32,29,59,0,100.09375,128.10344827586206,1128.1694915254238,,798734200.375,798728106,798739647,0.47540983606557374,0.5083333333333333,120,39.93671001875,0.00057705,2.5023437834098723e-9,3.2025862496556636e-9,2.8204237664702553e-8,,f2.ptu +85,5,32,61,0,91.8,146.34375,1134.1639344262296,,799970017.5816326,799965539,799975086,0.8648648648648649,0.37755102040816324,98,39.99850087908163,0.00047735,2.2950000306415364e-9,3.6585937988474655e-9,2.8354098739223555e-8,,f2.ptu +86,72,77,182,0,95.66666666666667,119.1948051948052,1136.9120879120878,,820631669.570997,820621200,820643018,0.5167785234899329,0.4501510574018127,331,41.03158347854985,0.0010909,2.3916666985988417e-9,2.9798701696556634e-9,2.8422802577287307e-8,,f2.ptu +87,14,45,53,0,127.28571428571429,133.9777777777778,1153.698113207547,,826249918.1607143,826245219,826254661,0.7627118644067796,0.5267857142857143,112,41.312495908035714,0.0004721,3.182142899629021e-9,3.349444489164324e-9,2.8842453215276722e-8,,f2.ptu +88,41,36,87,0,99.21951219512195,150.08333333333334,1147.528735632184,,833365263.0853659,833357354,833371571,0.4675324675324675,0.4695121951219512,164,41.668263154268296,0.00071085,2.480487837996113e-9,3.752083383429019e-9,2.8688218773833394e-8,,f2.ptu +89,34,37,97,0,109.08823529411765,122.97297297297297,1132.8762886597938,,850007814.0357143,850001533,850014321,0.5211267605633803,0.4226190476190476,168,42.50039070178571,0.0006393999999999999,2.727205918765045e-9,3.0743243653709563e-9,2.8321907594632863e-8,,f2.ptu +90,7,50,62,0,87.28571428571429,144.32,1159.4193548387098,,858072021.9159664,858067082,858076669,0.8771929824561403,0.4789915966386555,119,42.903601095798315,0.00047934999999999997,2.182142886277589e-9,3.6080000481719664e-9,2.898548425796546e-8,,f2.ptu +91,33,60,81,0,101.66666666666667,146.2,1139.0493827160494,,870776693.5574713,870770154,870783796,0.6451612903225806,0.5344827586206896,174,43.53883467787356,0.0006820999999999999,2.5416667006015565e-9,3.6550000487994837e-9,2.8476234948099745e-8,,f2.ptu +92,51,32,106,0,95.3921568627451,104.78125,1131.7358490566037,,885330639.7671958,885324026,885335906,0.3855421686746988,0.43915343915343913,189,44.26653198835979,0.000594,2.3848039534091747e-9,2.6195312849744933e-9,2.8293396604172446e-8,,f2.ptu +93,32,109,161,0,88.4375,168.0183486238532,1177.1987577639752,,895398814.1854304,895389705,895409153,0.7730496453900709,0.46688741721854304,302,44.769940709271516,0.0009724,2.2109375295191816e-9,4.2004587716784685e-9,2.9429969337031607e-8,,f2.ptu +94,17,26,56,0,99.88235294117646,112.96153846153847,1126.625,,908753868.6161616,908749454,908757223,0.6046511627906976,0.43434343434343436,99,45.437693430808075,0.00038845,2.4970588568687226e-9,2.824038499243419e-9,2.8165625376051426e-8,,f2.ptu +95,24,76,79,0,108.91666666666667,133.53947368421052,1153.0253164556962,,929621925.5027933,929614632,929626628,0.76,0.5586592178770949,179,46.48109627513966,0.0005997999999999999,2.7229167030215036e-9,3.338486886678843e-9,2.882563329625588e-8,,f2.ptu +96,22,59,88,0,109.72727272727273,151.864406779661,1162.659090909091,,930070976.1183432,930064774,930077686,0.7283950617283951,0.47928994082840237,169,46.50354880591716,0.0006456,2.7431818548072236e-9,3.796610220181708e-9,2.9066477660806368e-8,,f2.ptu +97,47,114,100,0,120.38297872340425,127.21052631578948,1143.09,,932797980.6321839,932789810,932806974,0.7080745341614907,0.6168582375478927,261,46.6398990316092,0.0008581999999999999,3.009574508267235e-9,3.180263200355804e-9,2.8577250381547207e-8,,f2.ptu +98,34,38,76,0,103.5,113.47368421052632,1125.0394736842106,,935171873.75,935166458,935177039,0.5277777777777778,0.4864864864864865,148,46.758593687499996,0.00052905,2.58750003454683e-9,2.8368421431390622e-9,2.8125987217627466e-8,,f2.ptu +99,38,42,101,0,96.15789473684211,135.95238095238096,1136.4851485148515,,935794462.6629834,935786673,935802361,0.525,0.4419889502762431,181,46.78972313314917,0.0007844,2.4039474005171924e-9,3.3988095691884983e-9,2.841212909221389e-8,,f2.ptu +100,29,39,69,0,105.89655172413794,133.82051282051282,1130.0869565217392,,935818146.8905109,935812870,935823463,0.5735294117647058,0.49635036496350365,137,46.79090734452554,0.00052965,2.6474138284502134e-9,3.3455128651802073e-9,2.825217429025046e-8,,f2.ptu +101,47,49,99,0,130.4255319148936,149.12244897959184,1181.7373737373737,,935893727.0769231,935887423,935900692,0.5104166666666666,0.49230769230769234,195,46.79468635384615,0.00066345,3.2606383414065305e-9,3.728061274264752e-9,2.9543434737881494e-8,,f2.ptu +102,27,74,78,0,123.92592592592592,163.77027027027026,1185.2820512820513,,935918402.2067039,935912232,935923347,0.7326732673267327,0.5642458100558659,179,46.795920110335196,0.0005557499999999999,3.0981481895128623e-9,4.094256811420947e-9,2.9632051677681597e-8,,f2.ptu +103,81,234,354,0,94.69135802469135,153.56837606837607,1174.8079096045199,,950000889.5082213,949980255,950021783,0.7428571428571429,0.47085201793721976,669,47.50004447541106,0.0020764,2.3672839822239144e-9,3.8392094529683445e-9,2.9370198132247192e-8,,f2.ptu +104,29,47,102,0,93.44827586206897,112.40425531914893,1128.0098039215686,,963819813.1460674,963813422,963826784,0.618421052631579,0.42696629213483145,178,48.19099065730337,0.0006680999999999999,2.3362069277434318e-9,2.8101064204976675e-9,2.820024547455287e-8,,f2.ptu +105,63,68,159,0,102.14285714285714,127.45588235294117,1122.9308176100628,,979617413.8586206,979605652,979629074,0.5190839694656488,0.4517241379310345,290,48.98087069293103,0.0011711,2.553571462665264e-9,3.186397101366493e-9,2.807327081506993e-8,,f2.ptu +106,20,33,59,0,92.4,102.72727272727273,1143.2881355932204,,979662297.9553572,979657377,979666220,0.6226415094339622,0.4732142857142857,112,48.983114897767855,0.00044215,2.310000030841808e-9,2.568181852470723e-9,2.8582203771443855e-8,,f2.ptu +107,38,34,123,0,93.76315789473684,122.82352941176471,1136.2032520325204,,1001394339.6410257,1001387226,1001402278,0.4722222222222222,0.36923076923076925,195,50.06971698205128,0.0007526,2.3440789786652316e-9,3.0705882762908676e-9,2.840508168006152e-8,,f2.ptu +108,27,34,54,0,105.4074074074074,123.5,1147.2037037037037,,1001412784.4347826,1001407317,1001417172,0.5573770491803278,0.5304347826086957,115,50.07063922173913,0.00049275,2.6351852203686807e-9,3.087500041222546e-9,2.86800929755129e-8,,f2.ptu +109,26,22,66,0,95.73076923076923,127.13636363636364,1134.5151515151515,,1007290574.8684211,1007286619,1007293535,0.4583333333333333,0.42105263157894735,114,50.364528743421054,0.0003458,2.393269262722802e-9,3.178409133345404e-9,2.8362879166563833e-8,,f2.ptu +110,53,28,98,0,104.05660377358491,140.53571428571428,1134.9591836734694,,1012000759.8100559,1011992567,1012008585,0.345679012345679,0.45251396648044695,179,50.60003799050279,0.0008009,2.6014151290722395e-9,3.5133929040516825e-9,2.8373979970669992e-8,,f2.ptu +111,8,58,52,0,99.625,149.0,1137.8653846153845,,1019949148.7457627,1019944310,1019954673,0.8787878787878788,0.559322033898305,118,50.99745743728813,0.00051815,2.4906250332534102e-9,3.725000049734084e-9,2.844663499518792e-8,,f2.ptu +112,55,37,112,1,100.14545454545454,103.35135135135135,1122.017857142857,1477.0,1023583782.7756097,1023577214,1023590308,0.40217391304347827,0.45098039215686275,205,51.17918913878049,0.0006546999999999999,2.5036363970634943e-9,2.583783818280997e-9,2.8050446803085056e-8,3.6925000493001625e-8,f2.ptu +113,90,125,257,0,96.64444444444445,104.224,1128.5097276264592,,1023628261.6991526,1023611146,1023646757,0.5813953488372093,0.4555084745762712,472,51.181413084957626,0.0017805499999999999,2.416111143369654e-9,2.605600034788491e-9,2.8212743567342e-8,,f2.ptu +114,51,65,155,0,96.19607843137256,125.13846153846154,1133.1741935483872,,1034263344.7675277,1034252787,1034273189,0.5603448275862069,0.4280442804428044,271,51.713167238376386,0.0010201,2.404901992893199e-9,3.12846158023098e-9,2.8329355216947133e-8,,f2.ptu +115,65,85,182,0,101.3076923076923,127.62352941176471,1133.989010989011,,1034290131.2409638,1034278420,1034301343,0.5666666666666667,0.45180722891566266,332,51.714506562048186,0.0011461499999999999,2.5326923415073766e-9,3.1905882778930395e-9,2.83497256532347e-8,,f2.ptu +116,5,41,49,0,79.4,133.78048780487805,1154.0,,1038086940.3473685,1038081595,1038091783,0.8913043478260869,0.4842105263157895,95,51.90434701736842,0.0005094,1.9850000265025927e-9,3.344512239775978e-9,2.8850000385188812e-8,,f2.ptu +117,27,41,58,0,94.48148148148148,137.8780487804878,1157.2758620689656,,1039076643.1984127,1039070602,1039081002,0.6029411764705882,0.5396825396825397,126,51.95383215992063,0.00052,2.3620370685736137e-9,3.44695126553393e-9,2.8931896938006387e-8,,f2.ptu +118,11,55,70,0,103.9090909090909,182.1818181818182,1169.2142857142858,,1039301895.6911764,1039297079,1039307293,0.8333333333333334,0.4852941176470588,136,51.965094784558815,0.0005107,2.5977273074106514e-9,4.554545515355159e-9,2.923035753312427e-8,,f2.ptu +119,1,0,2,0,90.0,,1223.5,,1055110857.0,1055110740,1055111031,0.0,0.3333333333333333,3,52.75554285,0.00001455,2.250000030040722e-9,,3.0587500408386925e-8,,f2.ptu +120,115,199,331,0,97.64347826086957,139.20100502512562,1155.7583081570997,,1057514914.6682171,1057496567,1057531510,0.6337579617834395,0.4868217054263566,645,52.87574573341085,0.0017471499999999998,2.441086989113746e-9,3.4800251720914594e-9,2.88939580897032e-8,,f2.ptu +121,32,74,114,0,95.84375,173.36486486486487,1160.3070175438597,,1057550269.3227273,1057543535,1057556376,0.6981132075471698,0.4818181818181818,220,52.877513466136364,0.00064205,2.3960937819912827e-9,4.334121679488352e-9,2.90076758258905e-8,,f2.ptu +122,19,52,72,0,96.10526315789474,136.1153846153846,1150.111111111111,,1058871394.4755244,1058866131,1058875972,0.7323943661971831,0.4965034965034965,143,52.94356972377622,0.00049205,2.4026316110259405e-9,3.402884660817998e-9,2.8752778161668535e-8,,f2.ptu +123,107,25,180,0,145.17757009345794,132.2,1134.0388888888888,,1093187565.5416667,1093178626,1093195733,0.1893939393939394,0.4230769230769231,312,54.659378277083334,0.00085535,3.62943930079466e-9,3.3050000441264825e-9,2.8350972600748295e-8,,f2.ptu +124,22,34,56,0,95.5,109.08823529411765,1140.4107142857142,,1100084162.044643,1100079772,1100089250,0.6071428571428571,0.5,112,55.00420810223214,0.00047389999999999997,2.387500031876544e-9,2.727205918765045e-9,2.8510268237795756e-8,,f2.ptu +125,72,68,121,0,106.81944444444444,126.80882352941177,1129.3801652892562,,1100537042.0114942,1100528158,1100547825,0.4857142857142857,0.5363984674329502,261,55.02685210057471,0.00098335,2.6704861467659248e-9,3.170220630562279e-9,2.8234504509202464e-8,,f2.ptu +126,77,57,65,2,166.9090909090909,138.17543859649123,1154.753846153846,1010.0,1101814701.164179,1101809748,1101820416,0.4253731343283582,0.6733668341708543,201,55.09073505820895,0.0005334,4.172727328439157e-9,3.45438601103328e-9,2.8868846539286587e-8,2.5250000337123657e-8,f2.ptu +127,45,48,63,0,100.68888888888888,115.14583333333333,1141.4603174603174,,1104930979.0576923,1104924262,1104937861,0.5161290322580645,0.5961538461538461,156,55.24654895288461,0.00067995,2.5172222558307432e-9,2.878645871767377e-9,2.853650831751118e-8,,f2.ptu +128,81,104,194,2,213.60493827160494,162.03846153846155,1141.381443298969,1316.0,1111585043.656168,1111568155,1111601219,0.5621621621621622,0.48812664907651715,381,55.579252182808396,0.0016531999999999999,5.340123528088418e-9,4.050961592547676e-9,2.8534536463451144e-8,3.290000043926211e-8,f2.ptu +129,59,39,112,0,95.03389830508475,143.10256410256412,1162.9375,,1115910647.1047618,1115901385,1115918756,0.3979591836734694,0.4666666666666667,210,55.79553235523809,0.0008685499999999999,2.3758474893480845e-9,3.5775641503297066e-9,2.9073437888172023e-8,,f2.ptu +130,49,37,105,0,94.59183673469387,138.72972972972974,1155.1619047619047,,1115936297.539267,1115928322,1115944842,0.43023255813953487,0.450261780104712,191,55.79681487696335,0.0008259999999999999,2.3647959499407585e-9,3.4682432895492573e-9,2.8879048004624256e-8,,f2.ptu +131,26,36,56,0,95.46153846153847,147.63888888888889,1153.0357142857142,,1119279102.2881355,1119273819,1119284344,0.5806451612903226,0.5254237288135594,118,55.96395511440677,0.00052625,2.3865384934021674e-9,3.690972271501987e-9,2.8825893242009802e-8,,f2.ptu +132,53,7,49,0,124.15094339622641,85.85714285714286,1152.3061224489795,,1125840704.5779817,1125836703,1125846055,0.11666666666666667,0.5504587155963303,109,56.29203522889908,0.0004676,3.103773626345482e-9,2.1464286000864664e-9,2.880765344584791e-8,,f2.ptu +133,11,28,55,0,90.18181818181819,137.0,1135.3818181818183,,1128104925.7978723,1128100248,1128109347,0.717948717948718,0.4148936170212766,94,56.40524628989361,0.00045494999999999997,2.254545484646865e-9,3.4250000457286545e-9,2.8384545833519784e-8,,f2.ptu +134,32,43,71,0,110.0625,123.0,1145.9014084507041,,1128126618.739726,1128121565,1128131038,0.5733333333333334,0.5136986301369864,146,56.4063309369863,0.00047365,2.7515625367372995e-9,3.0750000410556533e-9,2.8647535593753222e-8,,f2.ptu +135,19,33,110,0,118.57894736842105,153.63636363636363,1143.7181818181818,,1130477192.8888888,1130472275,1130480698,0.6346153846153846,0.32098765432098764,162,56.52385964444444,0.00042114999999999996,2.964473723790495e-9,3.840909142190727e-9,2.8592954927211434e-8,,f2.ptu +136,33,49,61,0,118.24242424242425,132.16326530612244,1132.7540983606557,,1140966036.160839,1140959455,1140972821,0.5975609756097561,0.5734265734265734,143,57.04830180804195,0.0006682999999999999,2.9560606455282484e-9,3.3040816767672823e-9,2.8318852837113625e-8,,f2.ptu +137,40,53,128,1,97.425,121.75471698113208,1131.5859375,1896.0,1142486087.373874,1142478648,1142493389,0.5698924731182796,0.42081447963800905,222,57.12430436869369,0.0007370499999999999,2.4356250325190816e-9,3.0438679651682974e-9,2.8289648815207316e-8,4.7400000632857875e-8,f2.ptu +138,36,42,72,0,100.63888888888889,121.76190476190476,1148.763888888889,,1144769065.18,1144763666,1144773988,0.5384615384615384,0.52,150,57.238453259,0.0005161,2.5159722558140543e-9,3.0440476596900136e-9,2.8719097605663294e-8,,f2.ptu +139,32,41,83,0,96.75,131.4878048780488,1129.6746987951808,,1144862014.7628205,1144855099,1144869304,0.5616438356164384,0.46794871794871795,156,57.243100738141024,0.0007102499999999999,2.418750032293776e-9,3.287195165839982e-9,2.8241867846948892e-8,,f2.ptu +140,65,45,111,1,95.56923076923077,105.0,1134.1711711711712,1098.0,1148394574.4684684,1148386651,1148402499,0.4090909090909091,0.497737556561086,222,57.41972872342342,0.0007924,2.389230801130421e-9,2.625000035047509e-9,2.835427965784951e-8,2.7450000366496807e-8,f2.ptu +141,27,31,58,0,110.5925925925926,142.74193548387098,1152.7068965517242,,1155292369.560345,1155288506,1155296703,0.5344827586206896,0.5,116,57.76461847801725,0.00040984999999999996,2.764814851729052e-9,3.5685484347420055e-9,2.88176727985503e-8,,f2.ptu +142,22,41,82,0,120.0,135.58536585365854,1130.5853658536585,,1156636678.2827587,1156630438,1156641101,0.6507936507936508,0.43448275862068964,145,57.83183391413793,0.0005331499999999999,3.000000040054296e-9,3.3896341915979333e-9,2.82646345237148e-8,,f2.ptu +143,30,41,105,1,93.93333333333334,109.14634146341463,1138.7904761904763,1105.0,1165333530.559322,1165327143,1165340470,0.5774647887323944,0.4034090909090909,177,58.266676527966105,0.00066635,2.348333364686946e-9,2.7286585730168646e-9,2.8469762284873995e-8,2.7625000368833308e-8,f2.ptu +144,31,59,98,0,106.35483870967742,151.5084745762712,1150.9591836734694,,1183145504.1010637,1183138962,1183152417,0.6555555555555556,0.4787234042553192,188,59.15727520505318,0.00067275,2.65887100324167e-9,3.787711914978157e-9,2.8773979976010565e-8,,f2.ptu +145,34,36,60,0,99.23529411764706,109.47222222222223,1123.35,,1183180121.3307693,1183175477,1183184472,0.5142857142857142,0.5384615384615384,130,59.15900606653846,0.00044974999999999995,2.4808823860645082e-9,2.736805592095829e-9,2.8083750374958277e-8,,f2.ptu +146,44,24,105,0,123.63636363636364,135.5,1159.7047619047619,,1197613772.50289,1197607524,1197621063,0.35294117647058826,0.3930635838150289,173,59.8806886251445,0.00067695,3.0909091321771535e-9,3.3875000452279758e-9,2.8992619434712027e-8,,f2.ptu +147,62,11,64,1,138.5,104.0909090909091,1133.265625,1103.0,1197630572.2536232,1197623677,1197636344,0.1506849315068493,0.5328467153284672,138,59.88152861268116,0.00063335,3.462500046229333e-9,2.602272762016795e-9,2.8331641003267972e-8,2.7575000368165736e-8,f2.ptu +0,26,48,80,1,106.8076923076923,155.22916666666666,1152.0625,1812.0,3901977.5548387095,3895697,3908923,0.6486486486486487,0.4805194805194805,155,0.19509887774193546,0.0006613,2.6701923433431984e-9,3.8807292184799575e-9,2.8801562884542102e-8,4.530000060481987e-8,f3.ptu +1,16,36,42,0,101.375,125.27777777777777,1153.7380952380952,,6286286.94680851,6283304,6290977,0.6923076923076923,0.5531914893617021,94,0.3143143473404255,0.00038365,2.5343750338375354e-9,3.1319444862603874e-9,2.8843452766053773e-8,,f3.ptu +2,17,34,70,0,97.17647058823529,130.08823529411765,1144.2571428571428,,11398790.14876033,11393872,11403283,0.6666666666666666,0.4214876033057851,121,0.5699395074380165,0.00047054999999999997,2.4294117971420082e-9,3.252205925774547e-9,2.8606428953365353e-8,,f3.ptu +3,21,42,41,0,114.38095238095238,159.35714285714286,1162.7560975609756,,33803256.54807692,33799677,33807537,0.6666666666666666,0.6057692307692307,104,1.6901628274038458,0.00039299999999999996,2.8595238477025473e-9,3.983928624619723e-9,2.9068902827135864e-8,,f3.ptu +4,11,1,6,0,133.27272727272728,86.0,1160.0,,37005964.833333336,37004761,37007008,0.08333333333333333,0.6666666666666666,18,1.8502982416666667,0.00011235,3.331818226302726e-9,2.1500000287055787e-9,2.9000000387191527e-8,,f3.ptu +5,43,44,110,0,113.72093023255815,135.02272727272728,1136.7181818181818,,51235429.654822335,51228165,51244585,0.5057471264367817,0.4416243654822335,197,2.5617714827411167,0.000821,2.8430232937723853e-9,3.375568226886851e-9,2.8417954924874933e-8,,f3.ptu +6,13,45,82,0,96.23076923076923,120.42222222222222,1138.1951219512196,,53981512.942857146,53975989,53987790,0.7758620689655172,0.4142857142857143,140,2.699075647142857,0.00059005,2.4057692628896947e-9,3.010555595750783e-9,2.8454878428693856e-8,,f3.ptu +7,10,78,109,0,106.0,139.12820512820514,1156.5412844036698,,54027024.50761421,54020484,54034570,0.8863636363636364,0.4467005076142132,197,2.7013512253807104,0.0007042999999999999,2.6500000353812947e-9,3.4782051746441476e-9,2.8913532496128803e-8,,f3.ptu +8,46,60,78,0,102.71739130434783,159.61666666666667,1160.128205128205,,61706820.152173914,61699364,61714175,0.5660377358490566,0.5760869565217391,184,3.0853410076086956,0.00074055,2.5679348168943022e-9,3.990416719944443e-9,2.9003205515439448e-8,,f3.ptu +9,95,145,233,0,101.08421052631579,146.4344827586207,1148.0643776824033,,61780056.60042283,61766110,61790592,0.6041666666666666,0.507399577167019,473,3.0890028300211414,0.0012240999999999999,2.5271052968983685e-9,3.6608621178432685e-9,2.870160982526767e-8,,f3.ptu +10,33,25,74,0,128.63636363636363,138.36,1120.7432432432433,,64689124.50757576,64683822,64695270,0.43103448275862066,0.4393939393939394,132,3.234456225378788,0.0005723999999999999,3.215909133846082e-9,3.4590000461826034e-9,2.801858145516926e-8,,f3.ptu +11,36,30,88,1,103.27777777777777,144.53333333333333,1158.9545454545455,1246.0,69611543.93548387,69606383,69616962,0.45454545454545453,0.42857142857142855,155,3.4805771967741936,0.0005289499999999999,2.5819444789170998e-9,3.6133333815765075e-9,2.8973864023206206e-8,3.1150000415897106e-8,f3.ptu +12,13,4,7,0,137.30769230769232,78.5,1180.7142857142858,,73314241.625,73313426,73314830,0.23529411764705882,0.7083333333333334,24,3.6657120812499997,0.0000702,3.4326923535236657e-9,1.9625000262021852e-9,2.9517857536962806e-8,,f3.ptu +13,42,90,107,0,122.80952380952381,133.6,1134.943925233645,,74087557.54393305,74080618,74092439,0.6818181818181818,0.5523012552301255,239,3.7043778771966522,0.00059105,3.07023813623017e-9,3.3400000445937825e-9,2.8373598509669287e-8,,f3.ptu +14,6,57,53,0,93.16666666666667,135.47368421052633,1165.433962264151,,75198294.51724137,75194772,75201969,0.9047619047619048,0.5431034482758621,116,3.7599147258620684,0.00035985,2.3291666977643772e-9,3.3868421504823502e-9,2.913584944560908e-8,,f3.ptu +15,11,26,51,0,99.0,101.96153846153847,1129.549019607843,,77304395.35227273,77299489,77308014,0.7027027027027027,0.42045454545454547,88,3.8652197676136364,0.00042625,2.475000033044794e-9,2.549038495571775e-9,2.82387258672235e-8,,f3.ptu +16,3,60,53,0,92.33333333333333,123.01666666666667,1160.377358490566,,107841792.71551724,107837415,107846790,0.9523809523809523,0.5431034482758621,116,5.392089635775862,0.00046875,2.3083333641528885e-9,3.075416707727883e-9,2.9009434349581632e-8,,f3.ptu +17,11,56,89,0,113.63636363636364,160.14285714285714,1198.0898876404494,,109646683.67307693,109641314,109651197,0.835820895522388,0.42948717948717946,156,5.482334183653846,0.00049415,2.8409091288392955e-9,4.00357148202484e-9,2.9952247590916626e-8,,f3.ptu +18,64,88,152,0,104.90625,112.07954545454545,1121.592105263158,,109675313.60197368,109664816,109687323,0.5789473684210527,0.5,304,5.483765680098684,0.00112535,2.6226562850162165e-9,2.801988673774197e-9,2.8039803005950464e-8,,f3.ptu +19,21,35,65,1,106.85714285714286,137.65714285714284,1141.6615384615384,1240.0,126754768.6147541,126749108,126760530,0.625,0.4628099173553719,122,6.337738430737705,0.0005711,2.671428607095968e-9,3.4414286173765705e-9,2.8541538842608868e-8,3.100000041389439e-8,f3.ptu +20,26,70,102,0,109.76923076923077,150.1,1153.2941176470588,,126773132.95454545,126766281,126781029,0.7291666666666666,0.48484848484848486,198,6.338656647727272,0.0007373999999999999,2.74423080587018e-9,3.752500050101249e-9,2.8832353326129668e-8,,f3.ptu +21,42,27,72,0,123.33333333333333,123.85185185185185,1129.013888888889,,129436049.36170213,129430712,129440129,0.391304347826087,0.48936170212765956,141,6.471802468085106,0.00047085,3.0833333745002483e-9,3.0962963376362855e-9,2.8225347599071024e-8,,f3.ptu +22,23,56,69,0,121.34782608695652,136.71428571428572,1157.304347826087,,141176797.1081081,141171483,141181315,0.7088607594936709,0.5337837837837838,148,7.058839855405405,0.0004916,3.033695692678094e-9,3.4178571884904302e-9,2.8932609081943932e-8,,f3.ptu +23,49,148,170,0,105.10204081632654,133.61486486486487,1139.7235294117647,,144226905.22343326,144211088,144242810,0.751269035532995,0.5367847411444142,367,7.211345261171663,0.0015861,2.6275510554897322e-9,3.340371666220366e-9,2.8493088615717647e-8,,f3.ptu +24,24,108,166,1,117.83333333333333,153.62037037037038,1156.4638554216867,1505.0,146405226.31772575,146392394,146417793,0.8181818181818182,0.4429530201342282,299,7.320261315886287,0.00126995,2.9458333726644264e-9,3.840509310535557e-9,2.891159677155338e-8,3.762500050234763e-8,f3.ptu +25,21,52,53,0,106.9047619047619,121.78846153846153,1156.9245283018868,,158867217.44444445,158861766,158872448,0.7123287671232876,0.5793650793650794,126,7.943360872222222,0.0005341,2.672619083302339e-9,3.0447115791127974e-9,2.8923113593712147e-8,,f3.ptu +26,23,5,24,0,110.26086956521739,166.0,1130.0833333333333,,166296488.40384614,166294488,166298515,0.17857142857142858,0.5384615384615384,52,8.314824420192307,0.00020135,2.7565217759339474e-9,4.150000055408443e-9,2.82520837105391e-8,,f3.ptu +27,16,27,34,0,98.5,126.55555555555556,1124.0294117647059,,167855298.79220778,167852132,167858426,0.627906976744186,0.5584415584415584,77,8.39276493961039,0.0003147,2.462500032877901e-9,3.163888931131336e-9,2.81007356693027e-8,,f3.ptu +28,15,36,47,0,94.53333333333333,119.72222222222223,1134.4468085106382,,168435612.91836736,168430916,168439242,0.7058823529411765,0.5204081632653061,98,8.421780645918368,0.0004163,2.3633333648872176e-9,2.9930555955171334e-9,2.836117059142819e-8,,f3.ptu +29,57,121,208,0,101.2280701754386,147.8512396694215,1159.4663461538462,,169622885.1761658,169609410,169636139,0.6797752808988764,0.46113989637305697,386,8.481144258808289,0.0013364499999999999,2.5307017881744573e-9,3.6962810410861813e-9,2.8986659040859556e-8,,f3.ptu +30,16,34,65,0,100.625,123.76470588235294,1140.6307692307691,,185596721.66956523,185590975,185602985,0.68,0.43478260869565216,115,9.27983608347826,0.0006005,2.515625033587196e-9,3.094117688369725e-9,2.8515769611495582e-8,,f3.ptu +31,9,64,60,0,108.55555555555556,140.03125,1165.9833333333333,,186009718.0451128,186003606,186016285,0.8767123287671232,0.5488721804511278,133,9.30048590225564,0.00063395,2.7138889251231917e-9,3.5007812967404427e-9,2.914958372252201e-8,,f3.ptu +32,40,21,128,0,133.4,115.42857142857143,1140.9765625,,193093704.66137567,193088156,193098287,0.3442622950819672,0.32275132275132273,189,9.654685233068783,0.0005065499999999999,3.335000044527026e-9,2.885714324242704e-9,2.8524414443341774e-8,,f3.ptu +33,75,84,205,1,118.08,145.42857142857142,1139.1365853658538,1208.0,201771631.43835616,201763015,201780023,0.5283018867924528,0.4368131868131868,365,10.088581571917807,0.0008504,2.952000039413427e-9,3.6357143342562774e-9,2.847841501437396e-8,3.0200000403213245e-8,f3.ptu +34,86,147,194,0,101.5,141.4625850340136,1145.7474226804125,,202615182.58313817,202597249,202633909,0.630901287553648,0.5456674473067916,427,10.130759129156909,0.001833,2.5375000338792586e-9,3.5365646730685422e-9,2.864368594944453e-8,,f3.ptu +35,47,5,52,0,133.89361702127658,77.8,1135.1346153846155,,205987459.57692307,205983126,205991462,0.09615384615384616,0.5,104,10.299372978846153,0.0004168,3.3473404702237027e-9,1.9450000259685352e-9,2.8378365763507202e-8,,f3.ptu +36,23,32,68,0,100.21739130434783,158.6875,1161.2058823529412,,209476034.21138212,209471052,209480220,0.5818181818181818,0.44715447154471544,123,10.473801710569106,0.0004584,2.5054348160598377e-9,3.967187552967634e-9,2.9030147446417564e-8,,f3.ptu +37,102,107,242,0,184.91176470588235,135.65420560747663,1163.6322314049587,,209778047.54767185,209759617,209795023,0.5119617224880383,0.4634146341463415,451,10.488902377383592,0.0017702999999999998,4.62279417936798e-9,3.391355185466363e-9,2.909080617352788e-8,,f3.ptu +38,13,38,59,0,91.76923076923077,145.21052631578948,1125.542372881356,,209990274.13636363,209985651,209994037,0.7450980392156863,0.4636363636363636,110,10.499513706818181,0.0004193,2.2942307998620355e-9,3.6302632063639484e-9,2.8138559697723958e-8,,f3.ptu +39,5,91,67,0,83.0,181.6153846153846,1157.7313432835822,,224927506.7361963,224921325,224933783,0.9479166666666666,0.588957055214724,163,11.246375336809814,0.0006229,2.0750000277042213e-9,4.540384676005251e-9,2.8943283968523836e-8,,f3.ptu +40,87,14,79,0,134.4712643678161,114.57142857142857,1151.73417721519,,227757625.41666666,227748596,227765415,0.13861386138613863,0.5611111111111111,180,11.387881270833333,0.0008409499999999999,3.361781654080001e-9,2.86428575252803e-9,2.879335481481226e-8,,f3.ptu +41,31,6,30,0,163.90322580645162,257.0,1146.0666666666666,,227777741.53731343,227774260,227779926,0.16216216216216217,0.5522388059701493,67,11.388887076865672,0.0002833,4.09758069986986e-9,6.42500008578295e-9,2.8651667049207443e-8,,f3.ptu +42,4,57,100,0,94.75,125.6842105263158,1178.36,,234194242.47826087,234187571,234202504,0.9344262295081968,0.37888198757763975,161,11.709712123913043,0.00074665,2.3687500316262045e-9,3.1421053051094994e-9,2.945900039331983e-8,,f3.ptu +43,31,40,115,0,103.38709677419355,150.85,1151.713043478261,,238663097.86021507,238656411,238668545,0.5633802816901409,0.3817204301075269,186,11.933154893010753,0.0006067,2.5846774538639834e-9,3.771250050351588e-9,2.879282647138198e-8,,f3.ptu +44,109,74,126,0,137.9908256880734,153.13513513513513,1152.468253968254,,246172255.77346277,246158180,246184303,0.40437158469945356,0.5922330097087378,309,12.308612788673138,0.0013061499999999998,3.4497706882612127e-9,3.8283784294927114e-9,2.8811706733883886e-8,,f3.ptu +45,46,89,154,0,104.32608695652173,151.02247191011236,1158.1623376623377,,246625232.16262975,246613752,246636150,0.6592592592592592,0.4671280276816609,289,12.331261608131488,0.0011198999999999998,2.60815220873561e-9,3.775561848161965e-9,2.8954058828136583e-8,,f3.ptu +46,23,36,81,0,107.1304347826087,125.36111111111111,1155.0987654320988,,263159114.68571427,263154177,263162071,0.6101694915254238,0.42142857142857143,140,13.157955734285713,0.0003947,2.6782609053238354e-9,3.1340278196215363e-9,2.8877469521358035e-8,,f3.ptu +47,26,62,119,0,115.65384615384616,135.5483870967742,1133.4117647058824,,268423510.29951692,268416196,268431125,0.7045454545454546,0.4251207729468599,207,13.421175514975845,0.00074645,2.8913461924497654e-9,3.388709722663482e-9,2.8335294495963813e-8,,f3.ptu +48,69,13,52,0,166.63768115942028,138.0,1149.4423076923076,,270656759.3507463,270651740,270661277,0.15853658536585366,0.6119402985074627,134,13.532837967537313,0.00047684999999999996,4.165942084606799e-9,3.4500000460624403e-9,2.873605807597521e-8,,f3.ptu +49,4,1,3,0,273.0,75.0,1128.6666666666667,,271172300.375,271172148,271172395,0.2,0.625,8,13.558615018749999,0.000012349999999999999,6.825000091123523e-9,1.875000025033935e-9,2.8216667043399573e-8,,f3.ptu +50,83,14,67,0,127.21686746987952,104.64285714285714,1129.8059701492537,,278789779.9756098,278783613,278794776,0.14432989690721648,0.5914634146341463,164,13.939488998780488,0.00055815,3.1804217292101717e-9,2.6160714634997283e-9,2.824514963084453e-8,,f3.ptu +51,30,2,43,0,133.3,99.5,1157.093023255814,,293058162.2133333,293054808,293061050,0.0625,0.4266666666666667,75,14.652908110666665,0.0003121,3.332500044493647e-9,2.487500033211687e-9,2.8927325967616567e-8,,f3.ptu +52,61,6,60,0,148.1639344262295,108.33333333333333,1152.55,,296473495.511811,296468562,296480290,0.08955223880597014,0.5275590551181102,127,14.82367477559055,0.0005863999999999999,3.7040984101107547e-9,2.7083333694934613e-9,2.881375038470482e-8,,f3.ptu +53,16,62,86,0,105.0625,146.90322580645162,1138.8139534883721,,318802038.63414633,318796949,318807490,0.7948717948717948,0.47560975609756095,164,15.940101931707316,0.0005270499999999999,2.6265625350683705e-9,3.672580694195501e-9,2.847034921732923e-8,,f3.ptu +54,3,2,8,0,83.33333333333333,242.5,1125.875,,328736686.15384614,328735422,328737664,0.4,0.38461538461538464,13,16.43683430769231,0.0001121,2.0833333611488163e-9,6.062500080943056e-9,2.8146875375801086e-8,,f3.ptu +55,62,29,94,0,132.69354838709677,118.10344827586206,1159.9148936170213,,328745906.03783786,328740093,328751660,0.31868131868131866,0.4918918918918919,185,16.437295301891893,0.0005783499999999999,3.3173387539686414e-9,2.9525862463178056e-9,2.8997872727588654e-8,,f3.ptu +56,18,17,43,0,104.38888888888889,127.23529411764706,1131.4186046511627,,337088438.5641026,337085294,337091088,0.4857142857142857,0.44871794871794873,78,16.854421928205127,0.0002897,2.609722257065751e-9,3.1808823954105106e-9,2.8285465493930532e-8,,f3.ptu +57,58,87,141,0,107.8103448275862,124.94252873563218,1140.6241134751774,,337537643.0979021,337527256,337548909,0.6,0.506993006993007,286,16.876882154895107,0.0010826499999999999,2.6952586566752173e-9,3.123563260094846e-9,2.8515603217603566e-8,,f3.ptu +58,11,81,190,0,87.0,150.45679012345678,1159.0631578947368,,344128524.858156,344120363,344135467,0.8804347826086957,0.3262411347517731,282,17.2064262429078,0.0007551999999999999,2.1750000290393645e-9,3.761419803306759e-9,2.8976579334247245e-8,,f3.ptu +59,10,67,99,0,80.3,135.47761194029852,1152.909090909091,,344147659.65340906,344142301,344154902,0.8701298701298701,0.4375,176,17.207382982670453,0.00063005,2.0075000268029997e-9,3.386940343727966e-9,2.8822727657551957e-8,,f3.ptu +60,22,96,75,0,103.27272727272727,150.60416666666666,1160.12,,344935367.48704666,344929644,344942164,0.8135593220338984,0.6113989637305699,193,17.24676837435233,0.0006259999999999999,2.5818182162891516e-9,3.765104216936198e-9,2.900300038723158e-8,,f3.ptu +61,26,30,60,0,99.42307692307692,121.06666666666666,1133.25,,351962347.88793105,351958244,351965967,0.5357142857142857,0.4827586206896552,116,17.598117394396553,0.00038615,2.485576956262934e-9,3.026666707077001e-9,2.8331250378262757e-8,,f3.ptu +62,27,18,41,0,184.03703703703704,156.77777777777777,1130.439024390244,,360733998.9186047,360730915,360737410,0.4,0.5232558139534884,86,18.036699945930234,0.00032475,4.600925987354876e-9,3.9194444967746404e-9,2.8260975987080593e-8,,f3.ptu +63,47,34,75,0,138.3404255319149,146.5,1144.12,,365265124.6217949,365259307,365269009,0.41975308641975306,0.5192307692307693,156,18.263256231089745,0.0004851,3.4585106844739416e-9,3.6625000488996196e-9,2.8603000381891006e-8,,f3.ptu +64,95,12,54,0,154.7157894736842,84.33333333333333,1199.1666666666667,,369488636.45341617,369483634,369493248,0.11214953271028037,0.6645962732919255,161,18.47443182267081,0.0004807,3.8678947884840385e-9,2.108333361482602e-9,2.9979167066931475e-8,,f3.ptu +65,70,21,155,1,134.75714285714287,126.0,1138.5290322580645,1137.0,371637696.44534415,371629228,371646713,0.23076923076923078,0.3699186991869919,247,18.581884822267206,0.0008742499999999999,3.3689286164085922e-9,3.1500000420570107e-9,2.8463226186476435e-8,2.8425000379514453e-8,f3.ptu +66,40,5,52,0,119.625,124.8,1130.3461538461538,,371655845.30927837,371650939,371660776,0.1111111111111111,0.4639175257731959,97,18.58279226546392,0.00049185,2.990625039929126e-9,3.120000041656468e-9,2.825865422344734e-8,,f3.ptu +67,65,14,125,0,123.76923076923077,111.35714285714286,1154.808,,383727875.627451,383721478,383732534,0.17721518987341772,0.3872549019607843,204,19.186393781372548,0.0005528,3.094230810543181e-9,2.7839286085980043e-9,2.887020038545851e-8,,f3.ptu +68,53,4,74,0,231.58490566037736,160.0,1141.6216216216217,,391704158.57251906,391699644,391708854,0.07017543859649122,0.4351145038167939,131,19.58520792862595,0.00046049999999999997,5.789622718809187e-9,4.000000053405728e-9,2.8540540921597628e-8,,f3.ptu +69,68,60,115,1,113.8529411764706,138.81666666666666,1150.1652173913044,1138.0,394361205.27868855,394353202,394369352,0.46875,0.5267489711934157,244,19.718060263934426,0.0008075,2.8463235674142596e-9,3.4704167130016988e-9,2.8754130818691426e-8,2.845000037984824e-8,f3.ptu +70,4,45,57,0,101.0,177.24444444444444,1157.6666666666667,,394705383.7169811,394701265,394708782,0.9183673469387755,0.46226415094339623,106,19.735269185849056,0.00037585,2.5250000337123657e-9,4.43111117027279e-9,2.894166705307936e-8,,f3.ptu +71,50,49,74,0,104.1,149.26530612244898,1157.8783783783783,,402373383.36416185,402366758,402379768,0.494949494949495,0.5722543352601156,173,20.11866916820809,0.0006504999999999999,2.6025000347471014e-9,3.731632702883864e-9,2.8946959845942817e-8,,f3.ptu +72,82,18,133,0,128.85365853658536,157.11111111111111,1140.6917293233082,,403130138.24892706,403122906,403137951,0.18,0.4291845493562232,233,20.156506912446353,0.00075225,3.221341506424155e-9,3.9277778302192354e-9,2.8517293613829405e-8,,f3.ptu +73,20,132,141,0,89.1,162.47727272727272,1165.723404255319,,425442248.8668942,425431657,425452681,0.868421052631579,0.5187713310580204,293,21.272112443344707,0.0010512,2.2275000297403144e-9,4.061931872414424e-9,2.9143085495484895e-8,,f3.ptu +74,16,43,78,0,100.5625,142.13953488372093,1156.8076923076924,,427214876.77372265,427209404,427219925,0.7288135593220338,0.4306569343065693,137,21.36074383868613,0.00052605,2.5140625335663344e-9,3.5534884195371816e-9,2.8920192693818288e-8,,f3.ptu +75,32,114,106,0,109.28125,135.21052631578948,1149.688679245283,,438328319.8095238,438319468,438335539,0.7808219178082192,0.5793650793650794,252,21.91641599047619,0.00080355,2.7320312864765293e-9,3.3802632030260904e-9,2.8742217364881832e-8,,f3.ptu +76,43,75,101,0,122.23255813953489,152.16,1158.881188118812,,446347749.4703196,446340217,446354875,0.635593220338983,0.5388127853881278,219,22.317387473515982,0.0007329,3.0558139942878642e-9,3.804000050788847e-9,2.897203008978838e-8,,f3.ptu +77,9,44,55,0,123.44444444444444,154.45454545454547,1149.9818181818182,,461070237.9814815,461066363,461073516,0.8301886792452831,0.49074074074074076,108,23.053511899074074,0.00035765,3.0861111523151137e-9,3.86136368791837e-9,2.8749545838393056e-8,,f3.ptu +78,113,78,181,0,128.0353982300885,114.24358974358974,1128.475138121547,,479178767.44623655,479166888,479191499,0.4083769633507853,0.5134408602150538,372,23.958938372311827,0.00123055,3.2008849984886105e-9,2.8560897817226314e-9,2.8211878829707648e-8,,f3.ptu +79,28,173,128,0,97.67857142857143,156.15606936416185,1176.328125,,483872408.1945289,483863293,483882461,0.8606965174129353,0.6109422492401215,329,24.193620409726442,0.0009584,2.441964318318006e-9,3.903901786226725e-9,2.9408203517641623e-8,,f3.ptu +80,30,66,84,0,118.3,152.62121212121212,1150.857142857143,,485058393.26111114,485051183,485065385,0.6875,0.5333333333333333,180,24.252919663055557,0.0007101,2.95750003948686e-9,3.815530353973097e-9,2.8771428955568342e-8,,f3.ptu +81,35,53,89,0,96.42857142857143,142.41509433962264,1142.6966292134832,,487154457.2542373,487147782,487159638,0.6022727272727273,0.4971751412429379,177,24.357722862711864,0.0005928,2.4107143179007737e-9,3.560377406026702e-9,2.8567416111752988e-8,,f3.ptu +82,1,55,63,0,73.0,138.65454545454546,1157.2539682539682,,488280364.8739496,488276237,488285825,0.9821428571428571,0.47058823529411764,119,24.414018243697477,0.0004794,1.8250000243663633e-9,3.4663636826445546e-9,2.8931349592624145e-8,,f3.ptu +83,55,93,127,0,95.32727272727273,122.0,1123.6377952755906,,490932251.7709091,490922602,490940938,0.6283783783783784,0.5381818181818182,275,24.546612588545454,0.0009168,2.3831818500007083e-9,3.0500000407218675e-9,2.8090945256944105e-8,,f3.ptu +84,32,58,101,0,106.1875,125.13793103448276,1132.6831683168316,,490991287.87434554,490983946,490999378,0.6444444444444445,0.4712041884816754,191,24.549564393717276,0.0007716,2.6546875354438795e-9,3.1284483176313334e-9,2.8317079585994347e-8,,f3.ptu +85,105,90,278,1,99.65714285714286,135.86666666666667,1159.1870503597122,1105.0,516908498.9177215,516891777,516924597,0.46153846153846156,0.41226215644820297,474,25.845424945886073,0.0016409999999999999,2.4914286046927105e-9,3.3966667120170308e-9,2.8979676645912982e-8,2.7625000368833308e-8,f3.ptu +86,38,55,79,0,109.21052631578948,151.83636363636364,1140.392405063291,,533692347.4244186,533688097,533699039,0.5913978494623656,0.5406976744186046,172,26.68461737122093,0.0005471,2.7302631943476596e-9,3.795909141589913e-9,2.8509810507229068e-8,,f3.ptu +87,35,42,98,0,93.8,116.04761904761905,1134.2857142857142,,540022155.6571429,540015010,540029029,0.5454545454545454,0.44,175,27.001107782857144,0.00070095,2.345000031309108e-9,2.9011905149255235e-9,2.8357143235751318e-8,,f3.ptu +88,19,64,95,0,105.63157894736842,115.140625,1136.178947368421,,540148105.6067415,540141010,540155467,0.7710843373493976,0.46629213483146065,178,27.007405280337075,0.0007228499999999999,2.6407895089425315e-9,2.8785156634323055e-9,2.840447406345092e-8,,f3.ptu +89,45,75,137,0,136.88888888888889,125.6,1140.2262773722628,,540275320.9688716,540266457,540284445,0.625,0.4669260700389105,257,27.01376604844358,0.0008994,3.4222222679137895e-9,3.140000041923496e-9,2.850565731489791e-8,,f3.ptu +90,62,99,118,0,95.62903225806451,157.04040404040404,1160.5084745762713,,567796610.8100358,567786234,567807160,0.6149068322981367,0.5770609318996416,279,28.38983054050179,0.0010463,2.3907258383712257e-9,3.926010153427958e-9,2.901271225176803e-8,,f3.ptu +91,61,56,122,0,97.45901639344262,114.71428571428571,1120.9098360655737,,572884441.6569037,572877376,572891683,0.47863247863247865,0.4895397489539749,239,28.644222082845186,0.00071535,2.436475442366501e-9,2.8678571811471423e-9,2.802274627578313e-8,,f3.ptu +92,32,29,69,0,99.125,142.44827586206895,1123.2463768115942,,573106839.6692308,573101834,573112059,0.47540983606557374,0.46923076923076923,130,28.65534198346154,0.00051125,2.4781250330865173e-9,3.5612069440989355e-9,2.8081159795213546e-8,,f3.ptu +93,20,33,72,0,92.5,105.36363636363636,1134.5694444444443,,579856754.544,579850925,579862366,0.6226415094339622,0.424,125,28.9928377272,0.0005720499999999999,2.3125000308751864e-9,2.6340909442597945e-9,2.8364236489814276e-8,,f3.ptu +94,0,1,1,0,,89.0,1121.0,,581674041.0,581674036,581674046,1.0,0.5,2,29.08370205,5e-7,,2.225000029706936e-9,2.802500037417388e-8,,f3.ptu +95,16,44,51,0,90.375,181.75,1155.921568627451,,594853744.7027028,594848722,594857500,0.7333333333333333,0.5405405405405406,111,29.742687235135136,0.0004389,2.2593750301658916e-9,4.543750060665569e-9,2.889803960151648e-8,,f3.ptu +96,26,54,89,0,122.11538461538461,152.1851851851852,1174.2921348314608,,597824957.5325444,597820030,597830613,0.675,0.47337278106508873,169,29.89124787662722,0.0005291499999999999,3.0528846561449967e-9,3.804629680426884e-9,2.9357303762748557e-8,,f3.ptu +97,2,3,4,0,138.5,73.33333333333333,1119.5,,619936745.4444444,619936584,619936953,0.6,0.5555555555555556,9,30.99683727222222,0.000018449999999999998,3.462500046229333e-9,1.8333333578109585e-9,2.7987500373673202e-8,,f3.ptu +98,66,60,164,0,96.0,148.01666666666668,1155.4573170731708,,621487760.2448276,621476057,621499241,0.47619047619047616,0.43448275862068964,290,31.07438801224138,0.0011592,2.4000000320434367e-9,3.7004167160725285e-9,2.8886433312504515e-8,,f3.ptu +99,36,34,64,0,96.22222222222223,134.23529411764707,1160.0,,621536092.0522388,621531393,621540836,0.4857142857142857,0.5223880597014925,134,31.07680460261194,0.00047214999999999996,2.405555587673167e-9,3.3558823977470116e-9,2.9000000387191527e-8,,f3.ptu +100,26,40,90,0,95.88461538461539,145.275,1147.7777777777778,,622468171.2307693,622461884,622473870,0.6060606060606061,0.4230769230769231,156,31.12340856153846,0.0005993,2.3971154166203075e-9,3.631875048490732e-9,2.869444482755637e-8,,f3.ptu +101,37,8,50,0,124.05405405405405,76.75,1128.02,,625689797.6526315,625686714,625692941,0.17777777777777778,0.47368421052631576,95,31.284489882631576,0.00031135,3.1013513927588327e-9,1.91875002561806e-9,2.8200500376517056e-8,,f3.ptu +102,117,14,63,0,164.991452991453,164.07142857142858,1188.6984126984128,,627782489.3298969,627775765,627789953,0.10687022900763359,0.6752577319587629,194,31.389124466494845,0.0007094,4.124786379858129e-9,4.101785769050427e-9,2.9717460714230968e-8,,f3.ptu +103,68,57,116,0,94.20588235294117,117.03508771929825,1130.8706896551723,,633764139.6514523,633756041,633772404,0.456,0.5186721991701245,241,31.688206982572613,0.0008181499999999999,2.355147090268115e-9,2.9258772320471063e-9,2.8271767618847885e-8,,f3.ptu +104,50,48,100,0,120.02,119.60416666666667,1141.85,,637563790.6414142,637555604,637572470,0.4897959183673469,0.494949494949495,198,31.878189532070706,0.0008433,3.0005000400609714e-9,2.9901042065888393e-9,2.8546250381133314e-8,,f3.ptu +105,42,31,56,0,96.66666666666667,98.58064516129032,1126.017857142857,,645885177.6744186,645880773,645890497,0.4246575342465753,0.5658914728682171,129,32.29425888372093,0.0004862,2.4166666989326275e-9,2.4645161619370774e-9,2.81504468044202e-8,,f3.ptu +106,41,55,101,0,111.48780487804878,109.61818181818182,1125.970297029703,,656678769.6649746,656670137,656686795,0.5729166666666666,0.4873096446700508,197,32.83393848324873,0.0008328999999999999,2.7871951591642655e-9,2.740454582043538e-9,2.814925780157547e-8,,f3.ptu +107,18,185,232,0,176.05555555555554,147.10270270270271,1156.0086206896551,,666976119.6367816,666961661,666991537,0.9113300492610837,0.4666666666666667,435,33.34880598183908,0.0014938,4.401388947653733e-9,3.677567616668361e-9,2.890021590310064e-8,,f3.ptu +108,7,78,78,1,87.28571428571429,143.43589743589743,1167.5384615384614,1109.0,667030187.1585366,667024573,667033457,0.9176470588235294,0.5214723926380368,164,33.35150935792683,0.00044419999999999996,2.182142886277589e-9,3.585897483774301e-9,2.9188461928169295e-8,2.772500037016845e-8,f3.ptu +109,38,28,53,0,107.5,186.39285714285714,1173.8867924528302,,695480517.0504202,695476757,695483860,0.42424242424242425,0.5546218487394958,119,34.77402585252101,0.00035515,2.6875000358819734e-9,4.659821490786717e-9,2.9347170203147494e-8,,f3.ptu +110,27,89,79,0,94.44444444444444,144.03370786516854,1148.493670886076,,696021777.1025641,696015688,696026735,0.7672413793103449,0.5948717948717949,195,34.80108885512821,0.00055235,2.3611111426353255e-9,3.6008427447056195e-9,2.8712342155502778e-8,,f3.ptu +111,28,26,44,0,100.0,97.11538461538461,1132.5681818181818,,709922986.6938776,709918332,709928192,0.48148148148148145,0.5510204081632653,98,35.496149334693875,0.000493,2.50000003337858e-9,2.4278846478003517e-9,2.8314204923489718e-8,,f3.ptu +112,38,57,87,0,101.76315789473684,151.1578947368421,1150.2988505747126,,727493796.8516483,727484537,727503105,0.6,0.521978021978022,182,36.37468984258241,0.0009283999999999999,2.544078981335518e-9,3.778947418875411e-9,2.8757471648321233e-8,,f3.ptu +113,35,72,91,1,92.22857142857143,142.41666666666666,1166.6703296703297,1772.0,727517877.3015076,727511814,727523926,0.6728971962616822,0.5404040404040404,199,36.375893865075376,0.0006056,2.305714316498873e-9,3.5604167142033274e-9,2.916675863117623e-8,4.4300000591468436e-8,f3.ptu +114,78,9,68,0,123.58974358974359,119.77777777777777,1126.514705882353,,748729997.8451613,748723781,748736712,0.10344827586206896,0.5612903225806452,155,37.43649989225806,0.00064655,3.0897436309960913e-9,2.9944444844245655e-9,2.8162868023073435e-8,,f3.ptu +115,13,102,136,0,86.84615384615384,149.2549019607843,1165.1985294117646,,797409925.7370518,797399510,797419658,0.8869565217391304,0.4581673306772908,251,39.87049628685259,0.0010073999999999999,2.171153875141859e-9,3.731372598838774e-9,2.912996362422084e-8,,f3.ptu +116,230,101,323,2,171.8304347826087,134.1089108910891,1145.4396284829722,1050.0,803014061.0762196,802994975,803033180,0.30513595166163143,0.5061162079510704,656,40.15070305381098,0.0019102499999999998,4.2957609269197765e-9,3.3527228170408773e-9,2.863599109440579e-8,2.625000035047509e-8,f3.ptu +117,103,122,270,2,98.85436893203884,111.94262295081967,1127.0148148148148,1480.5,807453428.7162977,807438763,807465712,0.5422222222222223,0.45454545454545453,497,40.37267143581489,0.00134745,2.4713592562971554e-9,2.7985656111353495e-9,2.817537074655191e-8,3.7012500494169875e-8,f3.ptu +118,26,63,80,0,99.84615384615384,133.4920634920635,1151.5125,,808333726.6390532,808326407,808341244,0.7078651685393258,0.5266272189349113,169,40.41668633195266,0.00074185,2.4961538794810743e-9,3.3373016318593424e-9,2.8787812884358522e-8,,f3.ptu +119,21,36,52,0,89.76190476190476,138.72222222222223,1139.4038461538462,,808708232.3944954,808703893,808712416,0.631578947368421,0.5229357798165137,109,40.43541161972477,0.00042615,2.244047649008868e-9,3.4680556018590636e-9,2.848509653416298e-8,,f3.ptu +120,53,128,170,0,120.84905660377359,136.96875,1137.894117647059,,820346705.9230769,820333617,820359956,0.7071823204419889,0.5156695156695157,351,41.01733529615384,0.0013169499999999999,3.021226455432039e-9,3.4242187957182237e-9,2.844735332098937e-8,,f3.ptu +121,25,53,99,0,100.76,138.32075471698113,1145.0,,830332202.1864407,830326403,830338721,0.6794871794871795,0.4406779661016949,177,41.51661010932203,0.0006159,2.519000033632257e-9,3.458018914094032e-9,2.862500038218474e-8,,f3.ptu +122,17,188,240,0,109.41176470588235,148.54787234042553,1165.425,,833555660.1617978,833540171,833570536,0.9170731707317074,0.4606741573033708,445,41.67778300808989,0.0015182499999999999,2.735294154167152e-9,3.7136968580938084e-9,2.9135625389002313e-8,,f3.ptu +123,35,51,86,0,89.94285714285714,120.84313725490196,1134.7790697674418,,834806109.1976744,834798351,834813507,0.5930232558139535,0.5,172,41.740305459883714,0.0007578,2.2485714585930767e-9,3.021078471708272e-9,2.8369477122959184e-8,,f3.ptu +124,71,117,141,0,102.19718309859155,128.69230769230768,1119.6879432624114,,845434096.893617,845424652,845446618,0.6223404255319149,0.5714285714285714,329,42.27170484468085,0.0010983,2.5549296115767573e-9,3.217307735263357e-9,2.799219895529622e-8,,f3.ptu +125,72,63,116,0,95.77777777777777,122.63492063492063,1119.9137931034484,,848302176.2470119,848292549,848310917,0.4666666666666667,0.5378486055776892,251,42.415108812350596,0.0009184,2.3944444764137063e-9,3.065873056806811e-9,2.799784520139753e-8,,f3.ptu +126,12,45,75,0,102.0,136.17777777777778,1160.92,,850098528.8712121,850091900,850103527,0.7894736842105263,0.4318181818181818,132,42.504926443560606,0.00058135,2.5500000340461515e-9,3.404444489898653e-9,2.9023000387498612e-8,,f3.ptu +127,48,28,66,0,106.9375,122.92857142857143,1142.6363636363637,,860686893.7676057,860679465,860693150,0.3684210526315789,0.5352112676056338,142,43.03434468838028,0.00068425,2.673437535694219e-9,3.0732143267460973e-9,2.8565909472304886e-8,,f3.ptu +128,16,174,117,1,132.5625,168.6264367816092,1166.7863247863247,1094.0,867401966.3506494,867393393,867412601,0.9157894736842105,0.6188925081433225,308,43.37009831753247,0.0009603999999999999,3.31406254424748e-9,4.2156609758253395e-9,2.9169658509114823e-8,2.7350000365161664e-8,f3.ptu +129,8,69,73,0,119.75,169.57971014492753,1173.972602739726,,867472236.04,867468173,867477153,0.8961038961038961,0.5133333333333333,150,43.373611802,0.00044899999999999996,2.9937500399708494e-9,4.2394928102264875e-9,2.934931546034853e-8,,f3.ptu +130,16,119,97,0,94.375,135.58823529411765,1170.4020618556701,,867892433.5215517,867884221,867899594,0.8814814814814815,0.5818965517241379,232,43.394621676077584,0.00076865,2.3593750315010348e-9,3.389705927610369e-9,2.926005193705534e-8,,f3.ptu +131,26,26,56,0,102.0,117.5,1124.8035714285713,,880159520.712963,880154565,880164244,0.5,0.48148148148148145,108,44.00797603564815,0.00048394999999999997,2.5500000340461515e-9,2.9375000392198314e-9,2.8120089661157743e-8,,f3.ptu +132,64,45,79,0,108.421875,113.97777777777777,1135.5569620253164,,880304327.9308511,880295624,880311895,0.41284403669724773,0.5797872340425532,188,44.015216396542556,0.00081355,2.710546911189682e-9,2.849444482488608e-9,2.8388924429665697e-8,,f3.ptu +133,28,94,110,0,90.5,130.43617021276594,1146.7727272727273,,881478169.3965517,881469943,881487057,0.7704918032786885,0.5258620689655172,232,44.073908469827586,0.0008556999999999999,2.262500030207615e-9,3.26090429885689e-9,2.866931856459463e-8,,f3.ptu +134,16,34,63,0,141.8125,152.47058823529412,1160.111111111111,,884135048.4513274,884129953,884139308,0.68,0.4424778761061947,113,44.20675242256637,0.00046774999999999996,3.5453125473349986e-9,3.81176475677487e-9,2.9002778165006393e-8,,f3.ptu +135,11,7,18,0,98.72727272727273,142.71428571428572,1144.7777777777778,,885088773.8888888,885086821,885090558,0.3888888888888889,0.5,36,44.25443869444444,0.00018685,2.46818185113558e-9,3.567857190493145e-9,2.861944482655501e-8,,f3.ptu +136,99,135,242,0,130.3939393939394,147.8148148148148,1147.3388429752067,,885113577.0483193,885094461,885128754,0.5769230769230769,0.49159663865546216,476,44.25567885241596,0.0017146499999999999,3.2598485283721304e-9,3.6953704197088565e-9,2.868347145734558e-8,,f3.ptu +137,32,39,71,0,109.3125,134.6153846153846,1132.3661971830986,,891888531.5422535,891883500,891894302,0.5492957746478874,0.5,142,44.59442657711267,0.0005401,2.73281253648696e-9,3.365384660317319e-9,2.830915530754522e-8,,f3.ptu +138,45,56,105,1,94.93333333333334,162.0,1142.4857142857143,1172.0,901081877.7342995,901072263,901091209,0.5544554455445545,0.49029126213592233,207,45.05409388671497,0.0009473,2.3733333650207317e-9,4.0500000540732994e-9,2.8562143238488364e-8,2.9300000391196956e-8,f3.ptu +139,24,45,75,0,99.375,152.3111111111111,1158.64,,902577156.0833334,902571213,902583453,0.6521739130434783,0.4791666666666667,144,45.128857804166664,0.000612,2.4843750331699638e-9,3.807777828617063e-9,2.896600038673758e-8,,f3.ptu +140,20,60,86,0,111.25,149.86666666666667,1146.7209302325582,,903498469.0240964,903491736,903505661,0.75,0.4819277108433735,166,45.17492345120482,0.0006962499999999999,2.78125003713367e-9,3.7466667166900315e-9,2.8668023638573116e-8,,f3.ptu +141,5,34,52,0,87.4,167.47058823529412,1152.25,,910004444.9890109,910000306,910008656,0.8717948717948718,0.42857142857142855,91,45.500222249450545,0.00041749999999999996,2.185000029172879e-9,4.186764761781657e-9,2.8806250384604687e-8,,f3.ptu +142,29,69,92,0,92.44827586206897,154.14492753623188,1161.6521739130435,,919823042.6157895,919815470,919828649,0.7040816326530612,0.5157894736842106,190,45.99115213078947,0.0006589499999999999,2.311206927409646e-9,3.853623239857185e-9,2.9041304735569085e-8,,f3.ptu +143,59,104,157,0,98.2542372881356,132.68269230769232,1133.5987261146497,,953836153.196875,953826880,953846914,0.6380368098159509,0.509375,320,47.69180765984375,0.0010017,2.456355964999259e-9,3.3170673519799064e-9,2.83399685312454e-8,,f3.ptu +144,61,107,204,0,116.29508196721312,121.55140186915888,1133.078431372549,,1011322013.8736559,1011310262,1011332990,0.6369047619047619,0.45161290322580644,372,50.56610069368279,0.0011363999999999999,2.9073770879979748e-9,3.038785087301104e-9,2.8326961162519213e-8,,f3.ptu +145,40,18,84,0,116.825,104.72222222222223,1130.5238095238096,,1012898980.0985916,1012894090,1012905790,0.3103448275862069,0.4084507042253521,142,50.64494900492958,0.000585,2.920625038994526e-9,2.6180555905103464e-9,2.8263095615448035e-8,,f3.ptu +146,40,54,63,0,115.625,131.77777777777777,1144.7936507936508,,1015454849.7452229,1015448738,1015461290,0.574468085106383,0.5987261146496815,157,50.77274248726114,0.0006276,2.890625038593983e-9,3.294444488429995e-9,2.8619841651957133e-8,,f3.ptu +147,132,17,120,0,123.6969696969697,109.0,1132.5666666666666,,1022146474.810409,1022135415,1022156191,0.11409395973154363,0.5539033457249071,269,51.10732374052044,0.0010387999999999999,3.0924242837125342e-9,2.725000036382652e-9,2.8314167044701335e-8,,f3.ptu +148,11,53,93,0,96.63636363636364,161.81132075471697,1153.752688172043,,1056003604.8917197,1055998519,1056008948,0.828125,0.40764331210191085,157,52.80018024458598,0.00052145,2.415909123164937e-9,4.045283072878245e-9,2.8843817589407338e-8,,f3.ptu +149,29,86,150,0,94.44827586206897,158.0,1161.26,,1110367685.8037736,1110357115,1110380260,0.7478260869565218,0.4339622641509434,265,55.51838429018868,0.0011572499999999999,2.3612069280772176e-9,3.950000052738156e-9,2.9031500387612098e-8,,f3.ptu +150,8,29,60,0,128.625,112.86206896551724,1149.55,,1110391476.2061856,1110386818,1110396846,0.7837837837837838,0.38144329896907214,97,55.519573810309275,0.0005013999999999999,3.2156250429331984e-9,2.8215517618096867e-9,2.8738750383703463e-8,,f3.ptu +151,14,2,17,0,120.14285714285714,82.5,1180.5882352941176,,1143755791.3939395,1143753994,1143757243,0.125,0.48484848484848486,33,57.187789569696974,0.00016245,3.003571468673408e-9,2.0625000275373284e-9,2.9514706276416525e-8,,f3.ptu +152,10,136,90,0,168.4,162.9485294117647,1165.8222222222223,,1149725260.5127118,1149717270,1149732977,0.9315068493150684,0.6186440677966102,236,57.48626302563559,0.00078535,4.210000056209528e-9,4.073713289684022e-9,2.9145555944690458e-8,,f3.ptu +153,50,37,98,0,99.36,113.29729729729729,1119.6326530612246,,1159399296.3891892,1159390996,1159405993,0.42528735632183906,0.4702702702702703,185,57.96996481945946,0.0007498499999999999,2.484000033164957e-9,2.832432470249461e-9,2.7990816700248093e-8,,f3.ptu +154,24,32,60,0,134.5,156.71875,1139.15,,1177315412.25,1177311824,1177319847,0.5714285714285714,0.4827586206896552,116,58.8657706125,0.00040114999999999997,3.36250004489419e-9,3.917968802310493e-9,2.8478750380232094e-8,,f3.ptu +155,33,43,99,0,127.9090909090909,168.09302325581396,1166.1818181818182,,1181289052.942857,1181282541,1181295620,0.5657894736842105,0.4342857142857143,175,59.06445264714285,0.0006539499999999999,3.1977273154215106e-9,4.202325637502413e-9,2.9154545843800388e-8,,f3.ptu +156,46,34,120,0,100.04347826086956,133.11764705882354,1147.5416666666667,,1190033041.44,1190026293,1190040067,0.425,0.4,200,59.501652072,0.0006887,2.5010869899148315e-9,3.3279412209033685e-9,2.868854204969978e-8,,f3.ptu +157,35,50,124,0,102.82857142857142,151.94,1151.782258064516,,1191968308.8899522,1191958916,1191975781,0.5882352941176471,0.40669856459330145,209,59.598415444497604,0.0008432499999999999,2.5707143200370026e-9,3.7985000507154145e-9,2.8794556836061463e-8,,f3.ptu +0,105,123,178,1,105.97142857142858,149.04065040650406,1150.6741573033707,1092.0,11642670.203931203,11625259,11658856,0.5394736842105263,0.5615763546798029,407,0.5821335101965601,0.0016798499999999999,2.6492857496574723e-9,3.726016309910254e-9,2.876685431666296e-8,2.7300000364494093e-8,f4.ptu +1,21,42,63,0,93.85714285714286,142.3095238095238,1164.4285714285713,,13035023.952380951,13030796,13039389,0.6666666666666666,0.5,126,0.6517511976190475,0.00042964999999999995,2.3464286027567528e-9,3.557738142738993e-9,2.9110714674384005e-8,,f4.ptu +2,44,50,101,0,127.1590909090909,168.3,1141.118811881188,,16892289.235897437,16885646,16899021,0.5319148936170213,0.48205128205128206,195,0.8446144617948718,0.00066875,3.1789773151711712e-9,4.2075000561761505e-9,2.8527970677918958e-8,,f4.ptu +3,70,43,128,0,111.74285714285715,130.2093023255814,1124.1328125,,50884668.32780083,50876588,50891597,0.3805309734513274,0.46887966804979253,241,2.5442334163900413,0.0007504499999999999,2.7935714658696076e-9,3.2552326016015513e-9,2.810332068771957e-8,,f4.ptu +4,85,15,72,0,140.8470588235294,90.4,1140.6944444444443,,58497713.343023255,58492257,58504784,0.15,0.5813953488372093,172,2.9248856671511625,0.00062635,3.5211765176009833e-9,2.2600000301742365e-9,2.8517361491858714e-8,,f4.ptu +5,126,17,75,0,124.32539682539682,117.88235294117646,1150.48,,58518519.47706422,58511110,58524442,0.11888111888111888,0.6559633027522935,218,2.925925973853211,0.0006665999999999999,3.1081349621329723e-9,2.947058862876867e-9,2.8762000384013887e-8,,f4.ptu +6,32,32,68,0,90.875,170.1875,1151.6470588235295,,62700559.60606061,62696314,62703431,0.5,0.48484848484848486,132,3.1350279803030303,0.00035585,2.2718750303327845e-9,4.254687556806171e-9,2.879117685499167e-8,,f4.ptu +7,17,61,65,0,130.47058823529412,191.65573770491804,1189.1692307692308,,65729103.755244754,65724243,65733771,0.782051282051282,0.5454545454545454,143,3.2864551877622374,0.0004764,3.2617647494315826e-9,4.791393506594914e-9,2.972923116615857e-8,,f4.ptu +8,34,20,40,0,149.73529411764707,156.6,1130.475,,81542555.59574468,81538616,81547095,0.37037037037037035,0.574468085106383,94,4.077127779787234,0.00042395,3.7433824029206915e-9,3.915000052270856e-9,2.82618753773365e-8,,f4.ptu +9,59,12,70,0,144.16949152542372,180.5,1131.7285714285715,,81556912.88652483,81552992,81561372,0.16901408450704225,0.5035460992907801,141,4.077845644326241,0.000419,3.604237336257322e-9,4.512500060248337e-9,2.8293214663469214e-8,,f4.ptu +10,21,47,61,0,100.23809523809524,143.29787234042553,1141.8524590163934,,92754569.11627907,92749796,92759180,0.6911764705882353,0.5271317829457365,129,4.637728455813953,0.00046919999999999997,2.5059524144104338e-9,3.582446856341433e-9,2.854631185654397e-8,,f4.ptu +11,33,78,98,0,94.27272727272727,150.75641025641025,1152.8061224489795,,92775193.66028708,92768502,92781747,0.7027027027027027,0.5311004784688995,209,4.638759683014354,0.00066225,2.3568182132850794e-9,3.768910306730605e-9,2.8820153446014802e-8,,f4.ptu +12,5,81,68,0,97.6,152.34567901234567,1179.3676470588234,,112350712.7987013,112346534,112355777,0.9418604651162791,0.5584415584415584,154,5.617535639935065,0.00046215,2.4400000325774937e-9,3.808642026159466e-9,2.948419157012676e-8,,f4.ptu +13,27,177,165,1,97.77777777777777,160.63276836158192,1155.4969696969697,1136.0,123613534.30540541,123598419,123631188,0.8676470588235294,0.5528455284552846,370,6.18067671527027,0.0016384499999999998,2.444444477081278e-9,4.015819262656485e-9,2.888742462811272e-8,2.8400000379180668e-8,f4.ptu +14,80,19,69,0,118.4375,165.68421052631578,1117.0579710144928,,128916163.35119048,128910620,128922047,0.1919191919191919,0.5892857142857143,168,6.445808167559524,0.00057135,2.9609375395327556e-9,4.142105318460931e-9,2.7926449648220407e-8,,f4.ptu +15,34,33,84,0,118.3529411764706,129.15151515151516,1147.9166666666667,,136967709.21854305,136960754,136974583,0.4925373134328358,0.44370860927152317,151,6.848385460927152,0.0006914499999999999,2.9588235689162957e-9,3.2287879218968205e-9,2.869791704982495e-8,,f4.ptu +16,64,5,63,0,137.671875,112.4,1152.6984126984128,,158237237.1818182,158232658,158242753,0.07246376811594203,0.5227272727272727,132,7.911861859090909,0.00050475,3.441796920952917e-9,2.810000037517524e-9,2.881746070221468e-8,,f4.ptu +17,5,75,63,0,140.4,127.21333333333334,1158.5555555555557,,187020281.02097902,187015644,187025731,0.9375,0.5594405594405595,143,9.351014051048951,0.00050435,3.5100000468635264e-9,3.1803333757953376e-9,2.8963889275598284e-8,,f4.ptu +18,23,35,67,0,120.78260869565217,117.0,1141.3432835820895,,188322496.864,188317955,188327064,0.603448275862069,0.464,125,9.416124843199999,0.00045545,3.019565257706824e-9,2.9250000390529385e-9,2.8533582470516418e-8,,f4.ptu +19,27,34,70,0,96.81481481481481,111.29411764705883,1138.9714285714285,,211836245.870229,211831428,211841080,0.5573770491803278,0.46564885496183206,131,10.591812293511449,0.00048259999999999997,2.4203704026857807e-9,2.7823529783248667e-9,2.8474286094458202e-8,,f4.ptu +20,41,100,157,0,105.1219512195122,143.66,1152.71974522293,,214755971.52684563,214746902,214767019,0.7092198581560284,0.47315436241610737,298,10.737798576342282,0.00100585,2.6280488155760192e-9,3.591500047951668e-9,2.881799401533473e-8,,f4.ptu +21,23,50,67,0,112.82608695652173,155.08,1166.8059701492537,,225350617.1142857,225345190,225356219,0.684931506849315,0.5214285714285715,140,11.267530855714284,0.00055145,2.820652211572789e-9,3.877000051763502e-9,2.9170149643194604e-8,,f4.ptu +22,30,65,72,0,95.53333333333333,145.30769230769232,1167.5277777777778,,258310249.91017964,258303847,258316497,0.6842105263157895,0.5688622754491018,167,12.915512495508981,0.0006324999999999999,2.3883333652210034e-9,3.632692356193952e-9,2.918819483414864e-8,,f4.ptu +23,5,53,77,0,99.4,139.62264150943398,1156.1688311688313,,260263241.04444444,260258613,260267710,0.9137931034482759,0.42962962962962964,135,13.01316205222222,0.00045484999999999997,2.4850000331783087e-9,3.490566084339904e-9,2.890422116513352e-8,,f4.ptu +24,1,1,12,0,75.0,112.0,1114.4166666666667,,264186671.7857143,264185922,264187479,0.5,0.14285714285714285,14,13.209333589285714,0.00007785,1.875000025033935e-9,2.8000000373840095e-9,2.7860417038643125e-8,,f4.ptu +25,24,2,25,0,121.75,98.0,1142.28,,264223825.7647059,264220530,264226408,0.07692307692307693,0.5098039215686274,51,13.211191288235295,0.0002939,3.043750040638421e-9,2.4500000327110083e-9,2.8557000381276842e-8,,f4.ptu +26,4,2,5,0,116.75,404.5,1133.4,,264232686.54545453,264231923,264233505,0.3333333333333333,0.5454545454545454,11,13.211634327272726,0.0000791,2.918750038969492e-9,1.0112500135016356e-8,2.8335000378312825e-8,,f4.ptu +27,34,48,87,0,87.67647058823529,124.14583333333333,1135.0114942528735,,276385506.7692308,276379911,276391570,0.5853658536585366,0.48520710059171596,169,13.819275338461539,0.0005829499999999999,2.191911793971043e-9,3.1036458747714492e-9,2.8375287735172555e-8,,f4.ptu +28,45,28,81,0,115.6,117.10714285714286,1132.1234567901236,,276409541.9415584,276401105,276415997,0.3835616438356164,0.474025974025974,154,13.820477097077921,0.0007446,2.890000038585638e-9,2.9276786105172726e-9,2.8303086797639822e-8,,f4.ptu +29,136,108,217,0,109.72058823529412,123.31481481481481,1131.2903225806451,,287640565.44251627,287623599,287659612,0.4426229508196721,0.5292841648590022,461,14.382028272125813,0.00180065,2.7430147425055272e-9,3.0828704115311044e-9,2.8282258442124773e-8,,f4.ptu +30,9,64,65,0,85.77777777777777,130.28125,1132.6461538461538,,291751155.65217394,291745135,291757892,0.8767123287671232,0.5289855072463768,138,14.587557782608696,0.0006378499999999999,2.1444444730758483e-9,3.257031293486031e-9,2.8316154224215047e-8,,f4.ptu +31,11,86,81,0,96.63636363636364,145.98837209302326,1155.6172839506173,,291826092.8202247,291819164,291833283,0.8865979381443299,0.5449438202247191,178,14.591304641011234,0.00070595,2.415909123164937e-9,3.649709351054427e-9,2.8890432484494072e-8,,f4.ptu +32,9,41,60,0,122.77777777777777,117.46341463414635,1156.95,,291841906.06363636,291837328,291845573,0.82,0.45454545454545453,110,14.592095303181818,0.00041224999999999996,3.069444485425923e-9,2.9365854050612786e-9,2.8923750386173482e-8,,f4.ptu +33,13,81,92,0,137.46153846153845,140.8148148148148,1151.0652173913043,,292234332.22043014,292227360,292240965,0.8617021276595744,0.5053763440860215,186,14.611716611021507,0.00068025,3.436538507421171e-9,3.520370417372356e-9,2.877663081899183e-8,,f4.ptu +34,11,46,51,1,166.0909090909091,150.04347826086956,1182.1764705882354,1535.0,311621902.6605505,311616738,311628033,0.8070175438596491,0.5277777777777778,109,15.581095133027523,0.0005647499999999999,4.152272782711514e-9,3.751087006604121e-9,2.95544121592996e-8,3.83750005123612e-8,f4.ptu +35,10,54,70,0,99.4,163.4814814814815,1176.3714285714286,,314432490.3731343,314427156,314437147,0.84375,0.47761194029850745,134,15.721624518656714,0.00049955,2.4850000331783087e-9,4.087037091604835e-9,2.940928610694179e-8,,f4.ptu +36,27,35,87,0,98.14814814814815,126.4,1129.2068965517242,,328463890.81208056,328458425,328469909,0.5645161290322581,0.4161073825503356,149,16.423194540604026,0.0005742,2.453703736464162e-9,3.1600000421905252e-9,2.8230172790706332e-8,,f4.ptu +37,40,22,54,0,111.075,170.04545454545453,1145.888888888889,,381766016.7844828,381762223,381769054,0.3548387096774194,0.5344827586206896,116,19.08830083922414,0.00034155,2.7768750370752575e-9,4.2511364203951215e-9,2.864722260470366e-8,,f4.ptu +38,203,53,427,0,136.98029556650246,124.75471698113208,1149.2833723653396,,402956166.9809663,402941544,402973785,0.20703125,0.37481698389458273,683,20.147808349048315,0.0016120499999999999,3.424507434884639e-9,3.118867966169655e-9,2.873208469274796e-8,,f4.ptu +39,57,66,165,0,108.29824561403508,135.86363636363637,1128.581818181818,,428430466.7916667,428420670,428440703,0.5365853658536586,0.4270833333333333,288,21.421523339583334,0.00100165,2.7074561764992935e-9,3.3965909544402617e-9,2.8214545831250036e-8,,f4.ptu +40,25,47,54,0,99.96,156.06382978723406,1155.648148148148,,432378301.3492063,432373970,432382722,0.6527777777777778,0.5714285714285714,126,21.618915067460314,0.00043759999999999996,2.4990000333652285e-9,3.901595796772742e-9,2.8891204089442642e-8,,f4.ptu +41,24,41,72,1,101.375,114.51219512195122,1128.0833333333333,1594.0,435195644.942029,435190735,435199331,0.6307692307692307,0.4744525547445255,138,21.759782247101448,0.0004298,2.5343750338375354e-9,2.862804916271325e-9,2.820208370987153e-8,3.9850000532054564e-8,f4.ptu +42,16,52,65,0,102.4375,121.0576923076923,1152.7230769230769,,442062125.33082706,442055808,442068249,0.7647058823529411,0.5112781954887218,133,22.103106266541353,0.00062205,2.5609375341921828e-9,3.026442348099646e-9,2.8818077307839515e-8,,f4.ptu +43,49,77,115,0,93.42857142857143,137.25974025974025,1136.695652173913,,448609784.4896265,448600405,448618984,0.6111111111111112,0.5228215767634855,241,22.430489224481324,0.00092895,2.3357143168994163e-9,3.4314935523088584e-9,2.841739168376069e-8,,f4.ptu +44,28,52,81,0,96.85714285714286,128.03846153846155,1140.9876543209878,,452343157.06832296,452338496,452347926,0.65,0.4968944099378882,161,22.617157853416145,0.00047149999999999997,2.42142860375811e-9,3.2009615811989587e-9,2.8524691738870168e-8,,f4.ptu +45,58,132,181,0,104.44827586206897,131.6818181818182,1148.414364640884,,453542748.9299191,453528874,453555287,0.6947368421052632,0.5121293800539084,371,22.677137446495955,0.00132065,2.6112069314150756e-9,3.2920454984989756e-9,2.8710359499346508e-8,,f4.ptu +46,25,59,53,0,130.96,149.05084745762713,1162.698113207547,,454991810.7518248,454987400,454996431,0.7023809523809523,0.6131386861313869,137,22.74959053759124,0.00045155,3.2740000437125883e-9,3.7262712361917344e-9,2.9067453218280794e-8,,f4.ptu +47,93,9,125,0,141.72043010752688,103.11111111111111,1134.28,,471100613.5330396,471090849,471109327,0.08823529411764706,0.44933920704845814,227,23.55503067665198,0.0009239,3.543010799992439e-9,2.5777778121948023e-9,2.8357000378606556e-8,,f4.ptu +48,52,63,88,0,112.61538461538461,149.34920634920636,1145.465909090909,,483037070.87684727,483030724,483043193,0.5478260869565217,0.5665024630541872,203,24.15185354384236,0.00062345,2.8153846529740316e-9,3.733730208580803e-9,2.863664810961298e-8,,f4.ptu +49,24,56,81,0,106.16666666666667,141.17857142857142,1167.3827160493827,,483113408.83229816,483108157,483118877,0.7,0.4968944099378882,161,24.155670441614905,0.000536,2.6541667021035926e-9,3.5294643328376877e-9,2.918456829089034e-8,,f4.ptu +50,43,10,47,0,121.44186046511628,155.8,1143.787234042553,,506053027.53,506047953,506057244,0.18867924528301888,0.53,100,25.3026513765,0.00046455,3.0360465521634754e-9,3.895000052003828e-9,2.8594681232843762e-8,,f4.ptu +51,57,67,128,0,103.43859649122807,122.43283582089552,1134.625,,509230802.4722222,509222567,509239139,0.5403225806451613,0.49206349206349204,252,25.46154012361111,0.0008286,2.5859649468070365e-9,3.06082093638873e-9,2.8365625378721712e-8,,f4.ptu +52,15,59,112,0,94.86666666666666,138.9322033898305,1141.5892857142858,,524840839.5967742,524832949,524848960,0.7972972972972973,0.3978494623655914,186,26.24204197983871,0.0008005499999999999,2.3716666983318126e-9,3.4733051311193593e-9,2.8539732523903437e-8,,f4.ptu +53,45,28,75,0,105.04444444444445,147.14285714285714,1136.5866666666666,,526780744.5405405,526774877,526786573,0.3835616438356164,0.49324324324324326,148,26.339037227027024,0.0005848,2.626111146173455e-9,3.6785714776856248e-9,2.8414667046043152e-8,,f4.ptu +54,26,28,45,0,109.46153846153847,105.96428571428571,1126.6666666666667,,535353510.54545456,535348663,535357574,0.5185185185185185,0.5454545454545454,99,26.767675527272726,0.00044554999999999996,2.7365384980751686e-9,2.6491071782265165e-9,2.8166667042732e-8,,f4.ptu +55,22,47,83,0,93.0909090909091,144.2340425531915,1152.3493975903614,,546718846.1381578,546713722,546724967,0.6811594202898551,0.45394736842105265,152,27.335942306907892,0.0005622499999999999,2.327272758345151e-9,3.605851111973063e-9,2.8808735324396898e-8,,f4.ptu +56,14,41,68,0,108.71428571428571,142.85365853658536,1156.6764705882354,,550675932.804878,550670409,550680096,0.7454545454545455,0.44715447154471544,123,27.5337966402439,0.00048435,2.7178571791444275e-9,3.5713415110971563e-9,2.8916912150788063e-8,,f4.ptu +57,51,23,99,0,144.13725490196077,141.7391304347826,1164.4444444444443,,576701346.7919075,576694377,576707359,0.3108108108108108,0.4277456647398844,173,28.835067339595376,0.0006491,3.603431420659988e-9,3.5434783081800736e-9,2.9111111499786127e-8,,f4.ptu +58,103,127,357,0,121.59223300970874,138.59055118110237,1154.4173669467787,,576745216.088586,576727249,576762123,0.5521739130434783,0.39182282793867124,587,28.8372608044293,0.0017437,3.039805865828479e-9,3.4647638257871173e-9,2.8860434558997588e-8,,f4.ptu +59,52,21,87,0,121.84615384615384,138.04761904761904,1173.344827586207,,577061798.96875,577055285,577068172,0.2876712328767123,0.45625,160,28.8530899484375,0.00064435,3.046153886824362e-9,3.4511905222688106e-9,2.9333621081301016e-8,,f4.ptu +60,50,27,86,1,121.18,130.85185185185185,1143.4418604651162,1684.0,577111057.7682927,577105825,577116225,0.35064935064935066,0.4723926380368098,164,28.855552888414632,0.00052,3.0295000404481633e-9,3.271296339972786e-9,2.858604689329256e-8,4.2100000562095286e-8,f4.ptu +61,3,13,21,0,148.66666666666666,125.84615384615384,1151.2857142857142,,585271041.1621622,585268522,585273021,0.8125,0.43243243243243246,37,29.263552058108107,0.00022495,3.7166667162894886e-9,3.146153888159505e-9,2.8782143241425677e-8,,f4.ptu +62,81,62,102,0,123.41975308641975,170.58064516129033,1134.578431372549,,587323208.1142857,587315621,587331397,0.43356643356643354,0.5836734693877551,245,29.366160405714282,0.0007888,3.0854938683562547e-9,4.264516185969655e-9,2.836446116301989e-8,,f4.ptu +63,11,43,95,0,93.27272727272727,121.32558139534883,1127.3473684210526,,602047247.0134228,602042458,602051173,0.7962962962962963,0.3624161073825503,149,30.10236235067114,0.00043575,2.3318182129512936e-9,3.033139575380477e-9,2.8183684586818855e-8,,f4.ptu +64,30,45,75,0,95.23333333333333,140.53333333333333,1155.6266666666668,,610106962.28,610101499,610112562,0.6,0.5,150,30.505348113999997,0.00055315,2.3808333651208676e-9,3.5133333802413643e-9,2.889066705239844e-8,,f4.ptu +65,75,14,56,0,133.6,94.85714285714286,1139.7857142857142,,632988326.2413793,632984136,632993603,0.15730337078651685,0.6137931034482759,145,31.64941631206896,0.00047335,3.3400000445937825e-9,2.3714286030905386e-9,2.849464323758714e-8,,f4.ptu +66,60,30,61,0,113.81666666666666,122.13333333333334,1151.7377049180327,,643196202.2119205,643190178,643202990,0.3333333333333333,0.5960264900662252,151,32.15981011059603,0.0006406,2.845416704657054e-9,3.053333374099706e-9,2.8793443007384507e-8,,f4.ptu +67,2,1,5,0,115.0,88.0,1217.2,,648260322.125,648259578,648261145,0.3333333333333333,0.375,8,32.41301610625,0.00007835,2.875000038385367e-9,2.2000000293731503e-9,3.043000040628407e-8,,f4.ptu +68,128,101,211,0,116.78125,158.21782178217822,1153.6445497630332,,704380476.1159091,704367793,704392401,0.4410480349344978,0.5204545454545455,440,35.21902380579545,0.0012304,2.919531288979923e-9,3.9554455973653175e-9,2.8841114129146e-8,,f4.ptu +69,39,55,58,0,116.53846153846153,140.36363636363637,1133.344827586207,,708443713.0986842,708437362,708448232,0.5851063829787234,0.618421052631579,152,35.42218565493421,0.0005434999999999999,2.913461577360422e-9,3.509090955942298e-9,2.8333621067949584e-8,,f4.ptu +70,28,35,91,0,118.92857142857143,147.05714285714285,1169.5384615384614,,754526163.5,754520984,754530815,0.5555555555555556,0.4090909090909091,154,37.726308175,0.00049155,2.973214325410954e-9,3.6764286205141572e-9,2.9238461928836866e-8,,f4.ptu +71,45,120,180,0,104.95555555555555,142.50833333333333,1158.9055555555556,,762051432.5246377,762042262,762059797,0.7272727272727273,0.4782608695652174,345,38.102571626231885,0.0008767499999999999,2.6238889239215626e-9,3.562708380900591e-9,2.8972639275715105e-8,,f4.ptu +72,26,48,58,1,105.34615384615384,123.1875,1143.6724137931035,1382.0,767384671.7368422,767378663,767391656,0.6486486486486487,0.5606060606060606,133,38.36923358684211,0.00064965,2.633653881316896e-9,3.079687541118238e-9,2.8591810726569197e-8,3.4550000461291974e-8,f4.ptu +73,3,94,52,0,258.0,133.2659574468085,1162.923076923077,,786905803.9328859,786901466,786911164,0.9690721649484536,0.6510067114093959,149,39.34529019664429,0.00048489999999999997,6.450000086116736e-9,3.3316489806524964e-9,2.9073077311244132e-8,,f4.ptu +74,40,59,99,0,111.575,134.61016949152543,1146.2121212121212,,804684966.8383838,804673911,804694551,0.5959595959595959,0.5,198,40.23424834191919,0.001032,2.7893750372421504e-9,3.3652542822190987e-9,2.865530341289236e-8,,f4.ptu +75,9,95,127,0,99.22222222222223,131.77894736842106,1168.3858267716535,,807389639.900433,807383698,807396926,0.9134615384615384,0.45021645021645024,231,40.369481995021644,0.0006613999999999999,2.4805555886745245e-9,3.294473728196468e-9,2.9209646059281935e-8,,f4.ptu +76,21,60,92,0,109.04761904761905,148.71666666666667,1163.108695652174,,807406102.6473988,807397243,807412533,0.7407407407407407,0.4682080924855491,173,40.37030513236994,0.0007645,2.726190512589023e-9,3.717916716306178e-9,2.9077717779533514e-8,,f4.ptu +77,26,26,62,0,102.15384615384616,140.1153846153846,1150.274193548387,,809600673.5964912,809596565,809604829,0.5,0.45614035087719296,114,40.48003367982456,0.00041319999999999996,2.553846187943657e-9,3.502884662153141e-9,2.8756855222654866e-8,,f4.ptu +78,6,57,56,0,84.66666666666667,144.19298245614036,1162.375,,809891712.7478992,809887614,809896485,0.9047619047619048,0.5294117647058824,119,40.494585637394955,0.00044354999999999997,2.116666694927198e-9,3.604824609533079e-9,2.9059375387984268e-8,,f4.ptu +79,61,46,130,0,94.67213114754098,114.8913043478261,1135.2846153846153,,813418513.4683545,813409126,813425116,0.42990654205607476,0.45147679324894513,237,40.67092567341772,0.0007995,2.3668033102887375e-9,2.872282647044738e-9,2.8382115763557267e-8,,f4.ptu +80,35,43,66,0,123.51428571428572,123.95348837209302,1132.121212121212,,817114233.8611112,817108314,817120505,0.5512820512820513,0.5416666666666666,144,40.855711693055554,0.0006095499999999999,3.0878571840844574e-9,3.0988372506762396e-9,2.8303030680916285e-8,,f4.ptu +81,73,64,109,0,138.3835616438356,131.25,1141.8899082568807,,817147534.0813009,817139066,817158736,0.46715328467153283,0.556910569105691,246,40.85737670406504,0.0009835,3.459589087286358e-9,3.281250043809386e-9,2.8547248087568655e-8,,f4.ptu +82,35,56,76,0,107.74285714285715,122.10714285714286,1127.1973684210527,,849088782.2215569,849082597,849095246,0.6153846153846154,0.5449101796407185,167,42.454439111077846,0.00063245,2.6935714645344645e-9,3.0526786121862016e-9,2.8179934586768793e-8,,f4.ptu +83,48,97,103,0,105.125,119.9381443298969,1138.0194174757282,,853486127.7419355,853478884,853491874,0.6689655172413793,0.5846774193548387,248,42.67430638709677,0.0006495,2.628125035089232e-9,2.998453648281072e-9,2.8450485816747925e-8,,f4.ptu +84,43,58,92,0,113.81395348837209,118.98275862068965,1131.2391304347825,,853971283.8652849,853965477,853978498,0.5742574257425742,0.5233160621761658,193,42.69856419326425,0.00065105,2.845348875198784e-9,2.9745690052319965e-9,2.828097863846112e-8,,f4.ptu +85,16,144,124,0,99.125,155.23611111111111,1170.1209677419354,,859697723.8521127,859689913,859704599,0.9,0.5633802816901409,284,42.98488619260563,0.0007343,2.4781250330865173e-9,3.880902829593387e-9,2.9253024584118147e-8,,f4.ptu +86,28,83,166,0,102.17857142857143,130.72289156626505,1147.9819277108434,,859896051.8158845,859886655,859905248,0.7477477477477478,0.4007220216606498,277,42.99480259079422,0.00092965,2.554464319820042e-9,3.268072332790071e-9,2.869954857595115e-8,,f4.ptu +87,13,1,14,0,91.23076923076923,71.0,1150.642857142857,,860635112.8214285,860633757,860637021,0.07142857142857142,0.5,28,43.03175564107143,0.00016319999999999998,2.2807692612207657e-9,1.7750000236987917e-9,2.8766071812639674e-8,,f4.ptu +88,12,0,10,0,104.83333333333333,,1110.9,,860642786.7272727,860641655,860643831,0.0,0.5454545454545454,22,43.032139336363635,0.00010879999999999999,2.620833368325211e-9,,2.7772500370802645e-8,,f4.ptu +89,6,39,39,0,117.83333333333333,150.10256410256412,1179.1025641025642,,869114299.8571428,869109546,869118815,0.8666666666666667,0.5357142857142857,84,43.45571499285714,0.00046344999999999996,2.9458333726644264e-9,3.752564152666207e-9,2.9477564496131795e-8,,f4.ptu +90,13,57,70,0,98.92307692307692,134.2280701754386,1159.3142857142857,,869130411.7142857,869123139,869136377,0.8142857142857143,0.5,140,43.45652058571429,0.0006619,2.4730769560960413e-9,3.3557017991893887e-9,2.8982857529819786e-8,,f4.ptu +91,78,107,191,0,105.37179487179488,155.8785046728972,1168.8010471204188,,873848609.6861702,873832984,873863503,0.5783783783783784,0.4920212765957447,376,43.69243048430851,0.0015259499999999999,2.6342949069664807e-9,3.896962668852462e-9,2.922002656813966e-8,,f4.ptu +92,20,63,96,0,89.65,103.88888888888889,1126.2708333333333,,885517891.0167598,885510342,885524426,0.7590361445783133,0.46368715083798884,179,44.27589455083798,0.0007042,2.241250029923897e-9,2.597222256898858e-9,2.8156771209266542e-8,,f4.ptu +93,14,41,50,0,87.71428571428571,136.29268292682926,1148.9,,887073028.8,887067849,887077635,0.7454545454545455,0.5238095238095238,105,44.35365143999999,0.0004893,2.1928571721349257e-9,3.4073171186632937e-9,2.8722500383486505e-8,,f4.ptu +94,45,156,272,0,105.68888888888888,128.01923076923077,1135.172794117647,,887117874.6088794,887105389,887130401,0.7761194029850746,0.4249471458773784,473,44.355893730443974,0.0012506,2.642222257499672e-9,3.2004808119617707e-9,2.8379320231845734e-8,,f4.ptu +95,119,133,266,0,113.27731092436974,150.04511278195488,1145.827067669173,,890840494.3088803,890822524,890859082,0.5277777777777778,0.4864864864864865,518,44.542024715444015,0.0018279,2.831932810919601e-9,3.7511278696318e-9,2.8645677074190127e-8,,f4.ptu +96,16,31,51,0,112.75,184.48387096774192,1174.6666666666667,,890995414.1632653,890990793,890999858,0.6595744680851063,0.47959183673469385,98,44.549770708163265,0.00045325,2.818750037634349e-9,4.6120968357716444e-9,2.936666705875372e-8,,f4.ptu +97,31,56,63,1,113.74193548387096,142.30357142857142,1159.2222222222222,1455.0,891065230.1125828,891059309,891072671,0.6436781609195402,0.58,151,44.55326150562914,0.0006680999999999999,2.843548425062217e-9,3.5575893332131968e-9,2.898055594248747e-8,3.637500048565834e-8,f4.ptu +98,46,103,225,0,97.8695652173913,149.05825242718447,1150.7688888888888,,898303555.302139,898292973,898314098,0.6912751677852349,0.3983957219251337,374,44.915177765106954,0.00105625,2.4467391631022534e-9,3.726456360433139e-9,2.8769222606332533e-8,,f4.ptu +99,121,56,156,0,134.8099173553719,178.33928571428572,1158.1858974358975,,910116574.6906906,910106393,910124362,0.3163841807909605,0.5315315315315315,333,45.50582873453453,0.00089845,3.3702479788819336e-9,4.458482202384264e-9,2.895464782248344e-8,,f4.ptu +100,40,28,63,0,117.775,130.75,1136.7142857142858,,929019407.0534351,929014762,929023805,0.4117647058823529,0.5190839694656488,131,46.45097035267175,0.00045214999999999996,2.9443750393116227e-9,3.2687500436424932e-9,2.841785752227623e-8,,f4.ptu +101,80,10,106,0,102.0,89.1,1127.5566037735848,,933257920.0255102,933249502,933266056,0.1111111111111111,0.45918367346938777,196,46.662896001275506,0.0008277,2.5500000340461515e-9,2.2275000297403144e-9,2.8188915470702004e-8,,f4.ptu +102,100,106,229,0,102.77,138.93396226415095,1146.5109170305677,,958860867.2275862,958844499,958878214,0.5145631067961165,0.4735632183908046,435,47.9430433613793,0.00168575,2.5692500343031663e-9,3.4733491029779572e-9,2.8662773308453255e-8,,f4.ptu +103,26,49,97,0,89.73076923076923,133.71428571428572,1165.2268041237114,,984047320.4593023,984039238,984053986,0.6533333333333333,0.436046511627907,172,49.202366022965116,0.0007373999999999999,2.243269260720087e-9,3.342857187489073e-9,2.9130670492028944e-8,,f4.ptu +104,18,18,31,0,110.22222222222223,113.38888888888889,1137.1935483870968,,992043501.0149254,992040738,992046346,0.5,0.5373134328358209,67,49.60217505074627,0.0002804,2.7555555923461683e-9,2.834722260069823e-9,2.842983908925648e-8,,f4.ptu +105,68,15,134,0,149.58823529411765,131.6,1146.6641791044776,,992797363.2580645,992790805,992804545,0.18072289156626506,0.3824884792626728,217,49.63986816290322,0.000687,3.73970593228337e-9,3.290000043926211e-9,2.866660486035216e-8,,f4.ptu +106,98,88,101,0,102.56122448979592,119.89772727272727,1151.1980198019803,,1000133243.0243902,1000126843,1000142509,0.4731182795698925,0.6480836236933798,287,50.00666215121951,0.0007833,2.5640306464783783e-9,2.9974432218383405e-9,2.8779950879303057e-8,,f4.ptu +107,48,101,147,0,120.6875,133.07920792079207,1134.0068027210884,,1007715289.0641892,1007705550,1007724407,0.6778523489932886,0.5033783783783784,296,50.385764453209454,0.00094285,3.0171875402837736e-9,3.3269802424397517e-9,2.8350170446542578e-8,,f4.ptu +108,34,9,70,0,170.44117647058823,140.11111111111111,1123.8714285714286,,1018104570.539823,1018101553,1018108814,0.20930232558139536,0.3805309734513274,113,50.90522852699115,0.00036304999999999996,4.26102946865555e-9,3.502777824544877e-9,2.8096786089418037e-8,,f4.ptu +109,2,2,2,0,180.5,81.5,1225.5,,1018112492.3333334,1018112305,1018112820,0.5,0.6666666666666666,6,50.905624616666664,0.00002575,4.512500060248337e-9,2.0375000272035426e-9,3.0637500409054497e-8,,f4.ptu +110,19,162,191,0,82.05263157894737,124.23456790123457,1150.0104712041884,,1038858730.016129,1038843516,1038873040,0.8950276243093923,0.48655913978494625,372,51.94293650080645,0.0014762,2.0513158168616874e-9,3.1058642389985987e-9,2.8750262163961875e-8,,f4.ptu +111,21,49,95,0,90.04761904761905,153.53061224489795,1182.2947368421053,,1055383079.2121212,1055377296,1055390225,0.7,0.42424242424242425,165,52.76915396060606,0.00064645,2.2511905062470927e-9,3.838265357368787e-9,2.9557368815685826e-8,,f4.ptu +112,42,52,115,0,95.64285714285714,125.65384615384616,1138.7826086956522,,1055443310.277512,1055433785,1055453027,0.5531914893617021,0.44976076555023925,209,52.77216551387559,0.0009620999999999999,2.391071460495656e-9,3.1413461957876234e-9,2.846956559750077e-8,,f4.ptu +113,58,12,105,0,122.3103448275862,177.08333333333334,1161.7904761904763,,1059037163.0685714,1059031743,1059041822,0.17142857142857143,0.4,175,52.95185815342857,0.00050395,3.0577586615151114e-9,4.427083392441236e-9,2.9044762292551068e-8,,f4.ptu +114,53,7,96,0,113.49056603773585,101.71428571428571,1147.09375,,1085408086.9807692,1085402977,1085413804,0.11666666666666667,0.38461538461538464,156,54.27040434903846,0.00054135,2.8372641888249354e-9,2.542857176807927e-9,2.8677344132883604e-8,,f4.ptu +115,98,20,215,1,202.31632653061226,211.4,1192.0372093023257,1201.0,1091008212.1227546,1090994607,1091019033,0.1694915254237288,0.35435435435435436,334,54.550410606137724,0.0012213,5.057908230795623e-9,5.285000070562318e-9,2.9800930630443235e-8,3.0025000400876745e-8,f4.ptu +116,20,33,55,0,107.45,156.42424242424244,1132.2545454545455,,1092858964.9814816,1092854858,1092862485,0.6226415094339622,0.49074074074074076,108,54.642948249074074,0.00038134999999999997,2.686250035865284e-9,3.910606112818252e-9,2.8306364014294123e-8,,f4.ptu +117,40,7,50,0,132.625,167.85714285714286,1151.62,,1092869369.3505154,1092865323,1092872045,0.14893617021276595,0.4845360824742268,97,54.643468467525764,0.0003361,3.3156250442683416e-9,4.196428627456902e-9,2.87905003843944e-8,,f4.ptu +118,170,141,290,1,128.04117647058823,138.02836879432624,1134.5413793103448,1856.0,1093009680.0963454,1092986776,1093031849,0.4533762057877814,0.5174708818635607,602,54.650484004817265,0.00225365,3.201029454503032e-9,3.4507092659300652e-9,2.836353486145242e-8,4.640000061950644e-8,f4.ptu +119,42,44,107,0,182.33333333333334,131.5909090909091,1123.822429906542,,1093054618.2901554,1093046590,1093061292,0.5116279069767442,0.44559585492227977,193,54.65273091450777,0.0007350999999999999,4.558333394193611e-9,3.2897727711959043e-9,2.809556112277952e-8,,f4.ptu +120,14,85,89,0,87.71428571428571,131.54117647058823,1131.8651685393259,,1112856228.5531914,1112848050,1112864865,0.8585858585858586,0.526595744680851,188,55.64281142765957,0.0008407499999999999,2.1928571721349257e-9,3.2885294556712825e-9,2.8296629591283667e-8,,f4.ptu +121,38,162,224,0,91.15789473684211,122.43827160493827,1135.2589285714287,,1118543857.8018868,1118526888,1118561006,0.81,0.4716981132075472,424,55.92719289009434,0.0017059,2.2789473988482634e-9,3.060956830991613e-9,2.8381473593219025e-8,,f4.ptu +122,23,48,53,0,136.08695652173913,129.22916666666666,1140.245283018868,,1119420163.5725806,1119414526,1119425733,0.676056338028169,0.5725806451612904,124,55.97100817862903,0.0005603499999999999,3.4021739584673715e-9,3.230729209801527e-9,2.850613245606938e-8,,f4.ptu +123,23,32,62,0,93.91304347826087,154.125,1193.3709677419354,,1122190355.4957266,1122184081,1122196289,0.5818181818181818,0.4700854700854701,117,56.109517774786326,0.0006104,2.3478261183033622e-9,3.853125051444736e-9,2.983427459187867e-8,,f4.ptu +124,20,52,72,0,86.95,125.98076923076923,1153.625,,1135495165.2083333,1135488052,1135502696,0.7222222222222222,0.5,144,56.77475826041666,0.0007322,2.173750029022675e-9,3.1495192728198223e-9,2.8840625385063642e-8,,f4.ptu +125,42,41,69,0,103.04761904761905,122.26829268292683,1131.1159420289855,,1137767220.8289473,1137760976,1137773904,0.4939759036144578,0.5460526315789473,152,56.88836104144736,0.0006464,2.576190510586308e-9,3.0567073578845903e-9,2.8277898928275077e-8,,f4.ptu +126,27,61,55,0,94.96296296296296,136.31147540983608,1145.1090909090908,,1140422466.4125874,1140417561,1140427746,0.6931818181818182,0.6153846153846154,143,57.021123320629364,0.0005092499999999999,2.3740741057713627e-9,3.407786930744737e-9,2.8627727654948423e-8,,f4.ptu +127,27,65,49,0,108.74074074074075,143.92307692307693,1134.6326530612246,,1149522180.9148936,1149516905,1149526888,0.7065217391304348,0.6524822695035462,141,57.47610904574468,0.00049915,2.718518554814634e-9,3.5980769711164027e-9,2.836581670525488e-8,,f4.ptu +128,53,92,136,0,98.05660377358491,125.54347826086956,1131.5735294117646,,1165917783.0818505,1165906855,1165928027,0.6344827586206897,0.5160142348754448,281,58.29588915409252,0.0010586,2.4514151270695247e-9,3.1385869984263694e-9,2.8289338612997292e-8,,f4.ptu +129,36,51,76,0,118.83333333333333,151.19607843137254,1146.8947368421052,,1174987425.0920246,1174981908,1174992766,0.5862068965517241,0.5337423312883436,163,58.74937125460123,0.0005429,2.970833372998212e-9,3.779902011251417e-9,2.8672368803869808e-8,,f4.ptu +130,52,69,89,0,97.40384615384616,115.55072463768116,1125.3820224719102,,1181141643.7809525,1181134523,1181147745,0.5702479338842975,0.5761904761904761,210,59.05708218904762,0.0006611,2.4350961863581746e-9,2.8887681545112197e-9,2.813455093743429e-8,,f4.ptu +131,68,84,100,0,106.19117647058823,115.86904761904762,1130.86,,1181415108.3015873,1181408177,1181422923,0.5526315789473685,0.6031746031746031,252,59.07075541507936,0.0007373,2.6547794472098123e-9,2.896726229151633e-9,2.8271500377465006e-8,,f4.ptu +0,35,33,66,0,94.97142857142858,108.6969696969697,1124.8333333333333,,1782233.537313433,1775847,1788183,0.4852941176470588,0.5074626865671642,134,0.08911167686567165,0.0006167999999999999,2.3742857459858285e-9,2.7174242787057473e-9,2.8120833708786725e-8,,f5.ptu +1,29,28,57,1,137.24137931034483,129.92857142857142,1132.7368421052631,1092.0,13865630.84347826,13859695,13870112,0.49122807017543857,0.5,115,0.693281542173913,0.00052085,3.431034528567844e-9,3.2482143290825975e-9,2.831842143072305e-8,2.7300000364494093e-8,f5.ptu +2,11,0,4,0,115.0,,1114.5,,28215061.266666666,28214356,28215849,0.0,0.7333333333333333,15,1.4107530633333332,0.00007465,2.875000038385367e-9,,2.7862500372004273e-8,,f5.ptu +3,31,27,62,1,130.41935483870967,134.0,1129.6774193548388,1226.0,30154441.669421487,30149391,30159706,0.46551724137931033,0.48333333333333334,121,1.5077220834710743,0.0005157499999999999,3.26048391449987e-9,3.350000044727297e-9,2.824193586094125e-8,3.065000040922139e-8,f5.ptu +4,34,17,76,0,120.73529411764706,145.1764705882353,1127.7236842105262,,41362101.56692913,41357438,41366966,0.3333333333333333,0.4015748031496063,127,2.0681050783464565,0.0004764,3.018382393240903e-9,3.629411813163727e-9,2.8193092481681306e-8,,f5.ptu +5,54,32,101,0,141.88888888888889,124.21875,1126.2871287128712,,41514704.22459893,41506703,41522003,0.37209302325581395,0.45989304812834225,187,2.0757352112299463,0.000765,3.5472222695827185e-9,3.1054687914624547e-9,2.815717859376043e-8,,f5.ptu +6,84,64,284,0,133.02380952380952,126.65625,1134.7711267605634,,41596219.8912037,41584671,41611325,0.43243243243243246,0.3425925925925926,432,2.079810994560185,0.0013327,3.3255952824966964e-9,3.1664062922760576e-9,2.8369278547784575e-8,,f5.ptu +7,22,64,89,0,111.36363636363636,132.4375,1148.0786516853932,,65341825.80571429,65336556,65347376,0.7441860465116279,0.49142857142857144,175,3.2670912902857143,0.0005409999999999999,2.7840909462625092e-9,3.3109375442057568e-9,2.870196667534718e-8,,f5.ptu +8,19,28,59,0,103.3157894736842,131.07142857142858,1124.2203389830509,,87850749.8490566,87845640,87855335,0.5957446808510638,0.44339622641509435,106,4.3925374924528295,0.00048475,2.5828947713274486e-9,3.276785758035496e-9,2.8105508849825055e-8,,f5.ptu +9,24,29,62,0,104.16666666666667,120.79310344827586,1136.3387096774193,,102063689.43478261,102059412,102068318,0.5471698113207547,0.4608695652173913,115,5.10318447173913,0.0004453,2.604166701436021e-9,3.019827626525919e-9,2.8408468121229207e-8,,f5.ptu +10,53,50,163,0,101.81132075471699,165.14,1144.8588957055215,,130299604.90225564,130292505,130306338,0.4854368932038835,0.38721804511278196,266,6.514980245112782,0.0006916499999999999,2.545283052851098e-9,4.1285000551213866e-9,2.8621472774775677e-8,,f5.ptu +11,50,26,77,0,139.86,144.26923076923077,1133.6753246753246,,152516668.18954247,152510996,152522336,0.34210526315789475,0.49673202614379086,153,7.625833409477123,0.000567,3.496500046683282e-9,3.60673081738579e-9,2.834188349528784e-8,,f5.ptu +12,21,29,53,0,108.0,146.72413793103448,1146.433962264151,,159495341.03883496,159491382,159499014,0.58,0.4854368932038835,103,7.974767051941748,0.0003816,2.7000000360488663e-9,3.6681034972502954e-9,2.866084943926715e-8,,f5.ptu +13,20,18,47,0,150.3,141.33333333333334,1140.9574468085107,,182890908.7529412,182886684,182895339,0.47368421052631576,0.4470588235294118,85,9.144545437647059,0.00043275,3.757500050168006e-9,3.533333380508393e-9,2.852393655104816e-8,,f5.ptu +14,30,32,76,0,98.63333333333334,127.34375,1136.921052631579,,195135837.07971016,195128695,195143324,0.5161290322580645,0.4492753623188406,138,9.756791853985508,0.0007314499999999999,2.4658333662557395e-9,3.1835937925055353e-9,2.8423026695277576e-8,,f5.ptu +15,56,56,69,0,111.17857142857143,139.78571428571428,1135.6521739130435,,234999274.26519337,234993336,235005397,0.5,0.6187845303867403,181,11.749963713259667,0.0006030499999999999,2.779464322824114e-9,3.494642903801343e-9,2.8391304726890654e-8,,f5.ptu +16,209,120,299,2,111.4688995215311,129.48333333333332,1138.2107023411372,1442.0,235304968.9015873,235278346,235334974,0.364741641337386,0.5238853503184714,630,11.765248445079365,0.0028314,2.786722525245013e-9,3.2370833765530308e-9,2.8455267938446998e-8,3.605000048131912e-8,f5.ptu +17,71,50,125,0,122.3943661971831,120.0,1146.304,,235361145.39430895,235353755,235369743,0.4132231404958678,0.491869918699187,246,11.768057269715447,0.0007993999999999999,3.0598591957830787e-9,3.000000040054296e-9,2.8657600382619998e-8,,f5.ptu +18,93,126,266,1,101.68817204301075,119.9047619047619,1132.1616541353383,1130.0,266648611.75514403,266631299,266666493,0.5753424657534246,0.4515463917525773,486,13.332430587757202,0.0017597,2.5422043350173366e-9,2.9976190876415543e-9,2.830404173128294e-8,2.8250000377177953e-8,f5.ptu +19,36,37,80,0,100.11111111111111,157.56756756756758,1154.5,,292520198.9607843,292514922,292526385,0.5068493150684932,0.477124183006536,153,14.626009948039215,0.00057315,2.502777811193445e-9,3.939189241783006e-9,2.8862500385355705e-8,,f5.ptu +20,45,54,115,0,100.4888888888889,175.03703703703704,1160.3217391304347,,292564297.13084114,292557491,292570097,0.5454545454545454,0.46261682242990654,214,14.628214856542057,0.0006303,2.5122222557639865e-9,4.3759259843508034e-9,2.9008043865559786e-8,,f5.ptu +21,28,22,50,0,119.10714285714286,140.77272727272728,1159.48,,335366428.14,335362253,335371319,0.44,0.5,100,16.768321407,0.00045329999999999996,2.9776786111848442e-9,3.5193182288061194e-9,2.898700038701796e-8,,f5.ptu +22,64,63,128,0,103.71875,157.84126984126985,1138.7421875,,335383903.3137255,335374749,335392163,0.49606299212598426,0.4980392156862745,255,16.769195165686273,0.0008707,2.592968784619846e-9,3.946031798716921e-9,2.846855506759597e-8,,f5.ptu +23,44,40,75,0,100.95454545454545,135.7,1140.9066666666668,,339704608.3710692,339698267,339711362,0.47619047619047616,0.5283018867924528,159,16.98523041855346,0.00065475,2.52386367006083e-9,3.392500045294733e-9,2.8522667047485113e-8,,f5.ptu +24,1,1,3,0,111.0,175.0,1120.6666666666667,,342765267.4,342765080,342765353,0.5,0.4,5,17.138263369999997,0.00001365,2.7750000370502237e-9,4.375000058412515e-9,2.8016667040729287e-8,,f5.ptu +25,20,52,66,0,103.0,127.03846153846153,1136.4848484848485,,344193857.76086956,344188351,344199621,0.7222222222222222,0.5217391304347826,138,17.209692888043477,0.0005635,2.5750000343799373e-9,3.175961580865173e-9,2.8412121591463717e-8,,f5.ptu +26,64,77,131,1,95.3125,126.44155844155844,1145.5343511450383,1702.0,399211261.2417582,399199915,399224052,0.5460992907801419,0.5183823529411765,273,19.96056306208791,0.00120685,2.382812531813959e-9,3.1610390032433576e-9,2.8638359160989054e-8,4.255000056810343e-8,f5.ptu +27,31,71,86,0,94.03225806451613,146.7605633802817,1146.7209302325582,,404720436.4893617,404713834,404727533,0.696078431372549,0.5425531914893617,188,20.236021824468086,0.0006849499999999999,2.3508064829995357e-9,3.6690141334936345e-9,2.8668023638573116e-8,,f5.ptu +28,18,52,65,0,118.77777777777777,127.86538461538461,1154.8461538461538,,404736470.3925926,404729969,404742277,0.7428571428571429,0.5185185185185185,135,20.23682351962963,0.0006154,2.9694444840907797e-9,3.196634658064265e-9,2.887115423162509e-8,,f5.ptu +29,2,3,8,0,143.5,148.33333333333334,1157.875,,418483050.46153843,418482341,418484007,0.6,0.38461538461538464,13,20.92415252307692,0.00008329999999999999,3.587500047898262e-9,3.7083333828448937e-9,2.8946875386482232e-8,,f5.ptu +30,39,24,82,0,122.33333333333333,117.33333333333333,1132.658536585366,,418494775.73103446,418489598,418500201,0.38095238095238093,0.43448275862068964,145,20.92473878655172,0.00053015,3.0583333741664625e-9,2.9333333724975335e-9,2.8316463792699482e-8,,f5.ptu +31,46,58,125,0,102.6304347826087,137.0,1141.48,,418528299.3318777,418520372,418536444,0.5576923076923077,0.45414847161572053,229,20.926414966593885,0.0008036,2.5657609038217993e-9,3.4250000457286545e-9,2.8537000381009815e-8,,f5.ptu +32,29,82,141,0,89.41379310344827,126.40243902439025,1146.177304964539,,418880495.8968254,418872325,418887728,0.7387387387387387,0.44047619047619047,252,20.94402479484127,0.0007701499999999999,2.2353448574312613e-9,3.1600610178010954e-9,2.8654433006691182e-8,,f5.ptu +33,66,43,101,0,102.68181818181819,116.18604651162791,1128.5544554455446,,434798518.9,434790785,434807147,0.3944954128440367,0.5190476190476191,210,21.739925945,0.0008181,2.5670454888191874e-9,2.90465120157195e-9,2.8213861762834066e-8,,f5.ptu +34,33,27,61,0,100.33333333333333,112.85185185185185,1126.377049180328,,434841249.1652893,434836864,434845170,0.45,0.49586776859504134,121,21.742062458264463,0.00041529999999999996,2.508333366823175e-9,2.8212963339646417e-9,2.8159426605476863e-8,,f5.ptu +35,31,48,80,0,110.64516129032258,161.39583333333334,1153.4,,446525078.6226415,446518617,446531464,0.6075949367088608,0.4968553459119497,159,22.326253931132076,0.00064235,2.766129069189848e-9,4.034895887204971e-9,2.883500038498854e-8,,f5.ptu +36,17,23,57,0,126.29411764705883,129.47826086956522,1140.8070175438597,,461989043.53608245,461984236,461994047,0.575,0.41237113402061853,97,23.09945217680412,0.00049055,3.1573529833316537e-9,3.2369565649571354e-9,2.8520175819381675e-8,,f5.ptu +37,36,21,77,0,115.80555555555556,159.61904761904762,1145.5324675324675,,487994784.5895522,487990715,487999197,0.3684210526315789,0.4253731343283582,134,24.39973922947761,0.00042409999999999995,2.8951389275431387e-9,3.990476243754762e-9,2.8638312070674158e-8,,f5.ptu +38,35,32,75,0,102.34285714285714,143.9375,1136.0133333333333,,490764698.90140843,490758125,490769889,0.47761194029850745,0.47183098591549294,142,24.53823494507042,0.0005882,2.558571462732021e-9,3.5984375480442934e-9,2.840033371251845e-8,,f5.ptu +39,41,64,116,0,105.34146341463415,131.53125,1134.646551724138,,525326103.90950227,525316495,525335629,0.6095238095238096,0.4751131221719457,221,26.266305195475113,0.0009567,2.6335366205273382e-9,3.2882812939032634e-9,2.8366164171832353e-8,,f5.ptu +40,36,33,77,0,99.75,121.48484848484848,1119.5454545454545,,542405845.5136986,542400417,542410832,0.4782608695652174,0.4726027397260274,146,27.12029227568493,0.0005207499999999999,2.4937500332951335e-9,3.0371212526711295e-9,2.7988636737324737e-8,,f5.ptu +41,9,63,69,0,126.44444444444444,146.04761904761904,1162.376811594203,,553290877.8794327,553285777,553295169,0.875,0.5106382978723404,141,27.664543893971633,0.0004696,3.161111153316471e-9,3.651190524939097e-9,2.9059420677839946e-8,,f5.ptu +42,67,64,90,0,112.53731343283582,130.1875,1138.4333333333334,,558575493.280543,558567661,558581972,0.48854961832061067,0.5927601809954751,221,27.92877466402715,0.00071555,2.8134328733842524e-9,3.2546875434547387e-9,2.8460833713326215e-8,,f5.ptu +43,28,24,88,0,94.42857142857143,114.08333333333333,1123.8977272727273,,568749676.0857143,568744867,568753917,0.46153846153846156,0.37142857142857144,140,28.437483804285716,0.0004525,2.360714317233202e-9,2.8520833714127296e-9,2.809744355695928e-8,,f5.ptu +44,35,47,104,0,109.6,151.17021276595744,1132.1634615384614,,575089437.7150538,575083421,575096691,0.573170731707317,0.44086021505376344,186,28.75447188575269,0.0006634999999999999,2.7400000365829233e-9,3.779255369607406e-9,2.8304086916361622e-8,,f5.ptu +45,85,88,211,0,109.03529411764706,127.29545454545455,1145.0331753554503,,596359166.6692709,596348323,596370636,0.5086705202312138,0.4505208333333333,384,29.817958333463544,0.00111565,2.725882389335609e-9,3.1823864061257786e-9,2.862582976608207e-8,,f5.ptu +46,19,55,70,0,97.05263157894737,141.92727272727274,1167.3857142857144,,603843112.9722222,603837800,603847920,0.7432432432432432,0.5138888888888888,144,30.19215564861111,0.0005059999999999999,2.4263158218684744e-9,3.5481818655551267e-9,2.918464324679963e-8,,f5.ptu +47,15,71,56,0,93.46666666666667,158.61971830985917,1161.357142857143,,603907036.6056339,603901897,603911594,0.8255813953488372,0.6056338028169014,142,30.19535183028169,0.00048485,2.3366666978645126e-9,3.965493010691488e-9,2.9033928959073093e-8,,f5.ptu +48,58,103,142,0,94.93103448275862,133.8640776699029,1159.725352112676,,619308212.0594059,619299502,619315138,0.639751552795031,0.5313531353135313,303,30.965410602970294,0.0007817999999999999,2.373275893755597e-9,3.346601986429501e-9,2.8993134189916754e-8,,f5.ptu +49,28,37,81,0,99.32142857142857,127.89189189189189,1140.1234567901236,,620974598.349315,620968769,620979970,0.5692307692307692,0.4452054794520548,146,31.04872991746575,0.00056005,2.4830357474377965e-9,3.1972973399857947e-9,2.850308680031011e-8,,f5.ptu +50,43,18,57,0,118.5813953488372,117.88888888888889,1137.421052631579,,625442479.9237288,625435932,625448314,0.29508196721311475,0.5169491525423728,118,31.27212399618644,0.0006190999999999999,2.964534923301716e-9,2.9472222615718593e-9,2.843552669544447e-8,,f5.ptu +51,17,41,60,0,105.11764705882354,155.1219512195122,1136.7,,661061668.0677966,661056833,661066164,0.7068965517241379,0.4915254237288136,118,33.05308340338983,0.00046655,2.627941211557366e-9,3.87804883226531e-9,2.841750037941432e-8,,f5.ptu +52,11,20,32,0,109.63636363636364,129.55,1138.53125,,661259989.7777778,661256308,661263855,0.6451612903225806,0.49206349206349204,63,33.062999488888885,0.00037735,2.7409091275041523e-9,3.2387500432419503e-9,2.8463281630025563e-8,,f5.ptu +53,34,53,63,1,99.97058823529412,122.37735849056604,1127.2698412698412,1109.0,661780501.807947,661773735,661788015,0.6091954022988506,0.58,151,33.08902509039735,0.000714,2.4992647392511157e-9,3.059434003111975e-9,2.8181746408012696e-8,2.772500037016845e-8,f5.ptu +54,34,27,61,0,111.41176470588235,132.11111111111111,1137.360655737705,,666840309.8770492,666835278,666845550,0.4426229508196721,0.5,122,33.34201549385246,0.0005136,2.7852941548347235e-9,3.3027778218745905e-9,2.843401677307746e-8,,f5.ptu +55,38,126,126,0,121.36842105263158,134.84920634920636,1157.9603174603174,,666877502.2862068,666866578,666887127,0.7682926829268293,0.5655172413793104,290,33.34387511431034,0.0010274499999999998,3.034210566826845e-9,3.371230203740909e-9,2.8949008323018644e-8,,f5.ptu +56,20,49,87,0,120.0,129.87755102040816,1139.1494252873563,,689054973.1923077,689048262,689061344,0.7101449275362319,0.4423076923076923,156,34.45274865961538,0.0006541,3.000000040054296e-9,3.246938818861486e-9,2.8478736012415807e-8,,f5.ptu +57,19,69,79,0,93.0,148.9855072463768,1160.1518987341772,,691134986.0299401,691127283,691142333,0.7840909090909091,0.5269461077844312,167,34.55674930149701,0.0007524999999999999,2.3250000310420793e-9,3.7246377308886667e-9,2.9003797855596656e-8,,f5.ptu +58,25,56,89,0,130.28,155.44642857142858,1150.8651685393259,,691255089.7882353,691248743,691260909,0.691358024691358,0.4764705882352941,170,34.562754489411766,0.0006083,3.2570000434856138e-9,3.886160766171525e-9,2.8771629597625597e-8,,f5.ptu +59,18,50,60,1,108.61111111111111,143.1,1157.1,1995.0,691631788.9224806,691626238,691636910,0.7352941176470589,0.53125,129,34.58158944612403,0.0005336,2.715277814030624e-9,3.5775000477647476e-9,2.8927500386223547e-8,4.987500066590267e-8,f5.ptu +60,24,54,110,0,105.66666666666667,127.25925925925925,1150.4454545454546,,709787208.143617,709779977,709795902,0.6923076923076923,0.4148936170212766,188,35.48936040718085,0.00079625,2.6416667019366997e-9,3.1814815239588147e-9,2.876113674763872e-8,,f5.ptu +61,41,54,97,0,94.29268292682927,115.83333333333333,1134.7319587628865,,710851146.8541666,710845040,710856468,0.5684210526315789,0.4947916666666667,192,35.54255734270833,0.0005714,2.35731710464429e-9,2.8958333719968548e-9,2.8368299347829576e-8,,f5.ptu +62,26,29,64,0,111.84615384615384,116.65517241379311,1140.109375,,715712803.2521008,715707928,715717537,0.5272727272727272,0.46218487394957986,119,35.78564016260504,0.00048045,2.796153883486504e-9,2.9163793492826677e-9,2.850273475555232e-8,,f5.ptu +63,13,10,12,0,101.23076923076923,157.4,1165.6666666666667,,717389025.0285715,717387609,717390736,0.43478260869565216,0.6571428571428571,35,35.86945125142857,0.00015635,2.5307692645586237e-9,3.935000052537885e-9,2.9141667055749647e-8,,f5.ptu +64,77,47,170,0,119.76623376623377,120.27659574468085,1138.5235294117647,,728720106.3197279,728707054,728731699,0.3790322580645161,0.4217687074829932,294,36.43600531598639,0.0012322499999999998,2.9941558841321123e-9,3.006914933763641e-9,2.8463088615317102e-8,,f5.ptu +65,65,37,114,0,123.50769230769231,129.75675675675674,1149.4473684210527,,730795855.0092592,730786816,730804187,0.3627450980392157,0.4722222222222222,216,36.53979275046296,0.0008685499999999999,3.0876923489174216e-9,3.2439189622298813e-9,2.8736184594195527e-8,,f5.ptu +66,67,18,88,0,114.7910447761194,134.38888888888889,1133.2613636363637,,744720650.450867,744712651,744727920,0.21176470588235294,0.4913294797687861,173,37.236032522543354,0.0007634499999999999,2.869776157718606e-9,3.359722267079325e-9,2.8331534469175645e-8,,f5.ptu +67,38,18,68,0,122.39473684210526,155.27777777777777,1142.5441176470588,,746863946.3709677,746858687,746869868,0.32142857142857145,0.45161290322580644,124,37.343197318548384,0.00055905,3.0598684619062566e-9,3.881944496273962e-9,2.856360332254147e-8,,f5.ptu +68,20,26,39,0,116.5,138.6153846153846,1131.3846153846155,,766022406.2705883,766018713,766024344,0.5652173913043478,0.5411764705882353,85,38.30112031352941,0.00028155,2.9125000388860456e-9,3.4653846616524624e-9,2.8284615762255505e-8,,f5.ptu +69,63,92,136,0,102.31746031746032,150.84782608695653,1151.3308823529412,,785664866.3642612,785652624,785677428,0.5935483870967742,0.5326460481099656,291,39.28324331821305,0.0012402,2.557936542088623e-9,3.771195702524775e-9,2.878327244312143e-8,,f5.ptu +70,13,56,79,0,109.07692307692308,148.91071428571428,1164.493670886076,,833735801.6486486,833730301,833741337,0.8115942028985508,0.46621621621621623,148,41.68679008243243,0.0005518,2.726923113331405e-9,3.7227679068471386e-9,2.911234216084335e-8,,f5.ptu +71,13,48,74,0,105.46153846153847,136.35416666666666,1143.2027027027027,,833765875.9111111,833759602,833770696,0.7868852459016393,0.45185185185185184,135,41.68829379555555,0.0005547,2.6365384967400254e-9,3.408854212179751e-9,2.8580067949152394e-8,,f5.ptu +72,22,31,52,0,95.68181818181819,131.8709677419355,1133.2307692307693,,853710164.0095239,853706645,853715182,0.5849056603773585,0.5047619047619047,105,42.68550820047619,0.00042685,2.3920454864826868e-9,3.2967742375650436e-9,2.833076960902557e-8,,f5.ptu +73,11,3,24,0,146.8181818181818,98.33333333333333,1140.5833333333333,,878695784.7894737,878694016,878697067,0.21428571428571427,0.3684210526315789,38,43.93478923947368,0.00015255,3.6704545944603695e-9,2.4583333661556033e-9,2.851458371404385e-8,,f5.ptu +74,111,44,233,0,103.41441441441441,116.4090909090909,1137.8755364806866,,881133908.1340206,881120118,881147124,0.2838709677419355,0.39948453608247425,388,44.056695406701024,0.0013503,2.5853603948786233e-9,2.910227311582974e-9,2.844688879182386e-8,,f5.ptu +75,46,21,85,0,106.54347826086956,118.52380952380952,1148.7176470588236,,883288533.8157895,883280908,883295162,0.31343283582089554,0.4407894736842105,152,44.16442669078947,0.0007126999999999999,2.6635869920844392e-9,2.9630952776568024e-9,2.8717941559896227e-8,,f5.ptu +76,260,112,221,1,139.21923076923076,131.96428571428572,1134.656108597285,1377.0,884197707.6430976,884183247,884215418,0.3010752688172043,0.627318718381113,594,44.20988538215488,0.0016085499999999998,3.480480815700171e-9,3.2991071869049477e-9,2.8366403093664222e-8,3.4425000459623045e-8,f5.ptu +77,76,62,105,0,118.98684210526316,120.8225806451613,1143.095238095238,,884238060.5967078,884229488,884248035,0.4492753623188406,0.5679012345679012,243,44.21190302983539,0.00092735,2.974671092347697e-9,3.020564556457894e-9,2.857738133392991e-8,,f5.ptu +78,47,32,72,0,120.14893617021276,115.625,1118.013888888889,,888191156.4238411,888186777,888195682,0.4050632911392405,0.5231788079470199,151,44.40955782119205,0.00044524999999999995,3.003723444359328e-9,2.890625038593983e-9,2.795034759539938e-8,,f5.ptu +79,59,67,149,0,102.50847457627118,132.02985074626866,1154.1073825503356,,899826096.4545455,899814835,899837545,0.5317460317460317,0.4581818181818182,275,44.99130482272727,0.0011355,2.562711898622653e-9,3.300746312726406e-9,2.8852684948983046e-8,,f5.ptu +80,89,124,197,0,106.95505617977528,140.32258064516128,1141.781725888325,,899871770.5341463,899854324,899890207,0.5821596244131455,0.5195121951219512,410,44.99358852670731,0.00179415,2.6738764401944608e-9,3.508064562966717e-9,2.8544543528318648e-8,,f5.ptu +81,100,80,118,0,111.92,123.975,1133.5,,913308804.1409396,913297639,913318303,0.4444444444444444,0.6040268456375839,298,45.66544020704698,0.0010332,2.7980000373573067e-9,3.099375041381094e-9,2.8337500378346203e-8,,f5.ptu +82,1,2,8,0,183.0,71.5,1124.25,,966219647.1818181,966218843,966220257,0.6666666666666666,0.2727272727272727,11,48.31098235909091,0.0000707,4.575000061082801e-9,1.7875000238656846e-9,2.8106250375258685e-8,,f5.ptu +83,65,20,210,0,99.6,91.35,1121.747619047619,,966268863.0338984,966262514,966275482,0.23529411764705882,0.288135593220339,295,48.31344315169491,0.0006483999999999999,2.4900000332450653e-9,2.2837500304913325e-9,2.80436908506139e-8,,f5.ptu +84,72,105,164,0,106.36111111111111,164.0952380952381,1169.4268292682927,,998980117.3489736,998971274,998987820,0.5932203389830508,0.5190615835777126,341,49.949005867448676,0.0008273,2.659027813279606e-9,4.1023810071536126e-9,2.9235671122045386e-8,,f5.ptu +85,10,2,12,0,116.3,112.0,1136.4166666666667,,1037067566.1666666,1037066084,1037068096,0.16666666666666666,0.5,24,51.853378308333326,0.00010059999999999999,2.9075000388192885e-9,2.8000000373840095e-9,2.8410417045986413e-8,,f5.ptu +86,54,13,78,1,154.03703703703704,122.53846153846153,1165.820512820513,1091.0,1041718110.5479453,1041712693,1041724112,0.19402985074626866,0.46206896551724136,146,52.08590552739726,0.00057095,3.850925977341302e-9,3.0634615793631368e-9,2.9145513209647155e-8,2.7275000364160307e-8,f5.ptu +87,115,11,131,0,155.54782608695652,124.72727272727273,1186.442748091603,,1041742571.1089494,1041734711,1041751327,0.0873015873015873,0.490272373540856,257,52.08712855544747,0.0008307999999999999,3.888695704093569e-9,3.1181818598140106e-9,2.9661069098307817e-8,,f5.ptu +88,18,32,60,0,111.83333333333333,126.46875,1122.3166666666666,,1086028713.2636364,1086024790,1086031169,0.64,0.45454545454545453,110,54.30143566318181,0.00031895,2.7958333706617116e-9,3.1617187922134728e-9,2.805791704128003e-8,,f5.ptu +89,50,70,160,0,92.8,123.08571428571429,1141.99375,,1088288552.2928572,1088279631,1088298333,0.5833333333333334,0.42857142857142855,280,54.414427614642854,0.0009350999999999999,2.3200000309753222e-9,3.077142898227121e-9,2.8549844131181297e-8,,f5.ptu +90,22,44,54,0,107.68181818181819,137.70454545454547,1147.537037037037,,1094624690.8,1094619315,1094630066,0.6666666666666666,0.55,120,54.731234539999996,0.00053755,2.6920454904881164e-9,3.4426136823274586e-9,2.868842630895749e-8,,f5.ptu +91,35,18,60,0,146.31428571428572,114.0,1132.0333333333333,,1105674648.9734514,1105669184,1105679219,0.33962264150943394,0.4690265486725664,113,55.283732448672566,0.00050175,3.6578571916947737e-9,2.850000038051581e-9,2.8300833711189985e-8,,f5.ptu +92,30,35,51,0,102.5,140.94285714285715,1162.1568627450981,,1107438627.0086207,1107434396,1107443065,0.5384615384615384,0.5603448275862069,116,55.37193135043103,0.00043345,2.5625000342130444e-9,3.523571475616153e-9,2.905392195653891e-8,,f5.ptu +93,41,37,87,0,103.34146341463415,144.3783783783784,1127.6206896551723,,1155130076.0666666,1155123732,1155137455,0.47435897435897434,0.4727272727272727,165,57.75650380333333,0.00068615,2.5835366198597666e-9,3.609459507650912e-9,2.819051761776308e-8,,f5.ptu +94,51,45,93,0,123.25490196078431,145.2888888888889,1130.7956989247311,,1160556038.3015873,1160548673,1160562986,0.46875,0.5079365079365079,189,58.027801915079365,0.00071565,3.081372590160344e-9,3.63222227071759e-9,2.8269892850561825e-8,,f5.ptu +95,45,36,100,0,111.55555555555556,143.88888888888889,1136.53,,1162370168.6464088,1162364465,1162377019,0.4444444444444444,0.44751381215469616,181,58.11850843232044,0.0006277,2.788888926124549e-9,3.59722227025029e-9,2.8413250379357574e-8,,f5.ptu +96,31,17,55,0,111.70967741935483,145.41176470588235,1134.0363636363636,,1178967371.8252428,1178961930,1178972876,0.3541666666666667,0.46601941747572817,103,58.94836859126214,0.0005473,2.7927419727709747e-9,3.6352941661834407e-9,2.8350909469434323e-8,,f5.ptu diff --git a/tests/test_ui.py b/tests/test_ui.py index 90b172e..50d6626 100644 --- a/tests/test_ui.py +++ b/tests/test_ui.py @@ -1,87 +1,55 @@ -import pandas as pd -import playwright.sync_api -import yaml +""" +playwright ui tests + + +playwright python code generator: https://playwright.dev/python/docs/codegen + +""" + from pathlib import Path + +import playwright.sync_api +import polars as pl import pytest +from IPython.display import display from dont_fret import cfg +from dont_fret.web.main import Page as MainPage cwd = Path(__file__).parent + input_dir = cwd / "test_data" / "input" data_dir = cwd / "test_data" / "output" / "web" CB_LOCATOR = "div:nth-child({}) > .v-list-item__action > .v-input > .v-input__control > .v-input__slot > .v-input--selection-controls__input > .v-input--selection-controls__ripple" -@pytest.mark.skip(reason="Takes too long") -def test_main_app( - page_session: playwright.sync_api.Page, solara_server, solara_app, tmp_path: Path -): - cfg.web.default_dir = input_dir - with solara_app("dont_fret.web.app"): - page_session.goto(solara_server.base_url) - - # switch between APBS / DCBS, fails on solara 1.12 - # Currently fails on timeout, but solara already errored - page_session.get_by_role("button", name="Burst search settings DCBS").click() - page_session.get_by_text("APBS").click() - page_session.get_by_role("button", name="Burst search settings APBS").click() - page_session.get_by_text("DCBS").click() - - page_session.get_by_text("ds2").click() - page_session.get_by_role("button", name="Add files").click() - page_session.get_by_role("button", name="Select None").click() - - for i in range(1, 6): - cb = page_session.locator(CB_LOCATOR.format(i)) - # expect(cb).not_to_be_checked() # is not a checkbox - - # Enable CBs 4 and 5 - for i in [4, 5]: - cb = page_session.locator(CB_LOCATOR.format(i)) - cb.click() - # expect(cb).to_be_checked() # is not a checkbox - - page_session.get_by_role("button", name="Search!").click() - page_session.get_by_text("Finished burst search.").wait_for() - - page_session.get_by_role("button", name="Burst set").click() - page_session.get_by_role("option", name="DCBS_default").get_by_text("DCBS_default").click() - with page_session.expect_download() as download_info: - page_session.get_by_role("button", name="Download csv").click() - download_info.value.save_as(tmp_path / "bursts.csv") - - compare_df = pd.read_csv(tmp_path / "bursts.csv") - reference_df = pd.read_csv(data_dir / "DCBS_default_bursts.csv") - - pd.testing.assert_frame_equal(reference_df, compare_df) - - with page_session.expect_download() as download_info: - page_session.get_by_role("button", name="Download settings").click() - - download_info.value.save_as(tmp_path / "settings.yaml") - burst_colors_dict = yaml.safe_load((tmp_path / "settings.yaml").read_text()) - assert burst_colors_dict == cfg.burst_search["DCBS"] - - # Set APBS settings really high, assert we dont find any bursts - page_session.get_by_role("button", name="Burst search settings DCBS").click() - page_session.get_by_text("APBS").click() - - page_session.locator(".v-sheet > .v-sheet > button").first.click() - page_session.get_by_label("L").click() - page_session.get_by_label("L").fill("5000") - page_session.get_by_label("L").press("Enter") - page_session.get_by_role("button", name="Save & close").click() - - page_session.get_by_role("button", name="Search!").click() - page_session.get_by_text("No bursts found.").wait_for() - - # open the burst view tab - page_session.get_by_role("tab", name="burst_view").click() - page_session.get_by_text("Number of bursts: 229").wait_for() - - # open the trace view tab - page_session.get_by_role("tab", name="trace_view").click() - page_session.get_by_role("button", name="Photon file").click() - page_session.get_by_text("f5.ptu").click() - page_session.get_by_text("Loaded 944419 photons.").click() +@pytest.mark.skip("fails on due to missing data files") +def test_mainpage(solara_test, page_session: playwright.sync_api.Page, tmp_path: Path): + # The test code runs in the same process as solara-server (which runs in a separate thread) + cfg.web.default_dir = input_dir / "ds2" + page = MainPage() + + display(page) + + # add photons and do burst search + page_session.get_by_role("button", name="").click() + page_session.get_by_text("Photons").click() + page_session.get_by_role("button", name="Add all files").click() + page_session.get_by_role("button", name="Search!").click() + page_session.get_by_text("Burst search completed, found").wait_for() + page_session.get_by_role("button", name="close").click() + page_session.get_by_role("button", name="Burst search settings DCBS").click() + page_session.get_by_text("APBS").click() + page_session.get_by_role("button", name="Search!").click() + + # download results and compare + page_session.get_by_role("button", name="").nth(2).click() + page_session.get_by_text("DCBS").first.click() + with page_session.expect_download() as download_info: + page_session.get_by_role("button", name="Download burst data.csv").click() + + download_info.value.save_as(tmp_path / "bursts.csv") + compare_df = pl.read_csv(tmp_path / "bursts.csv") + reference_df = pl.read_csv(data_dir / "DCBS_default_bursts.csv") + assert compare_df.equals(reference_df) diff --git a/tests/test_web.py b/tests/test_web.py index 48d3188..318c03a 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -12,10 +12,13 @@ import dont_fret.web.state as state from dont_fret import PhotonData, PhotonFile +from dont_fret.config import cfg from dont_fret.web.bursts.components import BurstFigure +from dont_fret.web.datamanager import ThreadedDataManager from dont_fret.web.home.methods import task_burst_search -from dont_fret.web.methods import burst_search, create_file_items -from dont_fret.web.models import BurstItem, FRETNode, PhotonFileItem + +# from dont_fret.web.methods import burst_search, create_file_items +from dont_fret.web.models import BurstNode, FRETNode, ListStore, PhotonNode cwd = Path(__file__).parent input_data_dir = cwd / "test_data" / "input" @@ -31,67 +34,67 @@ def ph_ds1() -> PhotonData: @pytest.fixture -def photon_file_items() -> List[PhotonFileItem]: - file_items = create_file_items(input_data_dir / "ds1") - return file_items +def photon_nodes() -> List[PhotonNode]: + pth = input_data_dir / "ds1" + return [PhotonNode(file_path=ptu_pth) for ptu_pth in pth.glob("*.ptu")] @pytest.fixture -def burst_items(photon_file_items: List[PhotonFileItem]) -> List[BurstItem]: +def burst_nodes(photon_nodes: List[PhotonNode]) -> List[BurstNode]: + dm = ThreadedDataManager() burst_settings = ["DCBS", "APBS"] - dtype = pl.Enum([item.name for item in photon_file_items]) - burst_items = [] + burst_nodes = [] for name in burst_settings: - # TODO there should be a function list[PhotonFileItem] -> BurstItem - dfs = [burst_search(f, name, dtype) for f in photon_file_items] - df = pl.concat(dfs, how="vertical_relaxed") + node = asyncio.run(dm.get_burst_node(photon_nodes, cfg.burst_search[name], name=name)) + burst_nodes.append(node) - burst_items.append(BurstItem(name=name, df=df)) - return burst_items + return burst_nodes @pytest.mark.asyncio -async def test_burst_search(ph_ds1): - ph_item = PhotonFileItem(file_path=input_data_dir / "ds1" / "datafile_1.ptu") +async def test_burst_search(): + ph_item = PhotonNode(file_path=input_data_dir / "ds1" / "datafile_1.ptu") node = FRETNode( - name="FRET NOT", - photons=[ph_item], + name=solara.Reactive("FRET NOT"), + photons=ListStore([ph_item]), ) state.fret_nodes.set([]) - assert len(state.fret_nodes.value) == 0 + assert len(state.fret_nodes) == 0 state.fret_nodes.append(node) - assert len(state.fret_nodes.value) == 1 + assert len(state.fret_nodes) == 1 - await task_burst_search.function("DCBS", node.id) # type: ignore + await task_burst_search.function("DCBS", [ph_item], node.bursts) # type: ignore new_node = state.fret_nodes.get_node(node.id) assert new_node.bursts burst_item = new_node.bursts[0] assert burst_item.name == "DCBS" - assert burst_item.df.shape == (72, 15) + assert burst_item.df.shape == (72, 22) assert burst_item.df["filename"].unique()[0] == "datafile_1.ptu" await asyncio.sleep(0) -def test_burst_figure(photon_file_items, burst_items): - state.fret_nodes.set([]) +def test_burst_figure(photon_nodes, burst_nodes): node = FRETNode( - name="FRET NOT", - photons=photon_file_items, - bursts=burst_items, + name=solara.Reactive("FRET NOT"), + photons=ListStore(photon_nodes), + bursts=ListStore(burst_nodes), ) - state.fret_nodes.append(node) - fig = BurstFigure(state.fret_nodes, state.filters) + fig = BurstFigure([node]) box, rc = solara.render(fig) - locator = rc.find(v.Select, label="Burst item") - assert locator.widget.v_model == 0 - assert locator.widget.items == [{"text": "DCBS", "value": 0}, {"text": "APBS", "value": 1}] + locator = rc.find(v.Select, label="Bursts") + locator.wait_for(timeout=3) + assert locator.widget.v_model == burst_nodes[0].id.hex + assert locator.widget.items == [ + {"text": "DCBS", "value": burst_nodes[0].id.hex}, + {"text": "APBS", "value": burst_nodes[1].id.hex}, + ] find_figure = rc.find(go.FigureWidget).wait_for(timeout=5) find_figure.assert_single() @@ -99,7 +102,7 @@ def test_burst_figure(photon_file_items, burst_items): img_ref = np.load(output_data_dir / "ds1" / "z_img_dcbs.npy") assert np.allclose(img_test, img_ref) - locator.widget.v_model = 1 + locator.widget.v_model = burst_nodes[1].id.hex time.sleep(0.5) # wait for the redraw to start find_figure = rc.find(go.FigureWidget).wait_for(timeout=5) find_figure.assert_single()