Beispiel #1
0
void LFont::text_out( int x, int y, SDL_Surface *thisSurface, string text, unsigned long int flags )
//////////////////////////////////////////////////////////////////////////////////////////////////////
{
	//get the new x and y coordinates
	this->y = y;
	this->x = x; 

	//the part of the text image going to be used
	SDL_Rect textImage;

    //align x offset
	if( bool( flags & LFONT_HCENTER ) )
	{
		x = ( thisSurface->w - calc_width( text, thisSurface ) ) / 2;
	}
	else if( bool( flags & LFONT_LEFT ) )
	{
        x = 0;    
    }
    else if( bool( flags & LFONT_RIGHT ) )
	{
        x = ( thisSurface->w - calc_width( text, thisSurface ) );
    }

    //align the y off set
	if( bool( flags & LFONT_VCENTER ) )
	{
		y = ( thisSurface->h - calc_max( text, thisSurface ).h ) / 2;
	}
	else if( bool( flags & LFONT_TOP ) )
	{
        y = 0;
    }
    else if( bool( flags & LFONT_BOTTOM ) )
	{
        y = ( thisSurface->h - calc_max( text, thisSurface ).h );
    }

	//go through the string
	for( int stringPosition = 0; text[ stringPosition ] != '\0'; stringPosition++ )//while the current postion in the string is not a null character, keep going through the string
	{
		switch( text[ stringPosition ] )//the current postion in the string
		{
			//assign the proper surface
			case 'A': textImage = textSurfaces[ LFONT_A ]; break;
			case 'B': textImage = textSurfaces[ LFONT_B ]; break;
			case 'C': textImage = textSurfaces[ LFONT_C ]; break;
			case 'D': textImage = textSurfaces[ LFONT_D ]; break;
			case 'E': textImage = textSurfaces[ LFONT_E ]; break;
			case 'F': textImage = textSurfaces[ LFONT_F ]; break;
			case 'G': textImage = textSurfaces[ LFONT_G ]; break;
			case 'H': textImage = textSurfaces[ LFONT_H ]; break;
			case 'I': textImage = textSurfaces[ LFONT_I ]; break;
			case 'J': textImage = textSurfaces[ LFONT_J ]; break;
			case 'K': textImage = textSurfaces[ LFONT_K ]; break;
			case 'L': textImage = textSurfaces[ LFONT_L ]; break;
			case 'M': textImage = textSurfaces[ LFONT_M ]; break;
			case 'N': textImage = textSurfaces[ LFONT_N ]; break;
			case 'O': textImage = textSurfaces[ LFONT_O ]; break;
			case 'P': textImage = textSurfaces[ LFONT_P ]; break;
			case 'Q': textImage = textSurfaces[ LFONT_Q ]; break;
			case 'R': textImage = textSurfaces[ LFONT_R ]; break;
			case 'S': textImage = textSurfaces[ LFONT_S ]; break;
			case 'T': textImage = textSurfaces[ LFONT_T ]; break;
			case 'U': textImage = textSurfaces[ LFONT_U ]; break;
			case 'V': textImage = textSurfaces[ LFONT_V ]; break;
			case 'W': textImage = textSurfaces[ LFONT_W ]; break;
			case 'X': textImage = textSurfaces[ LFONT_X ]; break;
			case 'Y': textImage = textSurfaces[ LFONT_Y ]; break;
			case 'Z': textImage = textSurfaces[ LFONT_Z ]; break;

			case 'a': textImage = textSurfaces[ LFONT_a ]; break;
			case 'b': textImage = textSurfaces[ LFONT_b ]; break;
			case 'c': textImage = textSurfaces[ LFONT_c ]; break;
			case 'd': textImage = textSurfaces[ LFONT_d ]; break;
			case 'e': textImage = textSurfaces[ LFONT_e ]; break;
			case 'f': textImage = textSurfaces[ LFONT_f ]; break;
			case 'g': textImage = textSurfaces[ LFONT_g ]; break;
			case 'h': textImage = textSurfaces[ LFONT_h ]; break;
			case 'i': textImage = textSurfaces[ LFONT_i ]; break;
			case 'j': textImage = textSurfaces[ LFONT_j ]; break;
			case 'k': textImage = textSurfaces[ LFONT_k ]; break;
			case 'l': textImage = textSurfaces[ LFONT_l ]; break;
			case 'm': textImage = textSurfaces[ LFONT_m ]; break;
			case 'n': textImage = textSurfaces[ LFONT_n ]; break;
			case 'o': textImage = textSurfaces[ LFONT_o ]; break;
			case 'p': textImage = textSurfaces[ LFONT_p ]; break;
			case 'q': textImage = textSurfaces[ LFONT_q ]; break;
			case 'r': textImage = textSurfaces[ LFONT_r ]; break;
			case 's': textImage = textSurfaces[ LFONT_s ]; break;
			case 't': textImage = textSurfaces[ LFONT_t ]; break;
			case 'u': textImage = textSurfaces[ LFONT_u ]; break;
			case 'v': textImage = textSurfaces[ LFONT_v ]; break;
			case 'w': textImage = textSurfaces[ LFONT_w ]; break;
			case 'x': textImage = textSurfaces[ LFONT_x ]; break;
			case 'y': textImage = textSurfaces[ LFONT_y ]; break;
			case 'z': textImage = textSurfaces[ LFONT_z ]; break;

			case '0': textImage = textSurfaces[ LFONT_0 ]; break;
			case '1': textImage = textSurfaces[ LFONT_1 ]; break;
			case '2': textImage = textSurfaces[ LFONT_2 ]; break;
			case '3': textImage = textSurfaces[ LFONT_3 ]; break;
			case '4': textImage = textSurfaces[ LFONT_4 ]; break;
			case '5': textImage = textSurfaces[ LFONT_5 ]; break;
			case '6': textImage = textSurfaces[ LFONT_6 ]; break;
			case '7': textImage = textSurfaces[ LFONT_7 ]; break;
			case '8': textImage = textSurfaces[ LFONT_8 ]; break;
			case '9': textImage = textSurfaces[ LFONT_9 ]; break;

			case '!': textImage = textSurfaces[ LFONT_EXCLAIM ]; break;
			case '@': textImage = textSurfaces[ LFONT_AT ]; break;
			case '#': textImage = textSurfaces[ LFONT_HASH ]; break;
			case '$': textImage = textSurfaces[ LFONT_DOLLAR ]; break;
			case '%': textImage = textSurfaces[ LFONT_PERCENT ]; break;
			case '^': textImage = textSurfaces[ LFONT_CARET ]; break;
			case '&': textImage = textSurfaces[ LFONT_AMPERSAND ]; break;
			case '*': textImage = textSurfaces[ LFONT_ASTERISK ]; break;
			case '(': textImage = textSurfaces[ LFONT_LEFTPAREN ]; break;
			case ')': textImage = textSurfaces[ LFONT_RIGHTPAREN ]; break;
			case '-': textImage = textSurfaces[ LFONT_MINUS ]; break;
			case '_': textImage = textSurfaces[ LFONT_UNDERSCORE ]; break;
			case '=': textImage = textSurfaces[ LFONT_EQUALS ]; break;
			case '+': textImage = textSurfaces[ LFONT_PLUS ]; break;
			case '[': textImage = textSurfaces[ LFONT_LEFTBRACKET ]; break;
			case ']': textImage = textSurfaces[ LFONT_RIGHTBRACKET ]; break;
			case '{': textImage = textSurfaces[ LFONT_LEFTBRACE ]; break;
			case '}': textImage = textSurfaces[ LFONT_RIGHTBRACE ]; break;
			case ';': textImage = textSurfaces[ LFONT_SEMICOLON ]; break;
			case ':': textImage = textSurfaces[ LFONT_COLON ]; break;
			case '\'': textImage = textSurfaces[ LFONT_QUOTE ]; break;
			case '\"': textImage = textSurfaces[ LFONT_DBLQUOTE ]; break;
			case ',': textImage = textSurfaces[ LFONT_COMMA ]; break;
			case '.': textImage = textSurfaces[ LFONT_PERIOD ]; break;
			case '<': textImage = textSurfaces[ LFONT_LESS ]; break;
			case '>': textImage = textSurfaces[ LFONT_GREATER ]; break;
			case '?': textImage = textSurfaces[ LFONT_QUESTION ]; break;
			case '/': textImage = textSurfaces[ LFONT_SLASH ]; break;
			case '|': textImage = textSurfaces[ LFONT_LINE ]; break;
			case '\\': textImage = textSurfaces[ LFONT_BACKSLASH ]; break;
			case '`': textImage = textSurfaces[ LFONT_BACKQUOTE ]; break;
			case '~': textImage = textSurfaces[ LFONT_TILDE ]; break;

			case ' ': x += w; break;//if there's a space move overthe space width

			case '\n': x = 0; y += h; break;//if there's newline, move down the text height
		}
	
	    // if the current character is not null, a newline or a space
		if( ( text[ stringPosition ] != '\0' ) && ( text[ stringPosition ] != '\n' ) && ( text[ stringPosition ] != ' ' ) )
		{
            //if the text surface will go off the screen
			if( x + textImage.w > thisSurface->w )
			{
                //if wrap is enabled
				if( bool( flags & LFONT_WRAP ) )
				{
                    //move down
					x = 0;
					y += h;

                    //and align the x offset
					if( bool( flags & LFONT_HCENTER ) )
					{
						x = ( thisSurface->w - calc_width( &text[ stringPosition + 1 ], thisSurface ) ) / 2;
					}
					else if( bool( flags & LFONT_LEFT ) )
	                {
                        x = 0;    
                    }
                    else if( bool( flags & LFONT_RIGHT ) )
	                {
                        x = ( thisSurface->w - calc_width( &text[ stringPosition + 1 ], thisSurface ) );
                    }
				}
			}
			
			//stick the text surface onto the surface
			apply_surface( x, y, font, thisSurface, &textImage );
			
			//and move over the x offset the width of the surface 
			x += textImage.w;
		}
		else
		{	
            //if there's a new line
			if( text[ stringPosition ] == '\n' )
			{
                //align the x offset
				if( bool( flags & LFONT_HCENTER ) )
				{
					x = ( thisSurface->w - calc_width( &text[ stringPosition + 1 ], thisSurface ) ) / 2;
				}
				else if( bool( flags & LFONT_LEFT ) )
	            {
                    x = 0;    
                }
                else if( bool( flags & LFONT_RIGHT ) )
	            {
                    x = ( thisSurface->w - calc_width( &text[ stringPosition + 1 ], thisSurface ) );
                }
			}
		}	
    
	}
}
Beispiel #2
0
int read_matches_header(char *filename_root_in,
                        int   i_read_start,
                        int   i_read_stop,
                        int   i_read_step,
                        int * n_files_return,
                        int **n_subgroups_return,
                        int **n_groups_return,
                        int * n_subgroups_max,
                        int * n_groups_max,
                        int * n_halos_max) {
    char       filename_out[256];
    char       filename_out_dir[256];
    char       filename_out_name[256];
    FILE *     fp_test;
    FILE *     fp_out;
    SID_fp     fp_in;
    int        i_read, k_read, l_read;
    int        i_read_start_file;
    int        i_read_stop_file;
    int        i_read_step_file;
    int        k_match;
    int        n_k_match;
    char       group_text_prefix[5];
    int        n_matches;
    int        j_read;
    char       filename_cat1[256];
    char       filename_cat2[256];
    char       filename_cat1_order[256];
    char       filename_cat2_order[256];
    char       filename_out_dir_snap[256];
    int        n_groups_1;
    int        n_groups_1_local;
    int        n_groups_2;
    int        n_groups_2_local;
    int        i_group;
    int        buffered_count;
    int        buffered_count_local;
    int        j_group;
    int        index_test;
    int        i_rank;
    int *      n_particles;
    int *      n_sub_group;
    int *      match_id    = NULL;
    float *    match_score = NULL;
    char       cat_name_1[20];
    char       cat_name_2[20];
    size_t *   match_rank  = NULL;
    size_t *   match_index = NULL;
    size_t     offset;
    plist_info plist1;
    plist_info plist2;
    void *     buffer;
    int *      buffer_int;
    size_t *   buffer_size_t;
    float *    buffer_float;
    int        n_buffer_max = 1000;
    int        n_buffer;
    int        i_buffer;
    int        j_buffer;
    int        flag_sucessful_completion = GBP_TRUE;

    SID_log("Reading header information...", SID_LOG_OPEN);

    // Count the number of snapshots we are going to use and
    //    initialize the arrays that are to be returned
    for(i_read = i_read_stop, (*n_files_return) = 0; i_read >= i_read_start; i_read -= i_read_step)
        (*n_files_return)++;
    (*n_subgroups_return) = (int *)SID_malloc(sizeof(int) * (*n_files_return));
    (*n_groups_return)    = (int *)SID_malloc(sizeof(int) * (*n_files_return));

    if(SID.I_am_Master) {
        FILE *fp_read_header;
        // Loop for subgroups and then groups
        for(k_match = 0; k_match < 2; k_match++) {
            switch(k_match) {
                case 0:
                    sprintf(group_text_prefix, "sub");
                    break;
                case 1:
                    sprintf(group_text_prefix, "");
                    break;
            }

            // Open file and read header
            int i_read_start_in;
            int i_read_stop_in;
            int n_search_total_in;
            int n_files_in;
            int i_read_in;
            sprintf(filename_out, "%s/%sgroup_matches_header.dat", filename_root_in, group_text_prefix);
            if((fp_read_header = fopen(filename_out, "r")) == NULL)
                SID_exit_error("Could not open file {%s} when reading header information.", SID_ERROR_IO_OPEN,
                               filename_out);
            SID_fread_verify(&i_read_start_in, sizeof(int), 1, fp_read_header);
            SID_fread_verify(&i_read_stop_in, sizeof(int), 1, fp_read_header);
            SID_fread_verify(&n_search_total_in, sizeof(int), 1, fp_read_header);
            SID_fread_verify(&n_files_in, sizeof(int), 1, fp_read_header);
            i_read_in = i_read_stop_in + 1;

            // Loop for each snapshot we want to keep
            int i_read_next;
            for(j_read = 0, i_read_next = i_read_stop; j_read < (*n_files_return); j_read++, i_read_next -= i_read_step) {
                // Read-forward to the desired snapshot
                int flag_continue = GBP_TRUE;
                while(flag_continue && i_read_in > i_read_start_in) {
                    SID_fread_verify(&i_read_in, sizeof(int), 1, fp_read_header);
                    SID_fread_verify(&n_groups_1, sizeof(int), 1, fp_read_header);
                    fseek(fp_read_header, n_groups_1 * sizeof(int), SEEK_CUR); // Skip halo sizes
                    if(k_match == 1)
                        fseek(fp_read_header, n_groups_1 * sizeof(int), SEEK_CUR); // Skip n_sub_per_group
                    if(i_read_in == i_read_next) {
                        switch(k_match) {
                            case 0:
                                (*n_subgroups_return)[j_read] = n_groups_1;
                                break;
                            case 1:
                                (*n_groups_return)[j_read] = n_groups_1;
                                break;
                        }
                        flag_continue = GBP_FALSE;
                    }
                }
            }
            fclose(fp_read_header);
            if(j_read != (*n_files_return))
                SID_exit_error("Was not able to read the appriate number of group/subgroup sizes (i.e. %d!=%d)",
                               SID_ERROR_LOGIC, j_read, (*n_files_return));
        }
    }
    SID_Bcast((*n_subgroups_return), (*n_files_return), SID_INT, SID_MASTER_RANK, SID_COMM_WORLD);
    SID_Bcast((*n_groups_return), (*n_files_return), SID_INT, SID_MASTER_RANK, SID_COMM_WORLD);

    // Compute some maxs (useful for array allocation)
    calc_max((*n_subgroups_return), n_subgroups_max, (*n_files_return), SID_INT, CALC_MODE_DEFAULT);
    calc_max((*n_groups_return), n_groups_max, (*n_files_return), SID_INT, CALC_MODE_DEFAULT);
    (*n_halos_max) = GBP_MAX((*n_subgroups_max), (*n_groups_max));

    SID_log("Done.", SID_LOG_CLOSE);

    return (flag_sucessful_completion);
}
Beispiel #3
0
int main(int argc, char *argv[]){
  char        filename_tree_in[256];
  int         n_trees;
  int         n_halos_total;
  int        *n_halos;
  int         i_tree;
  FILE       *fp;
  halo_properties_SAGE_info  *halos;
  halo_properties_SAGE_info   halo;
  int        *snap_num;
  size_t     *snap_num_index;
  int         i_snap,i_halo,j_halo,k_halo;
  int         n_halos_snap;
  int        *group_halo_first;
  int         group_halo_last;
  size_t     *group_halo_first_index;
  int        *snap_index;
  int descendant_min,descendant_max;
  int progenitor_first_min,progenitor_first_max;
  int progenitor_next_min,progenitor_next_max;
  int group_halo_first_min,group_halo_first_max;
  int group_halo_next_min,group_halo_next_max;
  int snap_num_min,snap_num_max;
  int halo_index_min,halo_index_max;
  int n_gal=0;
  int max_snap=0;
  int n_halos_max;
  int n_subtrees;
  int halo_search;
  int flag_search;

  SID_init(&argc,&argv,NULL,NULL);

  // Fetch user inputs
  strcpy(filename_tree_in,argv[1]);
  halo_search=atoi(argv[2]);

  SID_log("Finding halo #%d's tree in {%s}...",SID_LOG_OPEN|SID_LOG_TIMER,halo_search,filename_tree_in);
  fp=fopen(filename_tree_in,"r");
  fread_verify(&n_trees,      sizeof(int),1,fp);
  fread_verify(&n_halos_total,sizeof(int),1,fp);
  SID_log("%d trees and %d halos",SID_LOG_COMMENT,n_trees,n_halos_total);
  n_halos=(int *)SID_malloc(sizeof(int)*n_trees);
  fread_verify(n_halos,sizeof(int),n_trees,fp);
  calc_max(n_halos,&n_halos_max,n_trees,SID_INT,CALC_MODE_DEFAULT);
  halos      =(halo_properties_SAGE_info *)SID_malloc(sizeof(halo_properties_SAGE_info)*n_halos_max);
  for(i_tree=0,flag_search=TRUE;i_tree<n_trees && flag_search;i_tree++){
    fread_verify(halos,sizeof(halo_properties_SAGE_info),n_halos[i_tree],fp);
    for(i_halo=0,n_subtrees=0;i_halo<n_halos[i_tree];i_halo++){
      if(halos[i_halo].halo_id==halo_search){
        flag_search=FALSE;
        SID_log("Found it in tree #%d",SID_LOG_COMMENT,i_tree);
      }
    }
  }
  if(flag_search)
    SID_log("COULD NOT FIND HALO #%d IN THIS FILE!",SID_LOG_COMMENT,halo_search);

  // Clean-up
  fclose(fp);
  SID_free((void **)&halos);
  SID_log("Done.",SID_LOG_CLOSE);

  SID_exit(0);
}
void compute_trees_horizontal(char        *filename_halo_root_in,
                              char        *filename_cat_root_in,
                              char        *filename_snap_list_in,
                              char        *filename_root_matches,
                              char        *filename_output_dir,
                              cosmo_info **cosmo,
                              int          i_read_start,
                              int          i_read_stop,
                              int          i_read_step,
                              int          n_search,
                              int          flag_fix_bridges,
                              int         *flag_clean){
  char        group_text_prefix[5];
  FILE       *fp;
  char       *line=NULL;
  int         line_length=0;
  int         n_strays;
  int         n_strays_drop;
  int         n_strays_bridge;
  int         i_stray;
  int         n_match;
  int         n_match_halos;
  int         n_back_match;
  int         i_match;
  int         j_match;
  int         k_match;
  int         n_groups_1;
  int         n_groups_2;
  int         n_groups_3;
  int         i_group;
  int         j_group;
  int         k_group;
  int         l_group;
  int         n_subgroups_1;
  int         n_subgroups_2;
  int         i_subgroup;
  int         j_subgroup;
  int         i_drop;
  int         j_drop;
  int         k_drop;
  int         i_bridge;
  int         j_bridge;
  int         n_lines;
  int         i_file;
  int         j_file;
  int         i_write;
  int         j_write;
  int         l_write;
  int         l_read;
  int         j_file_1;
  int         j_file_2;
  int         i_read;
  int         j_read;
  int         j_read_1;
  int         j_read_2;
  int         n_descendant;
  int         n_progenitor;
  int         descendant_index;
  int         progenitor_index;
  int         my_descendant_index,my_descendant_id,my_descendant_list,my_index;
  int         index;
  int         max_id         =0;
  int         max_id_group   =0;
  int         max_id_subgroup=0;
  int        *my_descendant;
  int        *n_particles;
  int        *n_particles_groups;
  int        *n_particles_subgroups;
  int         my_trunk;
  double      expansion_factor;
  int         n_found;
  int         n_found_bridge;
  double      delta_r;
  double      delta_M;
  double      R_vir_p;
  double      R_vir_d;
  int         i_find,n_find;
  int         flag_continue;
  int         flag_drop;
  int        *match_id=NULL;
  int        *search_id=NULL;
  int         n_progenitors_max;
  int         i_search;
  int         flag_dropped;
  int         flag_first;
  int         n_particles_max;
  int         trunk_index;
  int        *n_groups=NULL;
  int        *n_subgroups=NULL;
  int         max_tree_id_group;
  int         max_tree_id_subgroup;
  int         max_tree_id;
  int       **n_subgroups_group=NULL;
  int        *n_subgroups_group_1=NULL;
  size_t    **sort_id=NULL;
  size_t    **sort_group_id=NULL;
  size_t    **sort_subgroup_id=NULL;
  size_t     *match_index=NULL;
  size_t     *bridge_index=NULL;
  size_t     *search_index=NULL;
  float      *match_score=NULL;
  char       *match_flag_two_way=NULL;
  int        *bridge_keep=NULL;
  int         flag_match_subgroups;
  int         flag_keep_strays=FALSE;
  int         n_k_match=2;
  int         n_snap;
  
  tree_horizontal_info **subgroups;
  tree_horizontal_info **groups;
  tree_horizontal_info **halos;
  tree_horizontal_info  *halos_i;
  match_info           **back_matches_groups;
  match_info           **back_matches_subgroups;
  match_info           **back_matches;

  int     n_files;
  int     n_subgroups_max;
  int     n_groups_max;
  int    *n_halos;
  int     n_halos_max;
  int     n_halos_i;
  int     i_halo;
  int     n_halos_1_matches;
  int     n_halos_2_matches;
  int     j_halo;
  int     k_halo;
  int     l_halo;

  int     n_list;
  int     k_file;
  int     l_file;
  int     k_index;
  int     k_file_temp;
  int     k_index_temp;

  int     n_wrap;
  int     i_file_start;
  
  char  filename_output_dir_horizontal[MAX_FILENAME_LENGTH];
  char  filename_output_dir_horizontal_cases[MAX_FILENAME_LENGTH];
  char  filename_output_file_root[MAX_FILENAME_LENGTH];
  char  filename_matching_out[MAX_FILENAME_LENGTH];
  FILE *fp_matching_out;
  int   i_column;

  SID_log("Constructing horizontal merger trees for snapshots #%d->#%d (step=%d)...",SID_LOG_OPEN|SID_LOG_TIMER,i_read_start,i_read_stop,i_read_step);

  if(n_search<1)
    SID_trap_error("n_search=%d but must be at least 1",ERROR_LOGIC,n_search);

  int flag_compute_fragmented=TRUE;
  int flag_compute_ghosts    =FALSE;

  if(!flag_fix_bridges)
    SID_log("Bridge-fixing is turned off.",SID_LOG_COMMENT);
  if(!flag_compute_fragmented)
    SID_log("Fragmented-halo propagation is turned off.",SID_LOG_COMMENT);
  if(!flag_compute_ghosts)
    SID_log("Ghost-populated tree construction is turned off.",SID_LOG_COMMENT);

  // Create the output directory
  mkdir(filename_output_dir,02755);

  // Create snapshot expansion factor list
  double *a_list=NULL;
  int     n_a_list_in;
  write_a_list(filename_snap_list_in,
               filename_output_dir,
               i_read_start,
               i_read_stop,
               i_read_step);
  read_a_list(filename_output_dir,
              &a_list,
              &n_a_list_in);

  write_tree_run_parameters(filename_output_dir,
                            i_read_start,
                            i_read_stop,
                            i_read_step,
                            n_search,
                            flag_fix_bridges,
                            flag_compute_fragmented,
                            flag_compute_ghosts);

  // Validate existing matching files &/or perfrom matching
  //if(!compute_trees_matches(filename_halo_root_in,
  //                          filename_root_matches,
  //                          i_read_start,
  //                          i_read_stop,
  //                          i_read_step,
  //                          n_search,
  //                          WRITE_MATCHES_MODE_TREES|WRITE_MATCHES_PERFORM_CHECK))
  //   SID_trap_error("Matching could not be completed.  Terminating.",ERROR_LOGIC);
  read_matches_header(filename_root_matches,
                      i_read_start,
                      i_read_stop,
                      i_read_step,
                      &n_files,
                      &n_subgroups,
                      &n_groups,
                      &n_subgroups_max,
                      &n_groups_max,
                      &n_halos_max);

  // We need these for allocating arrays
  calc_max(n_subgroups,&n_subgroups_max,n_files,SID_INT,CALC_MODE_DEFAULT);
  calc_max(n_groups,   &n_groups_max,   n_files,SID_INT,CALC_MODE_DEFAULT);
  n_halos_max=MAX(n_subgroups_max,n_groups_max);

  // We need enough indices to allow us to hold-on to descendants until outputing
  //   and for the current and last i_file as well
  n_wrap      =2*n_search+2;
  i_file_start=n_files-1;

  // Initialize arrays
  SID_log("Creating arrays...",SID_LOG_OPEN);
  n_particles_groups    =(int    *)SID_malloc(sizeof(int)   *n_halos_max);
  n_particles_subgroups =(int    *)SID_malloc(sizeof(int)   *n_halos_max);
  match_id              =(int    *)SID_malloc(sizeof(int)   *n_halos_max);
  match_score           =(float  *)SID_malloc(sizeof(float) *n_halos_max);
  match_index           =(size_t *)SID_malloc(sizeof(size_t)*n_halos_max);
  match_flag_two_way    =(char   *)SID_malloc(sizeof(char)  *n_halos_max);
  subgroups             =(tree_horizontal_info **)SID_malloc(sizeof(tree_horizontal_info *)*n_wrap);
  groups                =(tree_horizontal_info **)SID_malloc(sizeof(tree_horizontal_info *)*n_wrap);
  n_subgroups_group     =(int                  **)SID_malloc(sizeof(int                  *)*n_wrap);
  back_matches_subgroups=(match_info           **)SID_malloc(sizeof(match_info *)          *n_wrap);
  back_matches_groups   =(match_info           **)SID_malloc(sizeof(match_info *)          *n_wrap);
  for(i_search=0;i_search<n_wrap;i_search++){
     subgroups[i_search]             =(tree_horizontal_info *)SID_calloc(sizeof(tree_horizontal_info)*n_subgroups_max);
     groups[i_search]                =(tree_horizontal_info *)SID_calloc(sizeof(tree_horizontal_info)*n_groups_max);       
     n_subgroups_group[i_search]     =(int                  *)SID_calloc(sizeof(int)                 *n_groups_max);       
     back_matches_subgroups[i_search]=NULL;
     back_matches_groups[i_search]   =NULL;
  }
  SID_log("Done.",SID_LOG_CLOSE);

  // Process the first file separately
  //   (just give everything ids from a running index.  Also adds MMS flags.) ...
  init_trees_horizontal_roots(groups,
                              subgroups,
                              match_id,
                              match_score,
                              match_index,
                              match_flag_two_way,
                              n_particles_groups,
                              n_particles_subgroups,
                              n_subgroups_group,
                              n_groups_max,
                              n_subgroups_max,
                              filename_root_matches,
                              i_read_start,
                              i_read_stop,
                              i_read_step,
                              i_file_start,
                              n_wrap,
                              n_halos_max,
                              &max_id_group,
                              &max_tree_id_group,
                              &max_id_subgroup,
                              &max_tree_id_subgroup);

  // The first snapshot is done now (set to defaults as the roots of trees) ... now loop over all other snapshots ...
  //   There are a bunch of counters at work here.  Because we aren't necessarily using every 
  //     snapshot (if i_read_step>1), we need counters to keep track of which snapshots we
  //     are working with (i_read_*,j_read_*, etc), counters to keep track of which
  //     files's we're dealing with as far as the trees indices are concerned (i_file_*,j_file_*,etc), and
  //     counters to keep track of which files are being/have been written (i_write_*,j_write_* etc).
  //     We can't write files right away because previously processed snapshots can be changed
  //     when we deal with dropped and bridged halos.
  for(i_read   =i_read_stop-i_read_step,
        i_file =i_file_start-1, 
        j_file =1,             
        i_write=i_file_start,      
        j_write=i_read_stop,
        l_write=0;      
      i_read>=i_read_start;
      i_read-=i_read_step,    
         i_file--, 
         j_file++){
    SID_log("Processing snapshot #%d...",SID_LOG_OPEN|SID_LOG_TIMER,i_read);

    // Loop twice (1st to process subgroups, 2nd to process groups)
    for(k_match=0;k_match<n_k_match;k_match++){

       // Initialize a bunch of stuff which depends on whether
       //   we are processing groups or subgroups.
       // Do the groups first, so that we have access to n_subgroups_group,
       //   which we need for setting MOST_MASSIVE flags, etc
       switch(k_match){
          case 0:
          sprintf(group_text_prefix,"");
          flag_match_subgroups=MATCH_GROUPS;
          halos               =groups;
          back_matches        =back_matches_groups;
          n_halos             =n_groups;
          n_halos_max         =n_groups_max;
          max_id              =max_id_group;
          max_tree_id         =max_tree_id_group;
          n_particles         =n_particles_groups;
          break;
          case 1:
          sprintf(group_text_prefix,"sub");
          flag_match_subgroups=MATCH_SUBGROUPS;
          halos               =subgroups;
          back_matches        =back_matches_subgroups;
          n_halos             =n_subgroups;
          n_halos_max         =n_subgroups_max;
          max_id              =max_id_subgroup;
          max_tree_id         =max_tree_id_subgroup;
          n_particles         =n_particles_subgroups;
          break;
       }
       halos_i  =halos[i_file%n_wrap];
       n_halos_i=n_halos[j_file];

       SID_log("Processing %d %sgroups...",SID_LOG_OPEN|SID_LOG_TIMER,n_halos_i,group_text_prefix);

       // Initialize tree pointer-arrays with dummy values
       init_trees_horizontal_snapshot(halos_i,
                                      &(back_matches[i_file%n_wrap]),
                                      i_read,
                                      i_file,
                                      n_groups[j_file],
                                      n_groups_max,
                                      n_subgroups[j_file],
                                      n_subgroups_max,
                                      flag_match_subgroups);

       // Identify matches that will be used for progenitor building (and read halo sizes)
       if(flag_fix_bridges)
          identify_back_matches(halos,
                                halos_i,
                                &(back_matches[i_file%n_wrap]),
                                n_halos_i,
                                match_id,
                                match_score,
                                match_index,
                                match_flag_two_way,
                                n_particles,
                                i_file,
                                i_read,
                                i_read_start,
                                i_read_stop,
                                i_read_step,
                                n_search,
                                n_wrap,
                                n_halos_max,
                                n_files,
                                filename_root_matches,
                                flag_match_subgroups);

       // Perform forward-matching
       identify_progenitors(halos,
                            halos_i,
                            n_subgroups_group,
                            n_halos_i,
                            match_id,
                            match_score,
                            match_index,
                            match_flag_two_way,
                            n_particles,
                            i_file,
                            i_read,
                            i_read_start,
                            i_read_stop,
                            i_read_step,
                            n_search,
                            n_wrap,
                            n_halos_max,
                            n_files,
                            flag_fix_bridges,
                            &max_id,
                            &n_halos_1_matches,
                            &n_halos_2_matches,
                            filename_root_matches,
                            group_text_prefix,
                            flag_match_subgroups);

       // Add MOST_MASSIVE substructure flags
       if(flag_match_subgroups==MATCH_SUBGROUPS)
          add_substructure_info(subgroups[i_file%n_wrap],
                                n_subgroups_group[i_file%n_wrap],
                                n_particles_groups,
                                n_groups[j_file],
                                n_subgroups[j_file],
                                flag_match_subgroups);
      
       // Finalize matches to unprocessed halos.  In particular,
       //    resolve matches to bridged halos that were not matched
       //    to any emerged candidates.
       finalize_trees_horizontal(n_halos_1_matches,
                                 n_halos_i,
                                 halos,
                                 halos_i,
                                 i_file,
                                 n_search,
                                 n_wrap,
                                 &max_id,
                                 &max_tree_id);
 
       // Now that we know which halos are main progenitors, we
       //    can set the n_partices_largest_descendant values.
       set_largest_descendants(halos_i,n_halos_i);

       // Now that we know which halos are the main progenitors of this
       //    snapshot's bridged halos, we can mark any other back matches
       //    as candidate emerged halos and identify bridges.
       if(flag_fix_bridges)
          identify_bridges(halos_i,n_halos_i,n_search);

       // Report some statistics
       //   n.b.: This is only an estimate in some cases, since subsequent snapshots may alter this snapshot.  
       //         See the final written log.txt file for accurate numbers.
       write_trees_horizontal_report(n_halos_i,n_halos_max,halos_i);

       // Update the max_id variables
       switch(flag_match_subgroups){
          case MATCH_SUBGROUPS:
            max_id_subgroup=max_id;
            max_tree_id_subgroup=max_tree_id;
            break;
          case MATCH_GROUPS:
            max_id_group   =max_id;
            max_tree_id_group=max_tree_id;
            break;
       }
       SID_log("Done.",SID_LOG_CLOSE);
    } // k_match
 
    // Write trees once a few files have been processed
    //   and no more dropped groups etc. need to be given ids
    if(j_file>n_search){
       int mode_write;
       if(flag_compute_ghosts || flag_compute_fragmented)
          mode_write=TREE_HORIZONTAL_WRITE_EXTENDED|TREE_HORIZONTAL_WRITE_ALLCASES|TREE_HORIZONTAL_WRITE_CHECK_FRAGMENTED;
       else
          mode_write=TREE_HORIZONTAL_WRITE_ALLCASES|TREE_HORIZONTAL_WRITE_CHECK_FRAGMENTED;
       write_trees_horizontal((void **)groups, 
                              (void **)subgroups,
                              n_groups[l_write],   n_groups_max,   
                              n_subgroups[l_write],n_subgroups_max,
                              n_subgroups_group,
                              max_tree_id_subgroup,
                              max_tree_id_group,
                              i_write,
                              j_write,
                              l_write,
                              i_read_step,
                              n_search,
                              n_wrap,
                              i_file_start,
                              filename_cat_root_in,
                              filename_output_dir,
                              a_list,
                              cosmo,
                              n_k_match,
                              l_write==0,
                              mode_write);
       i_write--;
       l_write++;
       j_write-=i_read_step;
    }
    SID_log("Done.",SID_LOG_CLOSE);
  } // loop over snaps

  // Write the remaining snapshots
  for(;j_write>=i_read_start;i_write--,j_write-=i_read_step,l_write++){
     int mode_write;
     if(flag_compute_ghosts || flag_compute_fragmented)
        mode_write=TREE_HORIZONTAL_WRITE_EXTENDED|TREE_HORIZONTAL_WRITE_ALLCASES|TREE_HORIZONTAL_WRITE_CHECK_FRAGMENTED;
     else
        mode_write=TREE_HORIZONTAL_WRITE_ALLCASES|TREE_HORIZONTAL_WRITE_CHECK_FRAGMENTED;
     write_trees_horizontal((void **)groups,   
                            (void **)subgroups,
                            n_groups[l_write],   n_groups_max,   
                            n_subgroups[l_write],n_subgroups_max,
                            n_subgroups_group,
                            max_tree_id_subgroup,
                            max_tree_id_group,
                            i_write,
                            j_write,
                            l_write,
                            i_read_step,
                            n_search,
                            n_wrap,
                            i_file_start,
                            filename_cat_root_in,
                            filename_output_dir,
                            a_list,
                            cosmo,
                            n_k_match,
                            l_write==0,
                            mode_write);
  }
  int i_write_last;
  int l_write_last;
  int j_write_last;
  i_write_last=i_write+1;
  j_write_last=j_write+i_read_step;
  l_write_last=l_write-1;

  // Clean-up
  SID_log("Freeing arrays...",SID_LOG_OPEN);
  for(i_search=0;i_search<n_wrap;i_search++){
     // Free subgroup information
     SID_free(SID_FARG subgroups[i_search]);
     SID_free(SID_FARG back_matches_subgroups[i_search]);
     // Free group information
     SID_free(SID_FARG groups[i_search]);
     SID_free(SID_FARG back_matches_groups[i_search]);
  }
  SID_free(SID_FARG subgroups);
  SID_free(SID_FARG groups);
  SID_free(SID_FARG back_matches_subgroups);
  SID_free(SID_FARG back_matches_groups);
  SID_free(SID_FARG match_id);
  SID_free(SID_FARG match_score);
  SID_free(SID_FARG match_index);
  SID_free(SID_FARG match_flag_two_way);
  SID_free(SID_FARG n_particles_groups);
  SID_free(SID_FARG n_particles_subgroups);
  SID_log("Done.",SID_LOG_CLOSE);

  // Any information that needs to be communicated up the trees from the
  //    roots will be done here.  This includes any information needed
  //    for tracking mergers and fragmented halos.
  // Because fragmented halos might persist longer than the search interval, we have to
  //    walk the trees forward in time to propagate the TREE_CASE_FRAGMENTED_* flags.
  // At this point, fragmented halos are only labeled when they appear.
  //    This will propagate the fragmented halo flags forward in time.
  propagate_progenitor_info(n_groups,
                            n_subgroups,
                            n_subgroups_group,
                            i_file_start,
                            i_write_last,
                            j_write_last,
                            l_write_last,
                            i_read_stop,
                            i_read_step,
                            max_tree_id_subgroup,
                            max_tree_id_group,
                            n_subgroups_max,
                            n_groups_max,
                            n_search,
                            n_files,
                            n_wrap,
                            n_k_match,
                            a_list,
                            cosmo,
                            filename_output_dir,
                            flag_compute_fragmented);

  // If extended horizontal tree files were written for fragmented
  //    halo propagation or ghost tree construction, remove them.
  if(flag_compute_ghosts || flag_compute_fragmented){
     SID_log("Removing temporary tree files...",SID_LOG_OPEN);
     for(j_write=i_read_stop;j_write>=i_read_start;j_write-=i_read_step){
        char filename_output_dir_horizontal[MAX_FILENAME_LENGTH];
        char filename_output_dir_horizontal_trees[MAX_FILENAME_LENGTH];
        char filename_remove[MAX_FILENAME_LENGTH];
        sprintf(filename_output_dir_horizontal,      "%s/horizontal",filename_output_dir);
        sprintf(filename_output_dir_horizontal_trees,"%s/trees",     filename_output_dir_horizontal);
        sprintf(filename_remove,"%s/horizontal_trees_tmp_%03d.dat",filename_output_dir_horizontal_trees,j_write);
        remove(filename_remove);
     }
     SID_log("Done.",SID_LOG_CLOSE);
  }

  // Some final clean-up
  SID_log("Cleaning up...",SID_LOG_OPEN);
  SID_free(SID_FARG n_groups);
  SID_free(SID_FARG n_subgroups);
  for(i_search=0;i_search<n_wrap;i_search++)
     SID_free(SID_FARG n_subgroups_group[i_search]);
  SID_free(SID_FARG n_subgroups_group);
  SID_free(SID_FARG a_list);
  SID_log("Done.",SID_LOG_CLOSE);

  // Force the forest construction to use all snapshots
  int n_search_forests=i_read_stop;

  // Construct tree->forest mappings
  compute_forests(filename_output_dir,n_search_forests);

  SID_log("Done.",SID_LOG_CLOSE);
}