2016-02-01 6 views
1

Contexte: J'ai une image qui montre 3 CCD avec un tas d'interactions de rayons X montrés comme pixels brillants. J'ai tracé ces données sous la forme d'un histogramme (découper les données pour isoler chaque CCD individuel).Histogramme interactif utilisant matplotlib?

-je obtenir un histogramme qui ressemble à ceci:

enter image description here

Le grand pic à gauche est le bruit de fond (le pic réel de ce monte plus loin, mais je change la plage de l'axe pour montrer la autres parties de l'histogramme) et il devrait y avoir un pic beaucoup plus petit sur le côté droit (bien qu'il n'y en ait pas vraiment un visible sur cette image) qui sont les interactions aux rayons X.

Ma question spécifique .. Existe-t-il un moyen d'obtenir l'écart-type et la moyenne de chaque pic? Idéalement (et je ne suis pas sûr si c'est réellement possible en python) de dire, cliquez sur les deux côtés du pic et de calculer l'écart-type et la moyenne des données dans les deux clics?

J'utilise python 3.4 et version 1.4.3 matplotlib

Mon code est ci-dessous:

### read the data ### 

a = np.fromfile(filename.img, dtype=np.uint32)    #unpack the data and put it into a numpy array 

image_data = np.reshape(a[3:], (-1,Cols))    


### plotting the data ### 

fig, ax = plt.subplots() 
ax.imshow(image_data, cmap=cm.gray, interpolation='nearest', clim=(0,2000))   


numrows, numcols = image_data.shape 


def format_coord(x, y):            
    x = int(x +0.5)             
    y = int(y +0.5) 
    col = x 
    row = y 
    if col >= 0 and col < numcols and row >= 0 and row < numrows: 
     z = image_data[row, col]         
     return 'x=%1.0f, y=%1.0f, z=%1.0f' % (x, y, z)    
    else: 
     return 'x=%1.4f, y=%1.4f' % (x, y) 


ax.format_coord = format_coord          
plt.figure() 


### Obtaining a histogram ### 

which_CCD = int(input ('Which CCD? 1,2,3... ')) 

if which_CCD == 1: 
    CCD1_image = np.array(image_data[150:1500,300:1498]) 
    CCD1_data=np.reshape(CCD1_image,np.product(CCD1_image.shape)) 
    plt.hist(CCD1_data, bins = 2500, histtype='step') 
    plt.xlabel('Energy(ADC Channels)') 
    plt.title('CCD1 Histogram') 
    plt.figure() 



elif which_CCD == 2: 
    CCD2_image = np.array(image_data[1800:3150,300:1498]) 
    CCD2_data=np.reshape(CCD2_image,np.product(CCD2_image.shape)) 
    plt.hist(CCD2_data, bins = 2500, histtype='step') 
    plt.xlabel('Energy(ADC Channels)') 
    plt.title('CCD2 Histogram', fontsize=12) 
    plt.figure() 



elif which_CCD == 3: 
    CCD3_image = np.array(image_data[150:1500,1948:3146]) 
    CCD3_data=np.reshape(CCD3_image,np.product(CCD3_image.shape)) 
    plt.hist(CCD3_data, bins = 2500, histtype='step') 
    plt.xlabel('Energy(ADC Channels)') 
    plt.title('CCD3 Histogram') 
    plt.figure() 




plt.show() 
+1

alors ce que vous voulez, c'est créer une interface graphique, qui montre cet histogramme, et vous pouvez sélectionner une plage de valeurs X, et il calculera la moyenne et STD des valeurs Y dans cette gamme? –

Répondre

2

Si je vous ai bien compris, vous voulez sélectionner une plage de valeurs X et calculer moyenne et std des valeurs Y dans cette plage.

Voici un exemple simple de comment vous pouvez le faire. Je suis sûr que vous pouvez facilement l'adapter à vos besoins.

import matplotlib.pyplot as plt 
import numpy as np 
import numpy.random as npr 

# generate random data 
data = npr.randn(300) 

# calculate hist 
heights,edges = np.histogram(data,50) 

# center edges 
edges = edges[:-1]+(edges[1]-edges[0]) 

# plot histogram 
fig, ax = plt.subplots() 
ax.plot(edges,heights) 
ax.set(title='Click Twice', xlabel='X', ylabel='Y') 

# get input from 2 clicks on figure 
point1, point2 = fig.ginput(2) 

# paint selected area in red 
ax.axvspan(point1[0], point2[0], color='red', alpha=0.5) 

# calculate which values are selected and display mean and std 
mask = (edges>point1[0]) & (edges<point2[0]) 
fig.text(0.2,0.83,'Mean: ' + str(np.mean(heights[mask]))) 
fig.text(0.2,0.8,'Std: ' + str(np.std(heights[mask]))) 

fig.canvas.draw() 
plt.show() 

sortie:

Histogramme avec invite pour sélectionner des points enter image description here

Peinture zone et affichage sélectionné moyenne et std enter image description here

P.S. J'ai utilisé this response.

P.P.S. Je suis sur Python 2.7, certains changements de syntaxe peuvent être nécessaires pour Python 3.

+1

C'est dans la ligne de ce que je voulais. La seule chose est que l'écart-type que vous avez là est des valeurs y dans cette zone rouge. Mais parce que c'est un histogramme, ces valeurs ne sont que des comptes. Ce que je voulais vraiment, c'était l'écart-type des valeurs x dans cette plage (mais comme c'est un histogramme, je dois aussi utiliser les valeurs y). Je pense que le code principal que vous avez donné est ce dont j'ai besoin, bien que je doive juste faire quelques manipulations avec les données pour obtenir l'écart-type requis. – DavidG

+0

@DavidG Si je vous ai bien compris, il vous suffit de sélectionner des valeurs * data * comme ceci: * mask = (data> point1 [0]) & (data

+1

Oui, vous avez raison. Je l'ai fait à peu près et cela a fonctionné, merci pour l'aide. – DavidG