void ns_movement_visualization_generator::create_time_path_analysis_visualization(const ns_image_server_captured_image_region & region_image, const ns_death_time_annotation_compiler_region & compiler_region,const ns_image_standard & grayscale, ns_image_standard & out,ns_sql & sql){
	unsigned long thickness = 4;
	
	const ns_color_8 excluded_color = ns_color_8(50,50,255);

	ns_image_properties prop(grayscale.properties());
	prop.components = 3;
	out.init(prop);
	for (unsigned int y = 0; y < prop.height; ++y){
		for (unsigned long x = 0; x < prop.width; ++x){
			out[y][3*x+0] = 255-grayscale[y][x];
			out[y][3*x+1] = 255-grayscale[y][x];
			out[y][3*x+2] = 255-grayscale[y][x];
		}
	}


/*	ns_death_time_annotation_set movement_annotations;
//	movement_annotations.events.reserve(death_time_annotations.size());
//	for (unsigned long i = 0; i < death_time_annotations.size(); i++){

		switch(death_time_annotations[i].type){
			case ns_fast_moving_worm_observed:
			case ns_slow_moving_worm_observed:
			case ns_posture_changing_worm_observed:
			case ns_stationary_worm_observed:
					movement_annotations.push_back(death_time_annotations[i]);
			}
	}
*/
	
	ns_image_worm_detection_results results;
	results.id = region_image.region_detection_results_id;
	results.load_from_db(false,false,sql);
	ns_image_server_captured_image_region region_t(region_image);
	results.load_images_from_db(region_t,sql);
	const std::vector<const ns_detected_worm_info *> detected_worms(results.actual_worm_list());
	ns_font & font(font_server.default_font());
	const unsigned long font_height(25);
	font.set_height(font_height);

	std::vector<const ns_death_time_annotation *> representative_state_event_for_location(compiler_region.locations.size(),0);
	for (unsigned int i = 0; i < compiler_region.locations.size(); i++){
		for (unsigned int j = 0; j < compiler_region.locations[i].annotations.size(); j++){
			if (ns_movement_event_is_a_state_observation(compiler_region.locations[i].annotations[j].type) && 
								compiler_region.locations[i].annotations[j].time.period_end == region_image.capture_time){
				if (representative_state_event_for_location[i] != 0){
					cerr << "Found multiple state events for a time!\n";
				}
				else representative_state_event_for_location[i] = &compiler_region.locations[i].annotations[j];
			}
		}
	}
	
	std::vector<const ns_death_time_annotation *> fast_moving_animal_matches(detected_worms.size(),0);
	for (unsigned int i = 0; i < compiler_region.fast_moving_animals.size(); i++){
		for (unsigned long w = 0; w < detected_worms.size(); w++){
			if (detected_worms[w]->region_size == compiler_region.fast_moving_animals[i].size &&
				detected_worms[w]->region_position_in_source_image == compiler_region.fast_moving_animals[i].position){
				fast_moving_animal_matches[w] = &compiler_region.fast_moving_animals[i];
			}
		}
	}

	//for debugging
	std::vector<char> locations_matched(representative_state_event_for_location.size(),0);
	unsigned long locations_with_matches(0);
	//for real use
	std::vector<ns_death_time_annotation_compiler_region::ns_location_list::const_iterator> location_matches(detected_worms.size(),compiler_region.locations.end());
	unsigned long unmatched_detected_worms(0);
	for (unsigned long w = 0; w < detected_worms.size(); w++){
		for (unsigned int i = 0; i < representative_state_event_for_location.size(); i++){
			if (representative_state_event_for_location[i] == 0)
				continue;
			if (detected_worms[w]->region_size == representative_state_event_for_location[i]->size &&
				detected_worms[w]->region_position_in_source_image == representative_state_event_for_location[i]->position){
					if(location_matches[w] != compiler_region.locations.end()){
						cerr << "Found multiple locations that match detected worm!\n";
					}
					else{
						//for debugging
						locations_matched[i] = 1;
						locations_with_matches++;
						//for real use
						location_matches[w] = compiler_region.locations.begin()+i;
					}
			}
		}
		if (fast_moving_animal_matches[w] == 0 && location_matches[w]== compiler_region.locations.end())
			unmatched_detected_worms++;
	}
	if (unmatched_detected_worms > 0)
		cerr << "Could not match up " << unmatched_detected_worms << " of " << detected_worms.size() << " animals.\n";
	
	for (unsigned long w = 0; w < detected_worms.size(); w++){
		const ns_death_time_annotation_compiler_region::ns_location_list::const_iterator location(location_matches[w]);
		const ns_death_time_annotation * fast_animal_match(fast_moving_animal_matches[w]);
		const ns_vector_2i & pos = detected_worms[w]->region_position_in_source_image;
		//if we can't find info on the object, paint it white.
		if (fast_animal_match == 0 && location== compiler_region.locations.end()){
			const ns_color_8 color(255,255,255);
			ns_vector_2i size = detected_worms[w]->region_size;
			out.draw_line_color_thick(pos,pos+ns_vector_2i(size.x,0),color,3);
			out.draw_line_color_thick(pos,pos+ns_vector_2i(0,size.y),color,3);
			out.draw_line_color_thick(pos+ns_vector_2i(0,size.y),pos+size,color,3);
			out.draw_line_color_thick(pos+ns_vector_2i(size.x,0),pos+size,color,3);
			
			continue;
		}
		ns_color_8  color;
		if (location != compiler_region.locations.end()){
			color = (ns_movement_colors::color(ns_movement_event_state(representative_state_event_for_location[location-compiler_region.locations.begin()]->type)));
			if (location->properties.is_excluded())
			color = excluded_color;
		}
		else color = ns_movement_colors::color(ns_movement_fast);


		for (unsigned int y = 0; y < detected_worms[w]->bitmap().properties().height; y++){
			for (unsigned int x = 0; x < detected_worms[w]->bitmap().properties().width; x++){
				if (detected_worms[w]->bitmap()[y][x]){
					out[pos.y + y][3*(pos.x + x)+0]
						= (ns_8_bit)(.75*color.x + .25*out[pos.y + y][3*(pos.x + x)+0]);
					out[pos.y + y][3*(pos.x + x)+1]
						= (ns_8_bit)(.75*color.y + .25*out[pos.y + y][3*(pos.x + x)+1]);
					out[pos.y + y][3*(pos.x + x)+2]
						= (ns_8_bit)(.75*color.z + .25*out[pos.y + y][3*(pos.x + x)+2]);
				}
			}
		}
		ns_color_8 edge_color(color);
		if (location != compiler_region.locations.end() &&
			location->properties.number_of_worms_at_location_marked_by_hand > 1){
		//	font.draw_color(pos.x + (detected_worms[w]->region_size.x*3)/4,pos.y+font_height,ns_color_8(255,255,255),std::string("") + 
		//		ns_to_string(location->properties.number_of_worms_at_location_marked_by_hand),out);
			edge_color = ns_color_8(255,180,120);
			const int edge_width(3);
			// use signed ints for x and y so that "x + dx" type expressions are also properly signed.
			for (int y = 0; y < detected_worms[w]->edge_bitmap().properties().height; y++){
				for (int x = 0; x < detected_worms[w]->edge_bitmap().properties().width; x++){
					if (detected_worms[w]->edge_bitmap()[y][x]){
						for (int dx = -edge_width; dx <= edge_width; dx++)
							for (int dy = -edge_width; dy <= edge_width; dy++){
								if ( dx + dy > edge_width)
									continue; //round edges
								if (x + dx < 0 || x + dx >= detected_worms[w]->edge_bitmap().properties().width)
									continue;
								if (y + dy < 0 || y + dy >= detected_worms[w]->edge_bitmap().properties().height)
									continue;
								out[pos.y + y+dy][3*(pos.x + x+dx)+0]
									= (ns_8_bit)(.2*(ns_8_bit)(edge_color.x) + .8*out[pos.y + y+dy][3*(pos.x + x+dx)+0]);
								out[pos.y + y+dy][3*(pos.x + x+dx)+1]
									= (ns_8_bit)(.2*(ns_8_bit)(edge_color.y) + .8*out[pos.y + y+dy][3*(pos.x + x+dx)+1]);
								out[pos.y + y+dy][3*(pos.x + x+dx)+2]
									= (ns_8_bit)(.2*(ns_8_bit)(edge_color.z) + .8*out[pos.y + y+dy][3*(pos.x + x+dx)+2]);
							}
					}
				}
			}

		}	
	}
	for (unsigned int i = 0; i < compiler_region.locations.size(); i++){
		if (representative_state_event_for_location[i] == 0 || locations_matched[i])
			continue;
		const ns_death_time_annotation & a(*representative_state_event_for_location[i]);
		if (compiler_region.locations[i].properties.inferred_animal_location){
			ns_color_8 color = ns_movement_colors::color(ns_movement_event_state(a.type));
			if (compiler_region.locations[i].properties.is_excluded())
				color = excluded_color;
			unsigned long thickness = 4;
			out.draw_line_color_thick(a.position,a.position + ns_vector_2i(a.size.x,0),color,thickness,.8);
			out.draw_line_color_thick(a.position,a.position + ns_vector_2i(0,a.size.y),color,thickness,.8);
			out.draw_line_color_thick(a.position+ns_vector_2i(a.size.x,0),a.position + ns_vector_2i(a.size.x,a.size.y),color,thickness,.6);
			out.draw_line_color_thick(a.position+ns_vector_2i(0,a.size.y),a.position + ns_vector_2i(a.size.x,a.size.y),color,thickness,.6);
		}
	}
}