~adigitoleo/PlateMotionRequests.jl

cfd73175f8c6f02dbb07b3556ff1c4a262d61fa5 — adigitoleo 6 months ago f35cd2b
feat: Support reading right-aligned data

It is common for external tools to right-align delimited data files.
This commit makes `read_platemotion` strip spurrious whitespace from columns.
A test is also added.
M TODO.md => TODO.md +0 -1
@@ 4,7 4,6 @@
- New methods for `platemotion` that accept `Matrix` or array of tuples for lat/lon input.
- Rate limits? Prevent accidental spamming of requests to the server.
- Caching?
- Use `strip` in `read_platemotion` to be able to read vertically aligned columns

## Out of scope


M src/PlateMotionRequests.jl => src/PlateMotionRequests.jl +5 -4
@@ 468,13 468,14 @@ May throw a `PlateMotionRequests.ReadError`.
"""
function read_platemotion(file)
    data, header = readdlm(file, '\t', Any, '\n', header = true)
    isformat(format) = Set(header) == Set(String.(fieldnames(format)))
    isformat(format) = Set(strip.(header)) == Set(String.(fieldnames(format)))
    cleanstrings(data) = map(s -> s isa AbstractString ? strip(s) : s, data)
    if isformat(FormatASCII)
        table = as_table(FormatASCII, data)
        table = as_table(FormatASCII, cleanstrings(data))
    elseif isformat(FormatASCIIxyz)
        table = as_table(FormatASCIIxyz, data)
        table = as_table(FormatASCIIxyz, cleanstrings(data))
    elseif isformat(FormatPsvelo)
        table = as_table(FormatPsvelo, data)
        table = as_table(FormatPsvelo, cleanstrings(data))
    else
        throw(
            ReadError(

A test/data/parsed_rightaligned_GSRMv2_regular.dat => test/data/parsed_rightaligned_GSRMv2_regular.dat +19 -0
@@ 0,0 1,19 @@
  lon	  lat	velocity_east	velocity_north	plate_and_reference	    model
110.0	-35.0	        41.58	         56.94	            AU(NNR)	GSRM v2.1
110.0	-25.0	        42.45	         56.97	            AU(NNR)	GSRM v2.1
110.0	-15.0	        42.03	         56.99	            AU(NNR)	GSRM v2.1
110.0	 -5.0	        23.36	         -7.34	            EU(NNR)	GSRM v2.1
110.0	  5.0	        26.03	         -7.34	            EU(NNR)	GSRM v2.1
110.0	 15.0	        27.92	         -7.34	            EU(NNR)	GSRM v2.1
110.0	 25.0	        28.97	         -7.34	            EU(NNR)	GSRM v2.1
110.0	 35.0	        29.15	         -7.34	            EU(NNR)	GSRM v2.1
110.0	 45.0	        28.43	         -7.33	            EU(NNR)	GSRM v2.1
120.0	-35.0	        35.79	         58.98	            AU(NNR)	GSRM v2.1
120.0	-25.0	        38.18	         59.01	            AU(NNR)	GSRM v2.1
120.0	-15.0	        39.42	         59.03	            AU(NNR)	GSRM v2.1
120.0	 -5.0	        23.49	         -9.92	            EU(NNR)	GSRM v2.1
120.0	  5.0	         25.9	         -9.92	            EU(NNR)	GSRM v2.1
120.0	 15.0	        27.54	         -9.91	            EU(NNR)	GSRM v2.1
120.0	 25.0	        28.34	         -9.91	            EU(NNR)	GSRM v2.1
120.0	 35.0	        28.28	         -9.91	            EU(NNR)	GSRM v2.1
120.0	 45.0	        27.37	          -9.9	            EU(NNR)	GSRM v2.1

M test/runtests.jl => test/runtests.jl +35 -33
@@ 823,6 823,9 @@ end
                filename("tmp.dat"),
                Table(a = [1], b = [1]),
            )
            @test read_platemotion(
                filename("data/parsed_rightaligned_GSRMv2_regular.dat"),
            ) == mock_ascii_gsrm_regular
        finally
            rm(filename("tmp.dat"), force = true)
            rm(filename("ASCII_all_models_irregular.dat"), force = true)


@@ 835,10 838,7 @@ end

    @testset "NetCDF" begin
        try
            write_platemotion(
                filename("ASCII_GSRMv2_regular.nc"),
                mock_ascii_gsrm_regular,
            )
            write_platemotion(filename("ASCII_GSRMv2_regular.nc"), mock_ascii_gsrm_regular)
            ds = NCDataset(filename("ASCII_GSRMv2_regular.nc"))
            # Check global attributes.
            for key in ("Conventions", "title", "institution", "references", "comment")


@@ 847,8 847,10 @@ end
            @test ds.attrib["Conventions"] == "CF-1.9"
            @test ds.attrib["title"] == "Tectonic plate motions"
            @test ds.attrib["institution"] == "https://www.unavco.org/"
            @test ds.attrib["references"] == "See <https://www.unavco.org/software/geodetic-utilities/plate-motion-calculator/plate-motion-calculator.html#references>"
            @test ds.attrib["comment"] == "Produced using https://git.sr.ht/~adigitoleo/PlateMotionRequests.jl\n"
            @test ds.attrib["references"] ==
                  "See <https://www.unavco.org/software/geodetic-utilities/plate-motion-calculator/plate-motion-calculator.html#references>"
            @test ds.attrib["comment"] ==
                  "Produced using https://git.sr.ht/~adigitoleo/PlateMotionRequests.jl\n"
            # Check dimensions.
            @test haskey(ds.dim, "lat")
            @test haskey(ds.dim, "lon")


@@ 859,38 861,38 @@ end
                @test haskey(ds, key)
            end
            @test ds["velocity_east"][:] == [
                41.58 35.79;
                42.45 38.18;
                42.03 39.42;
                23.36 23.49;
                26.03 25.90;
                27.92 27.54;
                28.97 28.34;
                29.15 28.28;
                28.43 27.37;
                41.58 35.79
                42.45 38.18
                42.03 39.42
                23.36 23.49
                26.03 25.90
                27.92 27.54
                28.97 28.34
                29.15 28.28
                28.43 27.37
            ]
            @test ds["velocity_north"][:] == [
                56.94 58.98;
                56.97 59.01;
                56.99 59.03;
                -7.34 -9.92;
                -7.34 -9.92;
                -7.34 -9.91;
                -7.34 -9.91;
                -7.34 -9.91;
                -7.33 -9.90;
                56.94 58.98
                56.97 59.01
                56.99 59.03
                -7.34 -9.92
                -7.34 -9.92
                -7.34 -9.91
                -7.34 -9.91
                -7.34 -9.91
                -7.33 -9.90
            ]
            @test all(x -> x == "GSRM v2.1", ds["model"][:])
            @test ds["plate_and_reference"] == [
                "AU(NNR)" "AU(NNR)";
                "AU(NNR)" "AU(NNR)";
                "AU(NNR)" "AU(NNR)";
                "EU(NNR)" "EU(NNR)";
                "EU(NNR)" "EU(NNR)";
                "EU(NNR)" "EU(NNR)";
                "EU(NNR)" "EU(NNR)";
                "EU(NNR)" "EU(NNR)";
                "EU(NNR)" "EU(NNR)";
                "AU(NNR)" "AU(NNR)"
                "AU(NNR)" "AU(NNR)"
                "AU(NNR)" "AU(NNR)"
                "EU(NNR)" "EU(NNR)"
                "EU(NNR)" "EU(NNR)"
                "EU(NNR)" "EU(NNR)"
                "EU(NNR)" "EU(NNR)"
                "EU(NNR)" "EU(NNR)"
                "EU(NNR)" "EU(NNR)"
            ]
            @test_throws _pmr.WriteError write_platemotion(
                filename("ASCII_all_models_irregular.nc"),