<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Introduction
Step1:  Import raw data
The user needs to specify the directories containing the data of interest. Each sample type should have a key which corresponds to the directory path. Additionally, each object should have a list that includes the channels of interest.
Step2:  We'll generate a list of pairs of stypes and channels for ease of use.
Step3:  We can now read in all datafiles specified by the data dictionary above.
Step4:  Calculate landmark bins
Step5:  Calculate landmark bins based on user input parameters and the previously specified control sample.
Step6:  Calculate landmarks
<ASSISTANT_TASK:>
Python Code:
import deltascope as ds
import deltascope.alignment as ut
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import normalize
from scipy.optimize import minimize
import os
import tqdm
import json
import datetime
Explanation: Introduction: Landmarks
End of explanation
# --------------------------------
# -------- User input ------------
# --------------------------------
data = {
    # Specify sample type key
    '30hpf': {
        # Specify path to data directory
        'path': '.\\Data\\30hpf\\Output-02-14-2019',
        # Specify which channels are in the directory and are of interest
        'channels': ['AT','ZRF']
    },
    '28hpf': {
        'path': '.\Data\\28hpf\\Output-02-14-2019-yot-ilastik',
        'channels': ['AT','ZRF']
    },
    '26hpf': {
        'path': '.\Data\\26hpf\\Output-02-14-2019',
        'channels': ['AT','ZRF']
    },
    '24hpf': {
        'path': '.\Data\\24hpf\\Output-02-15-2019',
        'channels': ['AT','ZRF']
    },
    '22hpf': {
        'path': '.\Data\\22hpf\\Output-02-14-2019',
        'channels': ['AT','ZRF']
    }
}
Explanation: Import raw data
The user needs to specify the directories containing the data of interest. Each sample type should have a key which corresponds to the directory path. Additionally, each object should have a list that includes the channels of interest.
End of explanation
data_pairs = []
for s in data.keys():
    for c in data[s]['channels']:
        data_pairs.append((s,c))
Explanation: We'll generate a list of pairs of stypes and channels for ease of use.
End of explanation
D = {}
for s in data.keys():
    D[s] = {}
    for c in data[s]['channels']:
        D[s][c] = ds.read_psi_to_dict(data[s]['path'],c)
Explanation: We can now read in all datafiles specified by the data dictionary above.
End of explanation
# --------------------------------
# -------- User input ------------
# --------------------------------
# Pick an integer value for bin number 
anum = 30
# Specify the percentiles which will be used to calculate landmarks
percbins = [50]
theta_step = np.pi/4
Explanation: Calculate landmark bins
End of explanation
lm = ds.landmarks(percbins=percbins, rnull=np.nan)
lm.calc_bins(D['28hpf']['AT'], anum, theta_step)
print('Alpha bins')
print(lm.acbins)
print('Theta bins')
print(lm.tbins)
Explanation: Calculate landmark bins based on user input parameters and the previously specified control sample.
End of explanation
lmdf = pd.DataFrame()
# Loop through each pair of stype and channels
for s,c in tqdm.tqdm(data_pairs):
    print(s,c)
    # Calculate landmarks for each sample with this data pair
    for k,df in tqdm.tqdm(D[s][c].items()):
        lmdf = lm.calc_perc(df, k, '-'.join([s,c]), lmdf)
        
# Set timestamp for saving data
tstamp = datetime.datetime.now().strftime('%Y-%m-%d')
        
# Save completed landmarks to a csv file
lmdf.to_csv(os.path.join('.\Data',tstamp+'_landmarks.csv'))
# Save landmark bins to json file
bins = {
    'acbins':list(lm.acbins),
    'tbins':list(lm.tbins)
}
with open(os.path.join('.\Data', tstamp+'_landmarks_bins.json'), 'w') as outfile:
    json.dump(bins, outfile)
Explanation: Calculate landmarks
End of explanation
<END_TASK>