Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Now eles() renamed to eles_search(). #169

Merged
merged 1 commit into from
Dec 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/AcceleratorLattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ export show_lat, show_branch, show_beamline, bookkeeper!, set_param!
export Branch, Lattice, BeamLineEle, superimpose!, multipole_type
export BeamLineItem, BeamLine, Ele, propagate_ele_geometry, ele_floor_transform
export split!, construct_ele_type, ele_at_s, toggle_integrated!
export eles, next_ele, ele_at_offset, ele_param_value_str, strip_AL, ele_param_group_symbols
export eles_search, eles_substitute_lords!, eles_sort!
export next_ele, ele_at_offset, ele_param_value_str, strip_AL, ele_param_group_symbols
export branch, matches_branch, create_ele_vars, eval_str, Vertex1, LatticeGlobal
export EleParameterGroup, AlignmentGroup, FloorPositionGroup, BMultipole, BMultipoleGroup, BeamBeamGroup
export EMultipole, EMultipoleGroup, BendGroup, ApertureGroup, DescriptionGroup, RFGroup, SolenoidGroup
Expand Down
6 changes: 3 additions & 3 deletions src/accessor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -208,15 +208,15 @@ end

If `lat[name]` matches a branch name, return the branch. No wild cards permitted here.
If `lat[name]` does not match a branch name, return list of matching lattice elements.
In this case the returned vector is equivalent to `eles(lat, name)`.
In this case the returned vector is equivalent to `eles_search(lat, name)`.
""" Base.getindex(lat::Lattice, name::AbstractString)

function Base.getindex(lat::Lattice, name::AbstractString)
for br in lat.branch
if br.name == name; return br; end
end

return eles(lat, name)
return eles_search(lat, name)
end

#---------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -246,7 +246,7 @@ Match `branch[name]` to all lattice elements in `branch.ele[]` array.
""" Base.getindex(branch::Branch, name::AbstractString)

function Base.getindex(branch::Branch, name::AbstractString)
return eles(branch, name)
return eles_search(branch, name)

error(f"No element with name: {name}")
end
Expand Down
1 change: 1 addition & 0 deletions src/enum.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ enum("ExactMultipoles", ["OFF", "HORIZONTALLY_PURE", "VERTICALLY_PURE"], "Bend m
enum("TrackingMethod", ["RUNGE_KUTTA", "TIME_RUNGE_KUTTA", "STANDARD"], "Particle tracking method.")
enum("ParticleState", ["PREBORN", "ALIVE", "LOST", "LOST_NEG_X", "LOST_POS_X",
"LOST_NEG_Y", "LOST_POS_Y", "LOST_PZ", "LOST_Z"], "Particle state.")
enum("Order", ["BY_S", "BY_INDEX", "NONE"], "Ordering of vectors of elements selected from some lattice.")

# Useful abbreviations

Expand Down
144 changes: 85 additions & 59 deletions src/find.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,24 +82,22 @@ end

"""
Internal: eles_atomic(where_search, who, branch_id, ele_type, param_id,
match_str, offset, include_lords, wrap) -> ele_vector::Ele[]
match_str, offset, wrap) -> ele_vector::Ele[]

Internal function. Called by the `eles_group` function which in turn is called by `eles`.
Internal function. Called by the `eles_search_a_group` function which in turn is called by `eles`.
""" eles_atomic

function eles_atomic(where_search, who, branch_id, ele_type, param_id, match_str, offset, include_lords, wrap)
function eles_atomic(where_search, who, branch_id, ele_type, param_id, match_str, offset, wrap)

eles = Ele[]
ele_list = Ele[]
ix_ele = integer(match_str, -1)
julia_regex = (typeof(who) == Regex)
branches_searched = []

if typeof(where_search) == Lattice
lat = where_search
branch_vec = lat.branch
else
branch_vec = collect(where_search)
lat = lattice(branch_vec[1])
end

# Search branches
Expand All @@ -109,52 +107,36 @@ function eles_atomic(where_search, who, branch_id, ele_type, param_id, match_str
push!(branches_searched, branch)

if ix_ele != -1 && param_id == :name
push!(eles, ele_at_offset(branch.ele[ix_ele], offset, wrap))
push!(ele_list, ele_at_offset(branch.ele[ix_ele], offset, wrap))
else
for ele in branch.ele
if !isnothing(ele_type) && Symbol(typeof(ele)) != ele_type; continue; end
if !str_match(match_str, getproperty(ele, param_id)); continue; end
push!(eles, ele_at_offset(ele, offset, wrap))
push!(ele_list, ele_at_offset(ele, offset, wrap))
end
end
end

# Search lord branches

if include_lords && !isnothing(lat) && !(ix_ele != -1 && param_id == :name)
lord_branches = [lat["super"], lat["multipass"]]
for lbranch in lord_branches
if lbranch ∉ branches_searched
for lord in lbranch.ele
for slave in lord.slaves
if slave.branch in branches_searched
push!(eles, lord)
break
end
end
end
end
end
end

return eles
return ele_list
end

#---------------------------------------------------------------------------------------------------
# eles_by_index
# eles_search_a_group

"""
Internal: eles_by_index(where_search::Union{Lattice,Branch}, who::Union{AbstractString,Regex};
include_lords = true, wrap::Bool = true)
Internal: eles_search_a_group(where_search::Union{Lattice,Branch}, who::Union{AbstractString,Regex};
wrap::Bool = true)

Internal routine called by `eles`. See the `eles` documentation for details.
Essentially, this is `eles` except with the order_by_s argument.
""" eles_by_index
Internal routine called by `eles` to search for matches to a string that represents a single "group".
A string representing a single group is a string that does not contain, ",", "&", nor "~".
See the `eles` documentation for details.
Returned is a list that is naturally sorted by index.
""" eles_search_a_group

function eles_by_index(where_search::Union{Lattice,Branch}, who::Union{AbstractString,Regex},
include_lords = true, wrap::Bool = true)
function eles_search_a_group(where_search::Union{Lattice,Branch}, who::Union{AbstractString,Regex},
wrap::Bool = true)
# Julia regex is simple
if typeof(who) == Regex; return eles_group(where_search, who); end
if typeof(who) == Regex; return eles_search_a_group(where_search, who); end

# Not Julia regex
ele_type = nothing
Expand Down Expand Up @@ -198,13 +180,13 @@ function eles_by_index(where_search::Union{Lattice,Branch}, who::Union{AbstractS
# Non-range construct

if length(chunks) == 0
return eles_atomic(where_search, who, branch_id, ele_type, param_id, match_str, offset, include_lords, wrap)
return eles_atomic(where_search, who, branch_id, ele_type, param_id, match_str, offset, wrap)
end

# Range construct
# Note: ele_type not used in search for range end points.

ele_vec = eles_atomic(where_search, who, branch_id, nothing, param_id, match_str, offset, include_lords, wrap)
ele_vec = eles_atomic(where_search, who, branch_id, nothing, param_id, match_str, offset, wrap)

if chunks[1] != ":"; error("Malformed group: $who"); end
if length(ele_vec) == 0; error("First element in range construct does not match anything in the lattice: $who"); end
Expand Down Expand Up @@ -232,7 +214,7 @@ function eles_by_index(where_search::Union{Lattice,Branch}, who::Union{AbstractS

if length(chunks) > 0; error("Extra stuff in group construct: $who"); end

ele_vec2 = eles_atomic(where_search, who, branch_id, nothing, param_id, match_str, offset, include_lords, wrap)
ele_vec2 = eles_atomic(where_search, who, branch_id, nothing, param_id, match_str, offset, wrap)
if length(ele_vec2) == 0; error("Second element in range construct does not match anything in the lattice: $who"); end
if length(ele_vec2) > 1; error("Second element in range construct matches multiple elements: $who"); end

Expand Down Expand Up @@ -261,11 +243,11 @@ function eles_by_index(where_search::Union{Lattice,Branch}, who::Union{AbstractS
end

#---------------------------------------------------------------------------------------------------
# eles
# eles_search

"""
eles(where_search, who::Union{AbstractString,Regex};
order_by_s::Bool = true, include_lords = true, wrap::Bool = true) -> Ele[]
eles_search(where_search, who::Union{AbstractString,Regex};
order::Order.T = Order.NONE, substitute_lords = false, wrap::Bool = true) -> Ele[]

Returns a vector of all elements that match `who`.

Expand All @@ -275,10 +257,10 @@ Returns a vector of all elements that match `who`.
- `who` The string to match elements to.
Either a Julia `Regex` expression to match to element names or a string with matching
governed by the "AcceleratorLattice" (AL) regex syntax (see below).
- `order_by_s` If `false`, ordering of the output vector is by branch and ele index.
If `true`, order by s-position with super and multipass lords interspersed with tracking elements.
- `include_lords` If `true` include super and multipass lords that control elements in the
branches searched. This argument ignored with Julia regex searches.
- `order` If `Order.BY_INDEX`, ordering of the output vector is by branch and ele index.
If `Order.BY_S`, order by s-position with super and multipass lords interspersed with tracking elements.
- `substitute_lords` If `true`, for every matched element that is a slave, remove the slave and
add to the output list the slave's super or multipass lords.
- `wrap` Used if there is an `offset` specified in the search string (see below).

## AL Regex
Expand Down Expand Up @@ -320,35 +302,79 @@ same branch.
do not affect matching to the elements at the ends of the range. That is, the elements
at the range ends do not have to be of type `ele_type`.

Group expressions may be combined using the operators `","` (union), `"~"` (negation) or `"&"` (intersection):
If there are more than two group expressions involved, evaluation is left to right. For example:
```
"<group1>, <group2>" # Union of <group1> and <group2>.
"<group1>, <group2> & <group3>" # Intersection of <group3> with the union of <group1> and <group2>.
"<group1> ~<group2>" # All elements in <group1> that are not in <group2>.
```

## Notes

- The `parameter='match_str'` construct allows for matching to element parameters other than the element name.
Typically used with the standard element "string parameters" `ID`, `type`, and `class`
but matching is not limited to these parameters.
- To exclude matches to super slave elements, use `"~*!s"` at the end of an expression.
- The returned list will not have duplications. That is, a given element will not show up in multiple places.

## Examples
```
eles(lat, "r>>d") # All elements named "d" in the branch with name "r".
eles(lat, "Marker::*") # All Marker elements
eles(lat, "Marker::%5-1") # All elements just before Marker elements with two character names
eles_search(lat, "r>>d") # All elements named "d" in the branch with name "r".
eles_search(lat, "Marker::*") # All Marker elements
eles_search(lat, "Marker::%5-1") # All elements just before Marker elements with two character names
# ending in the digit "5"
eles(lat.branch["super"], "ID=`abc`")
eles_search(lat.branch["super"], "ID=`abc`")
```

Note: The index operator `[...]` is overloaded so that `branch[who]` where `branch` is a `Branch`
instance, or `lat[who]` where `lat` is a
`Lattice` instance is the same as `eles(branch, who)` and `eles(lat, who)` respectively.
""" eles

function eles(where_search::Union{Lattice,Branch}, who::Union{AbstractString,Regex};
order_by_s::Bool = true, include_lords = true, wrap::Bool = true)
ele_list = eles_by_index(where_search, who, include_lords, wrap)
if order_by_s
return sort(ele_list)
`Lattice` instance is the same as `eles_search(branch, who)` and `eles_search(lat, who)` respectively.
""" eles_search

function eles_search(where_search::Union{Lattice,Branch}, who::Union{AbstractString,Regex};
order::Order.T = Order.NONE, substitute_lords = false, wrap::Bool = true)
if typeof(who) == Regex
ele_list = eles_search_a_group(where_search, who, wrap)

else
return ele_list
list = str_split(who, "~&,")
ele_list = eles_search_a_group(where_search, list[1])
list = list[2:end]

while true
if length(list) == 0; break; end
if length(list) == 1; error("Bad `who` argument: $who"); end

list2 = eles_search(where_search, list[2], wrap = wrap)

if list[1] == "&"
combo_list = Ele[]
for ele1 in ele_list
if ele1 in list2; push!(combo_list, ele1); continue; end
end
ele_list = combo_list

elseif list[1] == "~"
combo_list = Ele[]
for ele1 in ele_list
if ele1 ∉ list2; push!(combo_list, ele1); continue; end
end
ele_list = combo_list

elseif list[1] == ","
ele_list = append!(ele_list, list2)

else
error("ParseError: Cannot parse: $who")
end

list = list[3:end]
end
end

if substitute_lords; eles_substitute_lords!(ele_list); end
return eles_sort!(ele_list, order = order)
end

#---------------------------------------------------------------------------------------------------
Expand Down
Loading
Loading