int define_Computed_field_type_canny_edge_detection_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_CANNYEDGEDETECTIONFILTER (if it is not
already) and allows its contents to be modified.
==============================================================================*/
{
	int return_code;
	double variance;
	double maximumError;
	double upperThreshold;
	double lowerThreshold;

	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_canny_edge_detection_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;
		variance = 0;
		maximumError = 0.01;
		upperThreshold = 0;
		lowerThreshold = 0;
		if ((NULL != field_modify->get_field()) &&
			(computed_field_canny_edge_detection_image_filter_type_string ==
				Computed_field_get_type_string(field_modify->get_field())))
		{
			return_code =
				cmzn_field_get_type_canny_edge_detection_image_filter(field_modify->get_field(), &source_field,
				  &variance, &maximumError, &upperThreshold, &lowerThreshold);
		}
		if (return_code)
		{
			/* must access objects for set functions */
			if (source_field)
			{
				ACCESS(Computed_field)(source_field);
			}

			/* Discover the source field */
			option_table = CREATE(Option_table)();
			Option_table_add_help(option_table,
				"The canny_edge_detection field uses the itk::CannyEdgeDetectionImageFilter code to detect edges in 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).  Increasing the <variance> smooths the input image more, which reduces sensitivity to image noise at the expense of losing some detail. Decreasing the <maximum_error> also reduces edges detected as the result of noise.  The <upper_threshold> sets the level which a point must be above to use it as the start of the edge. The edge will then grow from that point until the level drops below the <lower_threshold>. Increasing the <upper_threshold> will decrease the number of edges detected. Increasing the <lower_threshold> will reduce the length of edges.  See a/testing/image_processing_2D for an example of using this field.");

			/* 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);
			/* variance */
			Option_table_add_double_entry(option_table, "variance",
				&variance);
			/* maximumError */
			Option_table_add_double_entry(option_table, "maximum_error",
				&maximumError);
			/* upperThreshold */
			Option_table_add_double_entry(option_table, "upper_threshold",
				&upperThreshold);
			/* lowerThreshold */
			Option_table_add_double_entry(option_table, "lower_threshold",
				&lowerThreshold);
			return_code = Option_table_multi_parse(option_table, state);
			DESTROY(Option_table)(&option_table);

			if (return_code)
			{
				if (!source_field)
				{
					display_message(ERROR_MESSAGE,
						"define_Computed_field_type_canny_edge_detection_image_filter.  "
						"Missing source field");
					return_code = 0;
				}
			}
			if (return_code)
			{
				return_code = field_modify->update_field_and_deaccess(
					cmzn_fieldmodule_create_field_imagefilter_canny_edge_detection(
						field_modify->get_field_module(), source_field, variance,
						maximumError, upperThreshold, lowerThreshold));
			}

			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_canny_edge_detection_image_filter.  Failed");
				}
			}

			if (source_field)
			{
				DEACCESS(Computed_field)(&source_field);
			}
		}
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_canny_edge_detection_image_filter.  Invalid argument(s)");
		return_code = 0;
	}
	LEAVE;

	return (return_code);
} /* define_Computed_field_type_canny_edge_detection_image_filter */
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_binary_dilate_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_BINARYDILATEFILTER (if it is not
already) and allows its contents to be modified.
==============================================================================*/
{
	int radius;
	double dilate_value;
	int return_code;
	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_binary_dilate_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 = 1;
		dilate_value = 1;
		if ((NULL != field_modify->get_field()) &&
			(computed_field_binary_dilate_image_filter_type_string ==
				Computed_field_get_type_string(field_modify->get_field())))
		{
			return_code =
				Cmiss_field_get_type_binary_dilate_image_filter(field_modify->get_field(), &source_field,
					&radius, &dilate_value);
		}
		if (return_code)
		{
			/* must access objects for set functions */
			if (source_field)
			{
				ACCESS(Computed_field)(source_field);
			}

			option_table = CREATE(Option_table)();
			Option_table_add_help(option_table,
				"The binary_dilate_filter field uses the itk::BinaryDilateImageFilter code to produce an output field which is a dilation of a binary image (an image where each pixel has 1 of 2 values).  The region identified by the pixels with intensity <dilate_value> is dilate (enlarged), by replacing each pixel with a ball.  The size of the ball is set by specifying the <radius>. The <field> it operates on is usually a thresholded or segmented field. 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);
			/* radius */
			Option_table_add_int_non_negative_entry(option_table, "radius",
				&radius);
			/* dilate_value */
			Option_table_add_double_entry(option_table, "dilate_value",
				&dilate_value);

			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_binary_dilate_image_filter.  "
						"Missing source field");
					return_code = 0;
				}
			}
			if (return_code)
			{
				return_code = field_modify->update_field_and_deaccess(
					Cmiss_field_module_create_binary_dilate_image_filter(
						field_modify->get_field_module(),
						source_field, radius, dilate_value));
			}

			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_binary_dilate_image_filter.  Failed");
				}
			}
			if (source_field)
			{
				DEACCESS(Computed_field)(&source_field);
			}
		}
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_binary_dilate_image_filter.  Invalid argument(s)");
		return_code = 0;
	}
	LEAVE;

	return (return_code);
} /* define_Computed_field_type_binary_dilate_image_filter */
int define_Computed_field_type_sigmoid_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 COMPUTED_FIELD_SIGMOIDIMAGEFILTER (if it is not
already) and allows its contents to be modified.
==============================================================================*/
{
	int return_code;
		double min, max, alpha, beta;
	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_sigmoid_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;
		min = 0.0;
		max = 1.0;
		alpha = 0.25;
		beta = 0.5;
		if ((NULL != field_modify->get_field()) &&
			(computed_field_sigmoid_image_filter_type_string ==
				Computed_field_get_type_string(field_modify->get_field())))
		{
			return_code =
				cmzn_field_get_type_sigmoid_image_filter(field_modify->get_field(), &source_field,
					&min, &max, &alpha, &beta);
		}
		if (return_code)
		{
			/* must access objects for set functions */
			if (source_field)
			{
				ACCESS(Computed_field)(source_field);
			}

			option_table = CREATE(Option_table)();
			Option_table_add_help(option_table,
			  "The sigmoid_filter field uses the itk::SigmoidImageFilter code to nonlinearly scale the pixel intensity to vary between the specified minimum and maximum intensity values according to a sigmoid curve. It is useful for focusing attention on a particular set of values while providing a smooth transition at the borders of the range. The <field> it operates on is usually a sample_texture field, based on a texture that has been created from image file(s).  Intensity values are rescaled to vary from the <minimum> to the <maximum> value using a sigmoid curve which has a width and centre defined by <alpha> and <beta>.  Increasing the <alpha> parameter widens the curve while increasing the <beta> parameter moves the centre of the curve to the right. 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);
			/* minimum */
			Option_table_add_double_entry(option_table, "minimum",
				&min);
			/* maximum */
			Option_table_add_double_entry(option_table, "maximum",
				&max);
			/* alpha */
			Option_table_add_double_entry(option_table, "alpha",
				&alpha);
			/* beta */
			Option_table_add_double_entry(option_table, "beta",
				&beta);

			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_sigmoid_image_filter.  "
						"Missing source field");
					return_code = 0;
				}
			}
			if (return_code)
			{
				return_code = field_modify->update_field_and_deaccess(
					cmzn_fieldmodule_create_field_imagefilter_sigmoid(
						field_modify->get_field_module(),
						source_field, min, max, alpha, beta));
			}

			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_sigmoid_image_filter.  Failed");
				}
			}
			if (source_field)
			{
				DEACCESS(Computed_field)(&source_field);
			}
		}
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_sigmoid_image_filter.  Invalid argument(s)");
		return_code = 0;
	}
	LEAVE;

	return (return_code);
} /* define_Computed_field_type_sigmoid_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_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);
			}
		}
int define_Computed_field_type_gradient_magnitude_recursive_gaussian_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 GRADIENT_MAGNITUDE_RECURSIVE_GAUSSIAN (if it is not
already) and allows its contents to be modified.
==============================================================================*/
{
	int return_code;
	double sigma;
	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_gradient_magnitude_recursive_gaussian_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;
		sigma = 2.0;

		if ((NULL != field_modify->get_field()) &&
			(computed_field_gradient_magnitude_recursive_gaussian_image_filter_type_string ==
				Computed_field_get_type_string(field_modify->get_field())))
		{
			return_code =
				cmzn_field_get_type_gradient_magnitude_recursive_gaussian_image_filter(field_modify->get_field(), &source_field,
					&sigma);
		}
		if (return_code)
		{
			/* must access objects for set functions */
			if (source_field)
			{
				ACCESS(Computed_field)(source_field);
			}

			option_table = CREATE(Option_table)();
			Option_table_add_help(option_table,
				"The gradient_magnitude_recursive_filter field uses the itk::GradientMagnitudeRecursiveImageFilter code to compute the magnitude of the image gradient at each location in the field. It is useful for identifying regions where the pixel intensities change rapidly.  The <field> it operates on is usually a sample_texture field, based on a texture that has been created from image file(s).  The filter first smooths the image using a discrete gaussian image subfilter before calculating the gradient and magnitudes.  Increasing <sigma> increases the width of the gaussian distribution used during the smoothing and hence the number of pixels used to calculate the weighted average. This smooths the image more.  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);
			/* sigma */
			Option_table_add_double_entry(option_table, "sigma",&sigma);

			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_gradient_magnitude_recursive_gaussian_image_filter.  "
						"Missing source field");
					return_code = 0;
				}
			}
			if (return_code)
			{
				return_code = field_modify->update_field_and_deaccess(
					cmzn_fieldmodule_create_field_imagefilter_gradient_magnitude_recursive_gaussian(
						field_modify->get_field_module(),
						source_field, sigma));
			}

			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_gradient_magnitude_recursive_gaussian_image_filter.  Failed");
				}
			}
			if (source_field)
			{
				DEACCESS(Computed_field)(&source_field);
			}
		}
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_gradient_magnitude_recursive_gaussian_image_filter.  Invalid argument(s)");
		return_code = 0;
	}
	LEAVE;

	return (return_code);
} /* define_Computed_field_type_gradient_magnitude_recursive_gaussian_image_filter */
int define_Computed_field_type_curvature_anisotropic_diffusion_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 return_code;
		double timeStep;
	double conductance;
	int numIterations;
	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_curvature_anisotropic_diffusion_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;
		timeStep = 0.125;
		conductance=3.0;
		numIterations = 5;
		if ((NULL != field_modify->get_field()) &&
			(computed_field_curvature_anisotropic_diffusion_image_filter_type_string ==
				Computed_field_get_type_string(field_modify->get_field())))
		{
			return_code =
				Cmiss_field_get_type_curvature_anisotropic_diffusion_image_filter(field_modify->get_field(), &source_field,
					&timeStep, &conductance, &numIterations);
		}
		if (return_code)
		{
			/* must access objects for set functions */
			if (source_field)
			{
				ACCESS(Computed_field)(source_field);
			}

			option_table = CREATE(Option_table)();
			Option_table_add_help(option_table,
				"The curvature_anisotropic_filter field uses the itk::CurvatureAnisotropicImageFilter code to smooth a field to reduce noise (or unwanted detail) while preserving edges. The <field> it operates on is usually a sample_texture field, based on a texture that has been created from image file(s).  The smoothing is accomplished by numerically solving a modified curvature diffusion equation.  The accuracy of the numerical solution can be adjusted by varying the <time_step> and <num_iterations> used.  The <conductance> is a parameter used by the diffusion equation.  A high value of conductance causes the image to diffuse (smooth) more, while a low value puts more emphasis on preserving features.  Typical conductance values are often in the range 0.5 to 2. 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);
			/* timeStep */
			Option_table_add_double_entry(option_table, "time_step",
				&timeStep);
			/* conductance */
			Option_table_add_double_entry(option_table, "conductance",
				&conductance);
			/* numIterations */
			Option_table_add_int_non_negative_entry(option_table, "num_iterations",
																							(int*) &numIterations);

			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_curvature_anisotropic_diffusion_image_filter.  "
						"Missing source field");
					return_code = 0;
				}
			}
			if (return_code)
			{
				return_code = field_modify->update_field_and_deaccess(
					Cmiss_field_module_create_curvature_anisotropic_diffusion_image_filter(
						field_modify->get_field_module(),
						source_field, timeStep, conductance, numIterations));
			}

			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_curvature_anisotropic_diffusion_image_filter.  Failed");
				}
			}
			if (source_field)
			{
				DEACCESS(Computed_field)(&source_field);
			}
		}
	}
	else
	{
		display_message(ERROR_MESSAGE,
			"define_Computed_field_type_curvature_anisotropic_diffusion_image_filter.  Invalid argument(s)");
		return_code = 0;
	}
	LEAVE;

	return (return_code);
} /* define_Computed_field_type_curvature_anisotropic_diffusion_image_filter */
Exemplo n.º 9
0
int gfx_modify_rendition_graphic(struct Parse_state *state,
	enum Cmiss_graphic_type graphic_type, const char *help_text,
	struct Modify_rendition_data *modify_rendition_data,
	struct Rendition_command_data *rendition_command_data)
{
	if (!(state && rendition_command_data && modify_rendition_data))
	{
		display_message(ERROR_MESSAGE,
			"gfx_modify_rendition_graphic.  Invalid argument(s)");
		return 0;
	}
	Cmiss_graphic *graphic = 0;
	if (modify_rendition_data->modify_this_graphic)
	{
		graphic = Cmiss_graphic_access(modify_rendition_data->graphic);
		graphic_type = Cmiss_graphic_get_graphic_type(graphic);
	}
	else
	{
		graphic = get_graphic_for_gfx_modify(rendition_command_data->rendition,
			graphic_type, modify_rendition_data->graphic);
		if (modify_rendition_data->group && (!graphic->subgroup_field))
		{
			graphic->subgroup_field =
				Cmiss_field_access(Cmiss_field_group_base_cast(modify_rendition_data->group));
		}
	}
	if (!graphic)
	{
		display_message(ERROR_MESSAGE,
			"gfx_modify_rendition_graphic.  Could not create graphic");
		return 0;
	}
	REACCESS(Cmiss_graphic)(&(modify_rendition_data->graphic), graphic);

	int return_code = 1;
	Cmiss_graphics_coordinate_system coordinate_system = Cmiss_graphic_get_coordinate_system(graphic);
	char *font_name = (char *)NULL;
	Cmiss_field_id orientation_scale_field = 0;
	Cmiss_field_id variable_scale_field = 0;
	Cmiss_field_id xi_point_density_field = 0;
	GT_object *glyph = 0;
	Triple glyph_offset, glyph_scale_factors, glyph_size;
	enum Graphic_glyph_scaling_mode glyph_scaling_mode = GRAPHIC_GLYPH_SCALING_GENERAL;
	const char *glyph_scaling_mode_string = 0;
	if (Cmiss_graphic_type_uses_attribute(graphic_type, CMISS_GRAPHIC_ATTRIBUTE_GLYPH))
	{
		Cmiss_graphic_get_glyph_parameters(graphic,
			&glyph, &glyph_scaling_mode, glyph_offset, glyph_size,
			&orientation_scale_field, glyph_scale_factors,
			&variable_scale_field);
		if (glyph)
			ACCESS(GT_object)(glyph);
		if (orientation_scale_field)
		{
			ACCESS(Computed_field)(orientation_scale_field);
		}
		if (variable_scale_field)
		{
			ACCESS(Computed_field)(variable_scale_field);
		}
		glyph_scaling_mode_string = ENUMERATOR_STRING(Graphic_glyph_scaling_mode)(glyph_scaling_mode);
	}
	enum Use_element_type use_element_type;
	const char *use_element_type_string = 0;
	if (Cmiss_graphic_type_uses_attribute(graphic_type, CMISS_GRAPHIC_ATTRIBUTE_USE_ELEMENT_TYPE))
	{
		use_element_type = graphic->use_element_type;
		use_element_type_string = ENUMERATOR_STRING(Use_element_type)(use_element_type);
	}
	enum Xi_discretization_mode xi_discretization_mode;
	const char *xi_discretization_mode_string = 0;
	if (Cmiss_graphic_type_uses_attribute(graphic_type, CMISS_GRAPHIC_ATTRIBUTE_XI_DISCRETIZATION_MODE))
	{
		Cmiss_graphic_get_xi_discretization(graphic,
			&xi_discretization_mode, &xi_point_density_field);
		if (xi_point_density_field)
		{
			ACCESS(Computed_field)(xi_point_density_field);
		}
		xi_discretization_mode_string = ENUMERATOR_STRING(Xi_discretization_mode)(xi_discretization_mode);
	}
	int number_of_components = 3;
	int visibility = graphic->visibility_flag;
	int number_of_valid_strings;
	const char **valid_strings;
	enum Cmiss_graphics_render_type render_type = graphic->render_type;
	const char *render_type_string = ENUMERATOR_STRING(Cmiss_graphics_render_type)(render_type);
	/* The value stored in the graphic is an integer rather than a char */
	char reverse_track = (graphic->reverse_track) ? 1 : 0;
	char *seed_nodeset_name = 0;
	if (graphic->seed_nodeset)
	{
		seed_nodeset_name = Cmiss_nodeset_get_name(graphic->seed_nodeset);
	}

	Option_table *option_table = CREATE(Option_table)();
	if (help_text)
	{
		Option_table_add_help(option_table, help_text);
	}

	/* as */
	Option_table_add_entry(option_table,"as",&(graphic->name),
		(void *)1,set_name);

	/* cell_centres/cell_corners/cell_density/exact_xi */
	if (Cmiss_graphic_type_uses_attribute(graphic_type, CMISS_GRAPHIC_ATTRIBUTE_XI_DISCRETIZATION_MODE))
	{
		valid_strings = ENUMERATOR_GET_VALID_STRINGS(Xi_discretization_mode)(
			&number_of_valid_strings,
			(ENUMERATOR_CONDITIONAL_FUNCTION(Xi_discretization_mode) *)NULL,
			(void *)NULL);
		Option_table_add_enumerator(option_table,number_of_valid_strings,
			valid_strings,&xi_discretization_mode_string);
		DEALLOCATE(valid_strings);
	}

	/* centre */
	if (Cmiss_graphic_type_uses_attribute(graphic_type, CMISS_GRAPHIC_ATTRIBUTE_GLYPH))
	{
		Option_table_add_entry(option_table,"centre",glyph_offset,
			&(number_of_components),set_reversed_float_vector);
	}

	/* circle_discretization */
	if (graphic_type == CMISS_GRAPHIC_CYLINDERS)
	{
		Option_table_add_entry(option_table, "circle_discretization",
			(void *)&(graphic->circle_discretization), (void *)NULL,
			set_Circle_discretization);
	}

	/* constant_radius */
	if (graphic_type == CMISS_GRAPHIC_CYLINDERS)
	{
		Option_table_add_entry(option_table,"constant_radius",
			&(graphic->constant_radius),NULL,set_float);
	}

	/* coordinate */
	Set_Computed_field_conditional_data set_coordinate_field_data;
	set_coordinate_field_data.computed_field_manager = rendition_command_data->computed_field_manager;
	set_coordinate_field_data.conditional_function = Computed_field_has_up_to_3_numerical_components;
	set_coordinate_field_data.conditional_function_user_data = (void *)NULL;
	Option_table_add_Computed_field_conditional_entry(option_table, "coordinate",
		&(graphic->coordinate_field), &set_coordinate_field_data);

	/* coordinate system */
	const char *coordinate_system_string =
		ENUMERATOR_STRING(Cmiss_graphics_coordinate_system)(coordinate_system);
	valid_strings = ENUMERATOR_GET_VALID_STRINGS(Cmiss_graphics_coordinate_system)(
		&number_of_valid_strings,
		(ENUMERATOR_CONDITIONAL_FUNCTION(Cmiss_graphics_coordinate_system) *)NULL,
		(void *)NULL);
	Option_table_add_enumerator(option_table, number_of_valid_strings,
		valid_strings, &coordinate_system_string);
	DEALLOCATE(valid_strings);

	/* data */
	Set_Computed_field_conditional_data set_data_field_data;
	set_data_field_data.computed_field_manager = rendition_command_data->computed_field_manager;
	set_data_field_data.conditional_function = Computed_field_has_numerical_components;
	set_data_field_data.conditional_function_user_data = (void *)NULL;
	Option_table_add_Computed_field_conditional_entry(option_table, "data",
		&(graphic->data_field), &set_data_field_data);

	/* decimation_threshold */
	if (graphic_type == CMISS_GRAPHIC_ISO_SURFACES)
	{
		Option_table_add_double_entry(option_table, "decimation_threshold",
			&(graphic->decimation_threshold));
	}

	/* delete */
	Option_table_add_entry(option_table,"delete",
		&(modify_rendition_data->delete_flag),NULL,set_char_flag);

	/* density */
	Set_Computed_field_conditional_data set_xi_point_density_field_data;
	set_xi_point_density_field_data.computed_field_manager = rendition_command_data->computed_field_manager;
	set_xi_point_density_field_data.conditional_function = Computed_field_is_scalar;
	set_xi_point_density_field_data.conditional_function_user_data = (void *)NULL;
	if (Cmiss_graphic_type_uses_attribute(graphic_type, CMISS_GRAPHIC_ATTRIBUTE_XI_DISCRETIZATION_MODE))
	{
		Option_table_add_Computed_field_conditional_entry(option_table, "density",
			&xi_point_density_field, &set_xi_point_density_field_data);
	}

	/* discretization */
	if (Cmiss_graphic_type_uses_attribute(graphic_type, CMISS_GRAPHIC_ATTRIBUTE_DISCRETIZATION))
	{
		Option_table_add_entry(option_table,"discretization",
			&(graphic->discretization),NULL, set_Element_discretization);
	}

	/* ellipse/line/rectangle/ribbon */
	Streamline_type streamline_type = STREAM_LINE;
	const char *streamline_type_string = ENUMERATOR_STRING(Streamline_type)(streamline_type);
	if (graphic_type == CMISS_GRAPHIC_STREAMLINES)
	{
		valid_strings = ENUMERATOR_GET_VALID_STRINGS(Streamline_type)(
			&number_of_valid_strings,
			(ENUMERATOR_CONDITIONAL_FUNCTION(Streamline_type) *)NULL,
			(void *)NULL);
		Option_table_add_enumerator(option_table,number_of_valid_strings,
			valid_strings,&streamline_type_string);
		DEALLOCATE(valid_strings);
	}