Extracting minor mergers from TNG

Claire Ye
  • 8 Jul

Hi TNG Team!

I have a few questions regarding extracting full merger trees from the TNG simulations. I've been following the Python tutorial to extract the mass and snapshot number of minor mergers in TNG50, along with the mass of the subhalo they merge into. To do this, I modified the numMergers function from sublink.py.

As this is my first time working with the TNG data, I wanted to check whether my extraction approach is correct. I’ve attached the Python code I'm using--would you mind taking a quick look? Specifically, is fpMass = maxPastMass(tree, fpIndex, massPartType) always the stellar mass of the current FirstProgenitor subhalo (when massPartType=4)? I'm also wondering if I matched the IDs, masses, and snapshot numbers of the subhalos when I added them to a python dictionary since I'm unsure about the fpIndex and npIndex and where they're pointing to.

In addition, is it possible to extract the distance between the center of mass of the NextProgenitor subhalos and the center of mass of the FirstProgenitor subhalo from the merger tree or snapshots before they merge?

#Find the massive halos
basePath = '../sims.TNG/TNG50-1/output/'
ste_mass_min = 5*10**10/mass_unit_TNG

groupfields = ['GroupFirstSub', 'GroupMassType'] 
GroupFirstSub = il.groupcat.loadHalos(basePath,99,fields=groupfields)
groupids = GroupFirstSub['GroupFirstSub'] 
groupmass_star = GroupFirstSub['GroupMassType'][:,4]

selected_ids = groupids[groupmass_star>=ste_mass_min]
selected_m_star = groupmass_star[groupmass_star>=ste_mass_min]

#Using one id (selected_ids[3]) as an example
fields = ['SubhaloMass','SubfindID','SnapNum','SubhaloID','NextProgenitorID','SubhaloMassType', 'MainLeafProgenitorID','FirstProgenitorID',]
tree = il.sublink.loadTree(basePath, 99, selected_ids[3],fields=fields)

def Merger_Histories(tree, minMassRatio=1e-10, massPartType='stars',index=0, alongFullTree=True):  #copy from sublink.py
   """ Calculate the number of mergers, along the main progenitor branch, in this sub-tree (optionally above some mass ratio threshold). If alongFullTree, count across the full
   sub-tree and not only along the MPB. """
   # verify the input sub-tree has the required fields
   reqFields = ['SubhaloID', 'NextProgenitorID', 'MainLeafProgenitorID',
                'FirstProgenitorID', 'SubhaloMassType']

   if not set(reqFields).issubset(tree.keys()):
       raise Exception('Error: Input tree needs to have loaded fields: '+','.join(reqFields))

   num = 0
   #invMassRatio = 1.0 / minMassRatio
   dictTree = {}

   # walk back main progenitor branch
   rootID = tree['SubhaloID'][index]
   fpID   = tree['FirstProgenitorID'][index]

   while fpID != -1:
       fpIndex = index + (fpID - rootID)
       fpMass  = maxPastMass(tree, fpIndex, massPartType)

       if fpMass<10**10/mass_unit_TNG:
           break

       dictTree[str(fpID)] = {'Mstar': fpMass, 'Progen_ID':[fpID], 'Progen_Mass':[tree['SubhaloMassType'][fpIndex][partTypeNum('star')]],
                               'Progen_SnapNum':[tree['SnapNum'][fpIndex]]}

       # explore breadth
       npID = tree['NextProgenitorID'][fpIndex]

       while npID != -1:
           npIndex = index + (npID - rootID)
           npMass  = maxPastMass(tree, npIndex, massPartType)

           # count if both masses are non-zero, and ratio exceeds threshold
           if fpMass > 0.0 and npMass > 0.0:
               ratio = npMass / fpMass

               #if ratio >= minMassRatio and ratio <= invMassRatio:
               #    num += 1

               if npMass>=5*10**6/mass_unit_TNG and ratio <= 0.1:
                   num+=1

                   dictTree[str(fpID)]['Progen_ID'].append(npID)
                   dictTree[str(fpID)]['Progen_Mass'].append(npMass)

                   dictTree[str(fpID)]['Progen_SnapNum'].append(tree['SnapNum'][npIndex])

           npID = tree['NextProgenitorID'][npIndex]

           # count along full tree instead of just along the MPB? (non-standard)
           if alongFullTree:
               if tree['FirstProgenitorID'][npIndex] != -1:
                   numSubtree, dictSubtree = Merger_Histories(tree, minMassRatio=minMassRatio, massPartType=massPartType, index=npIndex, alongFullTree=True)
                   num += numSubtree
                   dictTree.update(dictSubtree)

       fpID = tree['FirstProgenitorID'][fpIndex]

   return num, dictTree

Thank you so much for you help!

Best,
Claire

  • Page 1 of 1