feat: compress and write to tzar format
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -21,4 +21,5 @@ _*.yaml
|
||||
NuGet.Config
|
||||
*.sif
|
||||
*.nc
|
||||
*.out
|
||||
*.out
|
||||
_*
|
||||
28
src/Copy.fs
28
src/Copy.fs
@@ -1,11 +1,14 @@
|
||||
module Tzar.Copy
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open FSharpPlus.Control
|
||||
open Serilog
|
||||
open FSharp.Compression
|
||||
open Oceanbox.FvcomKit
|
||||
open Types
|
||||
open Tzar.Cli
|
||||
open Tzar.Tzar
|
||||
open Fvcom
|
||||
|
||||
let private witherZfp tol x =
|
||||
@@ -79,7 +82,12 @@ let private writeToDest (dst: Uri) (transform: single[] -> single[]) (source: (i
|
||||
elif dst.LocalPath.EndsWith ".zarr" then
|
||||
notImplemented "file/zarr"
|
||||
else
|
||||
notImplemented "file/r3"
|
||||
if not (Directory.Exists dst.LocalPath) then
|
||||
Directory.CreateDirectory dst.LocalPath |> ignore
|
||||
source
|
||||
|> Seq.iter (fun (t, p) ->
|
||||
let data = toZarData transform p
|
||||
writeTzar dst.LocalPath Guid.Empty t data)
|
||||
| "s3" ->
|
||||
let bucket, key = S3.getBucketAndKey dst.LocalPath
|
||||
if dst.LocalPath.EndsWith ".nc" then
|
||||
@@ -130,8 +138,24 @@ let copyAction (a: CopyArgs) =
|
||||
let tol = 1e-4
|
||||
witherZfp tol
|
||||
elif a.Compress then
|
||||
failwith "not implemented"
|
||||
match a.Sz3 with
|
||||
| Some tol ->
|
||||
if a.Rel then
|
||||
Sz3.Single.sz3CompressRelToSingle tol
|
||||
else
|
||||
Sz3.Single.sz3CompressToSingle tol
|
||||
| None ->
|
||||
match a.Zfp with
|
||||
| Some tol -> Zfp.Single.zfpCompressToSingle tol
|
||||
| None ->
|
||||
let tol = 1e-4
|
||||
Zfp.Single.zfpCompressToSingle tol
|
||||
elif a.Decompress then
|
||||
// match a.Sz3 with
|
||||
// | Some tol ->
|
||||
// Sz3.Single.sz3Decompress x.Length
|
||||
// | None ->
|
||||
// Zfp.Single.zfpDecompress
|
||||
failwith "not implemented"
|
||||
else
|
||||
id
|
||||
|
||||
50
src/Sz3.fs
50
src/Sz3.fs
@@ -115,6 +115,31 @@ module Single =
|
||||
Marshal.FreeHGlobal p
|
||||
compressed
|
||||
|
||||
let sz3CompressToSingle (tol: double) (data: single[]) : single[] =
|
||||
use dp = fixed data
|
||||
let n = uint64 data.Length
|
||||
let mutable size = 0UL
|
||||
let p =
|
||||
Native.SZ_compress_args (
|
||||
Native.SZ3_FLOAT,
|
||||
NativePtr.toNativeInt dp,
|
||||
&size,
|
||||
Native.SZ3_ABS,
|
||||
tol,
|
||||
0,
|
||||
0,
|
||||
0UL,
|
||||
0UL,
|
||||
0UL,
|
||||
0UL,
|
||||
n
|
||||
)
|
||||
// printfn $"sz3 size: {data.Length * 4} -> {size}"
|
||||
let compressed: single[] = Array.zeroCreate (int size / 4)
|
||||
Marshal.Copy (p, compressed, 0, int size / 4)
|
||||
Marshal.FreeHGlobal p
|
||||
compressed
|
||||
|
||||
let sz3CompressRel (tol: double) (data: single[]) : byte[] =
|
||||
use dp = fixed data
|
||||
let n = uint64 data.Length
|
||||
@@ -140,6 +165,31 @@ module Single =
|
||||
Marshal.FreeHGlobal p
|
||||
compressed
|
||||
|
||||
let sz3CompressRelToSingle (tol: double) (data: single[]) : single[] =
|
||||
use dp = fixed data
|
||||
let n = uint64 data.Length
|
||||
let mutable size = 0UL
|
||||
let p =
|
||||
Native.SZ_compress_args (
|
||||
Native.SZ3_FLOAT,
|
||||
NativePtr.toNativeInt dp,
|
||||
&size,
|
||||
Native.SZ3_REL,
|
||||
0,
|
||||
tol,
|
||||
0,
|
||||
0UL,
|
||||
0UL,
|
||||
0UL,
|
||||
0UL,
|
||||
n
|
||||
)
|
||||
// printfn $"sz3 size: {data.Length * 4} -> {size}"
|
||||
let compressed: single[] = Array.zeroCreate (int size / 4)
|
||||
Marshal.Copy (p, compressed, 0, int size)
|
||||
Marshal.FreeHGlobal p
|
||||
compressed
|
||||
|
||||
let sz3Decompress (n: int) (data: byte[]) : single[] =
|
||||
use dp = fixed data
|
||||
let size = uint64 data.Length
|
||||
|
||||
65
src/Tzar.fs
Normal file
65
src/Tzar.fs
Normal file
@@ -0,0 +1,65 @@
|
||||
module Tzar.Tzar
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open Serilog
|
||||
|
||||
open Types
|
||||
|
||||
type TzarData = {
|
||||
s: single[][]
|
||||
t: single[][]
|
||||
u: single[][]
|
||||
v: single[][]
|
||||
w: single[][]
|
||||
z: single[]
|
||||
} with
|
||||
static member empty = {
|
||||
s = Array.zeroCreate 0
|
||||
t = Array.zeroCreate 0
|
||||
z = Array.zeroCreate 0
|
||||
u = Array.zeroCreate 0
|
||||
v = Array.zeroCreate 0
|
||||
w = Array.zeroCreate 0
|
||||
}
|
||||
|
||||
let private writeTzarData (path: string) (aid: Guid) (prop: string) (t: int) (l: int) (data: single[]) =
|
||||
let fname = Path.Join [| path; $"{aid}.{prop}.{t}.{l}.0" |]
|
||||
let buf: byte[] = Array.zeroCreate (data.Length * 4)
|
||||
for i = 0 to data.Length - 1 do
|
||||
let bytes = BitConverter.GetBytes data[i]
|
||||
let i' = i * 4
|
||||
buf[i' .. i' + 3] <- bytes
|
||||
File.WriteAllBytes (fname, buf)
|
||||
|
||||
let toZarData (f: single[] -> single[]) (ps: AsyncProp seq) : TzarData =
|
||||
let to2D (aa: Async<single[]>) = aa |> Async.RunSynchronously |> f
|
||||
let to3D (aa: Async<single[][]>) = aa |> Async.RunSynchronously |> Array.map f
|
||||
ps
|
||||
|> Seq.fold
|
||||
(fun a x ->
|
||||
match x with
|
||||
| U y -> { a with u = to3D y }
|
||||
| V y -> { a with v = to3D y }
|
||||
| W y -> { a with w = to3D y }
|
||||
| S y -> { a with s = to3D y }
|
||||
| T y -> { a with t = to3D y }
|
||||
| Z y -> { a with z = to2D y }
|
||||
| _ -> a)
|
||||
TzarData.empty
|
||||
|
||||
let writeTzar (path: string) (aid: Guid) (t: int) (data: TzarData) =
|
||||
let layers = data.t.Length
|
||||
try
|
||||
for l = 0 to layers - 1 do
|
||||
writeTzarData path aid "s" t l data.s[l]
|
||||
writeTzarData path aid "t" t l data.t[l]
|
||||
writeTzarData path aid "u" t l data.u[l]
|
||||
writeTzarData path aid "v" t l data.v[l]
|
||||
writeTzarData path aid "w" t l data.w[l]
|
||||
writeTzarData path aid "z" t 0 data.z
|
||||
with e ->
|
||||
Log.Fatal e.Message
|
||||
exit 1
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<Compile Include="Types.fs" />
|
||||
<Compile Include="Cli.fs" />
|
||||
<Compile Include="Fvcom.fs" />
|
||||
<Compile Include="Tzar.fs" />
|
||||
<Compile Include="R3.fs" />
|
||||
<Compile Include="S3.fs" />
|
||||
<Compile Include="Zarr.fs" />
|
||||
|
||||
25
src/Zfp.fs
25
src/Zfp.fs
@@ -109,7 +109,7 @@ module private Native =
|
||||
extern void zfp_stream_close(IntPtr zfp)
|
||||
|
||||
[<DllImport(libzfp, CallingConvention = CallingConvention.Cdecl)>]
|
||||
extern IntPtr stream_open(byte[] buf, uint size)
|
||||
extern IntPtr stream_open(IntPtr, uint size)
|
||||
|
||||
[<DllImport(libzfp, CallingConvention = CallingConvention.Cdecl)>]
|
||||
extern void stream_close(IntPtr stream)
|
||||
@@ -133,13 +133,14 @@ module private Native =
|
||||
extern bool zfp_stream_set_omp_chunk_size(IntPtr stream, uint threads)
|
||||
|
||||
module private Internal =
|
||||
let compress (tol: double) (field: ZfpField) : byte[] =
|
||||
let compress<'T when 'T: unmanaged> (tol: double) (field: ZfpField) : 'T[] =
|
||||
let zstream = Native.zfp_stream_open 0
|
||||
Native.zfp_stream_set_accuracy (zstream, tol)
|
||||
// Native.zfp_stream_set_precision(zstream, 16u)
|
||||
let bufsize = Native.zfp_stream_maximum_size (zstream, field)
|
||||
let compressed: byte[] = Array.zeroCreate (int bufsize)
|
||||
let stream = Native.stream_open (compressed, uint bufsize)
|
||||
let compressed: 'T[] = Array.zeroCreate (int bufsize)
|
||||
use compressed' = fixed compressed
|
||||
let stream = Native.stream_open (NativePtr.toNativeInt compressed', uint bufsize)
|
||||
Native.zfp_stream_set_bit_stream (zstream, stream)
|
||||
Native.zfp_stream_rewind zstream
|
||||
|
||||
@@ -154,7 +155,8 @@ module private Internal =
|
||||
compressed[0 .. size - 1]
|
||||
|
||||
let readHeader (compressed: byte[]) : ZfpField =
|
||||
let stream = Native.stream_open (compressed, uint compressed.Length)
|
||||
use compressed' = fixed compressed
|
||||
let stream = Native.stream_open (NativePtr.toNativeInt compressed', uint compressed.Length)
|
||||
let zstream = Native.zfp_stream_open 0
|
||||
Native.zfp_stream_set_bit_stream (zstream, stream)
|
||||
|
||||
@@ -166,7 +168,8 @@ module private Internal =
|
||||
field
|
||||
|
||||
let decompress<'T when 'T: unmanaged> (compressed: byte[]) : 'T[] =
|
||||
let stream = Native.stream_open (compressed, uint compressed.Length)
|
||||
use compressed' = fixed compressed
|
||||
let stream = Native.stream_open (NativePtr.toNativeInt compressed', uint compressed.Length)
|
||||
let zstream = Native.zfp_stream_open 0
|
||||
Native.zfp_stream_set_bit_stream (zstream, stream)
|
||||
|
||||
@@ -198,6 +201,16 @@ module Single =
|
||||
}
|
||||
Internal.compress tol field
|
||||
|
||||
let zfpCompressToSingle (tol: double) (data: single[]) : single[] =
|
||||
use data' = fixed data
|
||||
let field = {
|
||||
ZfpField.empty with
|
||||
_type = ZfpType.Float
|
||||
nx = uint64 data.Length
|
||||
data = NativePtr.toNativeInt data'
|
||||
}
|
||||
Internal.compress tol field
|
||||
|
||||
let zfpDecompress (data: byte[]) : single[] = Internal.decompress<single> data
|
||||
|
||||
module Double =
|
||||
|
||||
Reference in New Issue
Block a user