From 8260ed8c9ba423f6bf5cf2cbf462947391bbcff1 Mon Sep 17 00:00:00 2001 From: Joaquim Date: Mon, 3 Nov 2025 22:30:37 +0000 Subject: [PATCH 1/2] Add a new filter option to filter Datasets by BBox aspect ratio. Add a ind2bool function. Several fixes in new functions. --- src/GMT.jl | 1 + src/imgmorph/cc2bw.jl | 28 +++++++++++++++++++++++----- src/lepto_funs.jl | 35 ++++++++--------------------------- src/spatial_funs.jl | 28 +++++++++++++++++++--------- src/utils.jl | 14 ++++++++++++++ test/test_misc.jl | 2 ++ 6 files changed, 67 insertions(+), 41 deletions(-) diff --git a/src/GMT.jl b/src/GMT.jl index 073988999..df90b1836 100644 --- a/src/GMT.jl +++ b/src/GMT.jl @@ -196,6 +196,7 @@ export okada, haralick, mapsize2region, + ind2bool, cube, cylinder, circlepts, dodecahedron, ellipse3D, eulermat, flatfv, icosahedron, loft, sphere, spinmat, octahedron, tetrahedron, torus, replicant, revolve, rotate, rotate!, translate, translate!, diff --git a/src/imgmorph/cc2bw.jl b/src/imgmorph/cc2bw.jl index 25439eab1..e9e0f4b79 100644 --- a/src/imgmorph/cc2bw.jl +++ b/src/imgmorph/cc2bw.jl @@ -2,20 +2,38 @@ BW = cc2bw(cc::GMTConComp; obj2keep::Union{Int, Vector{Int}}=0) Convert connected components to binary image + +- `cc`: Connected components created with `bwconncomp` +- `obj2keep`: (optional) Integer, vector of integers or a vector of booleans specifying which + connected components to keep in the output binary image. By default, all components are kept. + +Returns a binary `GMTimage` where pixels belonging to the specified connected components are set to `true`. """ -function cc2bw(cc::GMTConComp; obj2keep::Union{Int, Vector{Int}}=0) +function cc2bw(cc::GMTConComp; obj2keep=Int[]) + isscalar(obj2keep) && return _cc2bw(cc, [Int(obj2keep)]) + if (isa(obj2keep, Vector{Int})) + return _cc2bw(cc, obj2keep) + elseif (isa(obj2keep, Vector{Bool}) || isa(obj2keep, BitVector)) + ind = findall(obj2keep) + isempty(ind) && error("No components selected to keep in the 'obj2keep' parameter") + return _cc2bw(cc, ind) + end + error("Invalid type for 'obj2keep' parameter. Must be an integer, vector of integers, or vector of booleans.") +end +function _cc2bw(cc::GMTConComp, obj2keep::Vector{Int}) # Create a binary image of the same size as the original + !isempty(obj2keep) && any((k -> k < 1 || k > cc.num_objects), obj2keep) && + error("Values in 'obj2keep' are out of range [1, $(cc.num_objects)]") I = mat2img(zeros(Bool, cc.image_size), x=cc.x, y=cc.y, inc=cc.inc, layout=cc.layout, is_transposed=(cc.layout[2] == 'R'), proj4=cc.proj4, wkt=cc.wkt, epsg=cc.epsg) # Mark pixels belonging to any connected component as true - plist = (obj2keep == 0) ? (1:cc.num_objects) : isvector(obj2keep) ? obj2keep : (obj2keep:obj2keep) - for k = 1:numel(plist) - for rc in cc.pixel_list[plist[k]] + plist = isempty(obj2keep) ? (1:cc.num_objects) : obj2keep + @inbounds for k = 1:numel(plist) + @inbounds for rc in cc.pixel_list[plist[k]] I[rc] = true end end I.range[6] = 1.0 return I end - diff --git a/src/lepto_funs.jl b/src/lepto_funs.jl index 367b112a7..544281c5e 100644 --- a/src/lepto_funs.jl +++ b/src/lepto_funs.jl @@ -340,17 +340,6 @@ which is not that much. - `conn::Int`: Connectivity for sink filling (4 or 8). Default is 8. - `region`: Limit the action to a region of the grid specified by `region`. See for example the ``coast`` manual for and extended doc on this keword, but note that here only `region` is accepted and not `R`, etc... -- `saco::Bool`: Save the lines (GMTdataset ~contours) used to fill the sinks in a global variable called - SACO. This is intended to avoid return them all the time when function ends. This global variable - is a ``[Dict{String,Union{AbstractArray, Vector{AbstractArray}}}()]``, so to access its contents you must use: - - ``D = get(SACO[1], "saco", nothing)``, where ``D`` is now a GMTdataset or a vector of them. - - NOTE: It is the user's responsibility to empty this global variable when it is no longer needed. - - You do that with: ``delete!(SACO[1], "saco")`` -- `insitu::Bool`: If `true`, modify the grid in place. Default is `false`. - Alternatively, use the conventional form ``fillsinks!(G; conn=4)``. ### Returns - A new `GMTgrid` with sinks filled, unless `insitu` is `true`, in which case the input grid is modified and returned. @@ -361,16 +350,8 @@ G = peaks(); G2 = fillsinks(G); viz(G2, shade=true) ``` - -Now save the filling contours and make a plot that overlayes them -```julia -G2 = fillsinks(G); -G2 = fillsinks(G, saco=true); -grdimage(G2) -plot!(get(SACO[1], "saco", nothing), color=:white, show=true) -``` """ -function fillsinks(GI::GItype; conn=8, region=nothing, saco=false, insitu=false) +function fillsinks(GI::GItype; conn=8, region=nothing) infa = eltype(GI) <: AbstractFloat ? -Inf : typemin(eltype(GI)) for k = 1:numel(GI) GI[k] *= -1 end @@ -1213,18 +1194,18 @@ A `GMTConComp` structure with the following fields: - `connectivity`: Connectivity value used to identify the connected components in I (4 or 8). - `num_objects`: Number of connected components found. - `image_size`: Size of the image. -- `range`: Range of the image. -- `inc`: Increment of the image. +- `range`: Range of the image coordinates. +- `inc`: Image's increment (!= 1 whem image is referenced). - `registration`: Registration of the image. - `x`: X coordinates of the image. - `y`: Y coordinates of the image. -- `layout`: Layout of the image used to find the components. -- `proj4`: Projection definition of the image used to find the components. -- `wkt`: Well-known text definition of the image used to find the components. -- `epsg`: EPSG code of the image used to find the components. +- `layout`: Memory layout of the image. +- `proj4`: Projection definition (optional). +- `wkt`: Well-known text definition (optional). +- `epsg`: EPSG code of the image (optional). - `bbox`: The bounding boxes as a vector of GMTdataset. - `pixel_list`: A vector of vectors with the list of linear pixel indices for each component. -- `centroid`: A vector of Float64 Tuples with the x,y coordinates of the centroids for each component. +- `centroid`: A Float64 Matrix with the x,y coordinates of the centroids for each component. - `area`: A vector of Float64 with the areas of each component. This area is approximated by the mean lat for geog images. """ bwconncomp(mat::BitMatrix; conn::Int=8) = bwconncomp(mat2img(collect(mat)); conn=conn) diff --git a/src/spatial_funs.jl b/src/spatial_funs.jl index 849b6da41..a53988af6 100644 --- a/src/spatial_funs.jl +++ b/src/spatial_funs.jl @@ -178,13 +178,16 @@ NOTE: Instead of ``getbyattrib`` one case use instead ``filter`` (...,`index=fal means select all elements from ``Antioquia`` and ``Caldas`` that have the attribute `feature_id` = 0. A second set of attributes can be used to select elements by region, number of polygon vertices and area. - For that, name the keyword with a leading underscore, e.g. `_region`, `_nps`, `_area`, `_unique`. Their values are - passed respectively a 4 elements tuple and numbers. E.g. `_region=(-8.0, -7.0, 37.0, 38.0)`, `_nps=100`, `_area=10`. - Areas are in square km when input is in geographic coordinates, otherwise square data units. The `_unique` case is - a bit special and is meant to be used when more than one polygon share the same attribute value (e.g. countries with islands). - In that case, set the value of `_unique` to the name of the attribute that is shared by the polygons (e.g. `_unique="NAME"`). - By default (e.g. `_unique=true`), the attribute name is `Feature_ID` which is the one used by GMT when creating unique - IDs for polygons read from OGR formats (.shp, .geojson, etc). If this attrib name is not found, we search for `CODE` which is + For that, name the keyword with a leading underscore, e.g. `_region`, `_nps`, `_area`, `_aspect`, `_unique`. Their values + are passed respectively a 4 elements tuple and numbers. E.g. `_region=(-8.0, -7.0, 37.0, 38.0)`, `_nps=100`, `_area=10`, + `_aspect=0.5`. Areas are in square km when input is in geographic coordinates, otherwise square data units. + The aspect ratio passed to the `_aspect` option is width/height of the bounding box, not of the polygon itself. + Values <= 1, == 1 and >= 1 select polygons with aspect ratios less than, equal to and greater than the specified value. + The `_unique` case is a bit special and is meant to be used when more than one polygon share the same attribute + value (e.g. countries with islands). In that case, set the value of `_unique` to the name of the attribute that + is shared by the polygons (e.g. `_unique="NAME"`). By default (e.g. `_unique=true`), the attribute name is `Feature_ID` + which is the one used by GMT when creating unique IDs for polygons read from OGR formats (.shp, .geojson, etc). + If this attrib name is not found, we search for `CODE` which is the one assigned by GMT when extracting polygons from the internal GMT coasts database. If none of these is found, it is users responsibility to provide a valid attribute name. The uniqueness is determined by selecting the polygon with the largest area. @@ -210,7 +213,7 @@ Or `nothing` if the query results in an empty GMTdataset function getbyattrib(D::Vector{<:GMTdataset}, ind_::Bool; kw...)::Vector{Int} # This method does the work but it's not the one normally used by the public. # It returns the indices of the selected segments. - (isempty(D[1].attrib)) && (@warn("This datset does not have an `attrib` field and is hence unusable here."); return Int[]) + (isempty(D[1].attrib) && !is_in_kwargs(kw, [:_aspect])) && (@warn("This datset does not have an `attrib` field and is hence unusable here."); return Int[]) dounion = Int(1e9) # Just a big number invert = (find_in_kwargs(kw, [:invert :not :revert :reverse])[1] !== nothing) if ((_att = find_in_kwargs(kw, [:att :attrib])[1]) !== nothing) # For backward compat. @@ -276,6 +279,11 @@ function getbyattrib(D::Vector{<:GMTdataset}, ind_::Bool; kw...)::Vector{Int} for k = 1:numel(D) _tf[k] = areas_[k] >= area_ end _tf end + function clip_aspect(D, ratio, _tf) # Clip by BBox aspect ratio + fun = (ratio >= 1) ? (>=) : (ratio == 1) ? (==) : <= + for k = 1:numel(D) dd = diff(D[k].bbox); _tf[k] = fun(dd[1] / dd[3], ratio) end + _tf + end function clip_unique(D, areas_, _tf, name) # Clip by uniqueness by using the areas to select the largest by group. att_tbl, att_names = make_attrtbl(D, true) ((ind_name = findfirst(att_names .== name)) === nothing) && error("Attribute name $name not found in dataset.") @@ -300,6 +308,7 @@ function getbyattrib(D::Vector{<:GMTdataset}, ind_::Bool; kw...)::Vector{Int} (ind = findfirst(atts .== "_region")) !== nothing && (lims = parse.(Float64, split(vals[ind][2:end-1], ", "))) (ind = findfirst(atts .== "_nps")) !== nothing && (nps = parse.(Float64, vals[ind])) + (ind = findfirst(atts .== "_aspect")) !== nothing && (ratio = parse(Float64, vals[ind])) ((ind = findfirst(atts .== "_area")) !== nothing || (ind = findfirst(atts .== "_unique")) !== nothing) && (area = parse.(Float64, vals[ind]); areas = gmt_centroid_area(G_API[1], D, Int(isgeog(D)), ca=1); isgeog(D) && (areas .*= 1e-6)) # areas in km^2 if geographic coords @@ -312,6 +321,7 @@ function getbyattrib(D::Vector{<:GMTdataset}, ind_::Bool; kw...)::Vector{Int} if (special) if (atts[n] == "_region") tf = clip_region(D, lims, tf) elseif (atts[n] == "_area") tf = clip_area(D, areas, area, tf) + elseif (atts[n] == "_aspect") tf = clip_aspect(D, ratio, tf) elseif (atts[n] == "_unique") tf = clip_unique(D, areas, tf, attrib_name) else tf = clip_np(D, nps, tf) end @@ -332,7 +342,6 @@ function getbyattrib(D::Vector{<:GMTdataset}; indices=false, kw...)::Union{Nothi # This is the intended public method. It returns a subset of the selected segments ind = getbyattrib(D, true; kw...) isempty(ind) && return nothing - (indices == 1) && return ind o = D[ind] set_dsBB!(o, false) o[1].proj4, o[1].wkt, o[1].epsg = D[1].proj4, D[1].wkt, D[1].epsg @@ -346,6 +355,7 @@ end See `? getbyattrib` """ Base.:filter(D::Vector{<:GMTdataset}; kw...) = getbyattrib(D; kw...) +Base.:filter(D::Vector{<:GMTdataset}, index::Bool; kw...) = getbyattrib(D, index; kw...) # --------------------------------------------------------------------------------------------------- """ diff --git a/src/utils.jl b/src/utils.jl index 8de6a13d1..4da617560 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -111,6 +111,20 @@ function count_chars(str::AbstractString, c::Char=',')::Int count(i->(i == c), str) end +# ---------------------------------------------------------------------------------------------------------- +""" + ind = ind2bool(x::Vector{<:Integer} [, maxind::Int=0]) -> BitVector + +Convert a vector of indices `x` to a boolean vector `ind` where positions in `x` are true. + +If `maxind` is provided, the output boolean vector will have length `maxind`, otherwise its length will be `maximum(x)`. +""" +function ind2bool(indices::Vector{<:Integer}, maxind::Int=0)::BitVector + bool_vec = (maxind > 0) ? falses(maxind) : falses(maximum(indices)) + bool_vec[indices] .= true + return bool_vec +end + # ---------------------------------------------------------------------------------------------------------- """ ind = uniqueind(x) diff --git a/test/test_misc.jl b/test/test_misc.jl index 73cc29da9..5561a2322 100644 --- a/test/test_misc.jl +++ b/test/test_misc.jl @@ -55,6 +55,8 @@ fileparts("C:/a/b/c.d"); GMT.resetGMT() + @test ind2bool([1,4]) == [true, false, false, true] + I1 = mat2img(fill(UInt8(255), 3, 3)); grid2img(img2grid(I1)) I2 = mat2img(fill(UInt8(0), 3, 3)); I2[2,2] = 255; From bf266663842fd7986c6c5216a808bdfcebeab300 Mon Sep 17 00:00:00 2001 From: Joaquim Date: Mon, 3 Nov 2025 23:13:28 +0000 Subject: [PATCH 2/2] Add example file. --- src/spatial_funs.jl | 1 + test/assets/track_sample_data.txt | 281 ++++++++++++++++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 test/assets/track_sample_data.txt diff --git a/src/spatial_funs.jl b/src/spatial_funs.jl index a53988af6..4e24733bc 100644 --- a/src/spatial_funs.jl +++ b/src/spatial_funs.jl @@ -342,6 +342,7 @@ function getbyattrib(D::Vector{<:GMTdataset}; indices=false, kw...)::Union{Nothi # This is the intended public method. It returns a subset of the selected segments ind = getbyattrib(D, true; kw...) isempty(ind) && return nothing + (indices == 1) && return ind o = D[ind] set_dsBB!(o, false) o[1].proj4, o[1].wkt, o[1].epsg = D[1].proj4, D[1].wkt, D[1].epsg diff --git a/test/assets/track_sample_data.txt b/test/assets/track_sample_data.txt new file mode 100644 index 000000000..f47c92783 --- /dev/null +++ b/test/assets/track_sample_data.txt @@ -0,0 +1,281 @@ +> DLH2CH +1610729900,3003AD,DLH2CH,18825,317,-53.855,49.5493,10.016,-1536,0262,A +1610729905,3003AD,DLH2CH,18700,317,-53.855,49.5554,10.0032,-1536,0262,A +1610729910,3003AD,DLH2CH,18575,317,-53.855,49.5554,10.0032,-1536,0262,A +1610729915,3003AD,DLH2CH,18531,313,-52.998,49.5649,9.98304,-914,0262,M +1610729920,3003AD,DLH2CH,18425,316,-53.8934,49.5673,9.97812,-1536,0262,A +1610729925,3003AD,DLH2CH,18271,316,-52.998,49.5734,9.96521,-1108,0262,M +1610729931,3003AD,DLH2CH,18050,314,-53.9319,49.5792,9.95289,-1536,0262,A +1610729936,3003AD,DLH2CH,17925,314,-54.0802,49.5792,9.95289,-1536,0262,A +1610729941,3003AD,DLH2CH,17843,320,-58.0023,49.5878,9.93395,-1282,0262,M +1610729946,3003AD,DLH2CH,17775,312,-54.1187,49.5888,9.93272,-1536,0262,A +1610729949,3003AD,DLH2CH,17669,310,-52.998,49.5929,9.92348,-1535,0262,M +1610729954,3003AD,DLH2CH,17508,319,-53.9978,49.599,9.91086,-1372,0262,M +1610729960,3003AD,DLH2CH,17508,319,-53.9978,49.599,9.91086,-1372,0262,M +1610729965,3003AD,DLH2CH,17312,287,-55.9973,49.6056,9.89659,-1388,0262,M +1610729971,3003AD,DLH2CH,17075,312,-54.1187,49.6107,9.88636,-1536,0262,A +1610729977,3003AD,DLH2CH,16979,311,-53.9978,49.6169,9.87309,-1291,0262,M +1610729982,3003AD,DLH2CH,16800,311,-54.0143,49.621,9.86457,-1536,0262,A +1610729986,3003AD,DLH2CH,16675,311,-54.0143,49.621,9.86457,-1536,0262,A +1610729992,3003AD,DLH2CH,16525,311,-54.8273,49.6313,9.84256,-1536,0262,A +1610729997,3003AD,DLH2CH,16425,312,-55.849,49.632,9.84108,-1536,0262,A +1610730002,3003AD,DLH2CH,16300,312,-55.849,49.6392,9.82378,-1536,0262,A +1610730007,3003AD,DLH2CH,16150,312,-55.849,49.6432,9.81324,-1536,0262,A +1610730011,3003AD,DLH2CH,16050,313,-60.4797,49.6432,9.81324,-1536,0262,A +1610730018,3003AD,DLH2CH,15900,314,-63.111,49.6501,9.79342,-1536,0262,A +1610730023,3003AD,DLH2CH,15775,314,-63.7592,49.6532,9.78354,-1536,0262,A +1610730027,3003AD,DLH2CH,15675,315,-64.6545,49.6558,9.77501,-1536,0262,A +1610730033,3003AD,DLH2CH,15525,315,-64.0063,49.6595,9.7633,-1536,0262,A +1610730038,3003AD,DLH2CH,15425,314,-63.7592,49.6615,9.75712,-1536,0262,A +1610730043,3003AD,DLH2CH,15275,313,-63.8416,49.6662,9.74249,-1536,0262,A +1610730048,3003AD,DLH2CH,15150,313,-63.8416,49.6693,9.73266,-1536,0262,A +1610730053,3003AD,DLH2CH,15050,312,-63.9294,49.6718,9.72478,-1536,0262,A +1610730058,3003AD,DLH2CH,14900,310,-64.0118,49.6758,9.71236,-1536,0262,A +1610730063,3003AD,DLH2CH,14750,309,-64.0997,49.6781,9.70483,-1472,0262,A +1610730068,3003AD,DLH2CH,14625,308,-64.0173,49.6825,9.69113,-1536,0262,A +1610730073,3003AD,DLH2CH,14500,308,-64.1821,49.6855,9.68127,-1536,0262,A +1610730079,3003AD,DLH2CH,14375,307,-64.1052,49.6885,9.67187,-1472,0262,A +1610730084,3003AD,DLH2CH,14250,307,-64.1052,49.6916,9.66203,-1472,0262,A +1610730089,3003AD,DLH2CH,14125,307,-64.1052,49.695,9.65142,-1472,0262,A +1610730094,3003AD,DLH2CH,14000,307,-64.1052,49.6982,9.64115,-1472,0262,A +1610730099,3003AD,DLH2CH,13875,308,-64.1821,49.7013,9.6313,-1472,0262,A +1610730104,3003AD,DLH2CH,13750,308,-64.1821,49.7043,9.62165,-1472,0262,A +1610730109,3003AD,DLH2CH,13625,308,-64.1821,49.7076,9.61116,-1472,0262,A +1610730114,3003AD,DLH2CH,13500,308,-64.1821,49.7102,9.60287,-1472,0262,A +1610730119,3003AD,DLH2CH,13400,308,-64.1821,49.7134,9.5928,-1472,0262,A +1610730124,3003AD,DLH2CH,13250,307,-64.3524,49.716,9.58427,-1472,0262,A +1610730129,3003AD,DLH2CH,13125,306,-64.27,49.72,9.57169,-1472,0262,A +1610730135,3003AD,DLH2CH,13000,305,-64.1876,49.7232,9.56107,-1472,0262,A +1610730140,3003AD,DLH2CH,12875,305,-64.1876,49.7265,9.55068,-1472,0262,A +1610730145,3003AD,DLH2CH,12750,304,-64.2755,49.7295,9.54112,-1472,0262,A +1610730150,3003AD,DLH2CH,12625,304,-64.2755,49.7318,9.53368,-1472,0262,A +1610730155,3003AD,DLH2CH,12500,303,-64.1931,49.7343,9.52567,-1472,0262,A +1610730160,3003AD,DLH2CH,12375,303,-64.3634,49.7389,9.51097,-1472,0262,A +1610730165,3003AD,DLH2CH,12275,303,-64.3634,49.742,9.50115,-1472,0262,A +1610730171,3003AD,DLH2CH,12125,302,-64.281,49.7452,9.49085,-1472,0262,A +1610730176,3003AD,DLH2CH,12000,301,-64.3744,49.7482,9.48113,-1472,0262,A +1610730181,3003AD,DLH2CH,11875,301,-64.3744,49.7516,9.47029,-1472,0262,A +1610730186,3003AD,DLH2CH,11775,300,-64.5447,49.7541,9.4622,-1472,0262,A +1610730191,3003AD,DLH2CH,11625,299,-64.4623,49.7577,9.45062,-1344,0262,A +1610730196,3003AD,DLH2CH,11550,298,-64.3799,49.7604,9.44174,-960,0262,A +1610730201,3003AD,DLH2CH,11475,298,-64.3799,49.7635,9.43169,-1024,0262,A +1610730207,3003AD,DLH2CH,11375,297,-64.2975,49.7667,9.42144,-1024,0262,A +1610730212,3003AD,DLH2CH,11300,297,-64.4678,49.7697,9.41181,-1024,0262,A +1610730217,3003AD,DLH2CH,11200,296,-64.3854,49.7727,9.40237,-1024,0262,A +1610730222,3003AD,DLH2CH,11125,296,-64.3854,49.7756,9.39309,-1024,0262,A +1610730227,3003AD,DLH2CH,11050,296,-64.5612,49.7786,9.38321,-768,0262,A +1610730232,3003AD,DLH2CH,11000,296,-64.5612,49.7815,9.37372,-192,0262,A +1610730237,3003AD,DLH2CH,11000,296,-64.3854,49.7845,9.36421,-64,0262,A +1610730242,3003AD,DLH2CH,11000,297,-64.2151,49.7878,9.35345,-64,0262,A +1610730248,3003AD,DLH2CH,11000,297,-64.2975,49.7912,9.34283,-64,0262,A +1610730252,3003AD,DLH2CH,11000,297,-64.2975,49.7937,9.33462,-64,0262,A +1610730258,3003AD,DLH2CH,11000,299,-64.4623,49.7968,9.32472,0,0262,A +1610730263,3003AD,DLH2CH,11000,299,-64.4623,49.8001,9.31402,64,0262,A +1610730268,3003AD,DLH2CH,11000,300,-64.5447,49.8027,9.30549,0,0262,A +1610730273,3003AD,DLH2CH,11000,300,-64.5447,49.8058,9.29545,-64,0262,A +1610730278,3003AD,DLH2CH,11000,301,-64.3744,49.8091,9.2846,-64,0262,A +1610730283,3003AD,DLH2CH,11000,300,-64.5447,49.8124,9.27417,0,0262,A +1610730288,3003AD,DLH2CH,11000,300,-64.5447,49.8149,9.26603,64,0262,A +1610730293,3003AD,DLH2CH,11000,300,-64.5447,49.8185,9.25446,64,0262,A +1610730298,3003AD,DLH2CH,11000,299,-64.4623,49.8213,9.24514,-64,0262,A +1610730303,3003AD,DLH2CH,11000,299,-64.4623,49.8241,9.23624,0,0262,A +1610730309,3003AD,DLH2CH,11000,299,-64.6381,49.8271,9.22629,0,0262,A +1610730314,3003AD,DLH2CH,11000,299,-64.6381,49.8303,9.21587,0,0262,A +1610730319,3003AD,DLH2CH,11000,300,-67.6318,49.8332,9.2061,-64,0262,A +1610730324,3003AD,DLH2CH,11000,304,-77.4701,49.8354,9.19505,192,0262,A +1610730329,3003AD,DLH2CH,11000,306,-81.925,49.8364,9.18568,192,0262,A +1610730334,3003AD,DLH2CH,11000,312,-93.1201,49.8364,9.17269,0,0262,A +1610730340,3003AD,DLH2CH,11000,314,-96.3995,49.8358,9.16371,-192,0262,A +1610730345,3003AD,DLH2CH,11000,315,-97.8497,49.8347,9.14995,-64,0262,A +1610730350,3003AD,DLH2CH,11000,314,-98.2343,49.8337,9.13877,0,0262,A +1610730355,3003AD,DLH2CH,11000,314,-98.4155,49.8329,9.13123,0,0262,A +1610730360,3003AD,DLH2CH,11000,314,-98.4155,49.8315,9.11612,64,0262,A +1610730365,3003AD,DLH2CH,11000,314,-98.4155,49.8304,9.1041,0,0262,A +1610730370,3003AD,DLH2CH,11000,313,-98.443,49.8293,9.09349,0,0262,A +1610730375,3003AD,DLH2CH,11000,313,-98.443,49.8283,9.08287,0,0262,A +1610730380,3003AD,DLH2CH,11000,314,-98.6188,49.8271,9.07073,64,0262,A +1610730385,3003AD,DLH2CH,11000,314,-98.8,49.8261,9.06068,0,0262,A +1610730390,3003AD,DLH2CH,11000,314,-98.8,49.8249,9.04876,64,0262,A +1610730396,3003AD,DLH2CH,11000,315,-98.7726,49.8237,9.03633,-64,0262,A +1610730401,3003AD,DLH2CH,11000,315,-98.5913,49.8226,9.02519,0,0262,A +1610730406,3003AD,DLH2CH,11000,314,-98.6188,49.8216,9.01458,0,0262,A +1610730411,3003AD,DLH2CH,11000,314,-98.6188,49.8205,9.00374,0,0262,A +1610730416,3003AD,DLH2CH,11000,313,-98.443,49.8194,8.99282,0,0262,A +1610730421,3003AD,DLH2CH,11000,313,-98.443,49.8182,8.98046,0,0262,A +1610730426,3003AD,DLH2CH,11000,313,-98.443,49.8172,8.96937,0,0262,A +1610730431,3003AD,DLH2CH,11000,313,-98.443,49.8161,8.95787,0,0262,A +1610730436,3003AD,DLH2CH,11000,313,-98.443,49.815,8.94718,0,0262,A +1610730442,3003AD,DLH2CH,11000,313,-98.443,49.8139,8.93528,0,0262,A +1610730447,3003AD,DLH2CH,11000,313,-98.443,49.8129,8.92466,0,0262,A +1610730452,3003AD,DLH2CH,11000,313,-98.443,49.8119,8.91403,-64,0262,A +1610730457,3003AD,DLH2CH,11000,313,-98.443,49.8106,8.901,0,0262,A +1610730462,3003AD,DLH2CH,11000,313,-98.443,49.8095,8.89011,0,0262,A +1610730467,3003AD,DLH2CH,11000,314,-98.4155,49.8084,8.87807,64,0262,A +1610730472,3003AD,DLH2CH,11000,314,-98.4155,49.8073,8.86691,0,0262,A +1610730477,3003AD,DLH2CH,11000,314,-98.4155,49.8062,8.85572,0,0262,A +1610730482,3003AD,DLH2CH,11000,314,-98.4155,49.8052,8.84464,0,0262,A +1610730487,3003AD,DLH2CH,11000,314,-98.4155,49.8042,8.83409,0,0262,A +1610730492,3003AD,DLH2CH,11000,313,-98.443,49.8031,8.8226,64,0262,A +1610730498,3003AD,DLH2CH,11000,314,-98.6188,49.8019,8.81059,-64,0262,A +1610730503,3003AD,DLH2CH,11000,314,-98.4155,49.8009,8.79997,-64,0262,A +1610730508,3003AD,DLH2CH,11000,314,-98.4155,49.7998,8.78825,64,0262,A +1610730513,3003AD,DLH2CH,11000,314,-98.4155,49.7987,8.77735,0,0262,A +1610730518,3003AD,DLH2CH,11000,314,-98.2343,49.7975,8.76492,64,0262,A +1610730523,3003AD,DLH2CH,11000,314,-95.6744,49.7967,8.75469,64,0262,A +1610730528,3003AD,DLH2CH,11000,312,-92.7521,49.7962,8.74179,-64,0262,A +1610730533,3003AD,DLH2CH,11000,311,-90.1868,49.796,8.73049,0,0262,A +1610730538,3003AD,DLH2CH,11000,311,-89.2639,49.7961,8.71995,-64,0262,A +1610730543,3003AD,DLH2CH,11000,311,-88.7091,49.7963,8.7097,0,0262,A +1610730549,3003AD,DLH2CH,11000,310,-88.5223,49.7964,8.69734,0,0262,A +1610730554,3003AD,DLH2CH,11000,310,-88.3356,49.7966,8.68625,0,0262,A +1610730559,3003AD,DLH2CH,11000,310,-88.3356,49.7969,8.67421,0,0262,A +1610730564,3003AD,DLH2CH,11000,309,-88.3301,49.797,8.66366,0,0262,A +1610730569,3003AD,DLH2CH,11000,309,-88.5168,49.7973,8.65181,-64,0262,A +1610730574,3003AD,DLH2CH,10975,309,-88.5168,49.7975,8.64067,-960,0262,A +1610730579,3003AD,DLH2CH,10825,307,-88.5059,49.7977,8.62976,-1984,0262,A +1610730585,3003AD,DLH2CH,10650,307,-88.6926,49.7978,8.61791,-2048,0262,A +1610730590,3003AD,DLH2CH,10475,307,-88.6926,49.798,8.60656,-1984,0262,A +1610730595,3003AD,DLH2CH,10300,306,-88.8794,49.7981,8.59593,-1984,0262,A +1610730600,3003AD,DLH2CH,10125,305,-88.8739,49.7983,8.585,-1984,0262,A +1610730605,3003AD,DLH2CH,9950,305,-88.8739,49.7984,8.57379,-1984,0262,A +1610730610,3003AD,DLH2CH,9800,304,-88.4949,49.7986,8.56251,-1984,0262,A +1610730615,3003AD,DLH2CH,9625,303,-88.1104,49.7988,8.5517,-1984,0262,A +1610730620,3003AD,DLH2CH,9450,302,-88.1049,49.7991,8.54001,-1984,0262,A +1610730626,3003AD,DLH2CH,9275,301,-88.0994,49.7993,8.52922,-2048,0262,A +1610730631,3003AD,DLH2CH,9100,300,-87.9016,49.7996,8.51715,-1984,0262,A +1610730636,3003AD,DLH2CH,8950,300,-87.7094,49.7999,8.50646,-1984,0262,A +1610730641,3003AD,DLH2CH,8775,299,-87.7039,49.8001,8.49533,-2048,0262,A +1610730646,3003AD,DLH2CH,8600,298,-87.6929,49.8004,8.48493,-1984,0262,A +1610730651,3003AD,DLH2CH,8450,297,-87.4951,49.8007,8.47484,-2048,0262,A +1610730656,3003AD,DLH2CH,8275,297,-87.4951,49.801,8.46385,-1984,0262,A +1610730661,3003AD,DLH2CH,8100,296,-87.4841,49.8013,8.45311,-1984,0262,A +1610730666,3003AD,DLH2CH,7925,295,-87.4786,49.8016,8.44181,-2048,0262,A +1610730672,3003AD,DLH2CH,7750,295,-87.2809,49.802,8.43089,-1984,0262,A +1610730677,3003AD,DLH2CH,7575,294,-87.2754,49.8023,8.42037,-1984,0262,A +1610730682,3003AD,DLH2CH,7425,294,-87.4677,49.8026,8.40989,-1984,0262,A +1610730687,3003AD,DLH2CH,7250,294,-87.6654,49.8028,8.39897,-1984,0262,A +1610730692,3003AD,DLH2CH,7100,294,-87.8577,49.8031,8.38842,-1920,0262,A +1610730697,3003AD,DLH2CH,6925,295,-87.6709,49.8034,8.37751,-1920,0262,A +1610730702,3003AD,DLH2CH,6750,295,-87.2809,49.8037,8.36659,-1984,0262,A +1610730707,3003AD,DLH2CH,6575,295,-86.8964,49.8041,8.35607,-1664,0262,A +1610730712,3003AD,DLH2CH,6475,293,-86.8744,49.8044,8.34549,-1536,0262,A +1610730717,3003AD,DLH2CH,6325,292,-86.8634,49.8048,8.33465,-1600,0262,A +1610730722,3003AD,DLH2CH,6225,291,-86.8524,49.8052,8.32511,-1280,0262,A +1610730728,3003AD,DLH2CH,6100,289,-86.6327,49.8056,8.31353,-1472,0262,A +1610730733,3003AD,DLH2CH,6000,288,-84.0125,49.8061,8.30366,-896,0262,A +1610730738,3003AD,DLH2CH,5925,283,-79.6069,49.8071,8.29319,-640,0262,A +1610730743,3003AD,DLH2CH,5875,278,-75.4156,49.8086,8.28333,-640,0262,A +1610730748,3003AD,DLH2CH,5850,273,-73.158,49.8104,8.27357,-256,0262,A +1610730753,3003AD,DLH2CH,5825,269,-72.2406,49.8124,8.2641,-448,0262,A +1610730758,3003AD,DLH2CH,5800,265,-71.9769,49.8142,8.25504,-576,0262,A +1610730763,3003AD,DLH2CH,5750,262,-71.9824,49.8161,8.24611,-512,0262,A +1610730768,3003AD,DLH2CH,5700,260,-72.0538,49.8181,8.23678,-768,0262,A +1610730773,3003AD,DLH2CH,5625,258,-71.9165,49.8199,8.22809,-896,0262,A +1610730778,3003AD,DLH2CH,5550,257,-72.8339,49.8216,8.2197,-1024,0262,A +1610730783,3003AD,DLH2CH,5450,256,-72.9822,49.8235,8.21042,-1088,0262,A +1610730788,3003AD,DLH2CH,5375,255,-72.2021,49.8252,8.2018,-1024,0262,A +1610730794,3003AD,DLH2CH,5275,254,-72.1362,49.827,8.19313,-1024,0262,A +1610730799,3003AD,DLH2CH,5200,253,-72.0648,49.8289,8.18415,-896,0262,A +1610730804,3003AD,DLH2CH,5125,252,-71.7078,49.8308,8.17524,-640,0262,A +1610730809,3003AD,DLH2CH,5075,250,-71.7847,49.8326,8.16675,-384,0262,A +1610730814,3003AD,DLH2CH,5075,246,-72.0044,49.8344,8.158,-320,0262,A +1610730819,3003AD,DLH2CH,5050,242,-69.917,49.8363,8.14978,-256,0262,A +1610730824,3003AD,DLH2CH,5025,237,-60.7324,49.8385,8.14221,-320,0262,A +1610730829,3003AD,DLH2CH,5000,232,-49.7186,49.8416,8.13545,-192,0262,A +1610730834,3003AD,DLH2CH,5000,227,-37.6776,49.8458,8.12936,-256,0262,A +1610730839,3003AD,DLH2CH,4975,223,-25.7629,49.8504,8.12513,-448,0262,A +1610730844,3003AD,DLH2CH,4925,220,-15.8038,49.8552,8.12251,-448,0262,A +1610730849,3003AD,DLH2CH,4875,219,-12.3871,49.8603,8.12063,-640,0262,A +1610730855,3003AD,DLH2CH,4825,218,-10.5853,49.8653,8.11912,-704,0262,A +1610730860,3003AD,DLH2CH,4750,217,-10.069,49.8704,8.11771,-768,0262,A +1610730865,3003AD,DLH2CH,4700,217,-9.81079,49.8756,8.1163,-704,0262,A +1610730870,3003AD,DLH2CH,4650,216,-9.85474,49.8805,8.11499,-512,0262,A +1610730875,3003AD,DLH2CH,4625,214,-9.68445,49.8855,8.11363,0,0262,A +1610730880,3003AD,DLH2CH,4625,214,-5.36682,49.8903,8.11261,-64,0262,A +1610730885,3003AD,DLH2CH,4625,215,7.48718,49.895,8.11275,128,0262,A +1610730890,3003AD,DLH2CH,4625,216,18.9404,49.9004,8.11478,64,0262,A +1610730895,3003AD,DLH2CH,4625,217,31.4154,49.9046,8.11786,-64,0262,A +1610730900,3003AD,DLH2CH,4625,219,44.0717,49.9088,8.12302,64,0262,A +1610730906,3003AD,DLH2CH,4625,220,49.0594,49.9126,8.12929,-128,0262,A +1610730911,3003AD,DLH2CH,4625,220,51.46,49.9158,8.13545,-64,0262,A +1610730916,3003AD,DLH2CH,4625,220,52.3993,49.9189,8.14154,-128,0262,A +1610730921,3003AD,DLH2CH,4625,219,52.9706,49.9221,8.14807,128,0262,A +1610730926,3003AD,DLH2CH,4625,220,53.1299,49.925,8.15408,0,0262,A +1610730931,3003AD,DLH2CH,4625,219,53.3386,49.9282,8.16069,-128,0262,A +1610730936,3003AD,DLH2CH,4625,217,53.4485,49.9312,8.16696,0,0262,A +1610730941,3003AD,DLH2CH,4625,213,53.399,49.9343,8.17339,-64,0262,A +1610730946,3003AD,DLH2CH,4600,209,53.3496,49.9373,8.17968,-64,0262,A +1610730951,3003AD,DLH2CH,4600,207,53.2397,49.9402,8.18571,64,0262,A +1610730956,3003AD,DLH2CH,4625,207,53.465,49.943,8.19161,192,0262,A +1610730961,3003AD,DLH2CH,4625,205,55.9204,49.9459,8.19782,-192,0262,A +1610730967,3003AD,DLH2CH,4600,205,60.8093,49.9483,8.20419,-384,0262,A +1610730972,3003AD,DLH2CH,4550,206,66.2915,49.9503,8.21076,-640,0262,A +1610730977,3003AD,DLH2CH,4475,205,69.7083,49.9521,8.21762,-832,0262,A +1610730982,3003AD,DLH2CH,4400,204,71.3892,49.9538,8.2249,-832,0262,A +1610730987,3003AD,DLH2CH,4325,202,71.8341,49.9552,8.23143,-896,0262,A +1610730992,3003AD,DLH2CH,4250,200,71.3837,49.9568,8.23908,-1152,0262,A +1610730997,3003AD,DLH2CH,4150,199,70.6531,49.9582,8.24561,-1088,0262,A +1610731002,3003AD,DLH2CH,4050,198,69.6478,49.9598,8.25225,-1152,0262,A +1610731007,3003AD,DLH2CH,3950,197,69.5435,49.9615,8.25926,-1088,0262,A +1610731012,3003AD,DLH2CH,3875,197,69.5435,49.963,8.26555,-1152,0262,A +1610731017,3003AD,DLH2CH,3750,195,69.6149,49.9647,8.27263,-1280,0262,A +1610731022,3003AD,DLH2CH,3650,190,69.6533,49.9662,8.27887,-1280,0262,A +1610731027,3003AD,DLH2CH,3550,186,69.516,49.9677,8.28514,-1216,0262,A +1610731032,3003AD,DLH2CH,3450,182,69.7742,49.9693,8.29178,-1152,0262,A +1610731037,3003AD,DLH2CH,3350,179,69.7412,49.9708,8.29786,-1152,0262,A +1610731042,3003AD,DLH2CH,3275,176,69.7083,49.9722,8.30381,-1088,0262,A +1610731048,3003AD,DLH2CH,3175,172,69.5599,49.9736,8.30964,-1088,0262,A +1610731053,3003AD,DLH2CH,3100,169,69.5215,49.975,8.31546,-1024,0262,A +1610731058,3003AD,DLH2CH,3025,166,69.6039,49.9763,8.32099,-960,0262,A +1610731063,3003AD,DLH2CH,2950,165,69.3622,49.9777,8.32677,-960,0262,A +1610731068,3003AD,DLH2CH,2850,165,69.3622,49.9792,8.33276,-960,0262,A +1610731073,3003AD,DLH2CH,2775,165,69.3622,49.9805,8.3381,-960,0262,A +1610731078,3003AD,DLH2CH,2700,165,69.3622,49.9819,8.34397,-960,0262,A +1610731083,3003AD,DLH2CH,2625,163,69.5654,49.9831,8.34909,-960,0262,A +1610731089,3003AD,DLH2CH,2550,163,69.5654,49.9845,8.35496,-896,0262,A +1610731094,3003AD,DLH2CH,2475,163,69.5654,49.9859,8.36067,-896,0262,A +1610731099,3003AD,DLH2CH,2400,162,69.4446,49.9872,8.36616,-1024,0262,A +1610731104,3003AD,DLH2CH,2300,163,69.5654,49.9885,8.37158,-1024,0262,A +1610731109,3003AD,DLH2CH,2225,163,69.5654,49.99,8.37752,-960,0262,A +1610731114,3003AD,DLH2CH,2150,164,69.2413,49.9912,8.38279,-960,0262,A +1610731119,3003AD,DLH2CH,2050,164,69.2413,49.9927,8.38878,-960,0262,A +1610731124,3003AD,DLH2CH,1975,163,69.5654,49.994,8.39406,-1024,0262,A +1610731129,3003AD,DLH2CH,1900,164,69.6863,49.9954,8.39984,-896,0262,A +1610731134,3003AD,DLH2CH,1825,164,69.6863,49.9966,8.40512,-960,0262,A +1610731139,3003AD,DLH2CH,1750,164,69.6863,49.998,8.41083,-960,0262,A +1610731144,3003AD,DLH2CH,1675,164,69.6863,49.9993,8.41634,-960,0262,A +1610731149,3003AD,DLH2CH,1575,161,69.6533,50.0007,8.42206,-1088,0262,A +1610731155,3003AD,DLH2CH,1500,157,69.4885,50.002,8.42763,-896,0262,A +1610731160,3003AD,DLH2CH,1425,152,69.5325,50.0033,8.4328,-960,0262,A +1610731165,3003AD,DLH2CH,1350,147,69.7192,50.0045,8.4378,-896,0262,A +1610731170,3003AD,DLH2CH,1275,142,69.7742,50.0056,8.44263,-896,0262,A +1610731175,3003AD,DLH2CH,1200,139,69.7357,50.0066,8.44682,-768,0262,A +1610731180,3003AD,DLH2CH,1125,138,69.2029,50.0079,8.4522,-768,0262,A +1610731185,3003AD,DLH2CH,1075,138,69.5874,50.0091,8.45716,-768,0262,A +1610731190,3003AD,DLH2CH,1000,137,69.4446,50.0102,8.46177,-832,0262,A +1610731195,3003AD,DLH2CH,950,135,68.7469,50.0113,8.46615,-832,0262,A +1610731200,3003AD,DLH2CH,875,136,68.3569,50.0125,8.47068,-768,0262,A +1610731205,3003AD,DLH2CH,800,135,69.1479,50.0137,8.47574,-768,0262,A +1610731211,3003AD,DLH2CH,750,136,69.8401,50.0148,8.48043,-768,0262,A +1610731216,3003AD,DLH2CH,675,136,70.2301,50.0157,8.48427,-768,0262,A +1610731221,3003AD,DLH2CH,625,135,70.0873,50.0168,8.48909,-832,0262,A +1610731226,3003AD,DLH2CH,550,135,70.4883,50.0181,8.49429,-832,0262,A +1610731231,3003AD,DLH2CH,500,134,69.9445,50.019,8.49836,-704,0262,A +1610731236,3003AD,DLH2CH,425,134,69.9445,50.0201,8.50306,-768,0262,A +1610731241,3003AD,DLH2CH,350,133,69.7961,50.0213,8.50812,-768,0262,A +1610731246,3003AD,DLH2CH,300,133,69.7961,50.0224,8.51238,-768,0262,A +1610731251,3003AD,DLH2CH,225,134,69.3951,50.0234,8.51693,-768,0262,A +1610731256,3003AD,DLH2CH,175,134,69.3951,50.0246,8.5217,-768,0262,A +1610731262,3003AD,DLH2CH,100,134,69.3951,50.0257,8.52647,-768,0262,A +1610731266,3003AD,DLH2CH,50,134,69.3951,50.0264,8.5291,-768,0262,A +1610731266,3003AD,DLH2CH,50,134,69.3951,50.0264,8.5291,-768,0262,A +1610731266,3003AD,DLH2CH,76,133,65.0006,50.0262,8.52863,-883,0262,M +1610731266,3003AD,DLH2CH,76,133,65.0006,50.0262,8.52863,-883,0262,M +1610731266,3003AD,DLH2CH,76,133,65.0006,50.0262,8.52863,-883,0262,M +1610731266,3003AD,DLH2CH,76,133,65.0006,50.0262,8.52863,-883,0262,M +1610731266,3003AD,DLH2CH,76,133,65.0006,50.0262,8.52863,-883,0262,M +1610731266,3003AD,DLH2CH,76,133,65.0006,50.0262,8.52863,-883,0262,M +1610731266,3003AD,DLH2CH,76,133,65.0006,50.0262,8.52863,-883,0262,M +1610731266,3003AD,DLH2CH,76,133,65.0006,50.0262,8.52863,-883,0262,M +1610731266,3003AD,DLH2CH,76,133,65.0006,50.0262,8.52863,-883,0262,M +1610731266,3003AD,DLH2CH,76,133,65.0006,50.0262,8.52863,-883,0262,M \ No newline at end of file