Skip to content

Commit

Permalink
Migrated and improved from previous iteration
Browse files Browse the repository at this point in the history
Tests to come
  • Loading branch information
kapple19 committed Jul 23, 2024
1 parent 2cc56b8 commit 1469127
Show file tree
Hide file tree
Showing 39 changed files with 1,230 additions and 18 deletions.
8 changes: 8 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,13 @@ uuid = "03019ade-4524-4ecd-af79-46d4f04a1b56"
authors = ["Aaron Kaw <[email protected]> and contributors"]
version = "1.0.0-DEV"

[deps]
IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253"
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"

[compat]
IntervalArithmetic = "0.22.14"
NaNMath = "1.0.2"
Symbolics = "5.34.0"
julia = "1.10"
34 changes: 31 additions & 3 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,35 @@
using OceanSonar
using Documenter

sidebar_title(path::String) = if isdir(path)
basename(path)[4:end]
elseif isfile(path)
basename(path)[4:end-3]
else
error("What even is $path?")
end |> OceanSonar.titlecase

src_dir = joinpath(@__DIR__, "src")

function populate_pages(current_path)
if isfile(current_path)
current_path[length(src_dir)+2 : end]
elseif isdir(current_path)
[
sidebar_title(subpath) => populate_pages(joinpath(current_path, subpath))
for subpath in readdir(current_path, join = true, sort = true)
if !contains(subpath, "index.md")
]
else
error("What even is $current_path?")
end
end

pages=[
"Home" => "index.md",
populate_pages(joinpath(@__DIR__, "src"))...
]

DocMeta.setdocmeta!(OceanSonar, :DocTestSetup, :(using OceanSonar); recursive=true)

makedocs(;
Expand All @@ -10,11 +39,10 @@ makedocs(;
format=Documenter.HTML(;
canonical="https://kapple19.github.io/OceanSonar.jl",
edit_link="main",
collapselevel = 1,
assets=String[],
),
pages=[
"Home" => "index.md",
],
pages=pages,
)

deploydocs(;
Expand Down
18 changes: 18 additions & 0 deletions docs/src/01_new_users_introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# New Users Introduction

"New" could apply to users as some combination of:

```@contents
Pages = ["01_new_users_introduction.md"]
Depth = 2:2
```

of which this page addresses all three, linked in the above list.

## New to the Field of Ocean Sonar

## New to Julia Programming

## New to Scientific Machine Learning

## New to this Package
1 change: 1 addition & 0 deletions docs/src/04_ocean_acoustics/00_introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Ocean Acoustics
5 changes: 5 additions & 0 deletions docs/src/04_ocean_acoustics/01_tracing/01_ray_tracing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ray Tracing

## Literature Fidelity

## References
1 change: 1 addition & 0 deletions docs/src/04_ocean_acoustics/01_tracing/02_beam_tracing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Beam Tracing
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Pressure Field
28 changes: 28 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,31 @@
## Citing

See [`citation.bib`](CITATION.bib) for the relevant reference(s).

## Roadmap

Usage Features:

* Ocean sonar related environmental metrics (ocean sound speed, life noise, metric conversions, etc).
* Acoustic propagation models with modular components (beam types, coherence, etc).
* The sonar equation and calculation of its many terms.
* Detection performance metrics applied to the signal-to-noise ratio.
* Acausal modelling of the sonar equation and detection algorithms.
* Easy and interactive visualisations of all of the above.
* Graphical user interface for streamlining usage and accessibility.

Implementation Features:

* Model name-based dispatch and handling avoids boilerplate and enables user extensibility.
* Modularisation of model components enables easy comparisons and the design of an algorithm for default best choices based on inputs ala `solve` from `DifferentialEquations.jl`.
* Interpolation methods built into the implementations to further enable user extensibility.
* Functor type system keeps external functions safe from this package's implementation design (e.g. `listmodels` will only work on `OceanSonar.AbstractModellingType` types and objects).
* Acausal modelling enabling the single implementation to flexibly apply for declaring different components of the sonar equation as the unknown to compute for.

## Credits

TODO.

## References

TODO.
35 changes: 35 additions & 0 deletions src/01_preliminary/01_general/01_auxiliary_functions.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export uniquesort!
export efficient_sampling
export output_extrema

const uniquesort! = unique! sort!

const cossin = reverse sincos
const nan_cossin = reverse nan_sincos
const cossind = reverse sincosd
const magang(z::Number) = (abs(z), angle(z))

function extract_all_underscored_alphanumeric_bodies(text::AbstractString)
idxs = findall(r"([a-z]|[A-Z]|[0-9]|_)+", text)
return getindex.(text, idxs)
end

function extract_first_underscored_alphanumeric_bodies(text::AbstractString)
return extract_all_underscored_alphanumeric_bodies(text)[1]
end

function extract_last_underscored_alphanumeric_bodies(text::AbstractString)
return extract_all_underscored_alphanumeric_bodies(text)[end]
end

function efficient_sampling(f::Function, x1::Real, xN::Real, N::Integer)
# WIP, to be replaced
range(x1, xN, N)
end

# function efficient_sampling(f::Function, x1::Real, xN::Real, θmin::Real)
# # WIP
# end

output_extrema(f::Function, ntv::Interval) = (:lo, :hi) .|> bnd -> getproperty(f(ntv).bareinterval, bnd)
output_extrema(f::Function, x_lo::Real, x_hi::Real) = output_extrema(f, interval(x_lo, x_hi))
19 changes: 19 additions & 0 deletions src/01_preliminary/01_general/02_flexible_math_functions.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export ocnson_sqrt

num_fcn(fcn::Function, args::Num...) = Term(fcn, [args...]) |> wrap

for op in (:sqrt, :cos, :sin, :cossin)
op_string = String(op)
ocnson_op = Symbol("ocnson_" * op_string)
nan_op = Symbol("nan_" * op_string)
eval(
quote
$ocnson_op(x::Real) = $nan_op(x)
$ocnson_op(x::Num) = $op(x)
$ocnson_op(x::Interval) = $op(x)
end
)
end

ocnson_hypot(args::Number...) = nan_hypot(args...)
ocnson_hypot(args::Union{<:Num, <:Interval}...) = hypot(args...)
118 changes: 118 additions & 0 deletions src/01_preliminary/01_general/02_string_cases.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
public stringcase
public titlecase
export snakecase
export kebabcase
export pascalcase

"""
Storage of all words that need to keep their case as is stored here,
e.g. acronyms, articles, prepositions, coordinating conjunctions, etc.
"""
keepcases = [
"NSW"
"the"
"a"
"to"
] |> uniquesort!

delims = (
snake = "_",
space = " ",
kebab = "-"
)

_stringcasesep(::Val{C}) where C = delims[C]
_stringcasesep(::Val{:camel}) = ""
_stringcasesep(::Val{:Snake}) = _stringcasesep(:snake |> Val)
_stringcasesep(::Val{:Space}) = _stringcasesep(:space |> Val)
_stringcasesep(::Val{:Kebab}) = _stringcasesep(:kebab |> Val)
_stringcasesep(::Val{:Camel}) = _stringcasesep(:camel |> Val)
_stringcasesep(::Val{:pascal}) = _stringcasesep(:Camel |> Val)
_stringcasesep(::Val{:Pascal}) = _stringcasesep(:Camel |> Val)
_stringcasesep(::Val{:title}) = _stringcasesep(:Space |> Val)

function _firstcap(::Val{C}, char::Char) where C
return if (C in (:pascal, :title)) || isuppercase(String(C)[1])
uppercase(char)
else
lowercase(char)
end
end

function _sepcap(::Val{C}, char::Char) where C
return if (C in (:pascal, :title, :camel)) || isuppercase(String(C)[1])
uppercase(char)
else
lowercase(char)
end
end

function _wordseparation(case::Val{C}, text::AbstractString) where C
text = text[1:end-1] * _sepcap(case, text[end])
end

function _caseconversions(::Val{C}, text::AbstractString; keepcases) where C
boolkeepcase = lowercase(text) .== lowercase.(keepcases)
iskeepcase = any(boolkeepcase)
keepcase = if iskeepcase
keepcases[boolkeepcase |> findall |> only]
else
""
end

iscamel = C in (:pascal, :Pascal, :camel, :Camel)
return if iskeepcase && (iscamel ? isuppercase(keepcase[1]) : true)
keepcase
elseif (C in (:pascal, :title, :camel)) || isuppercase(String(C)[1])
uppercase(text[1]) * text[2:end]
else
text
end
end

function stringcase(case::Val{C}, text::AbstractString; keepcases = keepcases) where C
tempsep = delims.snake

# Convert camel word separations to snake separations
camel_regexes = [
"[a-z][A-Z]"
"[0-9][A-Z]"
"[a-z][0-9]"
"[A-Z][0-9]"
] .|> Regex
for camel_regex = camel_regexes
text = replace(text,
[
text[idxs] => text[idxs[begin]] * tempsep * text[idxs[end]]
for idxs in findall(camel_regex, text, overlap = true)
]...
)
end

text = lowercase(text)

# Convert any delimiters to snake delimiter
text = replace(text, [sep => tempsep for sep in values(delims)]...)

texts = split(text, tempsep)

texts = [_caseconversions(case, text, keepcases = keepcases) for text in texts]

text = join(texts, _stringcasesep(case))

text = _firstcap(case, text[1]) * text[2:end]

return text
end

stringcase(::Val{:Pascal}, text::AbstractString; keepcases = keepcases) = stringcase(:Camel |> Val, text; keepcases = keepcases)
stringcase(::Val{:pascal}, text::AbstractString; keepcases = keepcases) = stringcase(:Camel |> Val, text; keepcases = keepcases)
stringcase(::Val{:title}, text::AbstractString; keepcases = keepcases) = stringcase(:Space |> Val, text; keepcases = keepcases)

stringcase(case::Symbol, text::AbstractString; keepcases = keepcases) = stringcase(case |> Val, text; keepcases = keepcases)
stringcase(case::AbstractString, text::AbstractString; keepcases = keepcases) = stringcase(case |> Symbol, text; keepcases = keepcases)

titlecase(text::AbstractString; keepcases = keepcases) = stringcase(:Space |> Val, text; keepcases = keepcases)
snakecase(text::AbstractString; keepcases = keepcases) = stringcase(:snake |> Val, text; keepcases = keepcases)
kebabcase(text::AbstractString; keepcases = keepcases) = stringcase(:Kebab |> Val, text; keepcases = keepcases)
pascalcase(text::AbstractString; keepcases = keepcases) = stringcase(:Pascal |> Val, text; keepcases = keepcases)
7 changes: 7 additions & 0 deletions src/01_preliminary/02_modelling/01_model_naming.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export ModelName

struct ModelName{m} end

ModelName(m::Symbol) = ModelName(m |> String)

ModelName(m::AbstractString) = ModelName{m |> snakecase |> Symbol}()
32 changes: 32 additions & 0 deletions src/01_preliminary/02_modelling/02_model_types.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
abstract type AbstractModellingType <: Function end
abstract type ModellingFunction <: AbstractModellingType end
abstract type ModellingFunctor <: AbstractModellingType end
abstract type ModellingFunctor2D <: ModellingFunctor end
abstract type ModellingFunctor3D <: ModellingFunctor end

function (::Type{Fun})(
model::Union{Symbol, <:AbstractString}, args::Real...; kw...
) where {Fun <: ModellingFunction}
Fun(model |> ModelName, args...; kw...)
end

function (::Type{Fct})(model::ModelName; pars...) where {Fct <: ModellingFunctor}
Fct(model, pars)
end

macro implement_modelling_functor(super_type, name)
@eval begin
struct $name <: $super_type
model::ModelName
pars::Pairs
end

function $name(model::Union{Symbol, <:AbstractString}, args...; pars...)
$name(model |> ModelName, args...; pars...)
end

function (fct::$name)(args::Real...)
$name(fct.model, args...; fct.pars...)
end
end
end
8 changes: 8 additions & 0 deletions src/01_preliminary/02_modelling/03_model_parsing.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
listmodels(modelling_function::AbstractModellingType) = [
modelpretty(modelling_function, type())
for type in [
collect(m.sig.types)[2] for m in methods(modelling_function)
] if type <: ModelName
]

listmodels(fct::Fct) where {Fct<:ModellingFunctor} = String(Fct)
43 changes: 43 additions & 0 deletions src/02_oceanography/volume/celerity.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export ocean_celerity

"""
```
ocean_celerity(model, ...)
```
"""
struct ocean_celerity <: ModellingFunction end

"""
```
ocean_celerity("Jensen", T::Real, S::Real, z::Real)::Real
```
Equation 1.1 of Jensen, et al (2011).
"""
function ocean_celerity(::ModelName{:jensen}, T::Real, S::Real, z::Real)
c = 1449.2 + 4.6T - 0.055T^2 + 0.00029T^3 + (1.34 - 0.01T) * (S - 35) + 0.016z
end

"""
```
ocean_celerity("Del Grosso", T::Real, S::Real, P::Real)
```
"""
function ocean_celerity(::ModelName{:del_grosso}, T::Real, S::Real, P::Real)
= T^2
= T^3
= P^2
= P^3

V_T = 4.5721T 4.4532e2 2.6045e4+ 7.9851e6T^4
V_P = 1.60272e1P + 1.0268e5+ 3.5216e9 3.3603e12P^4
V_S = 1.39799(S 35) + 1.69202e3(S 35)^2
V_STP = (S 35) * (
1.1244e2T + 7.7711e7+ 7.7016e5P 1.2943e7+ 3.1580e8P*T + 1.5790e9P*
) + P * (
1.8607e4T + 7.4812e6+ 4.5283e8
) +* (
2.5294e7T + 1.8563e9
) +* (1.9646e10T)

V = 1449.14 + V_T + V_P + V_S + V_STP
end
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Loading

0 comments on commit 1469127

Please sign in to comment.