2016-07-29 9 views
6

Ich bin relativ neu bei Python, also werde ich mein Bestes geben, um zu erklären, was ich versuche zu tun. Ich versuche, durch zwei Listen von Sternen (die beide Record-Arrays enthalten) zu iterieren und versuche, Sterne durch ihre Koordinaten mit einer Toleranz (in diesem Fall Ra und Dec, die beide Indizes innerhalb der Record-Arrays sind) zu vergleichen. Es scheint jedoch mehrere Sterne aus einer Liste zu geben, die mit dem gleichen Stern in der anderen übereinstimmen. * Dies liegt daran, dass beide Sterne im Atoll übereinstimmen. Gibt es einen Weg dies zu verhindern? Hier ist, was ich bisher:Mehrere Übereinstimmungen in Listeniteration verhindern

from __future__ import print_function 
import numpy as np  

###importing data### 
Astars = list() 
for s in ApStars:###this is imported but not shown 
    Astars.append(s) 

wStars = list() 
data1 = np.genfromtxt('6819.txt', dtype=None, delimiter=',', names=True) 
for star in data1: 
    wStars.append(star) 

###beginning matching stars between the Astars and wStars### 
list1 = list() 
list2 = list() 
for star,s in [(star,s) for star in wStars for s in Astars]: 
    if np.logical_and(np.isclose(s["RA"],star["RA"], atol=0.000277778)==True , 
         np.isclose(s["DEC"],star["DEC"],atol=0.000277778)==True): 
     if star not in list1: 
      list1.append(star) #matched wStars 
     if s not in list2: 
      list2.append(s) #matched Astars 

Ich kann die atol verringern, da sie über den Instrumentenfehler geht. Was passiert, ist folgendes: Es gibt mehrere Wstars, die zu einem Astar passen. Ich will nur einen Stern für einen Stern, wenn es möglich ist.

Irgendwelche Vorschläge?

+2

Off-Topic, aber Ihre 'continue' Anweisungen tun nichts –

+2

Können Sie Ihren Code klären/überarbeiten? Sie initialisieren 'list1' und' list2', aber beide sind leere Listen zum Zeitpunkt Ihrer 'for star, s ...' Schleife. –

+0

Könnte meine Bearbeitung sein ... @Thomas_Grier, könnten Sie die 'continue'-Anweisungen an ihren richtigen Ort einrücken? (Der letzte 'continue' ist überflüssig, aber Sie wollen wahrscheinlich den ersten auf der gleichen Ebene wie die' if' Anweisungen.) – Alexander

Antwort

0

Ich schätze alles, was Sie zur Verfügung gestellt haben! Ich habe auch etwas herumgefragt und einen cleveren Weg gefunden, das zu erreichen, wonach ich gesucht habe. Hier ist, was wir kamen mit:

sharedStarsW = list() 
sharedStarsA = list() 
for s in Astars: 
    distance = [((s["RA"] - star["RA"])**2 + (s["DEC"] - star["DEC"])**2)**0.5 for star in wStars] 
    if np.amin(distance) < 0.00009259266: 
     sharedStarsW.append(wStars[(np.argmin(distance))]) 
     sharedStarsA.append(s) 

Mit Liste Verständnis, diese berechnet den Abstand von einem Astar zu allen wStars und nimmt sie alle, die innerhalb der 1/3 arcsecond fallen. Wenn ein Astar-Stern mehrere wStars-Matches hat, fügt er den Wstar-Index hinzu, der die kürzeste Entfernung und seinen Astar angibt.

0

Zum ersten Mal eine Frage hier beantworten (wenn ich einen Fehler gemacht habe bitte angeben). Aber es scheint, dass was David kommentiert ist in der "Stern ist immer in Liste1 (und s ist immer in Liste2". Also ich würde vorschlagen, zu vergleichen und zu einem newlist1/newlist1 anhängt, die Spur der Sterne und s hält.

newlist1 = list() 
newlist2 = list() 

#new list will keep the unique star and s 
for star in list1: 
    for s in list2: 
     #assuming the comparison works haven't test it yet 
     if np.logical_and(np.isclose(s["RA"],star["RA"], atol=0.000277778)==True , np.isclose(s["DEC"],star["DEC"],atol=0.000277778)==True): 
       if star not in newlist1: 
        newlist1.append(s) 
       if s not in newlist2: 
        newlist2.append(s) 
       break 
       #once a match is found leave the second loop 
+0

Ich glaube nicht, dass das für was arbeiten würde Ich mache das, weil jeder Datensatz einzigartige Daten hat, und ich werde sie letztendlich am Ende kombinieren (deshalb brauche ich gerade Zahlen von Sternen.) Das Anfügen von 's' an beide Listen sagt mir nur, welche Sterne gefunden wurden und welche –

+1

Ah, Entschuldigung, ich habe falsch interpretiert, was Sie wollten als Ergebnis. Ich werde versuchen, in zukünftigen Antworten auf dieser Website vorsichtiger zu sein. –

+0

Kein Problem, ich schätze die Hilfe! –

1

ich Ihren Ansatz völlig die Tatsache passen ändern würde, dass diese astronomische Objekte sind über Sie sprechen. ich werde den Laden ignorieren Funktionalität und nehmen an, dass Sie bereits Ihre Eingabelisten Astar und haben.

Wir werden die nächstgelegene Sterne in zu jedem Stern in Astar mit einem kartesischen Skalarprodukt finden. Das sollte helfen, Unklarheiten über die beste Übereinstimmung zu lösen.

# Pre-process the data a little 
def getCV(ra, de): 
    return np.array([np.cos(aStar['DE']) * np.cos(aStar['RA']), 
        np.cos(aStar['DE']) * np.sin(aStar['RA']), 
        np.sin(aStar['DE'])]) 

for aStar in Astars: 
    aStar['CV'] = getCV(aStar['RA'], aStar['DE']) 
for wStar in wStars: 
    wStar['CV'] = getCV(wStar['RA'], wStar['DE']) 

# Construct lists of matching stars 
aList = [] 
wList = [] 

# This an extra list of lists of stars that are within tolerance but are 
# not best matches. This list will contain empty sublists, but never None 
wCandidates [] 

for aStar in AStars: 
    for wStar in wStars: 
     # Use native short-circuiting, and don't explicitly test for `True` 
     if np.isclose(aStar["RA"], wStar["RA"], atol=0.000277778) and \ 
      np.isclose(aStar["DEC"], wStar["DEC"], atol=0.000277778): 
      newDot = np.dot(aStar['CV'], wStar['CV']) 
      if aStar == aList[-1]: 
       # This star already has a match, possibly update it 
       if newDot > bestDot: 
        bestDot = newDot 
        # Move the previous best match to list of candidates 
        wCandidates[-1].append(wList[-1]) 
        wList[-1] = wStar 
       else: 
        wCandidates[-1].append(wStar) 
      else: 
       # This star does not yet have a match 
       bestDot = newDot 
       aList.append(aStar) 
       wList.append(wStar) 
       wCandidates.append([]) 

Das Ergebnis ist, dass die Sterne in wList an jedem Index die beste Übereinstimmung für den entsprechenden Stern repräsentieren in aList. Nicht alle Sterne haben eine Übereinstimmung, so dass nicht alle Sterne in einer der Listen erscheinen. Beachten Sie, dass es einige (sehr unwahrscheinliche) Fälle geben kann, in denen ein Stern in aList nicht die beste Übereinstimmung für den in wList ist.

Wir finden den nächsten absoluten Abstand zwischen zwei Sternen durch Berechnung der kartesischen Einheitsvektoren basierend auf und unter Verwendung des Skalarprodukts. Je näher der Punkt an einem ist, desto näher sind die Sterne. Dies sollte helfen, die Unklarheiten zu beheben.

Ich berechnete die kartesischen Vektoren für die Sterne außerhalb der Hauptschleife vor, um es zu vermeiden, es für wStars immer und immer wieder zu tun. Der Schlüsselname 'CV' steht für Cartesian Vector. Ändern Sie es so, wie Sie es für richtig halten.

Zum Schluss, diese Methode prüft nicht, ob ein Stern von wStars zu mehr als einem AStar passt. Es stellt nur sicher, dass das beste für jede AStar ausgewählt wird.

UPDATE

Ich habe eine dritte Liste mit dem Ausgang, der alle wStars Kandidaten aufgelistet, die innerhalb der Toleranz des entsprechenden AStars Element waren, aber nicht als die beste Übereinstimmung gewählt bekam.

+0

Ich habe angefangen, Ihre Lösung für mein Problem zu implementieren, aber es stellte sich als ziemlich komplex heraus, da ich die Datentabelle, mit der ich arbeitete, berechnen musste (ich würde diese kartesischen Skalarprodukte berechnen und diese Spalte mit dem Datensatzsatz zusammenführen) Array, und durchlaufen Sie den Rest des von Ihnen bereitgestellten Codes. Nach einer Inspektion durch einen anderen Studenten schlug er vor, das zu tun, was ich unten als Antwort geschrieben habe.Ich schätze Ihre Hilfe durch diesen Prozess sehr! –

0

Ich habe Ihre Probleme nicht vollständig aufgegriffen, aber ich werde damit beginnen, Ihre Berechnung zu vereinfachen.

Sieht aus wie Apstars und data1 sind strukturierte Arrays, beide 1d mit der gleichen dtype.

Astars = list() 
for s in ApStars:###this is imported but not shown 
    Astars.append(s) 

mit

Astarrs = list(ApStars) 

oder einfach weggelassen:

Diese Liste Iteration könnte ersetzt werden. Wenn Sie hier auf ApStars iterieren können, können Sie sie im Listenverständnis durchlaufen. Gleich für wStars.

Ich würde den Vergleich umschreiben als:

set1, set2 = set(), set() 
# for star,s in [(star,s) for star in data1 for s in ApStars]: 
# iteration on this list comprehension works, 
# but I think this nest iteration is clearer 
for star in data1: 
    for s in ApStars: 
     x1 = np.isclose(s["RA"],star["RA"], atol=0.000277778) 
     x2 = np.isclose(s["DEC"],star["DEC"],atol=0.000277778) 
     # isclose returns boolean, don't need the ==True 
     if x1 & x2: 
      set1.add(star) 
      set2.add(s) 

ersatzlos Hinzufügen mit set einfach ist, obwohl die Reihenfolge (wie bei dict) nicht definiert ist.

Ich würde gerne untersuchen, ob das Extrahieren der relevanten Felder vor der Iteration helfen würde.

Apstars['RA'], data1['RA'], Apstars['DEC'], data1['DEC'] 

x1 = np.isclose(Apstars['RA'][:,None], data1['RA'], atol=...) 
x2 = np.isclose(Apstars['DEC']....) 

x12 = x1 & x2 

x12 ist ein 2D-Array boolean; x12[i,j] ist True, wenn Apstars[i] 'nahe' an data1[j] ist.

Verwandte Themen