web-dev-qa-db-fra.com

Comment lire des lignes avec un intervalle spécifié à partir d'un fichier de données?

J'ai besoin de lire un fichier de test et de stocker les données dans un nouveau format de fichier HDF5. Je l'ai fait avec succès jusqu'à présent, mais maintenant, j'ai besoin de diviser les données dans différents groupes. Laisse-moi expliquer. Le fichier de données ressemble à ceci comme suit:

Generated by trjconv : P/L=1/400 t=   0.00000
11214
    1P1     aP1    1  80.48  35.36   4.25
    2P1     aP1    2  37.45   3.92   3.96
    3P2     aP2    3  18.53  -9.69   4.68
    4P2     aP2    4  55.39  74.34   4.60
    5P3     aP3    5  22.11  68.71   3.85
    6P3     aP3    6  -4.13  24.04   3.73
    7P4     aP4    7  40.16   6.39   4.73
    8P4     aP4    8  -5.40  35.73   4.85
    9P5     aP5    9  36.67  22.45   4.08
   10P5     aP5   10  -3.68 -10.66   4.18
   11P6     aP6   11  35.95  36.43   5.15
   12P6     aP6   12  57.17   3.88   5.08
   13P7     aP7   13 -23.64  50.44   4.32
   14P7     aP7   14   6.78   8.24   4.36
   15LI     ALi   15  21.34  50.63   5.21
   16LI     ALi   16  16.29  -1.34   5.28
   17LI     ALi   17  22.26  71.25   5.40
   18LI     ALi   18  19.76  10.38   5.34
   19LI     ALi   19  78.62  11.13   5.69
   20LI     ALi   20  22.14  59.70   4.92
   21LI     ALi   21  15.65  47.28   5.22
   22LI     ALi   22  82.41   2.09   5.24
   23LI     ALi   23  16.87 -11.68   5.35

Vous pouvez voir à partir de la première colonne chaque ligne a leur identifiant unique. Jusqu'à présent, je l'envisais un ensemble de données, mais je dois maintenant fractionner les lignes avec id * [~ # ~] p [~ # ~ ~] et avec id LI dans des groupes distincts. J'ai le code d'exécution pour l'ensemble du jeu de données, mais je ne sais pas si je peux modifier pour résoudre le problème actuel. code

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import struct
import numpy as np
import h5py
import re

csv_file = 'com'
fmtstring = '7s 8s 5s 7s 7s 7s'
fieldstruct = struct.Struct(fmtstring)
parse = fieldstruct.unpack_from
# Format for footer
fmtstring1 = '10s 10s 10s'
fieldstruct1 = struct.Struct(fmtstring1)
parse1 = fieldstruct1.unpack_from

with open(csv_file, 'r') as f, \
    h5py.File('test.h5', 'w') as hdf:
    ## Particles group with the attributes
    particles_grp = hdf.require_group('particles/lipids/box')
    particles_grp.attrs['dimension'] = 3
    particles_grp.attrs['boundary'] = ['periodic', 'periodic', 'periodic']
    pos_grp = particles_grp.require_group('positions')
    Edge_grp = particles_grp.require_group('edges')
    ## h5md group with the attributes
    h5md_grp = hdf.require_group('h5md')
    h5md_grp.attrs['version'] = 1.0
    author_grp = h5md_grp.require_group('author')
    author_grp.attrs['author'] = 'foo', '[email protected]'
    creator_grp = h5md_grp.require_group('creator')
    creator_grp.attrs['name'] = 'foo'
    creator_grp.attrs['version'] = 1.0
    # datasets with known sizes
    ds_time = pos_grp.create_dataset('time', dtype="f", shape=(0,),
                                           maxshape=(None,), compression='gzip', 
                                           shuffle=True)
    ds_step = pos_grp.create_dataset('step', dtype=np.uint64, shape=(0,),
                                           maxshape=(None,), compression='gzip',
                                           shuffle=True)
    ds_protein = None
    ds_lipid = None
    # datasets in Edge group
    Edge_ds_time = Edge_grp.create_dataset('time', dtype="f", shape=(0,),
                                           maxshape=(None,), compression='gzip', 
                                           shuffle=True)
    Edge_ds_step = Edge_grp.create_dataset('step', dtype="f", shape=(0,),
                                           maxshape=(None,), compression='gzip', 
                                           shuffle=True)
    Edge_ds_value = None

    Edge_data = Edge_grp.require_dataset('box_size', dtype=np.float32, shape=(0,3),
                                              maxshape=(None,3), compression='gzip', 
                                              shuffle=True)
    
    step = 0
    while True:
        header = f.readline()
        m = re.search("t= *(.*)$", header)
        if m:
            time = float(m.group(1))
        else:
            print("End Of File")
            break

        # get number of data rows, i.e., number of particles
        nparticles = int(f.readline())
        # read data lines and store in array
        arr = np.empty(shape=(nparticles, 3), dtype=np.float32)
        for row in range(nparticles):
            fields = parse( f.readline().encode('utf-8') )
            arr[row] = np.array((float(fields[3]), float(fields[4]), float(fields[5])))
        if nparticles > 0:
            # create a resizable dataset upon the first iteration
            if not ds_lipid:
## It is reading the whole dataset
                ds_protein = pos_grp.create_dataset('lipid', dtype=np.float32,
                                                        shape=(0, nparticles, 3), maxshape=(None, nparticles, 3),
                                                        chunks=(1, nparticles, 3), compression='gzip', shuffle=True)
                Edge_ds_value = Edge_grp.create_dataset('value', dtype=np.float32,
                                                        shape=(0, 3), maxshape=(None, 3),chunks=(1, 3), compression='gzip', shuffle=True)
            # append this sample to the datasets
            ds_time.resize(step + 1, axis=0)
            ds_step.resize(step + 1, axis=0)
            ds_protein.resize(step + 1, axis=0)
            # append the datasets in Edge group
            Edge_ds_time.resize(step + 1, axis=0)
            Edge_ds_step.resize(step + 1, axis=0)
            Edge_ds_value.resize(step + 1, axis=0)
            
            ds_time[step] = time
            ds_step[step] = step
            ds_protein[step] = arr
            Edge_ds_time[step] = time
            Edge_ds_step[step] = step

        footer = parse1( f.readline().encode('utf-8') )
        dat = np.array(footer).astype(float).reshape(1,3)
        new_size = Edge_data.shape[0] + 1
        Edge_data.resize(new_size, axis=0)
        Edge_data[new_size-1 : new_size, :] = dat
        step += 1
        #=============================================================================

Permettez-moi d'expliquer le code un peu. NParticules Lisez la ligne de fichier entière par ligne et les stocke dans le ds_proteine. Le nombre total de lignes est de 11214 dans une image, puis il répète dans 10 images que je n'ai pas montré ici. Pour être précis, je veux seulement des lignes avec [~ # ~] p [~ # ~ ~] ID à lire dans ds_proteine, qui ne sont que 14 dans un ensemble de données et repose 11200 dans ds_lipid. Existe-t-il un moyen d'utiliser l'indexation ou une condition pour le faire, car je ne veux pas fractionner le fichier texte?

3
Rohit

Premièrement, un mot d'avertissement ... vous avez défini ds_protein = None À la ligne 45, puis redéfinissez lorsque vous créez le jeu de données sur la ligne 81 (et la même chose pour ds_lipid = None). Je ne sais pas que cela fonctionnera comme vous le souhaitez. Voir les commentaires plus tard sur la vérification de l'existence de jeux de données.

Actuellement, vous ajoutez toutes les données au tableau arr, puis chargez-la ds_proteine de ce tableau. Puisque vous ne sauvegardez pas la première colonne de données, vous devez utiliser @white's Suggestion: Vérifiez la valeur dans fields[0] Lorsque vous lisez chaque ligne. La ligne 75 dans votre code analyse les données dans la variable fields. La première colonne de chaque ligne devient fields[0]. Vérifiez cette valeur. S'il a 'p', ajoutez-le à un tableau pour le jeu ds_proteine Dataset. S'il a "LI", ajoutez-le d'un tableau pour le jeu ds_lipid Dataset.

Une fois que vous avez les données de protéines et de lipides, vous devez modifier la méthode pour créer les jeux de données. Pour maintenant, vous utilisez .create_dataset() Dans une boucle de While, qui émettra une erreur la deuxième fois à la boucle. Pour éviter cela, j'ai ajouté un chèque sur chaque nom de jeu de données dans le groupe approprié.

code modifié ci-dessous.

    # get number of data rows, i.e., number of particles
    nparticles = int(f.readline())
    # read data lines and store in array
    arr_protein = np.empty(shape=(nparticles, 3), dtype=np.float32)
    arr_lipid = np.empty(shape=(nparticles, 3), dtype=np.float32)
    protein_cnt, lipid_cnt = 0, 0
    for row in range(nparticles):
        fields = parse( f.readline().encode('utf-8') )
        if 'P' in str(fields[0]):
            arr_protein[protein_cnt] = np.array((float(fields[3]), float(fields[4]), float(fields[5])))
            protein_cnt += 1
        Elif 'LI' in str(fields[0]):
            arr_lipid[lipid_cnt] = np.array((float(fields[3]), float(fields[4]), float(fields[5])))
            lipid_cnt += 1

    arr_protein = arr_protein[:protein_cnt,:]  ## New    
    arr_lipid = arr_lipid[:lipid_cnt,:]        ## New      

    if nparticles > 0:
        # create resizable datasets upon the first iteration
        if 'protein' not in pos_grp.keys():
            ds_protein = pos_grp.create_dataset('protein', dtype=np.float32,
                                                    shape=(0, protein_cnt, 3), maxshape=(None, protein_cnt, 3),
                                                    chunks=(1, protein_cnt, 3), compression='gzip', shuffle=True)
        if 'lipid' not in pos_grp.keys():
            ds_lipid   = pos_grp.create_dataset('lipid', dtype=np.float32,
                                                    shape=(0, lipid_cnt, 3), maxshape=(None, lipid_cnt, 3),                                                        
                                                    chunks=(1, lipid_cnt, 3), compression='gzip', shuffle=True)
        if 'value' not in Edge_grp.keys():
             Edge_ds_value = Edge_grp.create_dataset('value', dtype=np.float32,
                                                    shape=(0, 3), maxshape=(None, 3),
                                                    chunks=(1, 3), compression='gzip', shuffle=True)
        # append this sample to the datasets
        ds_time.resize(step + 1, axis=0)
        ds_step.resize(step + 1, axis=0)
        ds_protein.resize(step + 1, axis=0) ## Modified
        ds_lipid.resize(step + 1, axis=0)   ## Modified
        # append the datasets in Edge group
        Edge_ds_time.resize(step + 1, axis=0)
        Edge_ds_step.resize(step + 1, axis=0)
        Edge_ds_value.resize(step + 1, axis=0)
        
        ds_time[step] = time
        ds_step[step] = step
        ds_protein[step] = arr_protein ## Modified
        ds_lipid[step] = arr_lipid     ## Modified
        Edge_ds_time[step] = time
        Edge_ds_step[step] = step
1
kcw78