Spreading cash and fish

Here I dig a little bit into the split-among-ping process, with focus on understanding what {vmstool::splitAmongPings} does and does not do. Comparison is made using an alternative function, dc_spread_cash_and_catch that I belived is closer to the intent, at least by the current SFD members. The discrepanices revieled here may be examples of ‘corner cases’ so the overall impact may not be that large. I let the code speak a little for itself, so there is not much text to read beyond this header.
code
rtip
Author

Einar Hjörleifsson

Published

September 18, 2025

Here I run a bunch of test dataset cases and within each of them I do three tests:

Link to the documentation and script for dc_spread_cash_and_catch.R

library(vmstools)
library(tidyverse)
source("https://raw.githubusercontent.com/einarhjorleifsson/ramb/refs/heads/main/R/dc_spread_cash_and_catch.R")
# helpers to convert tacsat-eflalo speak to spread speak
to_trails <- function(tacsat) {
  tacsat |> 
    unite(col = "time", SI_DATE, SI_TIME, sep = " ") |> 
    mutate(time = dmy_hm(time, tz = "UTC")) |> 
    rename(ir = LE_RECT,
           state = SI_STATE) |> 
    as_tibble()
}
to_trails_noir <- function(tacsat) {
  tz(tacsat$SI_DATIM) <- "UTC"
  tacsat$LE_RECT <- vmstools::ICESrectangle(tacsat)
  tacsat |> 
    rename(time = SI_DATIM) |> 
    #unite(col = "time", SI_DATE, SI_TIME, sep = " ") |> 
    #mutate(time = dmy_hm(time, tz = "UTC")) |> 
    rename(ir = LE_RECT,
           state = SI_STATE) |> 
    as_tibble()
}
to_events <- function(eflalo) {
  eflalo |> 
    select(-c(FT_DDAT, FT_DTIME, FT_LDAT, FT_LTIME)) |> 
    rename(date = LE_CDAT) |> 
    mutate(date = dmy(date)) |> 
    as_tibble()
}
# helpers for the output printout
lh <- function(d) {
  d |> 
    select(.pid, FT_REF:SI_STATE, SI_DATIM, LE_KG)
}
lh2 <- function(d) {
  d |> 
    select(.pid, FT_REF:LE_KG, .how)
}

Some artifical data

time = seq(from = as.POSIXct("2025-01-01 09:00:00", tz="UTC"), 
           to   = as.POSIXct("2025-01-01 16:00:00", tz="UTC"), 
           by = "hour")
N <- length(time)
tacsat <- 
  tibble(.pid = 1:N,
         VE_COU = rep("IS", N),
         VE_REF = rep("A", N),
         FT_REF = rep("trip1", N),
         LE_RECT = c("A1", "A1", "A1", "A2", "A2", "A3", "A3", "A3"),
         SI_STATE = c(1, 1, 0, 1, 1, 0 , 1, 1),
         time = time) |> 
  mutate(SI_STATE = as.integer(SI_STATE)) |> 
  mutate(SI_DATE = format(as_date(time), "%d/%m/%Y"),
         SI_TIME = str_sub(as.character(time), 12, 16)) |> 
  #select(-time) |> 
  as.data.frame()
N <- 5
eflalo <- 
  tibble(.eid = 1:N,
         VE_COU = rep("IS",N),
         VE_REF = rep("A", N),
         FT_REF = c(rep("trip1", N - 1), "trip1"),
         LE_CDAT = c("01/01/2025", "01/01/2025", NA, NA, "01/01/2025"),
         LE_RECT = c("A1", "A1", "A2", NA, "B1"),
         LE_KG = c(133, 100, 2333, 12, 10000)) |> 
  mutate(.eid = as.integer(.eid),
         LE_EURO = LE_KG * 1.3) |> 
  mutate(T1 = min(tacsat$time),
         T2 = max(tacsat$time),
         FT_DDAT = format(as_date(T1), "%d/%m/%Y"),
         FT_DTIME = str_sub(as.character(T2), 12, 16),
         FT_LDAT = format(as_date(T2), "%d/%m/%Y"),
         FT_LTIME = str_sub(as.character(T2), 12, 16)) |> 
  select(-c(T1, T2)) |> 
  as.data.frame()
tacsat <- tacsat |> select(-time)

Data view

eflalo |> select(.eid:LE_KG)
  .eid VE_COU VE_REF FT_REF    LE_CDAT LE_RECT LE_KG
1    1     IS      A  trip1 01/01/2025      A1   133
2    2     IS      A  trip1 01/01/2025      A1   100
3    3     IS      A  trip1       <NA>      A2  2333
4    4     IS      A  trip1       <NA>    <NA>    12
5    5     IS      A  trip1 01/01/2025      B1 10000
tacsat |> 
  mutate(
    how = case_when(.pid %in% 1:2 ~ "trip-rect-day",
                    .pid %in% 4:5 ~ "trip_rect",
                    .pid %in% 7:8 ~ "trip",
                    .default = ""),
    eflalo_id = case_when(.pid %in% 1:2 ~ "1, 2",
                          .pid %in% 4:5 ~ "3",
                          .pid %in% 7:8 ~ "4",
                          .default = "")) |> 
  select(.pid, FT_REF:eflalo_id)
  .pid FT_REF LE_RECT SI_STATE    SI_DATE SI_TIME           how eflalo_id
1    1  trip1      A1        1 01/01/2025   09:00 trip-rect-day      1, 2
2    2  trip1      A1        1 01/01/2025   10:00 trip-rect-day      1, 2
3    3  trip1      A1        0 01/01/2025   11:00                        
4    4  trip1      A2        1 01/01/2025   12:00     trip_rect         3
5    5  trip1      A2        1 01/01/2025   13:00     trip_rect         3
6    6  trip1      A3        0 01/01/2025   14:00                        
7    7  trip1      A3        1 01/01/2025   15:00          trip         4
8    8  trip1      A3        1 01/01/2025   16:00          trip         4

The eflalo_id is my expectation of how eflalo data will be assigned to pings. Will not repeat this process downstream, make your own inference.

Test 1

splitAmongPings(tacsat, eflalo, conserve = FALSE, returnAll = TRUE) |> lh()
[1] "level: day"
[1] "kg in eflalo 536"
[1] "kg in merged tacsat 536"
[1] "kg removed from eflalo 536"
   .pid FT_REF LE_RECT SI_STATE            SI_DATIM LE_KG
1     1  trip1      A1        1 2025-01-01 09:00:00 116.5
2     2  trip1      A1        1 2025-01-01 10:00:00 116.5
31    3  trip1      A1        0 2025-01-01 11:00:00    NA
3     4  trip1      A2        1 2025-01-01 12:00:00    NA
4     5  trip1      A2        1 2025-01-01 13:00:00    NA
61    6  trip1      A3        0 2025-01-01 14:00:00    NA
5     7  trip1      A3        1 2025-01-01 15:00:00    NA
6     8  trip1      A3        1 2025-01-01 16:00:00    NA
splitAmongPings(tacsat, eflalo, conserve = TRUE,  returnAll = TRUE) |> lh()
[1] "level: day"
[1] "kg in eflalo 536"
[1] "kg in merged tacsat 536"
[1] "kg removed from eflalo 536"
   .pid FT_REF LE_RECT SI_STATE            SI_DATIM LE_KG
1     1  trip1      A1        1 2025-01-01 09:00:00 116.5
2     2  trip1      A1        1 2025-01-01 10:00:00 116.5
31    3  trip1      A1        0 2025-01-01 11:00:00    NA
3     4  trip1      A2        1 2025-01-01 12:00:00    NA
4     5  trip1      A2        1 2025-01-01 13:00:00    NA
61    6  trip1      A3        0 2025-01-01 14:00:00    NA
5     7  trip1      A3        1 2025-01-01 15:00:00    NA
6     8  trip1      A3        1 2025-01-01 16:00:00    NA
test1 <- dc_spread_cash_and_catch(to_trails(tacsat), to_events(eflalo))
test1 |> lh2()
# A tibble: 8 × 7
   .pid FT_REF ir    state time                LE_KG .how                
  <int> <chr>  <chr> <int> <dttm>              <dbl> <chr>               
1     1 trip1  A1        1 2025-01-01 09:00:00  116. 1 trip_rectangle_day
2     2 trip1  A1        1 2025-01-01 10:00:00  116. 1 trip_rectangle_day
3     3 trip1  A1        0 2025-01-01 11:00:00   NA  <NA>                
4     4 trip1  A2        1 2025-01-01 12:00:00 1166. 2 trip_rectangle    
5     5 trip1  A2        1 2025-01-01 13:00:00 1166. 2 trip_rectangle    
6     6 trip1  A3        0 2025-01-01 14:00:00   NA  <NA>                
7     7 trip1  A3        1 2025-01-01 15:00:00 5006  3 trip              
8     8 trip1  A3        1 2025-01-01 16:00:00 5006  3 trip              
near(sum(test1$LE_KG, na.rm = TRUE), sum(eflalo$LE_KG))
[1] TRUE

Test 2

# Lets change rectangle of the last trail
tacsat$LE_RECT[8] <- "B1"
splitAmongPings(tacsat, eflalo, conserve = FALSE, returnAll = TRUE) |> lh()
[1] "level: day"
[1] "kg in eflalo 23536"
[1] "kg in merged tacsat 23536"
[1] "kg removed from eflalo 23536"
   .pid FT_REF LE_RECT SI_STATE            SI_DATIM   LE_KG
1     1  trip1      A1        1 2025-01-01 09:00:00   116.5
2     2  trip1      A1        1 2025-01-01 10:00:00   116.5
31    3  trip1      A1        0 2025-01-01 11:00:00      NA
3     4  trip1      A2        1 2025-01-01 12:00:00      NA
4     5  trip1      A2        1 2025-01-01 13:00:00      NA
61    6  trip1      A3        0 2025-01-01 14:00:00      NA
5     7  trip1      A3        1 2025-01-01 15:00:00      NA
6     8  trip1      B1        1 2025-01-01 16:00:00 10000.0
splitAmongPings(tacsat, eflalo, conserve = TRUE,  returnAll = TRUE) |> lh()
[1] "level: day"
[1] "kg in eflalo 23536"
[1] "kg in merged tacsat 23536"
[1] "kg removed from eflalo 23536"
   .pid FT_REF LE_RECT SI_STATE            SI_DATIM   LE_KG
1     1  trip1      A1        1 2025-01-01 09:00:00   116.5
2     2  trip1      A1        1 2025-01-01 10:00:00   116.5
31    3  trip1      A1        0 2025-01-01 11:00:00      NA
3     4  trip1      A2        1 2025-01-01 12:00:00      NA
4     5  trip1      A2        1 2025-01-01 13:00:00      NA
61    6  trip1      A3        0 2025-01-01 14:00:00      NA
5     7  trip1      A3        1 2025-01-01 15:00:00      NA
6     8  trip1      B1        1 2025-01-01 16:00:00 10000.0
test2 <- dc_spread_cash_and_catch(to_trails(tacsat), to_events(eflalo))
test2 |> lh2()
# A tibble: 8 × 7
   .pid FT_REF ir    state time                 LE_KG .how                
  <int> <chr>  <chr> <int> <dttm>               <dbl> <chr>               
1     1 trip1  A1        1 2025-01-01 09:00:00   116. 1 trip_rectangle_day
2     2 trip1  A1        1 2025-01-01 10:00:00   116. 1 trip_rectangle_day
3     3 trip1  A1        0 2025-01-01 11:00:00    NA  <NA>                
4     4 trip1  A2        1 2025-01-01 12:00:00  1166. 2 trip_rectangle    
5     5 trip1  A2        1 2025-01-01 13:00:00  1166. 2 trip_rectangle    
6     6 trip1  A3        0 2025-01-01 14:00:00    NA  <NA>                
7     7 trip1  A3        1 2025-01-01 15:00:00    12  3 trip              
8     8 trip1  B1        1 2025-01-01 16:00:00 10000  1 trip_rectangle_day
near(sum(test2$LE_KG, na.rm = TRUE), sum(eflalo$LE_KG))
[1] TRUE

Test 3

# Now lets make the last eflalo record a separate trip
eflalo$FT_REF[5] <- "trip2"
splitAmongPings(tacsat, eflalo, conserve = FALSE, returnAll = TRUE) |> lh()
[1] "level: day"
[1] "kg in eflalo 536"
[1] "kg in merged tacsat 536"
[1] "kg removed from eflalo 536"
   .pid FT_REF LE_RECT SI_STATE            SI_DATIM LE_KG
1     1  trip1      A1        1 2025-01-01 09:00:00 116.5
2     2  trip1      A1        1 2025-01-01 10:00:00 116.5
31    3  trip1      A1        0 2025-01-01 11:00:00    NA
3     4  trip1      A2        1 2025-01-01 12:00:00    NA
4     5  trip1      A2        1 2025-01-01 13:00:00    NA
61    6  trip1      A3        0 2025-01-01 14:00:00    NA
5     7  trip1      A3        1 2025-01-01 15:00:00    NA
6     8  trip1      B1        1 2025-01-01 16:00:00    NA
splitAmongPings(tacsat, eflalo, conserve = TRUE,  returnAll = TRUE) |> lh()
[1] "level: day"
[1] "kg in eflalo 536"
[1] "kg in merged tacsat 536"
[1] "kg removed from eflalo 536"
[1] "level: day & conserve = T, by vessel"
[1] "kg in eflalo 23000"
[1] "kg in merged tacsat 23000"
[1] "kg removed from eflalo 23000"
[1] "level: year & conserve = T, by vessel"
[1] "kg in eflalo 0"
[1] "kg in merged tacsat 0"
[1] "kg removed from eflalo 0"
   .pid FT_REF LE_RECT SI_STATE            SI_DATIM   LE_KG
1     1  trip1      A1        1 2025-01-01 09:00:00   116.5
2     2  trip1      A1        1 2025-01-01 10:00:00   116.5
31    3  trip1      A1        0 2025-01-01 11:00:00      NA
3     4  trip1      A2        1 2025-01-01 12:00:00     0.0
4     5  trip1      A2        1 2025-01-01 13:00:00     0.0
61    6  trip1      A3        0 2025-01-01 14:00:00      NA
5     7  trip1      A3        1 2025-01-01 15:00:00     0.0
6     8  trip1      B1        1 2025-01-01 16:00:00 10000.0
test3 <- dc_spread_cash_and_catch(to_trails(tacsat), to_events(eflalo))
test3 |> lh2()
# A tibble: 8 × 7
   .pid FT_REF ir    state time                LE_KG .how                
  <int> <chr>  <chr> <int> <dttm>              <dbl> <chr>               
1     1 trip1  A1        1 2025-01-01 09:00:00  116. 1 trip_rectangle_day
2     2 trip1  A1        1 2025-01-01 10:00:00  116. 1 trip_rectangle_day
3     3 trip1  A1        0 2025-01-01 11:00:00   NA  <NA>                
4     4 trip1  A2        1 2025-01-01 12:00:00 1166. 2 trip_rectangle    
5     5 trip1  A2        1 2025-01-01 13:00:00 1166. 2 trip_rectangle    
6     6 trip1  A3        0 2025-01-01 14:00:00   NA  <NA>                
7     7 trip1  A3        1 2025-01-01 15:00:00    6  3 trip              
8     8 trip1  B1        1 2025-01-01 16:00:00    6  3 trip              
near(sum(test3$LE_KG, na.rm = TRUE), sum(eflalo$LE_KG))
[1] FALSE

Test 4

# Now lets make the last tacsat record a separate trip
tacsat$FT_REF[8] <- "trip2"
splitAmongPings(tacsat, eflalo, conserve = FALSE, returnAll = TRUE) |> lh()
[1] "level: day"
[1] "kg in eflalo 23536"
[1] "kg in merged tacsat 23536"
[1] "kg removed from eflalo 23536"
   .pid FT_REF LE_RECT SI_STATE            SI_DATIM   LE_KG
1     1  trip1      A1        1 2025-01-01 09:00:00   116.5
2     2  trip1      A1        1 2025-01-01 10:00:00   116.5
31    3  trip1      A1        0 2025-01-01 11:00:00      NA
3     4  trip1      A2        1 2025-01-01 12:00:00      NA
4     5  trip1      A2        1 2025-01-01 13:00:00      NA
61    6  trip1      A3        0 2025-01-01 14:00:00      NA
5     7  trip1      A3        1 2025-01-01 15:00:00      NA
6     8  trip2      B1        1 2025-01-01 16:00:00 10000.0
splitAmongPings(tacsat, eflalo, conserve = TRUE,  returnAll = TRUE) |> lh()
[1] "level: day"
[1] "kg in eflalo 23536"
[1] "kg in merged tacsat 23536"
[1] "kg removed from eflalo 23536"
   .pid FT_REF LE_RECT SI_STATE            SI_DATIM   LE_KG
1     1  trip1      A1        1 2025-01-01 09:00:00   116.5
2     2  trip1      A1        1 2025-01-01 10:00:00   116.5
31    3  trip1      A1        0 2025-01-01 11:00:00      NA
3     4  trip1      A2        1 2025-01-01 12:00:00      NA
4     5  trip1      A2        1 2025-01-01 13:00:00      NA
61    6  trip1      A3        0 2025-01-01 14:00:00      NA
5     7  trip1      A3        1 2025-01-01 15:00:00      NA
6     8  trip2      B1        1 2025-01-01 16:00:00 10000.0
test4 <- dc_spread_cash_and_catch(to_trails(tacsat), to_events(eflalo))
test4 |> lh2()
# A tibble: 8 × 7
   .pid FT_REF ir    state time                 LE_KG .how                
  <int> <chr>  <chr> <int> <dttm>               <dbl> <chr>               
1     1 trip1  A1        1 2025-01-01 09:00:00   116. 1 trip_rectangle_day
2     2 trip1  A1        1 2025-01-01 10:00:00   116. 1 trip_rectangle_day
3     3 trip1  A1        0 2025-01-01 11:00:00    NA  <NA>                
4     4 trip1  A2        1 2025-01-01 12:00:00  1166. 2 trip_rectangle    
5     5 trip1  A2        1 2025-01-01 13:00:00  1166. 2 trip_rectangle    
6     6 trip1  A3        0 2025-01-01 14:00:00    NA  <NA>                
7     7 trip1  A3        1 2025-01-01 15:00:00    12  3 trip              
8     8 trip2  B1        1 2025-01-01 16:00:00 10000  1 trip_rectangle_day
near(sum(test4$LE_KG, na.rm = TRUE), sum(eflalo$LE_KG))
[1] TRUE

Test 5

Prepare {vmstools} demo datasets

data(eflalo)

idx_kg <- grep("LE_KG_", colnames(eflalo)[!colnames(eflalo) %in% c("LE_KG_TOT")])
idx_euro <- grep("LE_EURO_", colnames(eflalo)[!colnames(eflalo) %in% c("LE_EURO_TOT")])
# Calculate the total KG and EURO for each row
if(!"LE_KG_TOT" %in% names(eflalo)) eflalo$LE_KG_TOT <- rowSums(eflalo[, idx_kg], na.rm = TRUE)
if(!"LE_EURO_TOT" %in% names(eflalo)) eflalo$LE_EURO_TOT <- rowSums(eflalo[, idx_euro], na.rm = TRUE)
# Remove the columns used for the total calculation
eflalo <- eflalo[, -c(idx_kg, idx_euro)]

eflalo <- 
  eflalo |> 
  select(VE_COU, VE_REF, FT_REF, FT_DDAT, FT_DTIME, FT_LDAT, FT_LTIME, LE_CDAT, LE_RECT, LE_KG_TOT, LE_EURO_TOT)

data(tacsat)
tacsat <- tacsat |> filter(!is.na(SI_SP))
tacsatp <- 
  mergeEflalo2Tacsat(eflalo,tacsat) |> 
  filter(FT_REF != "0") |> 
  filter(!is.na(SI_SP)) |> 
  mutate(SI_STATE = case_when(between(SI_SP, 0.5, 6) ~ 1L,
                              !between(SI_SP, 0.5, 6) ~ 0L,
                              .default = NA_integer_))
eflalo <- 
  eflalo |> 
  filter(FT_REF %in% unique(tacsatp$FT_REF))
trails <- 
  tacsatp |> 
  to_trails_noir() |> 
  mutate(.pid = 1:n(),
         .pid = as.integer(.pid)) 
events <- 
  eflalo |> 
  rename(LE_KG = LE_KG_TOT, LE_EURO = LE_EURO_TOT) |> 
  to_events() |> 
  mutate(.eid = 1:n())

Run the spreads

test_vmstools1 <- splitAmongPings(tacsatp, eflalo, conserve = FALSE, returnAll = TRUE)
[1] "level: day"
[1] "kg in eflalo 57215296"
[1] "kg in merged tacsat 57215296"
[1] "kg removed from eflalo 57215296"
test_vmstools2 <- splitAmongPings(tacsatp, eflalo, conserve = TRUE, returnAll = TRUE)
[1] "level: day"
[1] "kg in eflalo 57215296"
[1] "kg in merged tacsat 57215296"
[1] "kg removed from eflalo 57215296"
[1] "level: day & conserve = T, by vessel"
[1] "kg in eflalo 0"
[1] "kg in merged tacsat 0"
[1] "kg removed from eflalo 0"
[1] "level: year & conserve = T, by vessel"
[1] "kg in eflalo 288955"
[1] "kg in merged tacsat 288955"
[1] "kg removed from eflalo 288955"
[1] "level: day & conserve = T, no vessel match"
[1] "kg in eflalo 437366"
[1] "kg in merged tacsat 437366"
[1] "kg removed from eflalo 437366"
[1] "level: year & conserve = T, no vessel match"
[1] "kg in eflalo 2905083"
[1] "kg in merged tacsat 2905083"
[1] "kg removed from eflalo 2905083"
myway <- dc_spread_cash_and_catch(trails, events)

comp <- 
  tibble(
    what = c("eflalo", "splitting 1, conserve = FALSE", 
             "splitting 2, conserve = TRUE", "spead"),
    mass = c(sum(eflalo$LE_KG_TOT) / 1e6,
             sum(test_vmstools1$LE_KG_TOT, na.rm = TRUE) / 1e6,
             sum(test_vmstools2$LE_KG_TOT, na.rm = TRUE) / 1e6,
             sum(myway$LE_KG, na.rm = TRUE) / 1e6))
comp |> 
  knitr::kable(
    caption = "Catch total - comparisons of split methods and settings")
Catch total - comparisons of split methods and settings
what mass
eflalo 89.17854
splitting 1, conserve = FALSE 12.95100
splitting 2, conserve = TRUE 14.87392
spead 87.25344

Trips where mass is not conserved during spreading

Here I will only list the non-mass balance trip cases for the spread-process, for the split-process it would just be too long:

events |> 
  group_by(FT_REF) |> 
  summarise(pre = sum(LE_KG) / 1e3) |> 
  left_join(myway |> 
              group_by(FT_REF) |> 
              summarise(post = sum(LE_KG, na.rm = TRUE) / 1e3,
                        pings = n(),
                        n_fishing = sum(state))) |> 
  mutate(near = near(pre, post)) |> 
  filter(!near) |> 
  knitr::kable(caption = "Trips with only partial or no spreadings")
Trips with only partial or no spreadings
FT_REF pre post pings n_fishing near
271689 3.0794043 0.0000000 1 0 FALSE
272423 12.9774769 6.4892485 46 44 FALSE
272516 6.5788797 3.2897644 26 24 FALSE
272633 3.0793687 1.5388127 18 16 FALSE
273018 3.6193236 1.8078542 15 14 FALSE
273053 3.9752005 2.8754039 49 3 FALSE
273060 2.9345390 0.0000000 1 0 FALSE
273138 4.8779714 2.4391119 24 21 FALSE
273211 4.2151596 0.0000000 4 0 FALSE
274481 15.3598346 5.1195113 18 15 FALSE
287564 0.1652635 0.0000000 4 0 FALSE
288639 0.5802868 0.2898483 22 22 FALSE
290615 1.7803591 0.8900645 5 3 FALSE
291730 3.3515433 1.6768844 18 15 FALSE
291731 12.6399864 6.3184741 23 20 FALSE
291732 0.5998375 0.2996214 9 9 FALSE
291982 5.5066633 0.0000000 11 0 FALSE
292224 2.8267026 1.4895558 32 20 FALSE
292366 3.2998105 1.6499542 11 10 FALSE
292912 10.4922207 5.2462261 53 40 FALSE
296632 1738.0404093 0.0000000 1 0 FALSE
298618 0.2198232 0.1100109 60 43 FALSE
298736 0.7040151 0.3542368 85 76 FALSE
302290 7.4899575 3.7449258 35 26 FALSE
302320 2.5760675 1.2874603 11 9 FALSE
302978 11.5028956 5.7512173 40 36 FALSE
303566 0.0649724 0.0000000 21 0 FALSE
304028 1.4310910 0.0000000 7 0 FALSE
304409 8.3394137 4.1684286 21 18 FALSE
307549 0.0301983 0.0000000 2 0 FALSE
308915 0.0421952 0.0000000 2 0 FALSE
309048 1.7700934 0.0000000 1 0 FALSE
309695 1.8579194 0.0000000 12 0 FALSE
309951 0.1499060 0.0000000 7 0 FALSE
310329 0.0399264 0.0000000 4 0 FALSE
312143 0.0802948 0.0402008 12 7 FALSE
313040 0.2012608 0.0000000 9 0 FALSE
313993 1.4034780 0.7027758 11 6 FALSE
316755 15.0986104 0.0000000 25 0 FALSE
317101 3.7175365 1.8592935 54 48 FALSE
317426 8.5309829 0.0000000 1 0 FALSE
317581 7.3954041 2.4651845 42 37 FALSE
317597 5.6598791 2.8297489 46 38 FALSE
317618 1.4999954 0.7499121 18 17 FALSE
317801 3.6207399 1.8094879 23 20 FALSE
317846 1.6048712 0.5193498 12 2 FALSE
317897 3.3475789 1.1160429 21 18 FALSE
317898 4.0785134 1.3585665 22 16 FALSE
317905 2.1402949 1.0717649 15 10 FALSE
317906 0.8812796 0.0000000 6 0 FALSE
318001 8.2294625 0.0000000 1 0 FALSE
318019 19.0581830 0.0000000 14 0 FALSE
318276 0.6175826 0.3091527 10 6 FALSE
318282 1.5806380 0.7887007 23 22 FALSE
318302 2.8020617 1.4007680 37 33 FALSE
318484 2.5950273 0.8650927 18 12 FALSE
318935 0.1213109 0.0000000 3 0 FALSE
319065 3.7588260 1.8793704 38 33 FALSE
319150 9.9160091 3.3046616 42 38 FALSE
319159 4.3207604 2.1609422 49 45 FALSE
319439 0.4515615 0.0000000 11 0 FALSE
321747 0.0519695 0.0000000 3 0 FALSE
326484 1.8271857 0.0000000 2 0 FALSE
326486 1.5308389 0.0000000 4 0 FALSE
326495 3.5408965 0.0000000 5 0 FALSE
326496 2.9980388 0.0000000 2 0 FALSE
326499 8.3080183 0.0000000 6 0 FALSE

… so guess some little more work may we warranted, after some group discussion.