def get_positive_velocity_clouds(input_catalog, max_descendants=10, dendrogram=d): """ Extracts clouds from the positive-velocity region of the first quad. This is the 1Q's inner Galaxy. Here, the KDA applies to most structures, so we first define clouds based on (a) position in velocity space, (b) a cloud is not on an edge, (c) line widths between 1-10 km/s, (d) a cloud has less than `max_descendants` descendants, (e) the `fractional_gain` is below 0.9. Structures that meet the above criteria go into a pre-candidate-cloud list, and that list is "flattened" or "reduced" to remove degenerate substructure. Then the KDA is disambiguated for the relevant structures using the function `distance_disambiguator` and their physical properties are computed. A final list of clouds is generated by taking structures with a mass greater than 3 x 10^4 solar masses; this is what's returned. """ catalog = input_catalog.copy(copy_data=True) # one. grab the clouds we think are real disqualified = ((catalog['v_cen'] < 20) | (catalog['on_edge'] == 1) | (catalog['v_rms'] <= 1) | (catalog['v_rms'] > 10) | (catalog['max_vsplit'] > 3)) qualified = ((catalog['n_descendants'] < max_descendants) & (catalog['fractional_gain'] < 0.9)) pre_output_catalog = catalog[~disqualified & qualified] # now it's just got clouds that COULD be real almost_output_catalog = reduce_catalog(dendrogram, pre_output_catalog) # disambiguate distances here assign_distance_columns( almost_output_catalog, *distance_disambiguator(almost_output_catalog, ambiguous_threshold=0.05)) assign_properties(almost_output_catalog) # now let's do a thing final_qualified = ((almost_output_catalog['mass'] > 3e4) | ((almost_output_catalog['KDA_resolution'] == 'A') & (almost_output_catalog['far_mass'] > 3e4))) output_catalog = almost_output_catalog[final_qualified] return output_catalog
def get_negative_velocity_clouds(input_catalog, max_descendants=10): """ Extracts clouds from the negative-velocity region of the Carina survey. This is the 4Q's inner Galaxy. Here, the KDA might apply to some structures, so we first define clouds based on (a) position in velocity space, (b) a cloud is not on an edge, (c) line widths between 1-10 km/s, (d) a cloud has less than `max_descendants` descendants, (e) the `fractional_gain` is below 0.81. Structures that meet the above criteria go into a pre-candidate-cloud list, and that list is "flattened" or "reduced" to remove degenerate substructure. Then the KDA is disambiguated for the relevant structures using the function `distance_disambiguator` and their physical properties are computed. A final list of clouds is generated by taking structures with a mass greater than 3 x 10^4 solar masses; this is what's returned. """ catalog = input_catalog.copy(copy_data=True) # one. grab the clouds we think are real disqualified = ( (catalog['v_cen'] > -15) | (catalog['on_edge'] == 1) | (catalog['v_rms'] <= 1) | (catalog['v_rms'] > 10) | (catalog['x_cen'] < 280) ) qualified = ( (catalog['n_descendants'] < max_descendants) & (catalog['fractional_gain'] < 0.9)) pre_output_catalog = catalog[~disqualified & qualified] # now it's just got clouds that COULD be real almost_output_catalog = reduce_catalog(d, pre_output_catalog) # disambiguate distances here assign_distance_columns(almost_output_catalog, *distance_disambiguator(almost_output_catalog, ambiguous_threshold=0.05)) assign_properties(almost_output_catalog) # now let's do a thing final_qualified = ((almost_output_catalog['mass'] > 3e4) | ((almost_output_catalog['KDA_resolution']=='A') & (almost_output_catalog['far_mass'] > 3e4) ) ) output_catalog = almost_output_catalog[final_qualified] return output_catalog
def carina_cloud_catalog(): """ This generates a 'processed' dendrogram catalog, made from the global, pre-loaded `catalog` from the Carina survey. It identifies edge structures, computes tree statistics, determines the near & far distances (but does not resolve them), assigns a distance when there is no KDA, and then assigns physical properties to the unambiguously-distanced structures. Its output is meant to be the input to `get_positive_velocity_clouds()`, and `get_negative_velocity_clouds()`. """ catalog_cp = catalog.copy(copy_data=True) # assignment of tree statistic properties compute_tree_stats(catalog_cp, d) # note edge structures catalog_cp['on_edge'] = identify_edge_structures(d) near_distance_table = make_universal_distance_column(catalog, nearfar='near') far_distance_table = make_universal_distance_column(catalog, nearfar='far') # DISTANCE assignment distance_assigner_with_plusminus_errors( catalog_cp, near_distance_table, distance_column_name='near_distance') distance_assigner_with_plusminus_errors( catalog_cp, far_distance_table, distance_column_name='far_distance') # where there's no degeneracy, go ahead and apply the thing no_degeneracy = catalog_cp['near_distance'] == catalog_cp['far_distance'] distance_column = np.zeros_like(near_distance_table['D_k']) * np.nan error_distance_column_plus = np.zeros_like( near_distance_table['D_k']) * np.nan error_distance_column_minus = np.zeros_like( near_distance_table['D_k']) * np.nan KDA_resolution_column = np.array(['-'] * len(distance_column)) distance_column[no_degeneracy] = catalog_cp['near_distance'][no_degeneracy] error_distance_column_plus[no_degeneracy] = catalog_cp[ 'error_near_distance_plus'][no_degeneracy] error_distance_column_minus[no_degeneracy] = catalog_cp[ 'error_near_distance_minus'][no_degeneracy] KDA_resolution_column[no_degeneracy] = 'U' assign_distance_columns(catalog_cp, distance_column, KDA_resolution_column, np.zeros_like(distance_column), np.zeros_like(distance_column), error_distance_column_plus, error_distance_column_minus) # assignment of physical properties to unambigously-distanced structures # let's think critically about whether this step is needed. assign_properties(catalog_cp) near_catalog = catalog_cp.copy(copy_data=True) far_catalog = catalog_cp.copy(copy_data=True) near_catalog['distance'] = catalog_cp['near_distance'] far_catalog['distance'] = catalog_cp['far_distance'] assign_properties(near_catalog) assign_properties(far_catalog) catalog_cp['near_size'] = near_catalog['size'] catalog_cp['far_size'] = far_catalog['size'] catalog_cp['near_z_gal'] = near_catalog['z_gal'] catalog_cp['far_z_gal'] = far_catalog['z_gal'] catalog_cp['near_mass'] = near_catalog['mass'] catalog_cp['far_mass'] = far_catalog['mass'] return catalog_cp
def carina_cloud_catalog(): """ This generates a 'processed' dendrogram catalog, made from the global, pre-loaded `catalog` from the Carina survey. It identifies edge structures, computes tree statistics, determines the near & far distances (but does not resolve them), assigns a distance when there is no KDA, and then assigns physical properties to the unambiguously-distanced structures. Its output is meant to be the input to `get_positive_velocity_clouds()`, and `get_negative_velocity_clouds()`. """ catalog_cp = catalog.copy(copy_data=True) # assignment of tree statistic properties compute_tree_stats(catalog_cp, d) # note edge structures catalog_cp['on_edge'] = identify_edge_structures(d) near_distance_table = make_universal_distance_column(catalog, nearfar='near') far_distance_table = make_universal_distance_column(catalog, nearfar='far') # DISTANCE assignment distance_assigner_with_plusminus_errors(catalog_cp, near_distance_table, distance_column_name='near_distance') distance_assigner_with_plusminus_errors(catalog_cp, far_distance_table, distance_column_name='far_distance') # where there's no degeneracy, go ahead and apply the thing no_degeneracy = catalog_cp['near_distance'] == catalog_cp['far_distance'] distance_column = np.zeros_like(near_distance_table['D_k']) * np.nan error_distance_column_plus = np.zeros_like(near_distance_table['D_k']) * np.nan error_distance_column_minus = np.zeros_like(near_distance_table['D_k']) * np.nan KDA_resolution_column = np.array(['-']*len(distance_column)) distance_column[no_degeneracy] = catalog_cp['near_distance'][no_degeneracy] error_distance_column_plus[no_degeneracy] = catalog_cp['error_near_distance_plus'][no_degeneracy] error_distance_column_minus[no_degeneracy] = catalog_cp['error_near_distance_minus'][no_degeneracy] KDA_resolution_column[no_degeneracy] = 'U' assign_distance_columns(catalog_cp, distance_column, KDA_resolution_column, np.zeros_like(distance_column), np.zeros_like(distance_column), error_distance_column_plus, error_distance_column_minus) # assignment of physical properties to unambigously-distanced structures # let's think critically about whether this step is needed. assign_properties(catalog_cp) near_catalog = catalog_cp.copy(copy_data=True) far_catalog = catalog_cp.copy(copy_data=True) near_catalog['distance'] = catalog_cp['near_distance'] far_catalog['distance'] = catalog_cp['far_distance'] assign_properties(near_catalog) assign_properties(far_catalog) catalog_cp['near_size'] = near_catalog['size'] catalog_cp['far_size'] = far_catalog['size'] catalog_cp['near_z_gal'] = near_catalog['z_gal'] catalog_cp['far_z_gal'] = far_catalog['z_gal'] catalog_cp['near_mass'] = near_catalog['mass'] catalog_cp['far_mass'] = far_catalog['mass'] return catalog_cp
def get_low_velocity_perseus_clouds(input_catalog, max_descendants=10, dendrogram=d): """ Extracts clouds from the low-velocity Perseus region of Q1. This is the 1Q's Perseus Arm at low velocities. Here, the KDA applies to some structures, and we are targeting clouds that might overlap with local emission... so we first define clouds based on (a) position in velocity space AND LATITUDE, (b) a cloud is not on an edge, (c) line widths between 1-10 km/s, (d) a cloud has less than `max_descendants` descendants, (e) the `fractional_gain` is below 0.9, Structures that meet the above criteria go into a pre-candidate-cloud list, and that list is "flattened" or "reduced" to remove degenerate substructure. Then the KDA is disambiguated for the relevant structures using the function `distance_disambiguator` and their physical properties are computed. A final list of clouds is generated by taking structures with a mass greater than 3 x 10^4 solar masses AND a distance consistent with the Perseus Arm; this is what's returned. """ catalog = input_catalog.copy(copy_data=True) disqualified = ((catalog['v_cen'] < -5) | (catalog['v_cen'] > 20) | (np.abs(catalog['y_cen'] > 1)) | (catalog['x_cen'] < 35) | (catalog['on_edge'] == 1) | (catalog['v_rms'] <= 1) | (catalog['v_rms'] > 10)) qualified = ((catalog['n_descendants'] < max_descendants) & (catalog['fractional_gain'] < 0.9)) pre_output_catalog = catalog[~disqualified & qualified] # now it's just got clouds that COULD be real almost_output_catalog = reduce_catalog(dendrogram, pre_output_catalog) # disambiguate distances here assign_distance_columns( almost_output_catalog, *distance_disambiguator(almost_output_catalog, ambiguous_threshold=0.05)) assign_properties(almost_output_catalog) # now let's do a thing final_qualified = ((almost_output_catalog['mass'] > 3e4) & (almost_output_catalog['distance'] > 5) & (almost_output_catalog['distance'] < 14)) output_catalog = almost_output_catalog[final_qualified] return output_catalog
def get_low_velocity_perseus_clouds(input_catalog, max_descendants=10, dendrogram=d): """ Extracts clouds from the low-velocity Perseus region of Q1. This is the 1Q's Perseus Arm at low velocities. Here, the KDA applies to some structures, and we are targeting clouds that might overlap with local emission... so we first define clouds based on (a) position in velocity space AND LATITUDE, (b) a cloud is not on an edge, (c) line widths between 1-10 km/s, (d) a cloud has less than `max_descendants` descendants, (e) the `fractional_gain` is below 0.9, Structures that meet the above criteria go into a pre-candidate-cloud list, and that list is "flattened" or "reduced" to remove degenerate substructure. Then the KDA is disambiguated for the relevant structures using the function `distance_disambiguator` and their physical properties are computed. A final list of clouds is generated by taking structures with a mass greater than 3 x 10^4 solar masses AND a distance consistent with the Perseus Arm; this is what's returned. """ catalog = input_catalog.copy(copy_data=True) disqualified = ( (catalog['v_cen'] < -5) | (catalog['v_cen'] > 20) | (np.abs(catalog['y_cen'] > 1)) | (catalog['x_cen'] < 35) | (catalog['on_edge'] == 1) | (catalog['v_rms'] <= 1) | (catalog['v_rms'] > 10) ) qualified = ( (catalog['n_descendants'] < max_descendants) & (catalog['fractional_gain'] < 0.9)) pre_output_catalog = catalog[~disqualified & qualified] # now it's just got clouds that COULD be real almost_output_catalog = reduce_catalog(dendrogram, pre_output_catalog) # disambiguate distances here assign_distance_columns(almost_output_catalog, *distance_disambiguator(almost_output_catalog, ambiguous_threshold=0.05)) assign_properties(almost_output_catalog) # now let's do a thing final_qualified = ( (almost_output_catalog['mass'] > 3e4) & (almost_output_catalog['distance'] > 5) & (almost_output_catalog['distance'] < 14) ) output_catalog = almost_output_catalog[final_qualified] return output_catalog