2017-07-19 2 views
0

J'ai 200 fichiers de taille que je dois charger et faire une moyenne pour créer une carte. Cependant, je me demandais s'il y avait un moyen de faire tout cela sur une ligne plutôt que sur 200 lignes "fits.open". Je l'ai vu quelque part mais je ne me souviens plus où.Chargement de plusieurs fichiers en une seule ligne

Les noms de fichier vont comme Coadd000_5.fits, Coadd001_5.fits, Coadd002_5.fits, Coadd003_5.fits ... Coadd199_5.fits.

Il doit être quelque chose de similaire à

hdulist2 = fits.open('/Users/alibinesh/Desktop/Data/actpolS2Lensing/actPolS2LensProducts/realKappaCoadd' + xyz + '_5.fit') 

ou quelque chose de semblable. Devrais-je faire une boucle for avec je vais de 0 à 199?

Merci

+2

Quel est le problème avec la boucle for? Je trouve que c'est le moyen le plus simple et le plus propre. – EsotericVoid

+0

Ouais, utilisez probablement une boucle. Vous pouvez boucler la plage (200) si vous écrivez une fonction qui, pour chaque nombre i, produit le nom de fichier pour le fichier ith, puis une autre fonction qui effectue le traitement approprié du nom de fichier donné.C'est juste une suggestion de haut niveau; il y a plusieurs façons de le faire. – anandsun

Répondre

2

Vous tentez peut-être de se rappeler la list comprehension qui est une belle façon, lisible de faire for boucles.

mylist = [ deal_with('realKappaCoadd%03d_5.fit' % i) for i in range(200) ] 

(chemin de fichier raccourci pour la lisibilité)

Toute fois que vous vous trouvez vouloir initialiser un vide list puis .append() à elle dans une boucle for, pensez "list comprehension" de le faire en une seule ligne. Ou "generator expression", qui est une syntaxe étroitement liée, mais qui évalue paresseusement (qui vous permettrait de traiter quelque chose "profondeur d'abord" alors superficiellement apparaissant pour aller en largeur, mais je doute qu'il y ait un réel avantage à cela dans votre Cas).

Vous trouverez peut-être aussi utile de itérer sur la sortie de glob qui trouvera tous les noms de fichiers correspondant à un certain motif:

import glob 
list_of_filenames = sorted(glob.glob('realKappaCoadd*_5.fit')) 
mylist = [ deal_with(filename) for filename in list_of_filenames ] 

Depuis (des commentaires), il semble que l'ouverture d'un fichier fits nécessite beaucoup de frais généraux, vous n'en voudrez probablement qu'un ouvert à la fois. Par conséquent, vous devriez opérer efficacement "en profondeur d'abord", en terminant complètement votre entreprise avec un fichier avant de passer au suivant. OMI la manière la plus lisible de le faire est de mettre toutes les étapes nécessaires pour un fichier, dans l'ordre, dans votre fonction deal_with:

def deal_with(single_filename): 
    file_handle = fits.open(single_filename) 
    result = do_whatever_processing(file_handle) 
    # ... 
    # if necessary, explicitly close the file here 
    return result 
+0

Cette réponse et l'autre donnent tous les deux un mauvais conseil. Fichiers FITS. 'fits.open (...)' peut avoir beaucoup de frais généraux. Au lieu de cela, l'OP devrait ouvrir un fichier à la fois dans une boucle et calculer une moyenne courante des données dans les fichiers. Il n'y a probablement aucun sens à garder chaque fichier ouvert simultanément. – Iguananaut

+0

@Iguananaut qui pourrait être un bon cas pour une expression de générateur à la place - voir edit – jez

+0

Avec tout le respect dû, ce n'est pas utile ici. Tout le PO a besoin de savoir, semble-t-il, comment écrire une boucle for. Il n'y a aucun avantage à utiliser une expression de générateur pour faire une boucle sur certains fichiers FITS et faire quelque chose avec eux. Je suis le (ancien) mainteneur de la bibliothèque astropy.io.fits. – Iguananaut

0

Vous pouvez le faire assez facilement avec une boucle:

hdulist2 = [fits.open('/Users/alibinesh/Desktop/Data/actpolS2Lensing/actPolS2LensProducts/realKappaCoadd%03d_5.fit' % i) for i in range(200)] 
+0

'str (i)' ne vous obtiendra pas les fichiers dans lesquels le numéro de série a des zéros – jez

+0

Ah vrai. Et j'aurais dû utiliser une compréhension de liste. Merci –

+0

Il est parfaitement valide d'utiliser une boucle 'for' multi-lignes au lieu d'une compréhension de liste (bien que je suis sûr que l'OP essayait de se souvenir de cette dernière) en fonction de ce que vous trouvez plus lisible. Je voulais juste souligner le problème de formatage de chaîne complètement indépendant (qui pourrait se produire dans l'une ou l'autre approche en boucle). – jez

0

Utilisez une boucle for:

dirname = '<path_to_files>' 
average = 0 
for filename in glob.glob(os.path.join(dirname, 'Coadd*_5.fits')): 
    with fits.open(filename) as hdul: 
     # Update 'average', whatever that means in this specific case 

Ne pas ouvrir chaque fichier simultanément comme dans les autres réponses - cela peut engendrer un surcoût important et n'est probablement pas quelque chose dont vous avez besoin pour faire la moyenne de certaines données dans chaque fichier (ou même si vous avez besoin d'un accès simultané à plusieurs fichiers simultanés, parties pertinentes dans la mémoire et fermez les fichiers).

Qu'est-ce que vous essayez précisément de faire? Les chances sont qu'il existe déjà une bibliothèque qui vous aidera.