Giter Club home page Giter Club logo

Comments (14)

jgeller112 avatar jgeller112 commented on August 29, 2024

Hi Bonnie,

I would actually hold off on using the velocity function. I am going to incorporate Ronen's blink algo which does not require thresholds to be passed: https://link.springer.com/article/10.3758/s13428-017-1008-1. I will probably push that sometime in the next week or so.

mutate(extendpupil=extend_blinks(blinks_pupil, fillback=fillback, fillforward=fillforward, hz=hz)) %>%

You are correct! I should not have defined it again :)

Moreover, I am wondering if blink extension and interpolation need to be incorporated in this function at all... I find it odd not to give the choice of interpolation type (linear or cubic) or max gap which you have incorporated into the interpolation function.

This was roughly based on something Sebastiaan did in his blink paper. I could not quite capture what he did in that paper so I opted for a basic velocity measure. It is not the most elegant and I think Ronen's algo is a bit better and does not require interpolation or extending the blinks.

I do agree with you that interpolation should probably be taken out.

from gazer.

jgeller112 avatar jgeller112 commented on August 29, 2024

How is a basic velocity measure working for your group? I would be interested to know.

from gazer.

jgeller112 avatar jgeller112 commented on August 29, 2024

In this vignette I do separate them: https://github.com/dmirman/gazer/blob/master/vignettes/blink_detection.Rmd.
Not sure why I combined them.

from gazer.

bzuck-temple avatar bzuck-temple commented on August 29, 2024

oh great! Thanks for the clarity. I looked over Sebastiaan's paper and couldn't quite understand how you got here. We have not implemented velocity in our pipeline. I just starting working today to compare all of the options out there to see which we want to use moving forward. I started with what was implemented in Gazer (NA+extension, blink velocity+extension, MAD+extension) and then moved on to other options out there (Hampel filter, Ronens, etc.). I have the R code from osf for the noised based algo. Do you think you will change it substantially (other than fitting it to gazer format)?

I'm get justing the code down and then will run some tests. I'll let you know how they go!

from gazer.

jgeller112 avatar jgeller112 commented on August 29, 2024

When did you last download Ronen's code? I actually worked with him and Paul a month ago to fix some errors. I also wrote a bit of code to actually use the function.

from gazer.

jgeller112 avatar jgeller112 commented on August 29, 2024

I do not plan to change the function much. I will actually probably share my vignette/blog on how to use it with gazeR as well.

from gazer.

bzuck-temple avatar bzuck-temple commented on August 29, 2024

Just checked- I have the most up to date version of the code. Let me know when you post it. I was able to test it for one trial but I haven't had the chance to edit it to be able to run it grouped by subject x trial. Although I do not have an example to point to, I imagine there may be times where blinks are recorded with these sharp changes without having missing data. I think one draw back to their approach is the reliance on missing data.

from gazer.

jgeller112 avatar jgeller112 commented on August 29, 2024

Below is some code that will help you on your journey.

#this applies the noise function to each trail by subject
df_blinks<-interp_graph %>%
  dplyr::group_by(subject, trial) %>%
  dplyr::summarise(Blink_Index = list(noise_based_blink_detection(as.matrix(interp_graph$pupil), 250))) %>%
  unnest(c(Blink_Index))

The noise_based_blink_detection should be included in gazeR now.

#this will merge the blink data to your main df/tibble which is interp_graph above
i1 <- match(interp_graph$time, df_blinks$Blink_Index) # need to  match on time and not index to correspond to sampling rate
interp_graph[names(df_blinks)[1:2]] <- lapply(df_blinks[1:2], `[`, i1)

# once merged onsets must be duplicated across until offset in order to mark as blinks
blinks <- interp_graph %>%
        dplyr::group_by(grp = cumsum(!is.na(Label))) %>%
        dplyr::mutate(Label = replace(Label, first(Label) == 'Onset', 'Onset')) %>%
        dplyr::mutate(Blinks_New=ifelse(Label=="Onset" | Label=="Offset", 1, 0)) %>% #turn Onset and Offset 1
        mutate(Blinks_New=ifelse(is.na(Blinks_New), 0, Blinks_New)) %>% # turn rest of values 0 
        dplyr::ungroup()

Blink_Pupil<- blinks %>% 
        group_by(subject, trial) %>%
        mutate(blinks_pupil=ifelse(Blinks_New==1, pupil==NA, pupil)) %>%
         mutate(blinks_pupil=ifelse(blinks_pupil==0, NA, blinks_pupil))
  

from gazer.

ZKorda avatar ZKorda commented on August 29, 2024

Hi!
I cannot make the code from your last comment work. The first part workers, but merging the blink data with previous data does not. There is also no column called "Label" with values "Onset" and "Offset" - I am not sure where should this come from? Also, when I try to match and make "i1" it results in NAs with length nrow(interp_graph). Is there a way around this?

Best,
Ziva

from gazer.

jgeller112 avatar jgeller112 commented on August 29, 2024

Hi,

Have a look at this document. I want to say that I did not write this code and have not had time to extensively validate it. IMHO I would probably use the forward and backward fill method to treat blinks and then interpolate.

Blink Detetcion.pdf

The algo is from here: https://pubmed.ncbi.nlm.nih.gov/29340968/

from gazer.

bzuck-temple avatar bzuck-temple commented on August 29, 2024

Hi Jason & Ziva

The pdf fills in a few missing pieces but it still fails when trying to apply the function across subject and trials. My issue was that blinks that occurred in one trial were repeated for every other trial. Below is my fix (see points 2 & 4).

I agree that the forward and backward fill method is a good way to treat blinks. That is the method my group uses and will likely continue to use.

bz

  1. You have to move NAs back to 0 in the pupil column (ew)
pupil_files <- pupil_files %>%  
  dplyr::mutate(pupil=ifelse(is.na(pupil), 0, pupil))
  1. DIFFERENT THAN ABOVE - Do not include the datafile when passing the pupil column in the noise detection function.
df_blinks <- pupil_files %>% 
  group_by(subject, trial) %>% 
  dplyr::summarise(Blink_Index= list(noise_based_blink_detection(as.matrix(pupil), 1000))) %>% 
  unnest(c(Blink_Index)) 
  1. Assign labels to the blink index
df_blinks$Label <- rep(c("Onset", "Offset"), length.out=nrow(df_blinks))
  1. DIFFERENT THAN ABOVE -use dplyr left_join function to match blink index and time (so to include subject and trial)
pupil_files <- left_join(pupil_files, df_blinks, by=c("subject", "trial", c("time"="Blink_Index")))
  1. The rest of the code you provided worked for me.
###----------  CODE from JGeller: WORKING  ----------###
blinks <- pupil_files %>%
  dplyr::group_by(grp = cumsum(!is.na(Label))) %>%
  dplyr::mutate(Label = replace(Label, first(Label) == 'Onset', 'Onset')) %>%
  dplyr::mutate(Blinks_New=ifelse(Label=="Onset" | Label=="Offset", 1, 0)) %>% #turn Onset and Offset 1
  mutate(Blinks_New=ifelse(is.na(Blinks_New), 0, Blinks_New)) %>% # turn rest of values 0 
  dplyr::ungroup()


Blink_Pupil<- blinks %>% 
  group_by(subject, trial) %>%
  mutate(blinks_pupil=ifelse(Blinks_New==1, pupil==NA, pupil)) %>%
  mutate(blinks_pupil=ifelse(blinks_pupil==0, NA, blinks_pupil))
  1. You can plot a trial to test if its working
###---------- Plot Blinks ----------###
blink_graph <- Blink_Pupil  %>%
  dplyr::filter(subject=="YOUR SUBJECT", trial=="YOUR TRIAL")
bold <- element_text(face = "bold", color = "black", size = 14) #axis bold

#Graph
pup_g<- ggplot(blink_graph, aes(x=time, y= pupil)) + geom_point() +
  geom_line(aes(x=time, y=blinks_pupil), colour="green") + xlab("Time (ms)") + ylab("Pupil Size (arbitrary units)") + theme_bw() + theme(axis.title.y=element_text(size = 16, face="bold"), axis.title.x = element_text(size=16, face="bold"), axis.text.x=element_text(size = 12, face="bold"), axis.text.y=element_text(size=12, face="bold")) 
print(pup_g)
  1. Move on to interpolation

from gazer.

jgeller112 avatar jgeller112 commented on August 29, 2024

Thanks for looking into this @bzuck-temple :). I'm glad you fixed some of the kinks. Did you ever figure out what the best method was?

from gazer.

jgeller112 avatar jgeller112 commented on August 29, 2024

@bzuck-temple can share how the noise algo worked on your data? In my sample data I had some artifacts and it didn’t do a great job.

from gazer.

bzuck-temple avatar bzuck-temple commented on August 29, 2024

Anecdotally, I found that it struggled with marking the offset. It kept more of what I would identify as part of the blink than I would have liked.

I only compared the methods visually- never got around to doing a systematic comparison.

from gazer.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.