Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reconsider string representation of floating points for parameter files and parameter maps #383

Closed
N-Dekker opened this issue Jan 2, 2021 · 5 comments
Assignees

Comments

@N-Dekker
Copy link
Member

N-Dekker commented Jan 2, 2021

It seems more convenient to represent floating point (double) parameter values the same way for parameter files and parameter maps. Elastix currently uses scientific format, and default precision for parameter maps, and fixed (showpoint) format with a precision of 10 for parameter files. Both formats are lossy. C++11 allows specifying a lossless precision by max_digits10.

The following tables could be helpful. Related to issue #217 the "Origin" precision in TransformParameters is not high enough by @GouZi2019

Format Precision Length String representation of 0
scientific 6 (default) 1 0
scientific 10 (elastix-txt-file) 1 0
scientific 15 (digits10) 1 0
scientific 17 (max_digits10) 1 0
fixed (showpoint) 6 (default) 8 0.000000
fixed (showpoint) 10 (elastix-txt-file) 12 0.0000000000
fixed (showpoint) 15 (digits10) 17 0.000000000000000
fixed (showpoint) 17 (max_digits10) 19 0.00000000000000000
Format Precision Length String representation of 1
scientific 6 (default) 1 1
scientific 10 (elastix-txt-file) 1 1
scientific 15 (digits10) 1 1
scientific 17 (max_digits10) 1 1
fixed (showpoint) 6 (default) 8 1.000000
fixed (showpoint) 10 (elastix-txt-file) 12 1.0000000000
fixed (showpoint) 15 (digits10) 17 1.000000000000000
fixed (showpoint) 17 (max_digits10) 19 1.00000000000000000
Format Precision Length String representation of 0.1
scientific 6 (default) 3 0.1
scientific 10 (elastix-txt-file) 3 0.1
scientific 15 (digits10) 3 0.1
scientific 17 (max_digits10) 19 0.10000000000000001
fixed (showpoint) 6 (default) 8 0.100000
fixed (showpoint) 10 (elastix-txt-file) 12 0.1000000000
fixed (showpoint) 15 (digits10) 17 0.100000000000000
fixed (showpoint) 17 (max_digits10) 19 0.10000000000000001
Format Precision Length String representation of 1.0 / 3.0
scientific 6 (default) 8 0.333333
scientific 10 (elastix-txt-file) 12 0.3333333333
scientific 15 (digits10) 17 0.333333333333333
scientific 17 (max_digits10) 19 0.33333333333333331
fixed (showpoint) 6 (default) 8 0.333333
fixed (showpoint) 10 (elastix-txt-file) 12 0.3333333333
fixed (showpoint) 15 (digits10) 17 0.333333333333333
fixed (showpoint) 17 (max_digits10) 19 0.33333333333333331
Format Precision Length String representation of 1e-10
scientific 6 (default) 5 1e-10
scientific 10 (elastix-txt-file) 5 1e-10
scientific 15 (digits10) 5 1e-10
scientific 17 (max_digits10) 5 1e-10
fixed (showpoint) 6 (default) 8 0.000000
fixed (showpoint) 10 (elastix-txt-file) 12 0.0000000001
fixed (showpoint) 15 (digits10) 17 0.000000000100000
fixed (showpoint) 17 (max_digits10) 19 0.00000000010000000
Format Precision Length String representation of 1e+10
scientific 6 (default) 5 1e+10
scientific 10 (elastix-txt-file) 5 1e+10
scientific 15 (digits10) 11 10000000000
scientific 17 (max_digits10) 11 10000000000
fixed (showpoint) 6 (default) 18 10000000000.000000
fixed (showpoint) 10 (elastix-txt-file) 22 10000000000.0000000000
fixed (showpoint) 15 (digits10) 27 10000000000.000000000000000
fixed (showpoint) 17 (max_digits10) 29 10000000000.00000000000000000
Format Precision Length String representation of 1e+10 - 1
scientific 6 (default) 5 1e+10
scientific 10 (elastix-txt-file) 10 9999999999
scientific 15 (digits10) 10 9999999999
scientific 17 (max_digits10) 10 9999999999
fixed (showpoint) 6 (default) 17 9999999999.000000
fixed (showpoint) 10 (elastix-txt-file) 21 9999999999.0000000000
fixed (showpoint) 15 (digits10) 26 9999999999.000000000000000
fixed (showpoint) 17 (max_digits10) 28 9999999999.00000000000000000
Format Precision Length String representation of M_PI
scientific 6 (default) 7 3.14159
scientific 10 (elastix-txt-file) 11 3.141592654
scientific 15 (digits10) 16 3.14159265358979
scientific 17 (max_digits10) 18 3.1415926535897931
fixed (showpoint) 6 (default) 8 3.141593
fixed (showpoint) 10 (elastix-txt-file) 12 3.1415926536
fixed (showpoint) 15 (digits10) 17 3.141592653589793
fixed (showpoint) 17 (max_digits10) 19 3.14159265358979312
Format Precision Length String representation of DBL_MIN
scientific 6 (default) 12 2.22507e-308
scientific 10 (elastix-txt-file) 16 2.225073859e-308
scientific 15 (digits10) 20 2.2250738585072e-308
scientific 17 (max_digits10) 23 2.2250738585072014e-308
fixed (showpoint) 6 (default) 8 0.000000
fixed (showpoint) 10 (elastix-txt-file) 12 0.0000000000
fixed (showpoint) 15 (digits10) 17 0.000000000000000
fixed (showpoint) 17 (max_digits10) 19 0.00000000000000000
Format Precision Length String representation of DBL_EPSILON
scientific 6 (default) 11 2.22045e-16
scientific 10 (elastix-txt-file) 15 2.220446049e-16
scientific 15 (digits10) 20 2.22044604925031e-16
scientific 17 (max_digits10) 22 2.2204460492503131e-16
fixed (showpoint) 6 (default) 8 0.000000
fixed (showpoint) 10 (elastix-txt-file) 12 0.0000000000
fixed (showpoint) 15 (digits10) 17 0.000000000000000
fixed (showpoint) 17 (max_digits10) 19 0.00000000000000022
Format Precision Length String representation of DBL_MAX
scientific 6 (default) 12 1.79769e+308
scientific 10 (elastix-txt-file) 16 1.797693135e+308
scientific 15 (digits10) 21 1.79769313486232e+308
scientific 17 (max_digits10) 23 1.7976931348623157e+308
fixed (showpoint) 6 (default) 316 1797693134...4124858368.000000
fixed (showpoint) 10 (elastix-txt-file) 320 1797693134...4124858368.0000000000
fixed (showpoint) 15 (digits10) 325 1797693134...4124858368.000000000000000
fixed (showpoint) 17 (max_digits10) 327 1797693134...4124858368.00000000000000000
@N-Dekker
Copy link
Member Author

N-Dekker commented Jan 2, 2021

Code that produced the tables: https://rextester.com/JHSNQ26951

// Niels Dekker, LKEB, Leiden University Medical Center, 2021

#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <limits>
#include <string>

const std::string separator = " | ";

std::string GetPrecisionAsString(const long long i)
{
	return std::to_string(i) + " (" +
		((i == std::ostringstream{}.precision()) ? "default" :
			(i == 10) ? "elastix-txt-file" :
			(i == std::numeric_limits<double>::digits10) ? "digits10" :
			(i == std::numeric_limits<double>::max_digits10) ? "max_digits10" :
			" ") + ")";
};


template <bool FixedFormat>
void Print(const double& x)
{
	std::ostringstream outputStringStreams[4];

	outputStringStreams[1] << std::setprecision(10);
	outputStringStreams[2] << std::setprecision(std::numeric_limits<double>::digits10);
	outputStringStreams[3] << std::setprecision(std::numeric_limits<double>::max_digits10);

	for (auto& outputStringStream : outputStringStreams)
	{
		if (FixedFormat)
		{
			outputStringStream << std::showpoint << std::fixed;
		}
		outputStringStream << x;
		const auto str = outputStringStream.str();
		std::cout << (FixedFormat ? "fixed (showpoint)" : "scientific")
			<< separator << GetPrecisionAsString(outputStringStream.precision())
			<< separator << str.length()
			<< separator << str << '\n';
	}
}

void Print(const double& x, const std::string& str)
{
	const auto dashes = " --- ";
	std::cout
		<< ("Format" + separator + "Precision" + separator + "Length" + separator + "String representation of " + str + '\n')
		<< (dashes + separator + dashes + separator + dashes + separator + dashes + '\n');
	Print<false>(x);
	Print<true>(x);
	std::cout << '\n';
}

#define PRINT_MACRO(x) Print(x, #x);

int main()
{
	PRINT_MACRO(0);
	PRINT_MACRO(1);
	PRINT_MACRO(0.1);
	PRINT_MACRO(1.0 / 3.0);
	PRINT_MACRO(1e-10);
	PRINT_MACRO(1e+10);
	PRINT_MACRO(1e+10 - 1);
	PRINT_MACRO(M_PI);
	PRINT_MACRO(DBL_MIN);
	PRINT_MACRO(DBL_EPSILON);
	PRINT_MACRO(DBL_MAX);
}

@N-Dekker
Copy link
Member Author

N-Dekker commented Jan 3, 2021

For the record, ITK's itk::TransformFileWriter uses Google's double-conversion library to write transform parameters to file, like:

Parameters: 0 1 0.1 0.3333333333333333 1e-10 10000000000

and for 1e+10 - 1, M_PI, DBL_MIN, DBL_EPSILON, DBL_MAX:

Parameters: 9999999999 3.141592653589793 2.2250738585072014e-308 2.220446049250313e-16 1.7976931348623157e+308

@N-Dekker
Copy link
Member Author

N-Dekker commented Jan 3, 2021

If both the elastix parameter file and the parameterMap would use the very same floating point format and precision, elastix Transform::WriteToFile member functions could simply write the values from the parameterMap directly to file. I think that would be preferable to the current situation (with parameterMap being "out of sync" with the parameter file).

@N-Dekker
Copy link
Member Author

N-Dekker commented Jan 4, 2021

For the record, at the internal weekly elastix sprint this afternoon, Marius (@mstaring) and I agreed that it is worth adjusting the behavior of both Transform::WriteToFileand CreateTransformParametersMap to produce floating point values in the same format as ITK's itk::TransformFileWriter. So it is not necessary anymore to always write those numbers with 10 "fixed" decimals.

We agreed that it would be OK for Transform::WriteToFile to just call CreateTransformParametersMap, and then write the content of the map to file (in alphabetic order of the keys). It should be noted that string values that do not represent numeric values should get double-quotes, when written to file.

N-Dekker added a commit that referenced this issue Jan 6, 2021
Synchronized the string representation of double floating point values of transform parameter maps (produced by elastix `CreateTransformParametersMap`) with ITK's tfm file format (as written by `itk::TransformFileWriter`).

Increased the floating point precision from 6 to 16.

Part of issue #383 "Reconsider string representation of floating points for parameter files and parameter maps"
N-Dekker added a commit that referenced this issue Jan 6, 2021
Synchronized the string representation of double floating point values of transform parameter maps (produced by elastix `CreateTransformParametersMap`) with ITK's .tfm file format (as written by `itk::TransformFileWriter`).

Increased the floating point precision from 6 to 16. ITK's `itk::NumberToString` uses a lossless floating point conversion from the Google double-conversion library, https://github.com/google/double-conversion

Part of issue #383 "Reconsider string representation of floating points for parameter files and parameter maps"
N-Dekker added a commit that referenced this issue Jan 8, 2021
Adjusted `TransformBase::WriteToFile` by using the parameter map created by `CreateTransformParametersMap`. Ensured that the transform parameter txt file is kept in sync with the corresponding the parameter map.

Thereby also adjusted the floating point format for values written to file, as discussed at issue #383, "Reconsider string representation of floating points for parameter files and parameter maps", #383

Addresses issue #217 'the "Origin" precision in TransformParameters is not high enough', reported by GouZi2019, January 5, 2020: #217
N-Dekker added a commit that referenced this issue Jan 8, 2021
Adjusted `TransformBase::WriteToFile` by using the parameter map created by `CreateTransformParametersMap`. Ensured that the transform parameter txt file is kept in sync with the corresponding the parameter map.

Thereby also adjusted the floating point format for values written to file, as discussed at issue #383, "Reconsider string representation of floating points for parameter files and parameter maps", #383

Addresses issue #217 'the "Origin" precision in TransformParameters is not high enough', reported by GouZi2019, January 5, 2020: #217
N-Dekker added a commit that referenced this issue Jan 10, 2021
Synchronized the string representation of double floating point values of transform parameter maps (produced by elastix `CreateTransformParametersMap`) with ITK's .tfm file format (as written by `itk::TransformFileWriter`).

Increased the floating point precision from 6 to 16. ITK's `itk::NumberToString` uses a lossless floating point conversion from the Google double-conversion library, https://github.com/google/double-conversion

Part of issue #383 "Reconsider string representation of floating points for parameter files and parameter maps"
N-Dekker added a commit that referenced this issue Jan 10, 2021
Adjusted `TransformBase::WriteToFile` by using the parameter map created by `CreateTransformParametersMap`. Ensured that the transform parameter txt file is kept in sync with the corresponding the parameter map.

Thereby also adjusted the floating point format for values written to file, as discussed at issue #383, "Reconsider string representation of floating points for parameter files and parameter maps", #383

Addresses issue #217 'the "Origin" precision in TransformParameters is not high enough', reported by GouZi2019, January 5, 2020: #217
N-Dekker added a commit that referenced this issue Jan 13, 2021
Synchronized the string representation of double floating point values of transform parameter maps (produced by elastix `CreateTransformParametersMap`) with ITK's .tfm file format (as written by `itk::TransformFileWriter`).

Increased the floating point precision from 6 to 16. ITK's `itk::NumberToString` uses a lossless floating point conversion from the Google double-conversion library, https://github.com/google/double-conversion

Part of issue #383 "Reconsider string representation of floating points for parameter files and parameter maps"
N-Dekker added a commit that referenced this issue Jan 13, 2021
Adjusted `TransformBase::WriteToFile` by using the parameter map created by `CreateTransformParametersMap`. Ensured that the transform parameter txt file is kept in sync with the corresponding the parameter map.

Thereby also adjusted the floating point format for values written to file, as discussed at issue #383, "Reconsider string representation of floating points for parameter files and parameter maps", #383

Addresses issue #217 'the "Origin" precision in TransformParameters is not high enough', reported by GouZi2019, January 5, 2020: #217
N-Dekker added a commit that referenced this issue Jan 14, 2021
Adjusted `TransformBase::WriteToFile` by using the parameter map created by `CreateTransformParametersMap`. Removed 14 out of 16 `WriteToFile` overrides. Ensured that the transform parameter txt file is kept in sync with the corresponding the parameter map.

Thereby also adjusted the floating point format for values written to file, as discussed at issue #383, "Reconsider string representation of floating points for parameter files and parameter maps", #383

Addresses issue #217 'the "Origin" precision in TransformParameters is not high enough', reported by GouZi2019, January 5, 2020: #217
N-Dekker added a commit that referenced this issue Jan 14, 2021
Synchronized the string representation of double floating point values of transform parameter maps (produced by elastix `CreateTransformParametersMap`) with ITK's .tfm file format (as written by `itk::TransformFileWriter`).

Increased the floating point precision from 6 to 16. ITK's `itk::NumberToString` uses a lossless floating point conversion from the Google double-conversion library, https://github.com/google/double-conversion

Part of issue #383 "Reconsider string representation of floating points for parameter files and parameter maps"
N-Dekker added a commit that referenced this issue Jan 14, 2021
Adjusted `TransformBase::WriteToFile` by using the parameter map created by `CreateTransformParametersMap`. Removed 14 out of 16 `WriteToFile` overrides. Ensured that the transform parameter txt file is kept in sync with the corresponding the parameter map.

Thereby also adjusted the floating point format for values written to file, as discussed at issue #383, "Reconsider string representation of floating points for parameter files and parameter maps", #383

Addresses issue #217 'the "Origin" precision in TransformParameters is not high enough', reported by GouZi2019, January 5, 2020: #217
N-Dekker added a commit that referenced this issue Jan 14, 2021
Synchronized the string representation of double floating point values of transform parameter maps (produced by elastix `CreateTransformParametersMap`) with ITK's .tfm file format (as written by `itk::TransformFileWriter`).

Increased the floating point precision from 6 to 16. ITK's `itk::NumberToString` uses a lossless floating point conversion from the Google double-conversion library, https://github.com/google/double-conversion

Part of issue #383 "Reconsider string representation of floating points for parameter files and parameter maps"
N-Dekker added a commit that referenced this issue Jan 14, 2021
Adjusted `TransformBase::WriteToFile` by using the parameter map created by `CreateTransformParametersMap`. Removed 14 out of 16 `WriteToFile` overrides. Ensured that the transform parameter txt file is kept in sync with the corresponding the parameter map.

Thereby also adjusted the floating point format for values written to file, as discussed at issue #383, "Reconsider string representation of floating points for parameter files and parameter maps", #383

Addresses issue #217 'the "Origin" precision in TransformParameters is not high enough', reported by GouZi2019, January 5, 2020: #217
@N-Dekker
Copy link
Member Author

Addressed by pull request #385 "Sync Transform WriteToFile with CreateTransformParametersMap" commit e1f5dae and af382ee.

See also ITK pull request InsightSoftwareConsortium/ITK#2256 "ENH: Support calling a const NumberToString, add unit tests + style improvements"

N-Dekker added a commit that referenced this issue Feb 13, 2023
This elastix parameter was mainly intended to allow the user to specify the precision of floating point parameters in the transform parameter file. However, with pull request #385 commit af382ee "ENH: Sync Transform WriteToFile with CreateTransformParametersMap" (related to issue #383 "Reconsider string representation of floating points for parameter files and parameter maps"), this is no longer relevant. Floating point values are now written to transform parameter files in a lossless way.
N-Dekker added a commit that referenced this issue Feb 14, 2023
This elastix parameter was mainly intended to allow the user to specify the precision of floating point parameters in the transform parameter file. However, with pull request #385 commit af382ee "ENH: Sync Transform WriteToFile with CreateTransformParametersMap" (related to issue #383 "Reconsider string representation of floating points for parameter files and parameter maps"), this is no longer relevant. Floating point values are now written to transform parameter files in a lossless way.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants