Skip to content

Commit

Permalink
Mutable structure, chain
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonOresten committed Nov 4, 2024
1 parent dfe2947 commit 2b2bb9b
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 35 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ julia> propertynames(chain)
(:id, :atoms, :sequence, :numbering, :ins_codes, :renumbering)
```
To store additional properties, `addproperties` can be used to attach persistent chain-level properties or indexable residue-level properties:
To store additional properties, `addpropertie!s` can be used to attach persistent chain-level properties or indexable residue-level properties:
```julia
julia> new_chain = addproperties(chain; taxid=83332)
julia> addproperties!(chain; taxid=83332)
256-residue ProteinChain{Float64} (A)

julia> new_chain = addproperties(new_chain; rand3=IndexableProperty(rand(3,256))) # last dimension matches chain length
julia> addproperties!(new_chain; rand3=IndexableProperty(rand(3,256))) # last dimension matches chain length
256-residue ProteinChain{Float64} (A)

julia> new_chain[1:100].rand3
Expand Down
1 change: 1 addition & 0 deletions src/ProteinChains.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export Atom

include("properties.jl")
export AbstractProperty, StandardProperty, IndexableProperty
export setproperties!, addproperties!, removeproperties!
export setproperties, addproperties, removeproperties

include("chain.jl")
Expand Down
30 changes: 16 additions & 14 deletions src/chain.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
ProteinChain{T<:Real}
Represents a protein chain with a basic set of fields from which some other properties might be derived.
The [`addproperties`](@ref) function can be used to instantiate new chains with additional properties.
The [`addproperties!`](@ref) function can be used to add additional properties.
## Fields
- `id::String`: Identifier for the protein chain.
Expand All @@ -12,10 +12,10 @@ The [`addproperties`](@ref) function can be used to instantiate new chains with
- `numbering::Vector{Int32}`: Residue numbering (author). See [`renumber`](@ref) for renumbering.
- `properties::ProteinChains.NamedProperties`: Named properties associated with the chain.
See also [`addproperties`](@ref), [`StandardProperty`](@ref), [`IndexableProperty`](@ref).
See also [`addproperties!`](@ref), [`StandardProperty`](@ref), [`IndexableProperty`](@ref).
```
"""
struct ProteinChain{T<:Real}
mutable struct ProteinChain{T<:Real}
id::String
atoms::Vector{Vector{Atom{T}}}
sequence::String
Expand Down Expand Up @@ -45,7 +45,7 @@ function ProteinChain{T}(id, atoms, sequence, ins_codes, numbering::Vector{<:Int
end

function ProteinChain(id, atoms::Vector{Vector{Atom{T}}}, sequence, ins_codes=String(fill(0x40, length(sequence))), numbering=collect(1:length(sequence)), properties=(;)) where T
ProteinChain{T}(id, atoms, sequence, ins_codes, Int32.(numbering), namedproperties(properties))
ProteinChain{T}(id, atoms, sequence, ins_codes, numbering, properties)
end

Base.convert(::Type{ProteinChain{T}}, chain::ProteinChain) where T =
Expand All @@ -60,38 +60,40 @@ Base.length(chain::ProteinChain) = length(chain.atoms)

function Base.getindex(chain::ProteinChain, i::Union{AbstractVector,Colon})
properties = map(p -> p[i], chain.properties)
ProteinChain(chain.id, chain.atoms[i], chain.sequence[i], chain.numbering[i], properties)
ProteinChain(chain.id, chain.atoms[i], chain.sequence[i], chain.ins_codes[i], chain.numbering[i], properties)
end

Base.getproperty(chain::ProteinChain, name::Symbol) =
name in fieldnames(ProteinChain) ? getfield(chain, name) : unpack(getfield(getfield(chain, :properties), name))

Base.propertynames(chain::ProteinChain, private::Bool=false) = (setdiff(fieldnames(ProteinChain), private ? () : (:properties,))..., propertynames(chain.properties)...)

setproperties(chain::ProteinChain, ps::NamedTuple) =
ProteinChain(chain.id, chain.atoms, chain.sequence, chain.ins_codes, chain.numbering, setproperties(chain.properties, ps))
function setproperties!(chain::ProteinChain, ps::NamedTuple)
chain.properties = setproperties(chain.properties, ps)
chain
end

"""
addproperties(chain::ProteinChain, properties::NamedTuple)
addproperties(chain::ProteinChain; properties...)
addproperties!(chain::ProteinChain, properties::NamedTuple)
addproperties!(chain::ProteinChain; properties...)
Creates a new `ProteinChain` instance with the added properties.
Indexing of property values can be specified with a wrapper type,
such as `IndexableProperty`.
See also [`removeproperties`](@ref), [`IndexableProperty`](@ref).
"""
addproperties(chain::ProteinChain, properties::NamedTuple) = setproperties(chain, addproperties(chain.properties, properties))
addproperties(chain::ProteinChain; properties...) = setproperties(chain, addproperties(chain.properties, NamedTuple(properties)))
addproperties!(chain::ProteinChain, properties::NamedTuple) = setproperties!(chain, addproperties(chain.properties, properties))
addproperties!(chain::ProteinChain; properties...) = setproperties!(chain, addproperties(chain.properties, NamedTuple(properties)))

"""
removeproperties(chain::ProteinChain, names::Symbol...)
removeproperties!(chain::ProteinChain, names::Symbol...)
Creates a new `ProteinChain` instance with the property names in `names` removed.
See also [`addproperties`](@ref)
See also [`addproperties!`](@ref)
"""
removeproperties(chain::ProteinChain, names::Symbol...) = setproperties(chain, removeproperties(chain.properties, names...))
removeproperties!(chain::ProteinChain, names::Symbol...) = setproperties!(chain, removeproperties(chain.properties, names...))

Base.summary(chain::ProteinChain) = "$(length(chain))-residue $(typeof(chain)) ($(chain.id))"

Expand Down
12 changes: 10 additions & 2 deletions src/properties.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ addproperties(properties::NamedProperties, newproperties::NamedTuple) =
removeproperties(properties::NamedProperties, names::Symbol...) =
NamedTuple{filter(name -> name ∉ names, propertynames(properties))}(properties)

function setproperties! end
function addproperties! end
function removeproperties! end

setproperties(x, args...) = setproperties!(deepcopy(x), args...)
addproperties(x, args...; kwargs...) = addproperties!(deepcopy(x), args...; kwargs...)
removeproperties(x, args...) = removeproperties!(deepcopy(x), args...)

checkproperty(::Any, ::AbstractProperty) = nothing

unpack(x) = x
Expand All @@ -32,7 +40,7 @@ unpack(p::AbstractProperty) = p.value
A property with arbitrary type. The value is retained as is.
This is the default property type for [`addproperties`](@ref).
This is the default property type for [`addproperties!`](@ref).
See also [`IndexableProperty`](@ref).
"""
Expand All @@ -53,7 +61,7 @@ residue indexing of the chain being propagated to the last dimension of the arra
```jldoctest
julia> chain = pdb"1ASS"A;
julia> chain = addproperties(pdb"1ASS"A; y=IndexableProperty(rand(2,152)));
julia> addproperties!(pdb"1ASS"A; y=IndexableProperty(rand(2,152)));
julia> chain.y == chain[1:10].y
false
Expand Down
26 changes: 16 additions & 10 deletions src/structure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- `chains::Vector{ProteinChain{T}}`: a collection of `ProteinChain`s.
- `properties::NamedProperties`: arbitrary properties.
"""
struct ProteinStructure{T} <: AbstractVector{ProteinChain{T}}
mutable struct ProteinStructure{T} <: AbstractVector{ProteinChain{T}}
name::String
atoms::Vector{Atom{T}}
chains::Vector{ProteinChain{T}}
Expand All @@ -30,7 +30,11 @@ chainid_to_index(structure::ProteinStructure, id::AbstractString) = findfirst(c

Base.getindex(structure::ProteinStructure, i::Integer) = structure.chains[i]
Base.getindex(structure::ProteinStructure, id::AbstractString) = structure[chainid_to_index(structure, id)]
Base.getindex(structure::ProteinStructure, is::AbstractVector) = ProteinStructure(structure.name, structure.atoms, map(i -> structure[i], is))

function Base.getindex(structure::ProteinStructure, inds::AbstractVector{<:Integer})
properties = map(p -> p[inds], structure.properties)
return ProteinStructure(structure.name, structure.atoms, map(i -> structure[i], inds), properties)
end

Base.setindex!(structure::ProteinStructure, chain::ProteinChain, i::Integer) = (structure.chains[i] = chain)
Base.setindex!(structure::ProteinStructure, chain::ProteinChain, id::AbstractString) = (structure.chains[chainid_to_index(structure, id)] = chain)
Expand Down Expand Up @@ -68,14 +72,16 @@ Base.getproperty(structure::ProteinStructure, name::Symbol) =

Base.propertynames(structure::ProteinStructure, private::Bool=false) = (setdiff(fieldnames(ProteinStructure), private ? () : (:properties,))..., propertynames(structure.properties)...)

setproperties(structure::ProteinStructure, properties::NamedTuple) =
ProteinStructure(structure.name, structure.atoms, structure.chains, setproperties(structure.properties, properties))
function setproperties!(structure::ProteinStructure, properties::NamedTuple)
structure.properties = setproperties(structure.properties, properties)
structure
end

addproperties(structure::ProteinStructure, properties::NamedTuple) =
setproperties(structure, addproperties(structure.properties, properties))
addproperties!(structure::ProteinStructure, properties::NamedTuple) =
setproperties!(structure, addproperties(structure.properties, properties))

addproperties(structure::ProteinStructure; properties...) =
setproperties(structure, addproperties(structure.properties, NamedTuple(properties)))
addproperties!(structure::ProteinStructure; properties...) =
setproperties!(structure, addproperties(structure.properties, NamedTuple(properties)))

removeproperties(structure::ProteinStructure, names::Symbol...) =
setproperties(structure, removeproperties(structure.properties, names...))
removeproperties!(structure::ProteinStructure, names::Symbol...) =
setproperties!(structure, removeproperties(structure.properties, names...))
6 changes: 0 additions & 6 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ using Test

@testset "ProteinChains.jl" begin

@testset "ideal.jl" begin
geometry = BackboneGeometry(N_Ca_length=3, Ca_C_length=3, N_Ca_C_angle=π/2)
ideal_residue = IdealResidue{Float64}(geometry)
@test ideal_residue == Float64[-2 1 1; -1 -1 2; 0 0 0]
end

@testset "atom.jl" begin

@testset "atom name" begin
Expand Down

0 comments on commit 2b2bb9b

Please sign in to comment.