File: fluxdensity.h

package info (click to toggle)
wsclean 2.8-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 2,196 kB
  • sloc: cpp: 34,504; ansic: 234; python: 174; makefile: 10
file content (125 lines) | stat: -rw-r--r-- 3,180 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#ifndef FLUX_DENSITY_H
#define FLUX_DENSITY_H

#include <string>
#include <sstream>
#include <stdexcept>
#include <cmath>

#include <boost/algorithm/string/case_conv.hpp>

class FluxDensity
{
public:
	enum Unit { Jansky, MilliJansky, MicroJansky, NanoJansky, KiloJansky };
	/**
	 * Parse the string to a flux density, possibly with unit specification, and return in Jansky.
	 * @return The flux density
	 */
	static double Parse(const std::string& s, const std::string& valueDescription, Unit defaultUnit = Jansky);
	
	static std::string ToNiceString(double angleRad);
	
private:
	static size_t findNumberEnd(const std::string& s);
	static bool isDigit(const char c) { return c>='0' && c<='9'; }
	static bool isWhitespace(const char c) { return c==' ' || c=='\t'; }
};

inline std::string FluxDensity::ToNiceString(double valueJansky)
{
	std::ostringstream str;
	if(valueJansky == 0.0)
		return "0 Jy";
	else {
		if(valueJansky < 0.0)
		{
			str << "-";
			valueJansky = -valueJansky;
		}
		if(valueJansky >= 1000.0)
			str << round(valueJansky*0.1)/100.0 << " KJy";
		else if(valueJansky >= 1.0)
			str << round(valueJansky*1e2)/100.0 << " Jy";
		else if(valueJansky >= 1e-3)
			str << round(valueJansky*1e5)/100.0 << " mJy";
		else if(valueJansky >= 1e-6)
			str << round(valueJansky*1e8)/100.0 << " µJy";
		else if(valueJansky >= 1e-9)
			str << round (valueJansky*1e11)/100.0 << " nJy";
		else
			str << valueJansky << " Jy";
		return str.str();
	}
}

inline double FluxDensity::Parse(const std::string& s, const std::string& valueDescription, Unit defaultUnit)
{
  size_t end = findNumberEnd(s);
	if(end == 0)
		throw std::runtime_error("Error parsing " + valueDescription);
	std::string number = s.substr(0, end);
	double val = atof(number.c_str());
	// Skip whitespace after number
	const char *c = s.c_str();
	while(isWhitespace(c[end]))
		++end;
	std::string unitStr = std::string(&c[end]);
	std::string lUnitStr = boost::to_lower_copy(unitStr);

	// Unit string empty? Than use default unit.
	if(unitStr.empty())
	{
		switch(defaultUnit)
		{
			case KiloJansky:
				return val * 1000.0;
			case Jansky:
				return val;
			case MilliJansky:
				return val / 1e3;
			case MicroJansky:
				return val / 1e6;
			case NanoJansky:
				return val / 1e9;
		}
	}
	else if(lUnitStr=="jy" || lUnitStr=="jansky")
		return val;
	else if(unitStr=="mjy" || unitStr=="mJy" || lUnitStr == "millijansky")
		return val*1e-3;
	else if(unitStr=="KJy" || unitStr=="kjy" || lUnitStr=="kilojansky")
		return val*1e3;
	else if(unitStr=="µJy" || unitStr=="µjy" || lUnitStr=="microjansky")
		return val*1e-6;
	else if(unitStr=="njy" || unitStr=="nJy" || lUnitStr=="nanojansky")
		return val*1e-9;
	
	throw std::runtime_error("Invalid unit specification in flux density given for " + valueDescription);
}

inline size_t FluxDensity::findNumberEnd(const std::string& s)
{
	const char* c = s.c_str();
	size_t pos = 0;
	while(isWhitespace(c[pos]))
		++pos;
	while(isDigit(c[pos]))
		++pos;
	if(c[pos]=='.')
		++pos;
	while(isDigit(c[pos]))
		++pos;
	if(c[pos]=='e' || c[pos]=='E')
	{
		++pos;
		if(c[pos]=='-' || c[pos]=='+')
			++pos;
		while(isDigit(c[pos]))
			++pos;
	}
	return pos;
}

#endif