mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 09:40:21 +00:00
Adding some samples to verify new heuristics
This commit is contained in:
344
samples/Mathematica/HeyexImport.m
Normal file
344
samples/Mathematica/HeyexImport.m
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
(* Mathematica Package *)
|
||||||
|
(* Created with IntelliJ IDEA and the Mathematica Language plugin *)
|
||||||
|
|
||||||
|
(* :Title: Importer for the RAW data-format of the Heidelberg Eye Explorer (known as HEYEX) *)
|
||||||
|
|
||||||
|
(* :Context: HeyexImport` *)
|
||||||
|
|
||||||
|
(* :Author: Patrick Scheibe pscheibe@trm.uni-leipzig.de *)
|
||||||
|
|
||||||
|
(* :Package Version: 1.0 *)
|
||||||
|
|
||||||
|
(* :Mathematica Version: 8.0 *)
|
||||||
|
|
||||||
|
(* :Copyright: Patrick Scheibe, 2013-2015 *)
|
||||||
|
|
||||||
|
(* :Discussion: This package registers a new importer which can load the RAW data-format exported by a
|
||||||
|
Heidelberg Spectralis OCT. The import-functionality can access different information contained
|
||||||
|
in a file:
|
||||||
|
1. The file header which contains meta data like when the patient was scanned etc
|
||||||
|
2. The scanned volume data
|
||||||
|
3. Images which represent slices of the scanned volume
|
||||||
|
4. The Scanning laser ophthalmoscopy (SLO) image which is taken with every scanned patient
|
||||||
|
5. The segmentation data for different retina layers provided by the software
|
||||||
|
|
||||||
|
*)
|
||||||
|
|
||||||
|
(* :Keywords: Import, Heyex, OCT, Spectralis, Heidelberg Engineering *)
|
||||||
|
|
||||||
|
BeginPackage[ "HeyexImport`" ]
|
||||||
|
|
||||||
|
HeyexEyePosition::usage = "HeyexEyePosition[file] tries to extract which eye was scanned, left or right.";
|
||||||
|
|
||||||
|
HeyexImport::wrongHdr = "Error importing OCT data. Broken/Wrong file?";
|
||||||
|
|
||||||
|
|
||||||
|
Begin[ "`Private`" ];
|
||||||
|
|
||||||
|
(*
|
||||||
|
Registration of all import possibilities for the Heidelberg OCT.
|
||||||
|
*)
|
||||||
|
|
||||||
|
ImportExport`RegisterImport[
|
||||||
|
"Heyex" ,
|
||||||
|
{
|
||||||
|
"FileHeader" :> importHeader,
|
||||||
|
{ "Data" , n_Integer} :> (importData[n][##]&),
|
||||||
|
"Data" :> importData,
|
||||||
|
{ "Images" , n_Integer} :> (importImages[n][##]&),
|
||||||
|
"Images" :> importImages,
|
||||||
|
"SLOImage" :> importSLOImage,
|
||||||
|
"SegmentationData" :> importSegmentation,
|
||||||
|
{ "SegmentationData" , n_Integer} :> (importSegmentation[n][##]&),
|
||||||
|
"DataSize" :> importDataSize,
|
||||||
|
importData
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"Image3D" :> (Image3D["Data" /. #1]&)
|
||||||
|
},
|
||||||
|
|
||||||
|
"AvailableElements" -> {"FileHeader", "Data", "DataSize", "Images", "SLOImage", "SegmentationData", "Image3D"}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
If[Quiet[Check[TrueQ[Compile[{}, 0, CompilationTarget -> "C"][] == 0], False]],
|
||||||
|
$compileTarget = CompilationTarget -> "C",
|
||||||
|
$compileTarget = CompilationTarget -> "MVM"
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
(*
|
||||||
|
Helper function which reads data from a stream. This is
|
||||||
|
only a unification so I can map the read function over a
|
||||||
|
list.
|
||||||
|
*)
|
||||||
|
read[{id_String, type_String}, str_] :=
|
||||||
|
id -> BinaryRead[str, type];
|
||||||
|
read[{type_String, n_Integer}, str_] := BinaryReadList[str, type, n];
|
||||||
|
read[{id_String, {type_String, n_Integer}}, str_] := id -> BinaryReadList[str, type, n];
|
||||||
|
(*
|
||||||
|
Note that when reading bytes explicitly I convert them to
|
||||||
|
a string and remove any zeroes at the end.
|
||||||
|
*)
|
||||||
|
read[{id_String, { "Byte" , n_Integer}}, str_] :=
|
||||||
|
id -> StringJoin[
|
||||||
|
FromCharacterCode /@ (Rest[
|
||||||
|
NestList[BinaryRead[str, "Byte" ] &, Null,
|
||||||
|
n]] /. {chars___Integer, Longest[0 ...]} :> {chars})];
|
||||||
|
|
||||||
|
(*
|
||||||
|
The layout of a file exported with "Raw Export"
|
||||||
|
|
||||||
|
*****************
|
||||||
|
* File Header *
|
||||||
|
*****************
|
||||||
|
* SLO Image *
|
||||||
|
*****************
|
||||||
|
* B-Scan #0 *
|
||||||
|
*****************
|
||||||
|
* ..... *
|
||||||
|
*****************
|
||||||
|
* B-Scan #n-1 *
|
||||||
|
*****************
|
||||||
|
*)
|
||||||
|
|
||||||
|
With[{i = "Integer32", f = "Real32", d = "Real64", b = "Byte"},
|
||||||
|
|
||||||
|
$fileHeaderInfo = Transpose[{
|
||||||
|
{
|
||||||
|
"Version" , "SizeX" , "NumBScans" , "SizeZ" , "ScaleX" , "Distance" ,
|
||||||
|
"ScaleZ" , "SizeXSlo" , "SizeYSlo" , "ScaleXSlo" , "ScaleYSlo" ,
|
||||||
|
"FieldSizeSlo" , "ScanFocus" , "ScanPosition" , "ExamTime" ,
|
||||||
|
"ScanPattern" , "BScanHdrSize" , "ID" , "ReferenceID" , "PID" ,
|
||||||
|
"PatientID" , "Padding" , "DOB" , "VID" , "VisitID" , "VisitDate" ,
|
||||||
|
"Spare"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{b, 12}, i, i, i, d, d, d, i, i, d, d, i, d, {b, 4}, {i, 2}, i, i,
|
||||||
|
{b, 16}, {b, 16}, i, {b, 21}, {b, 3}, d, i, {b, 24}, d, {b, 1840}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
$bScanHeaderInfo = Transpose[{
|
||||||
|
{
|
||||||
|
"Version" , "BScanHdrSize" , "StartX" , "StartY" , "EndX" , "EndY" ,
|
||||||
|
"NumSeg" , "OffSeg" , "Quality" , "Spare"
|
||||||
|
},
|
||||||
|
{{b, 12}, i, d, d, d, d, i, i, f, {b, 196}}
|
||||||
|
}];
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
isHeyexRawFormat[{"Version" -> version_String, "SizeX" -> _Integer, "NumBScans" -> _Integer, _Rule..}] /; StringMatchQ[version, "HSF-OCT" ~~__] := True ;
|
||||||
|
isHeyexRawFormat[___] := False;
|
||||||
|
|
||||||
|
readFileHeader[str_InputStream] := With[{hdr = Quiet[read[#, str]] & /@ $fileHeaderInfo},
|
||||||
|
hdr /; TrueQ[isHeyexRawFormat[hdr]]
|
||||||
|
];
|
||||||
|
readFileHeader[___] := (Message[HeyexImport::wrongHdr]; Throw[$Failed]);
|
||||||
|
|
||||||
|
|
||||||
|
(* Reads the camera image of the retina. Note that you must have the
|
||||||
|
information from the fileheader and you must be at the right position
|
||||||
|
of the file stream for this.*)
|
||||||
|
readSLOImage[str_InputStream, fileHdr : {(_String -> _) ..}] :=
|
||||||
|
Image[Partition[
|
||||||
|
BinaryReadList[str, "Byte" , "SizeXSlo" * "SizeYSlo" /. fileHdr],
|
||||||
|
"SizeXSlo" /. fileHdr], "Byte" ];
|
||||||
|
|
||||||
|
skipSLOImage[str_InputStream, fileHdr : {(_String -> _) ..}] :=
|
||||||
|
Skip[str, "Byte" , "SizeXSlo" * "SizeYSlo" /. fileHdr];
|
||||||
|
|
||||||
|
|
||||||
|
(* One single BScan consists itself again of a header and a data part *)
|
||||||
|
readBScanHeader[str_InputStream, fileHdr : {(_String -> _) ..}] :=
|
||||||
|
Module[{i = "Integer32", f = "Real32", d = "Real64", b = "Byte",
|
||||||
|
bScanHdr},
|
||||||
|
bScanHdr = read[#, str] & /@ Transpose[{
|
||||||
|
{ "Version" , "BScanHdrSize" , "StartX" , "StartY" , "EndX" , "EndY" ,
|
||||||
|
"NumSeg" , "OffSeg" , "Quality" , "Spare" },
|
||||||
|
{{b, 12}, i, d, d, d, d, i, i, f, {b, 196}}}
|
||||||
|
];
|
||||||
|
AppendTo[bScanHdr,
|
||||||
|
read[{ "SegArray" , { "Real32" ,
|
||||||
|
"NumSeg" * "SizeX" /. bScanHdr /. fileHdr}}, str]
|
||||||
|
];
|
||||||
|
(*
|
||||||
|
This is horrible slow, therefore I just skip the fillbytes
|
||||||
|
|
||||||
|
AppendTo[bScanHdr,
|
||||||
|
read[{"Fillbytes", {"Byte",
|
||||||
|
"BScanHdrSize" - 256 - "NumSeg"*"SizeX"*4 /. bScanHdr /.
|
||||||
|
fileHdr}}, str]
|
||||||
|
]
|
||||||
|
*)
|
||||||
|
Skip[str, "Byte" , "BScanHdrSize" - 256 - "NumSeg" * "SizeX" * 4 /. bScanHdr /. fileHdr];
|
||||||
|
AppendTo[bScanHdr, "FillBytes" -> None]
|
||||||
|
]
|
||||||
|
|
||||||
|
skipBScanHeader[str_InputStream, fileHdr : {(_String -> _) ..}] :=
|
||||||
|
Skip[str, "Byte" , "BScanHdrSize" /. fileHdr];
|
||||||
|
|
||||||
|
readBScanData[str_InputStream, fileHdr : {(_String -> _) ..}] :=
|
||||||
|
Module[{},
|
||||||
|
Developer`ToPackedArray[
|
||||||
|
Partition[read[{ "Real32" , "SizeX" * "SizeZ" /. fileHdr}, str],
|
||||||
|
"SizeX" /. fileHdr]]
|
||||||
|
];
|
||||||
|
|
||||||
|
skipBScanData[str_InputStream, fileHdr : {(_String -> _) ..}] :=
|
||||||
|
Skip[str, "Byte" , "SizeX" * "SizeZ" * 4 /. fileHdr];
|
||||||
|
|
||||||
|
skipBScanBlocks[str_InputStream, fileHdr : {(_String -> _) ..}, n_Integer] :=
|
||||||
|
Skip[str, "Byte" , n * ("BScanHdrSize" + "SizeX" * "SizeZ" * 4) /. fileHdr];
|
||||||
|
|
||||||
|
|
||||||
|
importHeader[filename_String, ___] := Module[
|
||||||
|
{str, header},
|
||||||
|
str = OpenRead[filename, BinaryFormat -> True];
|
||||||
|
header = readFileHeader[str];
|
||||||
|
Close[str];
|
||||||
|
"FileHeader" -> header
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
(* Imports the dimension of the scanned volume. *)
|
||||||
|
importDataSize[filename_String, r___] := Module[{header = importHeader[filename]},
|
||||||
|
"DataSize" -> ({"NumBScans", "SizeZ", "SizeXSlo"} /. ("FileHeader" /. header))
|
||||||
|
]
|
||||||
|
|
||||||
|
importSLOImage[filename_String, ___] := Module[
|
||||||
|
{str, header, slo},
|
||||||
|
str = OpenRead[filename, BinaryFormat -> True];
|
||||||
|
header = readFileHeader[str];
|
||||||
|
slo = readSLOImage[str, header];
|
||||||
|
Close[str];
|
||||||
|
"SLOImage" -> slo
|
||||||
|
]
|
||||||
|
|
||||||
|
importData[filename_String, ___] := Module[
|
||||||
|
{str, header, nx, n, data},
|
||||||
|
str = OpenRead[filename, BinaryFormat -> True];
|
||||||
|
header = readFileHeader[str];
|
||||||
|
{nx, n} = { "SizeX" , "SizeX" * "SizeZ"} /. header;
|
||||||
|
skipSLOImage[str, header];
|
||||||
|
data = Table[
|
||||||
|
skipBScanHeader[str, header];
|
||||||
|
Partition[read[{ "Real32" , n}, str], nx],
|
||||||
|
{"NumBScans" /. header}
|
||||||
|
];
|
||||||
|
Close[str];
|
||||||
|
"Data" -> Developer`ToPackedArray[data]
|
||||||
|
];
|
||||||
|
|
||||||
|
importData[num_Integer][filename_String, ___] := Module[
|
||||||
|
{str, header, nx, n, data},
|
||||||
|
str = OpenRead[filename, BinaryFormat -> True];
|
||||||
|
header = readFileHeader[str];
|
||||||
|
{nx, n} = { "SizeX" , "SizeX" * "SizeZ"} /. header;
|
||||||
|
skipSLOImage[str, header];
|
||||||
|
skipBScanBlocks[str, header, Max[Min["NumBScans" /. header, num - 1], 0] ];
|
||||||
|
skipBScanHeader[str, header];
|
||||||
|
data = Partition[read[{ "Real32" , n}, str], nx];
|
||||||
|
Close[str];
|
||||||
|
{"Data" -> {num -> Developer`ToPackedArray[data]}}
|
||||||
|
];
|
||||||
|
|
||||||
|
(*
|
||||||
|
As suggested in the Heidelberg OCT Manual the importer will adjust
|
||||||
|
the graylevels when importing images. Since this is very time-consuming
|
||||||
|
for the whole scanned volume, I use an optimized version of this function.
|
||||||
|
*)
|
||||||
|
With[{$compileTarget = $compileTarget}, $adjustGraylevelFunc := ($adjustGraylevelFunc = Compile[{{values, _Real, 2}},
|
||||||
|
Map[Floor[255.0 * Min[Max[0.0, #], 1.0]^(0.25) + 0.5] &, values, {2}],
|
||||||
|
RuntimeAttributes -> {Listable},
|
||||||
|
Parallelization -> True,
|
||||||
|
RuntimeOptions -> "Speed",
|
||||||
|
$compileTarget
|
||||||
|
])];
|
||||||
|
|
||||||
|
importImages[filename_String, ___] := Module[
|
||||||
|
{data},
|
||||||
|
data = "Data" /. importData[filename];
|
||||||
|
"Images" -> (Image[#, "Byte" ]& /@ $adjustGraylevelFunc[data])
|
||||||
|
]
|
||||||
|
|
||||||
|
importImages[imageNumber_Integer][filename_String, ___] := Module[
|
||||||
|
{data},
|
||||||
|
data = {imageNumber /. ("Data" /. importData[imageNumber][filename])};
|
||||||
|
{"Images" -> {imageNumber -> (Image[#, "Byte" ]& @@ $adjustGraylevelFunc[data])}}
|
||||||
|
];
|
||||||
|
|
||||||
|
importSegmentation[filename_String, ___] := Module[
|
||||||
|
{str, header, data},
|
||||||
|
str = OpenRead[filename, BinaryFormat -> True];
|
||||||
|
header = readFileHeader[str];
|
||||||
|
skipSLOImage[str, header];
|
||||||
|
data = Table[
|
||||||
|
Module[{bScanHeader, t},
|
||||||
|
{t, bScanHeader} = Timing@readBScanHeader[str, header];
|
||||||
|
skipBScanData[str, header];
|
||||||
|
bScanHeader
|
||||||
|
], {"NumBScans" /. header}
|
||||||
|
];
|
||||||
|
Close[str];
|
||||||
|
(*
|
||||||
|
The BScanHeaderData contain the segmentation vectors as a single list
|
||||||
|
of numbers. Before returning the result, I check how many segmentations
|
||||||
|
there are inside the BScan an I transform the segmentation value list
|
||||||
|
into separate vectors and call them "ILM", "RPE" and "NFL" like described
|
||||||
|
in the manual
|
||||||
|
*)
|
||||||
|
"SegmentationData" -> Function[{bhdr},
|
||||||
|
Block[{numVecs = "NumSeg" /. bhdr, vecNames, nx = "SizeX" /. header},
|
||||||
|
If[numVecs > 0,
|
||||||
|
vecNames = Take[{ "ILM" , "RPE" , "NFL" }, numVecs];
|
||||||
|
bhdr /. ("SegArray" -> vec_) :> Sequence @@ (Rule @@@ Transpose[{vecNames, Partition[vec, nx]} ]),
|
||||||
|
bhdr
|
||||||
|
]
|
||||||
|
]] /@ data
|
||||||
|
]
|
||||||
|
|
||||||
|
importSegmentation[num_Integer][filename_String, ___] := Module[
|
||||||
|
{str, header, bhdr},
|
||||||
|
str = OpenRead[filename, BinaryFormat -> True];
|
||||||
|
header = readFileHeader[str];
|
||||||
|
skipSLOImage[str, header];
|
||||||
|
skipBScanBlocks[str, header, Max[Min["NumBScans" /. header, num - 1], 0] ];
|
||||||
|
bhdr = readBScanHeader[str, header];
|
||||||
|
Close[str];
|
||||||
|
(* See doc above *)
|
||||||
|
{"SegmentationData" -> {num -> Block[
|
||||||
|
{numVecs = "NumSeg" /. bhdr, vecNames, nx = "SizeX" /. header},
|
||||||
|
If[ numVecs > 0,
|
||||||
|
vecNames = Take[{ "ILM" , "RPE" , "NFL" }, numVecs];
|
||||||
|
bhdr /. ("SegArray" -> vec_) :> Sequence @@ (Rule @@@ Transpose[{vecNames, Partition[vec, nx]} ]),
|
||||||
|
bhdr
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
]
|
||||||
|
|
||||||
|
(* Extracts which eye was scanned. This is stored in the header of the file *)
|
||||||
|
(* OD stands for oculus dexter which is latin for "right eye" and OS stands
|
||||||
|
for oculus sinister which is latin for "left eye" *)
|
||||||
|
HeyexEyePosition[file_String /; FileExistsQ[file]] := Module[{position},
|
||||||
|
Check[
|
||||||
|
position = "ScanPosition" /. Import[file, { "Heyex" , "FileHeader" }];
|
||||||
|
Switch[
|
||||||
|
position,
|
||||||
|
"OD" ,
|
||||||
|
Right,
|
||||||
|
"OS" ,
|
||||||
|
Left,
|
||||||
|
_,
|
||||||
|
$Failed
|
||||||
|
],
|
||||||
|
$Failed
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
End[]
|
||||||
|
|
||||||
|
EndPackage[]
|
||||||
46
samples/Mercury/switch_detection_bug.m
Normal file
46
samples/Mercury/switch_detection_bug.m
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
% This is a regression test for a bug in switch detection
|
||||||
|
% where it was preferring incomplete switches to complete
|
||||||
|
% one-case switches, and hence inferring the wrong determinism.
|
||||||
|
|
||||||
|
%------------------------------------------------------------------------------%
|
||||||
|
|
||||||
|
:- module switch_detection_bug.
|
||||||
|
|
||||||
|
:- interface.
|
||||||
|
|
||||||
|
:- type note ---> note(rank, modifier, octave).
|
||||||
|
|
||||||
|
:- type rank ---> c ; d ; e ; f ; g ; a ; b .
|
||||||
|
|
||||||
|
:- type modifier ---> natural ; sharp ; flat .
|
||||||
|
|
||||||
|
:- type octave == int.
|
||||||
|
|
||||||
|
:- type qualifier ---> maj ; min .
|
||||||
|
|
||||||
|
:- pred next_topnote(note, qualifier, note).
|
||||||
|
:- mode next_topnote(in, in, out) is multi.
|
||||||
|
|
||||||
|
%------------------------------------------------------------------------------%
|
||||||
|
|
||||||
|
:- implementation.
|
||||||
|
|
||||||
|
next_topnote(note(c, _, Oct), _, note(d, natural, Oct)).
|
||||||
|
next_topnote(note(d, _, Oct), _, note(c, natural, Oct)).
|
||||||
|
next_topnote(note(d, _, Oct), maj, note(e, natural, Oct)).
|
||||||
|
next_topnote(note(d, _, Oct), min, note(e, flat, Oct)).
|
||||||
|
next_topnote(note(e, _, Oct), _, note(d, natural, Oct)).
|
||||||
|
next_topnote(note(e, _, Oct), _, note(f, natural, Oct)).
|
||||||
|
next_topnote(note(f, _, Oct), maj, note(e, natural, Oct)).
|
||||||
|
next_topnote(note(f, _, Oct), min, note(e, flat, Oct)).
|
||||||
|
next_topnote(note(g, _, Oct), _, note(f, natural, Oct)).
|
||||||
|
next_topnote(note(g, _, Oct), min, note(a, flat, Oct)).
|
||||||
|
next_topnote(note(g, _, Oct), maj, note(a, natural, Oct)).
|
||||||
|
next_topnote(note(a, _, Oct), _, note(g, natural, Oct)).
|
||||||
|
next_topnote(note(a, _, Oct), min, note(b, flat, Oct)).
|
||||||
|
next_topnote(note(a, _, Oct), maj, note(b, natural, Oct)).
|
||||||
|
next_topnote(note(b, _, Oct), maj, note(a, natural, Oct)).
|
||||||
|
next_topnote(note(b, _, Oct), min, note(a, flat, Oct)).
|
||||||
|
|
||||||
|
%------------------------------------------------------------------------------%
|
||||||
|
|
||||||
Reference in New Issue
Block a user