Как сериализовать сотни словарей и список кортежей из python, чтобы их можно было прочитать в функции C ++ - PullRequest
0 голосов
/ 09 мая 2019

Я не знаю, как принимать следующие аргументы: список кортежей, список строк, список целых и словари (ключ: строка, значение: float) в python и сохранять их в файл (сериализовать). Сделайте это для тысяч входов. А затем откройте все эти входные данные в C ++ и передайте их в качестве аргументов функции.

Эта проблема для моего проекта параллельного программирования. У меня есть конвейер, написанный на python2.7 лаборантом, которого я пытаюсь преобразовать в C ++, чтобы я мог распараллелить его либо с MPI, либо с openMP. Я профилировал устаревший код и нашел функцию, которая является горлышком бутылки. Поэтому я решил сделать преобразование этой функции моим проектом (весь конвейер слишком велик, чтобы завершить его в ближайшие 10 дней). Я не знаю, как взять переменные, которые передаются в эту функцию, и сериализовать их так, чтобы я мог открыть их в версии функции на С ++.

Я гуглил, и все, похоже, связано с расширением кода на Python с помощью C ++. И есть 10 различных способов сделать это (Ctypes, SWIG и т. Д.). Я не знаю, если это то, что я должен делать и какой способ использовать, исходя из моих конкретных потребностей. Моя конечная цель - создать весь этот конвейер в C ++ и просто запустить его из командной строки, а выходные данные направить в нейронную сеть свертки для обучения. Таким образом, я не уверен, нужен ли мне хотя бы один из них?

Вот трубопровод. Моя функция, которую я пишу на C ++, - build_box.

def featurization(aa_list, atom_coords_all, atom_names_all, p_charge_dict, sas_dict, box=box_size, voxel=voxel_size):
    all_data_array = []
    y_data_array = []
    capt_aa = spacing_size*np.sqrt(2)
    for i,ii in enumerate(atom_names_all):
        if 'Disordered' in ii:
            atom_names_all[i] = ii.replace('<Disordered Atom ','')
    for i in aa_list:
        a_coords_reori = [] 
        atom_coords = np.array(atom_coords_all)
        atom_names = np.array(atom_names_all)
        cb_coord, ca_coord, c_coord, n_coord, fail = get_central_atom_coords(i, atom_coords, atom_names)
        if fail == 1:
            continue
        else:
            if np.shape(cb_coord) != (1,3) and np.shape(cb_coord) != (3,):
                cb_coord = [cb_coord[0]]
            xvec, yvec, zvec = reorient_axis(ca_coord, c_coord, n_coord, cb_coord)
            box_origin = np.array([np.dot(cb_coord,xvec), \
                                np.dot(cb_coord,yvec), \
                                np.dot(cb_coord,zvec)])

            for j in atom_coords:
                u,v,w = np.dot(xvec,j), np.dot(yvec,j), np.dot(zvec,j)
                a_coords_reori += [tuple([u,v,w])]
            a_coords_reori_woAA, a_names_woAA = remove_central_aa(i, a_coords_reori, atom_names)
            # Insert code to serialize all of build_box parameters here

            x_array = build_box(a_coords_reori_woAA, a_names_woAA, box_origin, p_charge_dict, sas_dict, box, voxel)
            x_gaussian_array = gaussian_filter(x_array)

            all_data_array, y_data_array = build_xy_array(i, x_gaussian_array, all_data_array, y_data_array)

    return all_data_array, y_data_array




def build_box(a_coords_reori_woAA, a_names_woAA, box_origin, p_charge_dict, sas_dict, box_size, voxel):
    """
        :param a_coords_reori_woAA: list of tuples (x,y,z) - x,y,z are floats. size of list depends on the size of the protein.
        :param a_names_woAA: list of strings (unique name for each atom in the protein)
            format: 'stand_AAA[position_num]_AtomLetter'
            Example: 'A_ASP45_Oa' here the a after the Oxygen means alpha, The A at the beginning means alpha chain
        :param box_origin: list of 3 floats. Position (x,y,z) of alpha carbon for AA residue in protein
        :param p_charge_dict: dict keys: string, value: float  unique atoms partial charges.
        :param sas_dict: dict keys: string, value: float  unique atoms solvent accessibility
        :param box_size: int  size of each dimension in box in units of angstroms
        :param voxel: float discrete step size in boxes (either 1.0 or 0.5 angstroms)
        :return: array of floats  (7,20,20,20) dimensions
        """


    x_array = np.zeros([7,20,20,20])
    atom_dict = {'O':2, 'C':1, 'N':0, 'S':3, 'H':4}    

    delta = box_size/2.
    x1, x2 = box_origin[0]-delta, box_origin[0]+delta
    y1, y2 = box_origin[1]-delta, box_origin[1]+delta
    z1, z2 = box_origin[2]-delta, box_origin[2]+delta

    x_range = np.arange(x1,x2+.01,voxel)
    y_range = np.arange(y1,y2+.01,voxel)
    z_range = np.arange(z1,z2+.01,voxel)
    for k_i, k in enumerate(a_coords_reori_woAA):
        x_index, y_index, z_index = [-1,-1,-1]
        for xx_i,xx in enumerate(x_range[:len(x_range)-1]):
            if x_range[xx_i] < k[0] < x_range[xx_i+1]:
                x_index = xx_i
        for yy_i, yy in enumerate(y_range[:len(x_range)-1]):
            if y_range[yy_i] < k[1] < y_range[yy_i+1]:
                y_index = yy_i
        for zz_i, zz in enumerate(z_range[:len(x_range)-1]):
            if z_range[zz_i] < k[2] < z_range[zz_i+1]:
                z_index = zz_i
        if x_index >= 0 and y_index >= 0 and z_index >= 0:
            if a_names_woAA[k_i].split('_')[2][0] in ['D']:
                continue
            else:
                atom_type = atom_dict[a_names_woAA[k_i].split('_')[2][0]]
                x_array[atom_type, x_index, y_index, z_index] = 1
                if a_names_woAA[k_i] in p_charge_dict:
                    x_array[5, x_index, y_index, z_index] = p_charge_dict[a_names_woAA[k_i]]
                if a_names_woAA[k_i] in sas_dict:
                    x_array[6, x_index, y_index, z_index] = sas_dict[a_names_woAA[k_i]]
    return x_array

Новая версия, которую я пишу на C ++

atom_box build_box(vector<xyz_coords> all_atom_coords, vector<string> all_atom_names, vector<float> box_origin_coords,
                    map<string, float> p_charge_map, map <string, float> solv_access_map,
                    int box_size = 20, const int channels = 7, float voxel = 1.0)
 {
     float x1,x2, y1,y2, z1,z2; // first and last values of the box
     const int  x_dim = box_size, y_dim = box_size, z_dim = box_size;
     atom_box box(channels, x_dim, y_dim, z_dim);
     map<char,int> atom_chann_map = {    {'N', 0}, {'C', 1}, {'O', 2}, {'S', 3}, {'H', 4}    };

     float delta =  box_size/2.0;
     //cout << "Delta: " << delta << endl;

     x1 = box_origin_coords[0] - delta; x2 = box_origin_coords[0] + delta;
     y1 = box_origin_coords[1] - delta; y2 = box_origin_coords[1] + delta;
     z1 = box_origin_coords[2] - delta; z2 = box_origin_coords[2] + delta;

     int size = (x2 - x1)/voxel + 1;
     vector<float> x_range(size);vector<float> y_range(size); vector<float> z_range(size);

     for (float i = 0, x = x1, y = y1, z = z1;
              i < size;
              i++, x += voxel, y += voxel, z += voxel)
     {
         x_range[i] = x; y_range[i] = y; z_range[i] = z;
     }
     //Rest of function goes here.

     return box;
 }

Цель состоит в том, чтобы запустить множество белков по конвейеру в python и записать / сериализовать все их параметры в файл. Потом когда я скажу 10000 белков и все их параметры собраны. Я могу запустить их параллельно через эту функцию в C ++ с MPI или OpenMP.

Любая помощь или совет очень ценится!

...