<jupyter_start><jupyter_text>Functions Load a snapshot of a cluster in file 00000.dat, which has position units of pc and velocity units of km/s in clustercentric coordinates. Stellar masses are in solar units and were generated using a Salpeter IMF.<jupyter_code>cluster=ctools.load_cluster('snapshot',filename='00000.dat',units='pckms',origin='cluster',ofilename='orbit.dat',ounits='kpckms')<jupyter_output><empty_output><jupyter_text>Once initialized, any function within ``clustertools`` can be called internally via ``cluster.function_name()`` or externally via ``output=function_name(cluster)``. An internal call sets variables within ``cluster`` while an external call will return the calculated values but change nothing within ``cluster``. In the event that the snapshot is not centered, the centre of the cluster can be found via:<jupyter_code>cluster.find_centre()
print(cluster.xc,cluster.yc,cluster.zc)<jupyter_output>-0.149461195567 -0.220877437384 -0.0387801165707<jupyter_text>or<jupyter_code>xc,yc,zc,vxc,vyc,vzc=ctools.find_centre(cluster)
print(xc,yc,zc)<jupyter_output>-0.149461195567 -0.220877437384 -0.0387801165707<jupyter_text>It is important to note that, by default, the centre is calculated to be the centre of density. Similar to NBODY6 and phigrape, once the centre of density is found for the entire cluster population, a centralized subset of stars within an ever decreasing radius are used to find the true centre of density. The parameters ``rmin`` and ``nmax`` set the minimum radius that can encompass the subset of stars and the maximum number of stars within the subset. Setting ``density=False`` will instead find a central subset of stars to find the cluster's of centre by removing stars beyond ``nsigma`` standard deviations of the previously calculated centre. For systems with a large number of escaped stars, which make finding the cluster's centre difficult, it may also help to tell the function where to start. For example, it is possible to tell the cluster to start looking for the centre 1 pc away from the origin along the x-axis and remove stars beyond two standard deviations via:<jupyter_code>cluster.find_centre(xstart=1.,density=False, nsigma=1)<jupyter_output><empty_output><jupyter_text>Other functions that can be called include:<jupyter_code>print('Half-Mass Relaxation Time: ',ctools.half_mass_relaxation_time(cluster))
print('Core Relaxation Time: ',ctools.core_relaxation_time(cluster))
print('Lagrange Radii: ',ctools.rlagrange(cluster))
print('Virial Radius: ',ctools.virial_radius(cluster))<jupyter_output>Half-Mass Relaxation Time:  50.0495603562
Core Relaxation Time:  13.7137370833
Lagrange Radii:  [0.45296852224404172, 1.6747336886382542, 0.85763015700515854, 2.1140256120513246, 2.3598508504454285, 2.9993357861477326, 3.57394375759546, 3.6062209281265409, 5.590463514507733, 8.1648352217132008]
Virial Radius:  2.51937714706<jupyter_text>All functions allow for projected values to be used instead:<jupyter_code>print('Half-Mass Relaxation Time: ',ctools.half_mass_relaxation_time(cluster,projected=True))
print('Core Relaxation Time: ',ctools.core_relaxation_time(cluster,projected=True))
print('Lagrange Radii: ',ctools.rlagrange(cluster,projected=True))
print('Virial Radius: ',ctools.virial_radius(cluster,projected=True))<jupyter_output>Half-Mass Relaxation Time:  33.8815120123
Core Relaxation Time:  14.8385051821
Lagrange Radii:  [1.0923462093256802, 1.0096237533154075, 1.445758748646474, 1.6747336886382542, 1.7446113184162022, 1.9966802194186579, 2.7744389568656111, 4.0804203756208191, 4.5585430739623201, 8.6711592376469824]
Virial Radius:  1.57999162536<jupyter_text>It is also possible to easily measure the mass function and its slope within a given mass range:<jupyter_code>m_mean, m_hist, dm, alpha, ealpha, yalpha, eyalpha=ctools.mass_function(cluster,mmin=0.1,mmax=0.8,plot=True)<jupyter_output><empty_output><jupyter_text>Calling the mass function function internally simply sets the value of alpha and saves the mass range over which alpha was measured with cluster.mmin and cluster.mmax<jupyter_code>cluster.mass_function(mmin=0.1,mmax=0.8)
print(cluster.alpha)<jupyter_output>-2.26795818911<jupyter_text>How velocity dispersion varies with mass can also be viewed and the slope (eta) can be measured. The external call (shown below) and the internal call behave similarly to ``mass_function`` above.<jupyter_code>m_mean, sigvm, eta, eeta, yeta, eyeta=ctools.eta_function(cluster,plot=True)<jupyter_output><empty_output><jupyter_text>If the cluster's galactocentric position and velocity are known, then its tidal radius and limiting radius can also be determined. Note when calculating the limiting radius, it is possible to select ``plot=True`` to see how the cluster's density profile reaches the background density. By default ``clustertools`` assumed the external tidal field is MWPotential2014 from <NAME>., 2015, ApJS, 216, 29. Different potentials can be used by assigning a ``galpy`` potential to the ``pot`` variable.<jupyter_code>print('Tidal Radius: ',ctools.rtidal(cluster))
print('Limiting Radius: ',ctools.rlimiting(cluster,plot=True))<jupyter_output>Tidal Radius:  50820.8700415
Limiting Radius:  3.49061211561<jupyter_text>It is also worth noting that it is possible to calculate the tidal radius iteratively. For example, lets assume a snapshot also contains a large number of stars that are likely not members of the cluster. By setting ``rtiterate>0``, ``clustertools`` will first calculate the tidal radius using the mass of all stars in the snapshot (rt_old). However it will then calculate the tidal radius using only the mass of stars within the initial calculation (rt_new). This process is repeated ``rtiterate`` times or until the ratio of rt_new/rt_old is not less than ``rtconverge``, which by default is 0.9. Since not all snapshot will contain the energy of each star, ``clustertools`` can calculate these values as well by simply calling:<jupyter_code>ek, pot=ctools.energies(cluster)<jupyter_output><empty_output><jupyter_text>If energies were instead called internally, such that ``cluster.ek``,``cluster.pot``,``cluster.etot`` are set, a subset of stars could be defined that are gravitationally bound (E<0):<jupyter_code>cluster.energies()
bound_cluster=ctools.sub_cluster(cluster,emax=0.)<jupyter_output><empty_output><jupyter_text>Calling ``energies`` internally also set the virial parameter Qvir:<jupyter_code>print('Qvir = ',cluster.qvir)<jupyter_output>Qvir =  -0.598384601266<jupyter_text>Finally, in case one needs to know the distance to each stars nearest neighbour:<jupyter_code>distance_to_neighbour=ctools.closest_star(cluster)
print(np.amin(distance_to_neighbour))<jupyter_output>0.032610081984
{'fraction_non_alphanumeric': 0.08813056379821958, 'fraction_numerical': 0.08783382789317508, 'mean_word_length': 7.342821782178218, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '592844', 'license': 'MIT', 'n_tokens_mistral': 2484, 'n_tokens_neox': 2083, 'n_words': 679, 'path': 'docs/source/notebooks/functions.ipynb', 'repo_name': 'nstarman/clustertools', 'size': '6740'}