Skip to content

Commit 78b0525

Browse files
Merge pull request #81 from ProjectTorreyPines/updates
New updates to projection and plotting recipes ## Plotting: 2D heatmap plot of properties updated * Added option of provigin value_field * Added option of providing clims for colorbar * Added equal aspect ration for the heatmap ## Projection: * `project_prop_on_subset!` now has two methods. * `space` is a keyword argument now and optional as `get_space` can be used to get `space` object from `subset` objects. * Projection can be done for all time instances saved in different `ggd` by using the second method. **Note**: This changes the call sign of `project_prop_on_subset!` and thus can break previous code using this function.
2 parents 306adcc + 55b5856 commit 78b0525

File tree

6 files changed

+210
-125
lines changed

6 files changed

+210
-125
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "IMASggd"
22
uuid = "b7b5e640-9b39-4803-84eb-376048795def"
33
authors = ["Anchal Gupta <guptaa@fusion.gat.com>"]
4-
version = "3.1.1"
4+
version = "3.2.0"
55

66
[deps]
77
ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63"

docs/src/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ can be imported for further use.
5858
IMASggd.all__grid_ggd
5959
IMASggd.all__space
6060
IMASggd.all__grid_subset
61+
IMASggd.all__ggd
6162
IMASggd.all__grid_subset_prop
6263
```
6364

src/recipes.jl

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,28 @@ is the heatmap and b is the colorbar.
128128
yaxis --> "Z / m"
129129
layout := @layout [a{0.95w} b]
130130
if subset.element[1].object[1].dimension == 3
131+
if :value_field in keys(plotattributes)
132+
value_field = plotattributes[:value_field]
133+
else
134+
value_field = :values
135+
end
136+
prop_values = getfield(prop, value_field)
131137
if :seriescolor in keys(plotattributes)
132138
color_scheme = plotattributes[:seriescolor]
133139
else
134140
color_scheme = :inferno
135141
end
136-
color_grad = getproperty(ColorSchemes, color_scheme)
137-
val_min = minimum(prop.values)
138-
val_max = maximum(prop.values)
139-
function get_color(prop_value)
140-
return color_grad[(log10(prop_value/val_min)/log10(val_max/val_min))]
142+
if :clims in keys(plotattributes)
143+
val_min, val_max = plotattributes[:clims]
144+
else
145+
val_min = minimum(prop_values)
146+
val_max = maximum(prop_values)
141147
end
148+
color_grad = getproperty(ColorSchemes, color_scheme)
149+
colors = [
150+
color_grad[(log10(pv/val_min)/log10(val_max/val_min))] for
151+
pv prop_values
152+
]
142153

143154
if :colorbar_title in keys(plotattributes)
144155
prop_name = plotattributes[:colorbar_title]
@@ -163,13 +174,14 @@ is the heatmap and b is the colorbar.
163174

164175
# Actual plot is plotted as different cell shapes filled with color values
165176
# based on property value
166-
for (ele, prop_value) zip(subset.element, prop.values)
177+
for (ele, color) zip(subset.element, colors)
167178
cell = cells[ele.object[1].index]
168179
@series begin
169180
subplot := 1
170181
seriestype := :shape
171-
linecolor := get_color(prop_value)
172-
fillcolor := get_color(prop_value)
182+
linecolor := color
183+
fillcolor := color
184+
aspect_ratio := :equal
173185
label := ""
174186
[Tuple(nodes[cell.nodes[ii]].geometry) for ii [1, 2, 4, 3]]
175187
end

src/subset_tools.jl

Lines changed: 139 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,11 @@ end
202202

203203
"""
204204
subset_do(
205-
set_operator,
206-
itrs::Vararg{all__grid_subset};
207-
use_nodes=false,
208205
209-
)::all__grid_subset
206+
set_operator,
207+
itrs::Vararg{all__grid_subset};
208+
use_nodes=false,
209+
)::all__grid_subset
210210
211211
Function to perform any set operation (intersect, union, setdiff etc.) on
212212
subset.element to generate a list of elements to go to subset object. If use_nodes is
@@ -271,91 +271,108 @@ end
271271

272272
"""
273273
project_prop_on_subset!(
274-
prop_arr::AbstractVector{<:all__grid_subset_prop}),
275-
from_subset::all__grid_subset),
276-
to_subset::all__grid_subset),
277-
space::all__space,
274+
prop_arr::IMASdd.IDSvector{<:all__grid_subset_prop},
275+
from_subset::all__grid_subset,
276+
to_subset::all__grid_subset;
277+
space::all__space=get_space(from_subset),
278278
value_field::Symbol=:values,
279-
TPS_mats::Union{
280-
Nothing,
281-
Tuple{Matrix{U}, Matrix{U}, Matrix{U}, Vector{Tuple{U, U}}},
282-
}=nothing,
279+
280+
TPS_mats::Tuple{Matrix{U}, Matrix{U}, Matrix{U}, Vector{Tuple{U, U}}}=get_TPS_mats(
281+
space,
282+
from_subset,
283+
),
284+
283285
) where {U <: Real}
284286
285287
This function can be used to add another instance on a property vector representing the
286288
value in a new subset that can be taken as a projection from an existing larger subset.
287289
288290
Input Arguments:
289291
290-
- prop: A property like electrons.density that is a vector of objects with fields
292+
- `prop`: A property like electrons.density that is a vector of objects with fields
291293
coefficients, grid_index, grid_subset_index, and values. The different instances
292294
in the vector correspond to different grid_subset for which the property is
293295
provided.
294-
- from_subset: grid_subset object which is already represented in the property instance.
296+
- `from_subset`: grid_subset object which is already represented in the property instance.
295297
grid subset with index 5 is populated in electrons.density already if the
296298
values for all cells are present.
297-
- to_subset: grid_subset which is either a smaller part of from_subset (core, sol, idr,
299+
- `to_subset`: grid_subset which is either a smaller part of from_subset (core, sol, idr,
298300
odr) but has same dimensions as from_subset
299301
OR
300302
is smaller in dimension that goes through the from_subset (core_boundary,
301303
separatix etc.)
302-
- space: (optional) space object in grid_ggd is required only when from_subset is
303-
higher dimensional than to_subset.
304+
- `space`: (optional) space object in grid_ggd corresponding to the subsets
305+
- `value_field`: If the values field is called something else, that can be provided here.
304306
305307
Returns:
306308
NOTE: This function ends in ! which means it updates prop argument in place. But for
307309
the additional utility, this function also returns a tuple
308-
(to_subset_centers, to_prop_values) when from_subset dimension is greater than
309-
to_subset dimension
310-
OR
311-
(to_subset_ele_obj_inds, to_prop_values) when from_subset dimension is same as
312-
to_subset dimension)
313-
314-
Descriptions:
315-
to_subset_centers: center of cells or center of edges of the to_subset where property
316-
values are defined and stored
317-
to_subset_ele_obj_inds: Indices of the elements of to_subset where property values are
318-
defined and stored
319-
to_prop_values: The projected values of the properties added to prop object in a new
320-
instance
310+
311+
(`to_subset_centers`, `to_prop_values`)
312+
313+
- `to_subset_centers`: center of cells or center of edges of the to_subset where
314+
property values are defined and stored
315+
- `to_prop_values`: The projected values of the properties added to prop object in a
316+
new instance
321317
"""
322318
function project_prop_on_subset!(
323319
prop_arr::IMASdd.IDSvector{<:all__grid_subset_prop},
324320
from_subset::all__grid_subset,
325-
to_subset::all__grid_subset,
326-
space::all__space,
321+
to_subset::all__grid_subset;
322+
space::all__space=get_space(from_subset),
327323
value_field::Symbol=:values,
328-
TPS_mats::Union{
329-
Nothing,
330-
Tuple{Matrix{U}, Matrix{U}, Matrix{U}, Vector{Tuple{U, U}}},
331-
}=nothing,
324+
TPS_mats::Tuple{Matrix{U}, Matrix{U}, Matrix{U}, Vector{Tuple{U, U}}}=get_TPS_mats(
325+
space,
326+
from_subset,
327+
),
332328
) where {U <: Real}
333-
if from_subset.element[1].object[1].dimension ==
334-
to_subset.element[1].object[1].dimension
335-
return project_prop_on_subset!(prop_arr, from_subset, to_subset, value_field)
336-
elseif from_subset.element[1].object[1].dimension >
337-
to_subset.element[1].object[1].dimension
338-
if length(prop_arr) < 1
339-
error(
340-
"The property $(strip(repr(prop_arr))) is empty; ",
341-
"there are no data available for any subset.",
342-
)
343-
end
344-
from_prop =
345-
get_prop_with_grid_subset_index(prop_arr, from_subset.identifier.index)
346-
if isnothing(from_prop)
329+
if length(prop_arr) < 1
330+
error(
331+
"The property $(strip(repr(prop_arr))) is empty; ",
332+
"there are no data available for any subset.",
333+
)
334+
end
335+
from_prop = get_prop_with_grid_subset_index(prop_arr, from_subset.identifier.index)
336+
if isnothing(from_prop)
337+
error(
338+
"from_subset ($(from_subset.identifier.index)) not represented in the ",
339+
"property yet",
340+
)
341+
end
342+
to_subset_centers = get_subset_centers(space, to_subset)
343+
from_dim = from_subset.element[1].object[1].dimension
344+
to_dim = to_subset.element[1].object[1].dimension
345+
resize!(prop_arr, length(prop_arr) + 1)
346+
to_prop = prop_arr[end]
347+
to_prop.grid_index = from_prop.grid_index
348+
to_prop.grid_subset_index = to_subset.identifier.index
349+
to_prop_values = getfield(to_prop, value_field)
350+
from_prop_values = getfield(from_prop, value_field)
351+
if from_dim == to_dim
352+
from_subset_ele_obj_inds = [ele.object[1].index for ele from_subset.element]
353+
to_subset_ele_obj_inds = [ele.object[1].index for ele to_subset.element]
354+
if to_subset_ele_obj_inds from_subset_ele_obj_inds
355+
from_ele_inds = []
356+
for to_ele_obj_ind to_subset_ele_obj_inds
357+
for (from_ele_ind, from_ele_obj_ind)
358+
enumerate(from_subset_ele_obj_inds)
359+
if from_ele_obj_ind == to_ele_obj_ind
360+
append!(from_ele_inds, from_ele_ind)
361+
end
362+
end
363+
end
364+
filtered_values =
365+
[from_prop_values[from_ele_ind] for from_ele_ind from_ele_inds]
366+
resize!(to_prop_values, length(filtered_values))
367+
setproperty!(to_prop, value_field, filtered_values)
368+
return to_subset_centers, filtered_values
369+
else
347370
error(
348-
"from_subset ($(from_subset.identifier.index)) not represented in the ",
349-
"property yet",
371+
"to_subset ($(to_subset.identifier.index)) does not lie entirely inside ",
372+
"from_subset ($(from_subset.identifier.index)). Projection not possible.",
350373
)
351374
end
352-
to_subset_centers = get_subset_centers(space, to_subset)
353-
resize!(prop_arr, length(prop_arr) + 1)
354-
to_prop = prop_arr[end]
355-
to_prop.grid_index = from_prop.grid_index
356-
to_prop.grid_subset_index = to_subset.identifier.index
357-
to_prop_values = getfield(to_prop, value_field)
358-
from_prop_values = getfield(from_prop, value_field)
375+
elseif from_dim > to_dim
359376
resize!(to_prop_values, length(to_subset.element))
360377
if isnothing(TPS_mats)
361378
prop_interp = interp(prop_arr, space, from_subset)
@@ -375,74 +392,83 @@ end
375392

376393
"""
377394
project_prop_on_subset!(
378-
prop_arr::AbstractVector{<:all__grid_subset_prop}),
379-
from_subset::all__grid_subset),
380-
to_subset::all__grid_subset),
395+
ggds::IMASdd.IDSvector{<:all__ggd},
396+
prop_path::String,
397+
from_subset::all__grid_subset,
398+
to_subset::all__grid_subset;
399+
space::all__space=get_space(from_subset),
381400
value_field::Symbol=:values,
382-
)
401+
TPS_mats::Tuple{Matrix{U}, Matrix{U}, Matrix{U}, Vector{Tuple{U, U}}}=get_TPS_mats(
402+
space,
403+
from_subset,
404+
),
405+
) where {U <: Real}
383406
384-
If the dimensions of from_subset and to_subset are the same, this function can be used
385-
to add another instance on a property vector representing the value in to_subset without
386-
any interpolation or use of space object. The function returns a tuple of indices of
387-
elements of to_subset and the values of the property in to_subset.
407+
This function projects properties from `from_subset` to `to_subset` for each of the
408+
`ggds` element. Here property is given as a relative path from `ggd` object. For
409+
example, for electron density in `edge_profiles`, one would provide `edge_profiles.ggd`
410+
as the `ggds` argument and "electrons.density" as the `prop_path` argument. Note that
411+
`prop_path` can be parsed even if it includes array in it. For example, in
412+
`edge_profiles.ggd`, `prop_path` of "ion.state[7].density" would correspond to the
413+
index 7 in `state` array of `ion` while a `prop_path` of "ion.state[:].density" would
414+
do the projection for all the states of the `ion`. This function call returns a combined
415+
list of return tuples for all projections performed.
388416
"""
389417
function project_prop_on_subset!(
390-
prop_arr::IMASdd.IDSvector{<:all__grid_subset_prop},
418+
ggds::IMASdd.IDSvector{<:all__ggd},
419+
prop_path::String,
391420
from_subset::all__grid_subset,
392-
to_subset::all__grid_subset,
421+
to_subset::all__grid_subset;
422+
space::all__space=get_space(from_subset),
393423
value_field::Symbol=:values,
394-
)
395-
from_prop = get_prop_with_grid_subset_index(prop_arr, from_subset.identifier.index)
396-
if length(prop_arr) < 1
397-
error(
398-
"The property $(strip(repr(prop_arr))) is empty; ",
399-
"there are no data available for any subset.",
400-
)
424+
TPS_mats::Tuple{Matrix{U}, Matrix{U}, Matrix{U}, Vector{Tuple{U, U}}}=get_TPS_mats(
425+
space,
426+
from_subset,
427+
),
428+
) where {U <: Real}
429+
prop_arrays = Array{IMASdd.IDSvector{<:all__grid_subset_prop}}[]
430+
for ggd ggds
431+
append!(prop_arrays, _prop_arrays_from_path(prop_path::String, ggd))
401432
end
402-
if isnothing(from_prop)
403-
error(
404-
"from_subset ($(from_subset.identifier.index)) not represented in the property yet",
433+
to_return = []
434+
for prop_arr prop_arrays
435+
append!(
436+
to_return,
437+
project_prop_on_subset!(
438+
prop_arr,
439+
from_subset,
440+
to_subset;
441+
space,
442+
value_field,
443+
TPS_mats,
444+
),
405445
)
406446
end
407-
if from_subset.element[1].object[1].dimension ==
408-
to_subset.element[1].object[1].dimension
409-
resize!(prop_arr, length(prop_arr) + 1)
410-
to_prop = prop_arr[end]
411-
to_prop.grid_index = from_prop.grid_index
412-
to_prop.grid_subset_index = to_subset.identifier.index
413-
to_prop_values = getfield(to_prop, value_field)
414-
from_prop_values = getfield(from_prop, value_field)
415-
from_subset_ele_obj_inds = [ele.object[1].index for ele from_subset.element]
416-
to_subset_ele_obj_inds = [ele.object[1].index for ele to_subset.element]
417-
if to_subset_ele_obj_inds from_subset_ele_obj_inds
418-
from_ele_inds = []
419-
for to_ele_obj_ind to_subset_ele_obj_inds
420-
for (from_ele_ind, from_ele_obj_ind)
421-
enumerate(from_subset_ele_obj_inds)
422-
if from_ele_obj_ind == to_ele_obj_ind
423-
append!(from_ele_inds, from_ele_ind)
424-
end
447+
return to_return
448+
end
449+
450+
function _prop_arrays_from_path(prop_path::String, parent)
451+
prop_arrays = Array{IMASdd.IDSvector{<:all__grid_subset_prop}}[]
452+
if occursin(".", prop_path)
453+
pf = split(prop_path, ".")[1]
454+
rem_path = prop_path[(findfirst('.', prop_path)+1):end]
455+
if occursin("[", pf)
456+
new_parent = getfield(parent, Symbol(pf[1:(findfirst('[', pf)-1)]))
457+
ind_str = pf[(findfirst('[', pf)+1):(findfirst(']', pf)-1)]
458+
if ind_str == ":"
459+
for np new_parent
460+
append!(prop_arrays, _prop_arrays_from_path(rem_path, np))
425461
end
462+
else
463+
ind = parse(Int, ind_str)
464+
append!(prop_arrays, _prop_arrays_from_path(rem_path, new_parent[ind]))
426465
end
427-
filtered_values =
428-
[from_prop_values[from_ele_ind] for from_ele_ind from_ele_inds]
429-
resize!(to_prop_values, length(filtered_values))
430-
to_prop_values = filtered_values
431-
return to_subset_ele_obj_inds, to_prop_values
432466
else
433-
error(
434-
"to_subset ($(to_subset.identifier.index)) does not lie entirely inside ",
435-
"from_subset ($(from_subset.identifier.index)). Projection not possible.",
436-
)
467+
new_parent = getfield(parent, Symbol(pf))
468+
append!(prop_arrays, _prop_arrays_from_path(rem_path, new_parent))
437469
end
438-
else
439-
error(
440-
"Dimensions of from_subset ($(from_subset.identifier.index)) and to_subset ",
441-
"($(to_subset.identifier.index)) do not match. Provide keyword ",
442-
"argument space if you want to project to a smaller dimension as space ",
443-
"information is required for that. Use\n",
444-
"project_prop_on_subset!(prop, from_subset, to_subset; space=space)")
445470
end
471+
return prop_arrays
446472
end
447473

448474
"""

0 commit comments

Comments
 (0)