1818
1919from ndx_fiber_photometry import FiberPhotometryResponseSeries , ExcitationSource , OpticalFiber , Photodetector
2020from .plotting .plot_photometry import (
21- plot_raw_photometry_signals ,
22- plot_405_470_correlation ,
23- plot_405_565_correlation ,
24- plot_470_565_correlation ,
25- plot_ratio_565_correlation ,
26- plot_normalized_signals
21+ plot_signal_correlation ,
22+ plot_photometry_signals ,
2723)
2824
2925# Get the location of the resources directory when the package is installed from pypi
@@ -501,15 +497,12 @@ def process_and_add_pyphotometry_to_nwb(nwbfile: NWBFile, ppd_file_path, logger,
501497 raw_405 = pd .Series (ppd_data ['analog_3' ])
502498 relative_raw_signal = raw_green / raw_405
503499
504- # Get port visits and sampling rate from ppd file
500+ # Get port visits (in photometry sample time) and sampling rate from ppd file
505501 visits = ppd_data ['pulse_inds_1' ][1 :]
506502 logger .debug (f"There were { len (visits )} port visits recorded by pyPhotometry" )
507503 sampling_rate = ppd_data ['sampling_rate' ]
508504 logger .info (f"pyPhotometry sampling rate: { sampling_rate } Hz" )
509505
510- # Convert port visits to seconds
511- visits = [visit_time / sampling_rate for visit_time in visits ]
512-
513506 # Convert pyphotometry photometry start time to datetime object and set timezone to Pacific Time
514507 photometry_start = datetime .strptime (ppd_data ['date_time' ], "%Y-%m-%dT%H:%M:%S.%f" )
515508 photometry_start = photometry_start .replace (tzinfo = ZoneInfo ("America/Los_Angeles" ))
@@ -519,14 +512,20 @@ def process_and_add_pyphotometry_to_nwb(nwbfile: NWBFile, ppd_file_path, logger,
519512 for phot_key in ppd_data :
520513 logger .debug (f"{ phot_key } : { ppd_data [phot_key ]} " )
521514
522- # Plot the raw signals
523- plot_raw_photometry_signals (visits , raw_green , raw_red , raw_405 , relative_raw_signal ,
524- sampling_rate , fig_dir )
515+ # Plot the raw pyPhotometry signals
516+ plot_photometry_signals (visits = visits ,
517+ sampling_rate = sampling_rate ,
518+ signals = [raw_green , raw_405 , relative_raw_signal , raw_red ],
519+ signal_labels = ["Raw 470" , "Raw 405" , "Raw 470/405 ratio" , "Raw 565" ],
520+ signal_colors = ["blue" , "purple" , "grey" , "red" ],
521+ title = "Raw pyPhotometry signals" ,
522+ signal_units = ["V" , "V" , "ratio" , "V" ],
523+ fig_dir = fig_dir )
525524
526525 # Plot the correlation between the raw signals
527- plot_405_470_correlation ( raw_405 , raw_green , fig_dir )
528- plot_405_565_correlation ( raw_405 , raw_red , fig_dir )
529- plot_470_565_correlation ( raw_green , raw_red , fig_dir )
526+ plot_signal_correlation ( sig1 = raw_405 , sig2 = raw_green , label1 = 'Raw 405' , label2 = 'Raw 470' , fig_dir = fig_dir )
527+ plot_signal_correlation ( sig1 = raw_405 , sig2 = raw_red , label1 = 'Raw 405' , label2 = 'Raw 565' , fig_dir = fig_dir )
528+ plot_signal_correlation ( sig1 = raw_green , sig2 = raw_red , label1 = 'Raw 470' , label2 = 'Raw 565' , fig_dir = fig_dir )
530529
531530 # Low pass filter at 10Hz to remove high frequency noise
532531 print ('Filtering data...' )
@@ -549,10 +548,11 @@ def process_and_add_pyphotometry_to_nwb(nwbfile: NWBFile, ppd_file_path, logger,
549548 red_highpass = filtfilt (b ,a , red_denoised , padtype = 'even' )
550549 ratio_highpass = filtfilt (b ,a , ratio_denoised , padtype = 'even' )
551550 highpass_405 = filtfilt (b ,a , denoised_405 , padtype = 'even' )
552-
551+
553552 # Plot the correlation between the filtered signals of interest (ACh and DA)
554- plot_ratio_565_correlation (ratio_highpass , red_highpass , fig_dir )
555-
553+ plot_signal_correlation (sig1 = ratio_highpass , sig2 = red_highpass ,
554+ label1 = 'GACh3.8 470/405 ratio' , label2 = 'rDA3m' , fig_dir = fig_dir )
555+
556556 # Z-score each signal to normalize the data
557557 print ('Z-scoring photometry signals...' )
558558 logger .info ('Z-scoring filtered photometry signals...' )
@@ -561,10 +561,16 @@ def process_and_add_pyphotometry_to_nwb(nwbfile: NWBFile, ppd_file_path, logger,
561561 zscored_405 = np .divide (np .subtract (highpass_405 ,highpass_405 .mean ()),highpass_405 .std ())
562562 ratio_zscored = np .divide (np .subtract (ratio_highpass ,ratio_highpass .mean ()),ratio_highpass .std ())
563563
564- # Plot the processed photometry signals
565- plot_normalized_signals (visits , green_zscored , zscored_405 ,
566- red_zscored , ratio_zscored , sampling_rate , fig_dir )
567-
564+ # Plot the processed pyPhotometry signals
565+ plot_photometry_signals (visits = visits ,
566+ sampling_rate = sampling_rate ,
567+ signals = [green_zscored , zscored_405 , ratio_zscored , red_zscored ],
568+ signal_labels = ["ACh3.8 470nm" , "ACh3.8 405nm" , "ACh3.8 470/405 ratio" , "rDA3m 565nm" ],
569+ signal_colors = ["blue" , "purple" , "grey" , "red" ],
570+ title = "Processed pyPhotometry signals" ,
571+ signal_units = "Z-score" ,
572+ fig_dir = fig_dir )
573+
568574 # Add photometry signals to the NWB
569575 print ("Adding photometry signals to NWB..." )
570576 logger .info ("Adding photometry signals to NWB..." )
@@ -643,14 +649,17 @@ def process_and_add_pyphotometry_to_nwb(nwbfile: NWBFile, ppd_file_path, logger,
643649 nwbfile .add_acquisition (z_scored_565_response_series )
644650 nwbfile .add_acquisition (z_scored_ratio_response_series )
645651
652+ # Convert port visits to seconds to use for alignment
653+ visits_in_seconds = [visit_time / sampling_rate for visit_time in visits ]
654+
646655 # Return photometry start time, sampling rate, and port visit times in seconds to use for alignment
647656 # Add 'signals_to_plot' indicating processed signals to plot aligned to port entry (after behavior is parsed)
648657 signals_to_plot = ["zscored_565" , "zscored_470_405_ratio" ]
649- return {'sampling_rate' : sampling_rate , 'port_visits' : visits ,
658+ return {'sampling_rate' : sampling_rate , 'port_visits' : visits_in_seconds ,
650659 'photometry_start' : photometry_start , 'signals_to_plot' : signals_to_plot }
651660
652661
653- def process_and_add_labview_to_nwb (nwbfile : NWBFile , signals , logger ):
662+ def process_and_add_labview_to_nwb (nwbfile : NWBFile , signals , logger , fig_dir = None ):
654663 """
655664 Process LabVIEW signals and add the processed signals to the NWB file.
656665
@@ -678,8 +687,19 @@ def process_and_add_labview_to_nwb(nwbfile: NWBFile, signals, logger):
678687 raw_green = pd .Series (np .squeeze (signals ["sig1" ])[:: int (SR / Fs )])
679688 port_visits = np .divide (np .squeeze (signals ["visits" ]), SR / Fs ).astype (int )
680689
681- # Convert port visits to seconds
682- port_visits = [visit_time / Fs for visit_time in port_visits ]
690+ # Plot the raw LabVIEW signals
691+ plot_photometry_signals (visits = port_visits ,
692+ sampling_rate = Fs ,
693+ signals = [raw_green , raw_reference ],
694+ signal_labels = ["Raw 470nm signal" , "Raw 405nm signal" ],
695+ signal_colors = ["blue" , "purple" ],
696+ title = "Raw LabVIEW photometry signals" ,
697+ signal_units = "a.u." ,
698+ fig_dir = fig_dir )
699+
700+ # Plot the correlation between the raw 405nm and 470nm signals
701+ plot_signal_correlation (sig1 = raw_green , sig2 = raw_reference ,
702+ label1 = "Raw 470" , label2 = "Raw 405" , fig_dir = fig_dir )
683703
684704 # Smooth the signals using a rolling mean
685705 smooth_window = int (Fs / 30 )
@@ -737,6 +757,45 @@ def process_and_add_labview_to_nwb(nwbfile: NWBFile, signals, logger):
737757 logger .info ("Calculating deltaF/F via subtraction (z_scored_green - z_scored_reference_fitted)..." )
738758 z_scored_green_dFF = z_scored_green - z_scored_reference_fitted
739759
760+ # Plot the processing steps for 470nm wavelength
761+ signals_to_plot = [raw_green , signal_green , baseline_subtracted_green , z_scored_green ]
762+ signal_labels = ["Raw 470nm signal" , "Smoothed 470nm signal" ,
763+ "Baseline-subtracted 470nm signal" , "Z-scored 470nm signal" ]
764+ plot_photometry_signals (visits = port_visits ,
765+ sampling_rate = Fs ,
766+ signals = signals_to_plot ,
767+ signal_labels = signal_labels ,
768+ title = "470nm signal processing" ,
769+ signal_units = ["a.u." , "a.u." , "a.u." , "Z-score" ],
770+ overlay_signals = [(green_baseline , 1 , "red" , "airPLS baseline" )],
771+ fig_dir = fig_dir )
772+
773+ # Plot the processing steps for 405nm wavelength
774+ signals_to_plot = [raw_reference , reference , baseline_subtracted_ref , z_scored_reference ]
775+ signal_labels = ["Raw 405nm signal" , "Smoothed 405nm signal" ,
776+ "Baseline-subtracted 405nm signal" , "Z-scored 405nm signal" ]
777+ plot_photometry_signals (visits = port_visits ,
778+ sampling_rate = Fs ,
779+ signals = signals_to_plot ,
780+ signal_labels = signal_labels ,
781+ title = "405nm signal processing" ,
782+ signal_units = ["a.u." , "a.u." , "a.u." , "Z-score" ],
783+ overlay_signals = [(ref_baseline , 1 , "red" , "airPLS baseline" )],
784+ fig_dir = fig_dir )
785+
786+ # Plot steps of isosbestic correction
787+ signals_to_plot = [z_scored_green , z_scored_reference , z_scored_reference_fitted , z_scored_green_dFF ]
788+ signal_labels = ["Z-scored 470nm signal" , "Z-scored 405nm signal" ,
789+ "Predicted 470nm signal from 405nm signal" , "Z-scored dF/F (post isosbestic correction)" ]
790+ plot_photometry_signals (visits = port_visits ,
791+ sampling_rate = Fs ,
792+ signals = signals_to_plot ,
793+ signal_labels = signal_labels ,
794+ signal_colors = ["blue" , "purple" , "gray" , "green" ],
795+ title = "dLight isosbestic correction" ,
796+ signal_units = ["Z-score" , "Z-score" , "Z-score" , "Z-score" ],
797+ fig_dir = fig_dir )
798+
740799 # Add photometry signals to the NWB
741800 print ("Adding photometry signals to NWB..." )
742801 logger .info ("Adding photometry signals to NWB..." )
@@ -777,10 +836,13 @@ def process_and_add_labview_to_nwb(nwbfile: NWBFile, signals, logger):
777836 nwbfile .add_acquisition (raw_green_response_series )
778837 nwbfile .add_acquisition (raw_reference_response_series )
779838
839+ # Convert port visits to seconds to use for alignment
840+ visits_in_seconds = [visit_time / Fs for visit_time in port_visits ]
841+
780842 # Return photometry start time, sampling rate, and port visit times in seconds to use for alignment
781843 # Add 'signals_to_plot' indicating processed signals to plot aligned to port entry (after behavior is parsed)
782844 signals_to_plot = ['z_scored_green_dFF' ]
783- return {'sampling_rate' : Fs , 'port_visits' : port_visits ,
845+ return {'sampling_rate' : Fs , 'port_visits' : visits_in_seconds ,
784846 'photometry_start' : signals .get ('photometry_start' ), 'signals_to_plot' : signals_to_plot }
785847
786848
@@ -907,7 +969,7 @@ def add_photometry(nwbfile: NWBFile, metadata: dict, logger, fig_dir=None):
907969 phot_file_path = metadata ["photometry" ]["phot_file_path" ]
908970 box_file_path = metadata ["photometry" ]["box_file_path" ]
909971 signals = process_raw_labview_photometry_signals (phot_file_path , box_file_path , logger )
910- photometry_data_dict = process_and_add_labview_to_nwb (nwbfile , signals , logger )
972+ photometry_data_dict = process_and_add_labview_to_nwb (nwbfile , signals , logger , fig_dir )
911973
912974 # If we have already processed the LabVIEW .phot and .box files into signals.mat (true for older recordings)
913975 elif "signals_mat_file_path" in metadata ["photometry" ]:
@@ -919,8 +981,8 @@ def add_photometry(nwbfile: NWBFile, metadata: dict, logger, fig_dir=None):
919981 print ("Processing signals.mat file of photometry signals from LabVIEW..." )
920982 signals_mat_file_path = metadata ["photometry" ]["signals_mat_file_path" ]
921983 signals = scipy .io .loadmat (signals_mat_file_path , matlab_compatible = True )
922- photometry_data_dict = process_and_add_labview_to_nwb (nwbfile , signals , logger )
923-
984+ photometry_data_dict = process_and_add_labview_to_nwb (nwbfile , signals , logger , fig_dir )
985+
924986 # If we have a ppd file from pyPhotometry
925987 elif "ppd_file_path" in metadata ["photometry" ]:
926988 # Process ppd file from pyPhotometry and add signals to the NWB
0 commit comments