int define_Computed_field_type_connected_threshold_image_filter(struct Parse_state *state,
	void *field_modify_void, void *computed_field_simple_package_void)
/*******************************************************************************
LAST MODIFIED : 30 August 2006

DESCRIPTION :
Converts <field> into type COMPUTED_FIELD_CONNECTED_THRESHOLD_IMAGE_FILTER (if it is not
already) and allows its contents to be modified.
==============================================================================*/
{
	double lower_threshold, upper_threshold, replace_value;
	int num_seed_points;
	int seed_dimension;
  double *seed_points;
	int return_code;
	int seed_points_length;
	int previous_state_index, expected_parameters;

	struct Computed_field *source_field;
	Computed_field_modify_data *field_modify;
	struct Option_table *option_table;
	struct Set_Computed_field_conditional_data set_source_field_data;

	ENTER(define_Computed_field_type_connected_threshold_image_filter);
	USE_PARAMETER(computed_field_simple_package_void);
	if (state && (field_modify=(Computed_field_modify_data *)field_modify_void))
	{
		return_code = 1;

		source_field = (struct Computed_field *)NULL;
		lower_threshold = 0.0;
		upper_threshold = 1.0;
		replace_value = 1;
		num_seed_points = 0;
		seed_dimension  = 2;
		seed_points = (double *)NULL;

		// should probably default to having 1 seed point
		//		seed_points[0] = 0.5;  // pjb: is this ok?
		//		seed_points[1] = 0.5;
		seed_points_length = 0;

		/* get valid parameters for projection field */
		if ((NULL != field_modify->get_field()) &&
			(computed_field_connected_threshold_image_filter_type_string ==
				Computed_field_get_type_string(field_modify->get_field())))
		{
			return_code =
				Cmiss_field_get_type_connected_threshold_image_filter(field_modify->get_field(), &source_field,
				&lower_threshold, &upper_threshold, &replace_value,
		  &num_seed_points, &seed_dimension, &seed_points);
		}
		if (return_code)
		{

			if (source_field)
			{
				ACCESS(Computed_field)(source_field);
			}

			if (state->current_token &&
				(!(strcmp(PARSER_HELP_STRING, state->current_token)&&
					strcmp(PARSER_RECURSIVE_HELP_STRING, state->current_token))))
			{
				/* Handle help separately */
				option_table = CREATE(Option_table)();
			Option_table_add_help(option_table,
				"The connected_threshold_filter field uses the itk::ConnectedThresholdImageFilter code to segment a field. The <field> it operates on is usually a sample_texture field, based on a texture that has been created from image file(s).  The segmentation is based on a region growing algorithm which requires at least one seed point.  To specify the seed points first set the <num_seed_points> and the <dimension> of the image.  The <seed_points> are a list of the coordinates for the first and any subsequent seed points.  Starting from the seed points any neighbouring pixels with an intensity between <lower_threshold> and the <upper_threshold> are added to the region.  Pixels within the region have their pixel intensity set to <replace_value> while the remaining pixels are set to 0. See a/testing/image_processing_2D for an example of using this field.  For more information see the itk software guide.");

				/* field */
				set_source_field_data.computed_field_manager =
					field_modify->get_field_manager();
				set_source_field_data.conditional_function = Computed_field_is_scalar;
				set_source_field_data.conditional_function_user_data = (void *)NULL;
				Option_table_add_entry(option_table, "field", &source_field,
															 &set_source_field_data, set_Computed_field_conditional);
				/* lower_threshold */
				Option_table_add_double_entry(option_table, "lower_threshold",
																			&lower_threshold);
				/* upper_threshold */
				Option_table_add_double_entry(option_table, "upper_threshold",
																			&upper_threshold);
				/* replace_value */
				Option_table_add_double_entry(option_table, "replace_value",
																			&replace_value);
				/* num_seed_points */
				Option_table_add_int_positive_entry(option_table, "num_seed_points",
																						&num_seed_points);
				Option_table_add_int_positive_entry(option_table, "dimension",
																						&seed_dimension);
				Option_table_add_double_vector_entry(option_table, "seed_points",
																						 seed_points, &seed_points_length);
				return_code = Option_table_multi_parse(option_table, state);
				DESTROY(Option_table)(&option_table);
			}

			if (return_code)
			{

				// store previous state so that we can return to it
				previous_state_index = state->current_index;

				/* parse the two options which determine the number of seed values
					 and hence the size of the array that must be created to read in
					 the number of seed values. */

				option_table = CREATE(Option_table)();
				/* num_seed_points */
				Option_table_add_int_positive_entry(option_table, "num_seed_points",
																						&num_seed_points);
				/* dimension */
				Option_table_add_int_positive_entry(option_table, "dimension",
																						&seed_dimension);
				/* Ignore all the other entries */
				Option_table_ignore_all_unmatched_entries(option_table);
				return_code = Option_table_multi_parse(option_table, state);
				DESTROY(Option_table)(&option_table);
				/* Return back to where we were */
				shift_Parse_state(state, previous_state_index - state->current_index);

			}

			/* parse the rest of the table */
			if (return_code)
			{
				seed_points_length = num_seed_points * seed_dimension;

				REALLOCATE(seed_points, seed_points, double, seed_points_length);
				// pjb: should I populate array with dummy values?

				option_table = CREATE(Option_table)();
				/* field */
				set_source_field_data.computed_field_manager =
					field_modify->get_field_manager();
				set_source_field_data.conditional_function = Computed_field_is_scalar;
				set_source_field_data.conditional_function_user_data = (void *)NULL;
				Option_table_add_entry(option_table, "field", &source_field,
															 &set_source_field_data, set_Computed_field_conditional);
				/* lower_threshold */
				Option_table_add_double_entry(option_table, "lower_threshold",
																			&lower_threshold);
				/* upper_threshold */
				Option_table_add_double_entry(option_table, "upper_threshold",
																			&upper_threshold);
				/* replace_value */
				Option_table_add_double_entry(option_table, "replace_value",
																			&replace_value);
				expected_parameters = 1;
				Option_table_add_ignore_token_entry(option_table, "num_seed_points",
																						&expected_parameters);
				expected_parameters = 1;
				Option_table_add_ignore_token_entry(option_table, "dimension",
																						&expected_parameters);
				Option_table_add_double_vector_entry(option_table, "seed_points",
																						 seed_points, &seed_points_length);
				return_code=Option_table_multi_parse(option_table,state);
				DESTROY(Option_table)(&option_table);
			}

			/* no errors,not asking for help */
			if (return_code)
			{
				if (!source_field)
				{
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_connected_threshold_image_filter.  "
						"Missing source field");
					return_code = 0;
				}
			}
			if (return_code)
			{
				return_code = field_modify->update_field_and_deaccess(
					Cmiss_field_module_create_connected_threshold_image_filter(
						field_modify->get_field_module(),
						source_field, lower_threshold, upper_threshold, replace_value,
						num_seed_points, seed_dimension, seed_points));
			}

			if (!return_code)
			{
				if ((!state->current_token) ||
					(strcmp(PARSER_HELP_STRING, state->current_token)&&
						strcmp(PARSER_RECURSIVE_HELP_STRING, state->current_token)))
				{
					/* error */
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_connected_threshold_image_filter.  Failed");
				}
			}

			if (source_field)
			{
				DEACCESS(Computed_field)(&source_field);
			}

			if (seed_points) {
				DEALLOCATE(seed_points);
			}
		}
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_connected_threshold_image_filter.  Invalid argument(s)");
		return_code = 0;
	}
	LEAVE;

	return (return_code);
} /* define_Computed_field_type_connected_threshold_image_filter */
int define_Computed_field_type_fast_marching_image_filter(struct Parse_state *state,
	void *field_modify_void, void *computed_field_simple_package_void)
/*******************************************************************************
LAST MODIFIED : 30 August 2006

DESCRIPTION :
Converts <field> into type COMPUTED_FIELD_FAST_MARCHING_IMAGE_FILTER (if it is not
already) and allows its contents to be modified.
==============================================================================*/
{
	double stopping_value;
	int num_seed_points;
	int dimension;
	double *seed_points;
	double *seed_values;
	int *output_size;
	int length_seed_points;
	int return_code;
	int previous_state_index;
	int i;

	struct Computed_field *source_field;
	Computed_field_modify_data *field_modify;
	struct Option_table *option_table;
	struct Set_Computed_field_conditional_data set_source_field_data;

	ENTER(define_Computed_field_type_fast_marching_image_filter);
	USE_PARAMETER(computed_field_simple_package_void);
	if (state && (field_modify=(Computed_field_modify_data *)field_modify_void))
	{
		return_code = 1;

		source_field = (struct Computed_field *)NULL;
		stopping_value = 100;
		num_seed_points = 1;
		dimension  = 2;
		length_seed_points = num_seed_points * dimension;

		seed_points = (double *)NULL;
		seed_values = (double *)NULL;
		output_size = (int *)NULL;

		ALLOCATE(seed_points, double, length_seed_points);
		ALLOCATE(seed_values, double, num_seed_points);
		ALLOCATE(output_size, int, dimension);

		// should probably default to having 1 seed
		seed_points[0] = 0.5;  // pjb: is this ok?
		seed_points[1] = 0.5;
		seed_values[0] = 0.0;
		output_size[0] = 128;
		output_size[1] = 128;

		/* get valid parameters for projection field */
		if ((NULL != field_modify->get_field()) &&
			(computed_field_fast_marching_image_filter_type_string ==
				Computed_field_get_type_string(field_modify->get_field())))
		{
			return_code =
				cmzn_field_get_type_fast_marching_image_filter(field_modify->get_field(), &source_field,
				  &stopping_value, &num_seed_points, &dimension, &seed_points, &seed_values, &output_size);
		}
		if (return_code)
		{

			if (source_field)
			{
				ACCESS(Computed_field)(source_field);
			}

			if (state->current_token &&
				(!(strcmp(PARSER_HELP_STRING, state->current_token)&&
					strcmp(PARSER_RECURSIVE_HELP_STRING, state->current_token))))
			{
				/* Handle help separately */
				option_table = CREATE(Option_table)();
				Option_table_add_help(option_table,
					"The fast_marching_filter field uses the itk::FastMarchingImageFilter code to segment a field. The segmentation is based on a level set algorithm.  The <field> it operates on is used as a speed term, to govern where the level set curve grows quickly.  The speed term is usually some function (eg a sigmoid) of an image gradient field.  The output field is a time crossing map, where the value at is each pixel is the time take to reach that location from the specified seed points.  Values typically range from 0 through to extremely large (10 to the 38).  To convert the time cross map into a segmented region use a binary threshold filter. To specify the seed points first set the <num_seed_points> and the <dimension> of the image.  The <seed_points> are a list of the coordinates for the first and any subsequent seed points.   It is also possible to specify non-zero initial <seed_values> if desired and to set the <output_size> of the time crossing map. See a/segmentation for an example of using this field.  For more information see the itk software guide.");

				/* field */
				set_source_field_data.computed_field_manager =
					field_modify->get_field_manager();
				set_source_field_data.conditional_function = Computed_field_is_scalar;
				set_source_field_data.conditional_function_user_data = (void *)NULL;
				Option_table_add_entry(option_table, "field", &source_field,
					&set_source_field_data, set_Computed_field_conditional);
				/* stopping_value */
				Option_table_add_double_entry(option_table, "stopping_value",
																			&stopping_value);
				/* num_seed_points */
				Option_table_add_int_positive_entry(option_table, "num_seed_points",
																						&num_seed_points);
				/* dimension */
				Option_table_add_int_positive_entry(option_table, "dimension",
																						&dimension);
				/* seed_points */
				Option_table_add_double_vector_entry(option_table, "seed_points",
																						 seed_points, &length_seed_points);
				/* seed_values */
				Option_table_add_double_vector_entry(option_table, "seed_values",
																						 seed_values, &num_seed_points);
				/* output_size */
				Option_table_add_int_vector_entry(option_table, "output_size",
																						 output_size, &dimension);

				return_code = Option_table_multi_parse(option_table, state);
				DESTROY(Option_table)(&option_table);
			}

			if (return_code)
			{

				// store previous state so that we can return to it
				previous_state_index = state->current_index;

				/* parse the two options which determine the number of seed values
					 and hence the size of the array that must be created to read in
					 the number of seed values. */

				option_table = CREATE(Option_table)();
				/* num_seed_points */
				Option_table_add_int_positive_entry(option_table, "num_seed_points",
																						&num_seed_points);
				/* dimension */
				Option_table_add_int_positive_entry(option_table, "dimension",
																						&dimension);
				/* Ignore all the other entries */
				Option_table_ignore_all_unmatched_entries(option_table);
				return_code = Option_table_multi_parse(option_table, state);
				DESTROY(Option_table)(&option_table);

				/* Return back to where we were */
				shift_Parse_state(state, previous_state_index - state->current_index);

			}

			/* parse the rest of the table */
			if (return_code)
			{
				length_seed_points = num_seed_points * dimension;

				/* reallocate memory for arrays */
				REALLOCATE(seed_points, seed_points, double, length_seed_points);
				REALLOCATE(seed_values, seed_values, double, num_seed_points);
				REALLOCATE(output_size, output_size, int, dimension);

				/* set default values, in case options are not specified in field definition. */
				for (i=0; i < length_seed_points ;i++) {
					seed_points[i] = 0;
				}
				for (i=0; i < num_seed_points ;i++) {
					seed_values[i] = 0;
				}
				for (i=0; i < dimension ;i++) {
					output_size[i] = 128;
				}

				option_table = CREATE(Option_table)();
				/* field */
				set_source_field_data.computed_field_manager =
					field_modify->get_field_manager();
				set_source_field_data.conditional_function = Computed_field_is_scalar;
				set_source_field_data.conditional_function_user_data = (void *)NULL;
				Option_table_add_entry(option_table, "field", &source_field,
															 &set_source_field_data, set_Computed_field_conditional);
				/* stopping_value */
				Option_table_add_double_entry(option_table, "stopping_value",
					&stopping_value);
				int num_seed_points_expected_parameters = 1;
				Option_table_add_ignore_token_entry(option_table, "num_seed_points",
					&num_seed_points_expected_parameters);
				int dimension_expected_parameters = 1;
				Option_table_add_ignore_token_entry(option_table, "dimension",
					&dimension_expected_parameters);
				Option_table_add_double_vector_entry(option_table, "seed_points",
					seed_points, &length_seed_points);
				Option_table_add_double_vector_entry(option_table, "seed_values",
					seed_values, &num_seed_points);
				Option_table_add_int_vector_entry(option_table, "output_size",
					output_size, &dimension);

				return_code=Option_table_multi_parse(option_table,state);
				DESTROY(Option_table)(&option_table);

			}

			/* no errors,not asking for help */
			if (return_code)
			{
				if (!source_field)
				{
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_fast_marching_image_filter.  "
						"Missing source field");
					return_code = 0;
				}
			}
			if (return_code)
			{
				return_code = field_modify->update_field_and_deaccess(
					cmzn_fieldmodule_create_field_imagefilter_fast_marching(
						field_modify->get_field_module(),
						source_field, stopping_value, num_seed_points, dimension,
						seed_points, seed_values, output_size));
			}

			if (!return_code)
			{
				if ((!state->current_token) ||
					(strcmp(PARSER_HELP_STRING, state->current_token)&&
						strcmp(PARSER_RECURSIVE_HELP_STRING, state->current_token)))
				{
					/* error */
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_fast_marching_image_filter.  Failed");
				}
			}

			if (source_field)
			{
				DEACCESS(Computed_field)(&source_field);
			}

			if (seed_points) {
				DEALLOCATE(seed_points);
			}

			if (seed_values) {
				DEALLOCATE(seed_values);
			}

			if (output_size) {
				DEALLOCATE(output_size);
			}

		}
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_fast_marching_image_filter.  Invalid argument(s)");
		return_code = 0;
	}
	LEAVE;

	return (return_code);
} /* define_Computed_field_type_fast_marching_image_filter */
int define_Computed_field_type_mean_image_filter(struct Parse_state *state,
	void *field_modify_void, void *computed_field_simple_package_void)
/*******************************************************************************
LAST MODIFIED : 30 August 2006

DESCRIPTION :
Converts <field> into type COMPUTED_FIELD_MEANIMAGEFILTER (if it is not
already) and allows its contents to be modified.
==============================================================================*/
{
	int dimension, expected_parameters, i, old_dimension, previous_state_index,
		*radius_sizes, return_code, *sizes;
	struct Computed_field *source_field, *texture_coordinate_field;
	Computed_field_modify_data *field_modify;
	struct Option_table *option_table;
	struct Set_Computed_field_conditional_data set_source_field_data;

	ENTER(define_Computed_field_type_mean_image_filter);
	USE_PARAMETER(computed_field_simple_package_void);
	if (state && (field_modify=(Computed_field_modify_data *)field_modify_void))
	{
		return_code = 1;
		/* get valid parameters for projection field */
		source_field = (struct Computed_field *)NULL;
		radius_sizes = (int *)NULL;
		old_dimension = 0;
		if ((NULL != field_modify->get_field()) &&
			(computed_field_mean_image_filter_type_string ==
				Computed_field_get_type_string(field_modify->get_field())))
		{
			return_code =
				cmzn_field_get_type_mean_image_filter(field_modify->get_field(), &source_field,
					&radius_sizes);
			return_code = Computed_field_get_native_resolution(source_field,
				&old_dimension, &sizes, &texture_coordinate_field);
			if (return_code)
			{
				DEALLOCATE(sizes);
			}
		}
		if (return_code)
		{
			/* must access objects for set functions */
			if (source_field)
			{
				ACCESS(Computed_field)(source_field);
			}

			if ((!state->current_token) ||
				(strcmp(PARSER_HELP_STRING, state->current_token)&&
					strcmp(PARSER_RECURSIVE_HELP_STRING, state->current_token)))
			{

				previous_state_index = state->current_index;

				/* Discover the source field */
				option_table = CREATE(Option_table)();
				/* field */
				set_source_field_data.computed_field_manager =
					field_modify->get_field_manager();
				set_source_field_data.conditional_function = Computed_field_has_numerical_components;
				set_source_field_data.conditional_function_user_data = (void *)NULL;
				Option_table_add_entry(option_table, "field", &source_field,
					&set_source_field_data, set_Computed_field_conditional);
				/* Ignore all the other entries */
				Option_table_ignore_all_unmatched_entries(option_table);
				return_code = Option_table_multi_parse(option_table, state);
				DESTROY(Option_table)(&option_table);
				/* Return back to where we were */
				shift_Parse_state(state, previous_state_index - state->current_index);
				/* no errors,not asking for help */
				if (return_code)
				{
					if (!source_field)
					{
						display_message(ERROR_MESSAGE,
							"define_Computed_field_type_mean_image_filter.  "
							"Missing source field");
						return_code = 0;
					}
				}
				if (return_code)
				{
					return_code = Computed_field_get_native_resolution(source_field,
						&dimension, &sizes, &texture_coordinate_field);
					if (return_code)
					{
						DEALLOCATE(sizes);

						if (!radius_sizes || (old_dimension != dimension))
						{
							REALLOCATE(radius_sizes, radius_sizes, int, dimension);
							for (i = old_dimension ; i < dimension ; i++)
							{
								radius_sizes[i] = 1;
							}
						}
						/* Read the radius sizes */
						option_table = CREATE(Option_table)();
						/* field */
						expected_parameters = 1;
						Option_table_add_ignore_token_entry(option_table, "field",
							&expected_parameters);
						/* radius_sizes */
						Option_table_add_int_vector_entry(option_table,
							"radius_sizes", radius_sizes, &dimension);
						return_code = Option_table_multi_parse(option_table, state);
						DESTROY(Option_table)(&option_table);
					}
					else
					{
						display_message(ERROR_MESSAGE,
							"define_Computed_field_type_mean_image_filter.  "
							"Source field does not have an image dimension.");
						return_code = 0;
					}
				}
				if (return_code)
				{
					return_code = field_modify->update_field_and_deaccess(
						cmzn_fieldmodule_create_field_imagefilter_mean(
							field_modify->get_field_module(),
							source_field, dimension, radius_sizes));
				}

				if (!return_code)
				{
					/* error */
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_mean_image_filter.  Failed");
				}
			}
			else
			{
				/* Write help */
					option_table = CREATE(Option_table)();
					Option_table_add_help(option_table,
				"The mean_filter field uses the itk::MeanImageFilter code to replace each pixel with the mean intensity of the pixel and its surrounding neighbours.  It is useful for reducing the level of noise.   The <field> it operates on is usually a sample_texture field, based on a texture that has been created from image file(s).   The size of the neighbourhood of pixels used to calculate the mean is determined be a list of <radius_sizes>, one value for each dimension.  Each radius size sets how many pixels to include either side of the central pixel for the corresponding dimension. If radius values are increased, more neighbouring pixels are included and the image becomes smoother. See a/testing/image_processing_2D for an example of using this field. For more information see the itk software guide.");

					/* field */
					set_source_field_data.computed_field_manager =
						field_modify->get_field_manager();
					set_source_field_data.conditional_function = Computed_field_has_numerical_components;
					set_source_field_data.conditional_function_user_data = (void *)NULL;
					Option_table_add_entry(option_table, "field", &source_field,
						&set_source_field_data, set_Computed_field_conditional);
					/* radius_sizes */
					Option_table_add_int_vector_entry(option_table,
						"radius_sizes", radius_sizes, &dimension);
					return_code = Option_table_multi_parse(option_table, state);
					DESTROY(Option_table)(&option_table);
			}
			if (source_field)
			{
				DEACCESS(Computed_field)(&source_field);
			}
			if (radius_sizes)
			{
				DEALLOCATE(radius_sizes);
			}
		}
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_mean_image_filter.  Invalid argument(s)");
		return_code = 0;
	}
	LEAVE;

	return (return_code);
} /* define_Computed_field_type_mean_image_filter */
int define_Computed_field_type_histogram_image_filter(struct Parse_state *state,
	void *field_modify_void, void *computed_field_simple_package_void)
/*******************************************************************************
LAST MODIFIED : 18 October 2006

DESCRIPTION :
Converts <field> into type DISCRETEGAUSSIAN (if it is not
already) and allows its contents to be modified.
==============================================================================*/
{
	int i, original_number_of_components, previous_state_index, return_code;
	int *numberOfBins;
	double marginalScale, *histogramMinimum, *histogramMaximum;
	struct Computed_field *source_field;
	Computed_field_modify_data *field_modify;
	struct Option_table *option_table;
	struct Set_Computed_field_conditional_data set_source_field_data;

	ENTER(define_Computed_field_type_histogram_image_filter);
	USE_PARAMETER(computed_field_simple_package_void);
	if (state && (field_modify=(Computed_field_modify_data *)field_modify_void))
	{
		return_code = 1;
		/* get valid parameters for projection field */
		source_field = (struct Computed_field *)NULL;
		numberOfBins = (int *)NULL;
		histogramMinimum = (double *)NULL;
		histogramMaximum = (double *)NULL;
		marginalScale = 10.0;
		original_number_of_components = 0;
		if ((NULL != field_modify->get_field()) &&
			(computed_field_histogram_image_filter_type_string ==
				Computed_field_get_type_string(field_modify->get_field())))
		{
			return_code =
				Cmiss_field_get_type_histogram_image_filter(field_modify->get_field(), &source_field,
					&numberOfBins, &marginalScale, &histogramMinimum, &histogramMaximum);
			original_number_of_components = source_field->number_of_components;
		}
		if (return_code)
		{
			/* must access objects for set functions */
			if (source_field)
			{
				ACCESS(Computed_field)(source_field);
			}

			if (state->current_token &&
				(!(strcmp(PARSER_HELP_STRING, state->current_token)&&
					strcmp(PARSER_RECURSIVE_HELP_STRING, state->current_token))))
			{
				/* Handle help separately */
				option_table = CREATE(Option_table)();
				Option_table_add_help(option_table,
					"The histogram_filter field uses the itk::ImageToHistogramGenerator code to generate binned values representing the relative frequency of the various pixel intensities.  There should be a number_of_bins for each component direction, and so the total number of bins will be a product of these, so that for a 3 component image you would get a volume histogram.  "
						"If you wanted a histogram for a single component then set the number_of_bins for the other components to 1. "
						"If you do not set the optional histogram_minimums or histogram_maximums (which is a vector of values, 1 for each source component) then the histogram will automatically range the values to the minimum and maximum values in the source image.");

				/* field */
				set_source_field_data.computed_field_manager =
					field_modify->get_field_manager();
				set_source_field_data.conditional_function = Computed_field_has_numerical_components;
				set_source_field_data.conditional_function_user_data = (void *)NULL;
				Option_table_add_entry(option_table, "field", &source_field,
					&set_source_field_data, set_Computed_field_conditional);
				/* histogramMinimum */
				double dummyHistogramMinimum = 0.0;
				Option_table_add_double_entry(option_table, "histogram_minimums",
					&dummyHistogramMinimum);
				/* histogramMinimum */
				double dummyHistogramMaximum = 1.0;
				Option_table_add_double_entry(option_table, "histogram_maximums",
					&dummyHistogramMaximum);
				/* numberOfBins */
				int dummyNumberOfBins = 64;
				Option_table_add_int_positive_entry(option_table, "number_of_bins",
					&dummyNumberOfBins);
				/* marginalScale */
				Option_table_add_double_entry(option_table, "marginal_scale",
					&marginalScale);

				return_code = Option_table_multi_parse(option_table, state);
				DESTROY(Option_table)(&option_table);
			}

			if (return_code)
			{
				// store previous state so that we can return to it
				previous_state_index = state->current_index;

				/* parse the source field so we know the dimension. */

				option_table = CREATE(Option_table)();
				/* field */
				set_source_field_data.computed_field_manager =
					field_modify->get_field_manager();
				set_source_field_data.conditional_function = Computed_field_has_numerical_components;
				set_source_field_data.conditional_function_user_data = (void *)NULL;
				Option_table_add_entry(option_table, "field", &source_field,
					&set_source_field_data, set_Computed_field_conditional);

				/* Ignore all the other entries */
				Option_table_ignore_all_unmatched_entries(option_table);
				return_code = Option_table_multi_parse(option_table, state);
				DESTROY(Option_table)(&option_table);

				/* Return back to where we were */
				shift_Parse_state(state, previous_state_index - state->current_index);
				if (!source_field)
				{
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_histogram_image_filter.  "
						"Missing source field");
					return_code = 0;
				}
			}
			if (return_code)
			{
				if (source_field->number_of_components != original_number_of_components)
				{
					REALLOCATE(numberOfBins, numberOfBins, int,
						source_field->number_of_components);
					for (i = 0 ; i < source_field->number_of_components ; i++)
					{
						numberOfBins[i] = 64;
					}
				}

				option_table = CREATE(Option_table)();

				/* field, ignore as we have already got it */
				int field_expected_parameters = 1;
				Option_table_add_ignore_token_entry(
					option_table, "field", &field_expected_parameters);
				/* histogramMinimum */
				int histogramMinimumLength = 0;
				if (histogramMinimum)
					histogramMinimumLength = original_number_of_components;
				Option_table_add_variable_length_double_vector_entry(option_table, "histogram_minimums",
					&histogramMinimumLength, &histogramMinimum);
				/* histogramMaximum */
				int histogramMaximumLength = 0;
				if (histogramMaximum)
					histogramMaximumLength = original_number_of_components;
				Option_table_add_variable_length_double_vector_entry(option_table, "histogram_maximums",
					&histogramMaximumLength, &histogramMaximum);
				/* numberOfBins */
				Option_table_add_int_vector_entry(option_table, "number_of_bins",
					numberOfBins, &source_field->number_of_components);
				/* marginalScale */
				Option_table_add_double_entry(option_table, "marginal_scale",
					&marginalScale);

				return_code = Option_table_multi_parse(option_table, state);
				DESTROY(Option_table)(&option_table);

				if (histogramMinimum && histogramMinimumLength != source_field->number_of_components)
				{
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_histogram_image_filter.  Length of histogram_minimums vector does not match source field compontents");
					return_code = 0;
				}
				if (histogramMaximum && histogramMaximumLength != source_field->number_of_components)
				{
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_histogram_image_filter.  Length of histogram_Maximums vector does not match source field compontents");
					return_code = 0;
				}

				if (return_code)
				{
					return_code = field_modify->update_field_and_deaccess(
						Cmiss_field_module_create_histogram_image_filter(
							field_modify->get_field_module(),
							source_field, numberOfBins, marginalScale, histogramMinimum, histogramMaximum));
				}

				if (!return_code)
				{
					/* error */
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_histogram_image_filter.  Failed");
				}
			}
			if (source_field)
			{
				DEACCESS(Computed_field)(&source_field);
			}
			if (numberOfBins)
			{
				DEALLOCATE(numberOfBins);
			}
		}