BeginPackage["Fits`"] FitsRead::usage = "FitsRead[file] reads a 2D FITS image from a file and stores it as a real array." FitsHeader::usage = "FitsHeader[file] reads the header from a FITS file." FitsHeaderToRules::usage = "FitsHeaderToRules[header] converts the FITS header returned by FitsHeader[] to a list of rules." fits::mlink = "There has been a low-level MathLink error. The message is: `1`." fits::cfitsio = "There has been a low-level CFITSIO error. The message is: `1`." fits::nofile = "File not found." Begin["`Private`"] Install["C:\\Mathematica FITS Reader\\fitsread.exe"]; (*------------ FitsHeaderToRules[] This parses a long FITS header string into a set of rules. Things are slightly complicated because the FITS standard allows keywords with forms like "FOO-BAR" and "FOO_BAR" which are not valid Mathematica symbols. We convert these by simply dropping the offending characters (eg. "FOO-BAR" becomes "FOOBAR"). Another complication is that the FITS standard allows numbers to be encoded in Fortran-based scientific notation, ie. numbers like: 1.1E+05, 1.1e+05, 1.1e5. We need to convert these to valid Mathematica numbers. ----------------------------------------------------------------------- *) FitsHeaderToRules[h_] := Module[{l}, l = ReadList[StringToStream[h], String]; l = Select[l, StringTake[#1, {9}] == "=" &]; l = Map[ ReadList[StringToStream[#], Word, 2, WordSeparators -> {"=", " /"}] &, l]; (* Convert FITS Keywords to valid Mathematica symbols *) l = Map[{StringReplace[#[[1]], {"-" -> "", "_" -> "", "+" -> "", "/" -> "", "*" -> "", "&" -> ""}], #[[2]]} &, l]; (* Convert FITS single quotes to double quotes *) l = Map[{#[[1]], StringReplace[#[[2]], "'" -> "\""]} &, l]; (* Convert values from scientific notation to explicit exponents and remove padding from strings *) l = Map[{ToExpression[#[[1]]], stringFortranFormToNumber[#[[2]]]} &, l]; l = Map[{#[[1]], StringUnpad[#[[2]]]} &, l]; l = Map[Apply[Rule, #] &, l]]; (*--------------------------------------------------------------------- stringFortranFormToNumber[] This converts a numeric string to a number if it's given in Fortran-esque notation. If it isn't a number of this kind it just passes the input through. ----------------------------------------------------------------------- *) stringFortranFormToNumber[str_] := Module[{s, isNumber, signOfNumber, notMultiple, noFunnyCharacters, noPathologicalCase}, s = ReadList[StringToStream[str], Word]; notMultiple = Length[s] < 2; s = ToUpperCase[s[[1]]]; signOfNumber = If[StringTake[s, 1] == "-", -1, 1]; noFunnyCharacters = DigitQ[StringReplace[ s, {"E" -> "", "D" -> "", "-" -> "", "+" -> "", "." -> ""}]]; noRepeatedExponent = Length[Select[Characters[s], (Equal[#, "E"] || Equal[#, "D"]) &]] <= 1; isNumber = If[ notMultiple && noRepeatedExponent && noFunnyCharacters && (StringMatchQ[s, "@*E@"] || StringMatchQ[s, "@*D@"] || DigitQ[StringReplace[s, "." -> ""]] || (DigitQ[StringReplace[StringDrop[s, 1], "." -> ""]] && signOfNumber == -1)) , True, False]; If[isNumber, ToExpression @ StringReplace[s, {"E" -> "*10^", "D" -> "*10^"}], str] ]; (*--------------------------------------------------------------------- stringUnpad[] This removes leading and trailing space from a string. If it is passed something other than a string it just passes it through. ----------------------------------------------------------------------- *) StringUnpad[str_] := If[StringQ[str], StringDrop[ StringJoin[ Map[StringInsert[#, " ", -1] &, ReadList[StringToStream[str], Word]]], -1], str]; End[] EndPackage[]