Astro-Constants

 view release on metacpan or  search on metacpan

script/xml_to_pm.pl  view on Meta::CPAN

GetOptions ("data=s" => \$datafile,
            "name=s" => \$module,
            "verbose"  => \$verbose)
or die("Error in command line arguments\n");

die 'Option "output" not working yet' unless $module eq 'Constants.pm'; # use File::Basename

my $xml = XML::LibXML->load_xml(location => $datafile);

my $lib = 'lib';	# where is the lib directory
mkdir "$lib/Astro/Constants" unless -d "$lib/Astro/Constants";
open my $ac_fh, '>:utf8', "$lib/Astro/Constants.pm";

write_module_header($ac_fh, 'Astro::Constants');

write_pod_synopsis($ac_fh);

for my $constant ( $xml->getElementsByTagName('PhysicalConstant') ) {
	my ($options, ) = undef;

	my $name        = $constant->getChildrenByTagName('name')->shift()->textContent();
	my $value       = $constant->getChildrenByTagName('value')->shift()->textContent();
	my $description = $constant->getChildrenByTagName('description')->shift()->textContent();

	# recognise that there can be more than one alternateName
	my $alternate = undef;
	my @alternates = ();
	if ( $constant->getChildrenByTagName('alternateName') ) {
		for my $node ( $constant->getChildrenByTagName('alternateName') ) {
			$alternate = $node->textContent();
			next unless $alternate =~ /\S/;

			push @{$tagname->{alternates}}, $alternate;
			if ($node->hasAttribute('type') && $node->getAttribute('type') eq 'deprecated') {
				push @{$tagname->{deprecated}}, $alternate;
			}
			else {
				push @{$tagname->{all}}, $alternate;
			}
			push @alternates, $alternate;

			write_constant($ac_fh, $value, $alternate) if $value;
		}
	}
	$options->{deprecated} = 1 if $constant->getChildrenByTagName('deprecated');

	#### write to the module files
	write_method_pod($name, $description, $value, \@alternates);
	write_constant($ac_fh, $value, $name, $options) if $value;

	push @{$tagname->{all}}, $name if $name;
		

	for my $cat_node ( $constant->getElementsByTagName('category') ) {
		my $category =	$cat_node->textContent();
		next unless $category;
		push @{$tagname->{$category}}, $name;
		push @{$tagname->{$category}}, $alternate if $alternate;
	}

	my $precision = $constant->getChildrenByTagName('uncertainty')->shift();
	store_precision($name,
		$precision->textContent(), 
		$precision->getAttribute('type'));
}

write_pod_footer($ac_fh);
write_module_footer($ac_fh, $tagname);

exit;

####

sub write_module_header {
	my ($fh, $name) = @_;

	print $fh <<HEADER;
package $name;
# ABSTRACT: Perl library to provide physical constants for use in Physics and Astronomy based on values from 2018 CODATA.
#
#  They are not constant but are changing still. - Cymbeline, Act II, Scene 5

use 5.006;
use strict;
use warnings;

use base qw(Exporter);

HEADER
}

sub write_module_footer {
	my ($fh, $tags) = @_;

	write_precision($fh);

	print $fh <<FOOT;

# some helper functions
sub pretty {
	if (\@_ > 1) {
		return map { sprintf("\%1.3e", \$_) } \@_;
	}
	return sprintf("\%1.3e", shift);
}

sub precision {
	my (\$name, \$type) = \@_;
	warn "precision() requires a string, not the constant value" 
		unless exists \$_precision{\$name};

	return \$_precision{\$name}->{value};
}

our \@EXPORT_OK = qw(
	@{$tags->{all}}
	@{$tags->{alternates}}
	pretty precision
);

our \%EXPORT_TAGS = (

script/xml_to_pm.pl  view on Meta::CPAN


You are tired of typing in all those numbers and having to make sure that they are
all correct.  How many significant figures is enough or too much?  Where's the
definitive source, Wikipedia?  And which mass does "$m1" refer to, solar or lunar?

The constant values in this module are protected against accidental re-assignment
in your code.  The test suite protects them against accidental finger trouble in my code. 
Other people are using this module, so more eyeballs are looking for errors
and we all benefit.  The constant names are a little longer than you might like,
but you gain in the long run from readable, sharable code that is clear in meaning.
Your programming errors are a little easier to find when you can see that the units 
don't match.  Isn't it reassuring that you can verify how a number is produced
and which meeting of which standards body is responsible for its value?

Trusting someone else's code does carry some risk, which you I<should> consider, 
but have you also considered the risk of doing it yourself with no one else 
to check your work?  And, are you going to check for the latest values from NIST
every 4 years?

=head3 And plus, it's B<FASTER>

Benchmarking has shown that the imported constants can be more than 3 times
faster than using variables or other constant modules because of the way
the compiler optimizes your code.  So, if you've got a lot of calculating to do,
this is the module to do it with.

=head1 EXPORT

Nothing is exported by default, so the module doesn't clobber any of your variables.  
Select from the following tags:

=for :list
* C<:all>             (everything except :deprecated)
* C<:fundamental>
* C<:conversion>
* C<:mathematics>
* C<:cosmology>
* C<:planetary>
* C<:electromagnetic>
* C<:nuclear>
* C<:alternates>
* C<:deprecated>
=cut

POD
}

sub write_pod_footer {
	my ($fh, ) = @_;

    say $fh @pod; # delayed writing pod until after the code.
	say $fh <<'POD';
=head1 FUNCTIONS

=head2 pretty

This is a helper function that rounds a value or list of values to 5 significant figures.

=head2 precision

Give this method the string of the constant and it returns the precision or uncertainty
listed.

  \$rel_precision = precision('GRAVITATIONAL');
  \$abs_precision = precision('MASS_EARTH');

At the moment you need to know whether the uncertainty is relative or absolute.
Looking to fix this in future versions.

=head2 Deprecated functions

I've gotten rid of C<list_constants> and C<describe_constants> because they are now in
the documentation.  Use C<perldoc Astro::Constants> for that information.

=head1 SEE ALSO

=for :list
* L<Astro::Cosmology>
* L<Perl Data Language|PDL>
* L<NIST|http://physics.nist.gov>
* L<Astronomical Almanac|http://asa.usno.navy.mil>
* L<IAU 2015 Resolution B3|http://iopscience.iop.org/article/10.3847/0004-6256/152/2/41/meta>
* L<Neil Bower's review on providing read-only values|http://neilb.org/reviews/constants.html>
* L<Test::Number::Delta>
* L<Test::Deep::NumberTolerant> for testing values within objects

Reference Documents:

=for :list
* L<IAU 2009 system of astronomical constants|http://aa.usno.navy.mil/publications/reports/Luzumetal2011.pdf>
* L<Astronomical Constants 2016|http://asa.usno.navy.mil/static/files/2016/Astronomical_Constants_2016.pdf>
* L<IAU recommendations concerning units|https://www.iau.org/publications/proceedings_rules/units>
* L<Re-definition of the Astronomical Unit|http://syrte.obspm.fr/IAU_resolutions/Res_IAU2012_B2.pdf>

=head1 REPOSITORY

* L<github|https://github.com/duffee/Astro-Constants>

=head1 ISSUES

Feel free to file bugs or suggestions in the
L<Issues|https://github.com/duffee/Astro-Constants/issues> section of the Github repository.

Using C<strict> is a must with this code.  Any constants you forgot to import will
evaluate to 0 and silently introduce errors in your code.  Caveat Programmer.

If you are using this module, drop me a line using any available means at your 
disposal, including
*gasp* email (address in the Author section), to let me know how you're using it. 
What new features would you like to see?

Current best method to contact me is via a Github Issue.

=head2 Extending the data set

If you want to add in your own constants or override the factory defaults,
run make, edit the F<PhysicalConstants.xml> file and then run C<dzil build> again.
If you have a pre-existing F<PhysicalConstants.xml> file, drop it in place
before running C<dzil build>.

=head2 Availability

the original astroconst sites have disappeared

=head1 ROADMAP

I have moved to a I<noun_adjective> format for long names.



( run in 1.009 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )