#!/usr/bin/env python # coding: utf-8 # # Convert ns-ALEX Becker-Hickl SPC/SET files to Photon-HDF5 # # ## Summary # This executable document (it is called a [Jupyter notebook](http://ipython.org/notebook.html)) # will guide you through the conversion of a ns-ALEX data file from **SPC/SET** # to [Photon-HDF5](http://photon-hdf5.org) format. # # If you are reading this notebook online, please refer to # [this quick-start guide](http://jupyter-notebook-beginner-guide.readthedocs.org) # for instructions on how to install the required software and run the notebook # on your machine. # # If it's the first time you are using a Jupyter notebook, please click on # *Help* -> *User Interface Tour* for a quick tour of the interface. # # In this notebook there are "text cells", such as this paragraph, and "code cells", # containing the code to be executed. To execute a code cell, select it and # press SHIFT+ENTER. To edit a code cell it must be selected and with a green # frame around it. # # ## Prepare the data files # Your can run this notebook using example data files available # [on figshare](http://dx.doi.org/10.6084/m9.figshare.1455963). If you use these # example files, please unzip them and put them in a folder named "data" (lower case) # inside the folder containing this notebook. # # Alternatively, you can use your own SPC/SET files. In this case, you need to paste # the full path of your SPC file in the following cell, instead of the path between # single quotes `'`. # # > **NOTE**: if your path contains the `'` character please use `"` as string delimiter. # In[ ]: filename = r'data/dsdna_d7_d17_50_50_1.spc' # If you also have a SET file it is expected to be in the same folder and # have the same name as the SPC file, with extension ".set". # # The next cell will check whether the `filename` location is correct: # In[ ]: import os try: with open(filename): pass print('Data file found, you can proceed.') except IOError: print('ATTENTION: Data file not found, please check the filename.\n' ' (current value "%s")' % filename) # In case of file not found, please double check that have you put the example # data files in the "data" folder, or that the path you have pasted in `filename` # is correct. Please re-execute the last two cells until the file is found. # ## Data file description # # In the next few cells, we specify the additional metadata that will be stored # in the Photon-HDF5 file. If you are using the example file you don't need to # edit any of these. If are using your own file, please modify these description # accordingly. # ### Author # # These fields will go in the [identity](http://photon-hdf5.readthedocs.org/en/latest/phdata.html#identity-group) group: # In[ ]: author = 'Eitan Lerner' author_affiliation = 'UCLA' creator = 'Antonino Ingargiola' creator_affiliation = 'UCLA' license = 'Public Domain' # ### Sample # # Except for `description`, all these fields will go in the [sample](http://photon-hdf5.readthedocs.org/en/latest/phdata.html#sample-group) group: # In[ ]: description = 'A demonstrative smFRET-nsALEX measurement.' sample_name = '50-50 mixture of two FRET samples' dye_names = 'ATTO550, ATTO647N' buffer_name = 'TE50' # Please edit the previous cells and execute them (SHIFT+ENTER) to make sure # there are no errors. Then proceed to the next section. # ## Load the data # # Before loading the data we need to load a few library functions: # In[ ]: get_ipython().run_line_magic('matplotlib', 'inline') import matplotlib.pyplot as plt import numpy as np import phconvert as phc print('phconvert version: ' + phc.__version__) # Next, we can load the input file and assign the measurement parameters # ([measurement_specs](http://photon-hdf5.readthedocs.org/en/latest/phdata.html#measurement-specs)), # necessary to create a complete Photon-HDF5 file. # # If using your own file, please review all the parameters in the next cell. # In[ ]: d, meta = phc.loader.nsalex_bh(filename, donor = 4, acceptor = 6, laser_repetition_rate = 40e6, tcspc_range = 60e-9, timestamps_unit = 60e-9, alex_period_donor = (1800, 3300), alex_period_acceptor = (270, 1500), excitation_wavelengths = (532e-9, 635e-9), detection_wavelengths = (580e-9, 680e-9), allow_missing_set = False) # The next cell plots a `nanotimes` histogram for the donor and acceptor channel separately. # The shaded areas marks the donor (*green*) and acceptor (*red*) excitation periods. # # If the histogram looks wrong in some aspects (no photons, wrong detectors # assignment, wrong period selection) please go back to the previous cell # and tweak the relevant parameters until the histogram looks correct. # In[ ]: fig, ax = plt.subplots(figsize=(10, 4)) phc.plotter.alternation_hist(d, ax=ax) # You may also find useful to see how many different detectors are present # and their number of photons. This information is shown in the next cell. # In[ ]: detectors = d['photon_data']['detectors'] print("Detector Counts") print("-------- --------") for det, count in zip(*np.unique(detectors, return_counts=True)): print("%8d %8d" % (det, count)) # # File conversion # # Once you finished editing the the previous sections you can proceed with # the actual conversion. It is suggested to execute the notebook in # one step by clicking on the menu *Cells* -> *Run All*. # # After that, you should find a new `.hdf5` file in the same folder of the input # file. You can check it's content by using [HDFView](https://www.hdfgroup.org/products/java/hdfview/). # # The cells below contain the code to convert the input file to Photon-HDF5. # ## Add metadata # In[ ]: d['description'] = description d['sample'] = dict( sample_name=sample_name, dye_names=dye_names, buffer_name=buffer_name, num_dyes = len(dye_names.split(','))) d['identity'] = dict( author=author, author_affiliation=author_affiliation, creator=creator, creator_affiliation=creator_affiliation) # ## Add custom (user) data # # Here we save a custom (*user*) group to store all the metadata # found in the original file (.SET). # # The important metadata has already been extracted and placed # in standard Photon-HDF5 fields. # However, here we dump the full content of the metadata in # the input file to prevent any possible information loss # during the conversion. # In[ ]: # Put `meta` in /user/becker_hickl d['user'] = dict(becker_hickl=meta) # Descriptions for custom fields user_descr = {'/user': 'A custom group.', '/user/becker_hickl': 'Full metadata from original .SET file.'} # ## Save to Photon-HDF5 # # This command saves the new file to disk. If the input data does not follows the Photon-HDF5 specification it returns an error (`Invalid_PhotonHDF5`) printing what violates the specs. # In[ ]: phc.hdf5.save_photon_hdf5(d, close=False, overwrite=True, user_descr=user_descr) # In[ ]: h5file = d['_data_file'] # In[ ]: #d['_data_file'].close() # ## Print HDF5 file content # # Finally, we print the file content to see what's inside the newly-created Photon-HDF5. Here we print the content of the root node: # In[ ]: phc.hdf5.print_children(h5file.root) # And here we retrieve some information from the user group: # In[ ]: phc.hdf5.dict_from_group(h5file.root.user.becker_hickl.identification) # In[ ]: #phc.hdf5.dict_from_group(h5file.root.user.becker_hickl.sys_params) # In[ ]: h5file.close() # ## Load Photon-HDF5 # # Finally we try to reload the file to check that there are no errors. # In[ ]: from pprint import pprint # In[ ]: filename = d['_data_file'].filename # In[ ]: h5data = phc.hdf5.load_photon_hdf5(filename) # In[ ]: phc.hdf5.dict_from_group(h5data.identity) # In[ ]: phc.hdf5.dict_from_group(h5data.setup) # In[ ]: pprint(phc.hdf5.dict_from_group(h5data.photon_data)) # In[ ]: h5data._v_file.close() # If the next cell output shows "OK" then the execution is terminated. # In[ ]: print('OK')