Skip to content
Merged
Show file tree
Hide file tree
Changes from 59 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
8f4991e
create graph.js and export Tree class
nafiz1001 May 5, 2022
df4433e
add Lineage section with JSON visualization
nafiz1001 May 5, 2022
5b8118c
produce nodes and edge objects for React Flow
nafiz1001 May 6, 2022
32be41d
implement with react-d3-graph
nafiz1001 May 6, 2022
88e951d
make Lineage a component
nafiz1001 May 6, 2022
d7c58e5
add React.StrictMode
nafiz1001 May 9, 2022
2e75d05
add and use Lineage tab
nafiz1001 May 9, 2022
b5eba8c
use map.flat instead of reduce
nafiz1001 May 9, 2022
72df7a6
empty list instead of undefined
nafiz1001 May 9, 2022
65629bd
create and use SampleDetailsLineage.js
nafiz1001 May 9, 2022
64da437
don't display id
nafiz1001 May 9, 2022
0c399ce
make current node red
nafiz1001 May 9, 2022
a413f0f
Tree to Graph
nafiz1001 May 10, 2022
4097147
use symbol for representing current node instead
nafiz1001 May 10, 2022
3094e7f
use color to indicate qc flag
nafiz1001 May 10, 2022
0023bae
document graph constructor
nafiz1001 May 10, 2022
cc8c210
use history
nafiz1001 May 10, 2022
ec8b01f
decoupole edge with with subgraph
nafiz1001 May 11, 2022
d0a3d7b
remove React.StrictNode
nafiz1001 May 11, 2022
e05a8e5
100% async tree construction (wip)
nafiz1001 May 11, 2022
210b770
give up on async
nafiz1001 May 13, 2022
ab02a2a
reject undefined values
nafiz1001 May 13, 2022
c87082a
don't throw exception
nafiz1001 May 16, 2022
4137e47
use dagre
nafiz1001 May 16, 2022
494014a
add sample_lineage service and view
nafiz1001 May 17, 2022
01deb57
integrate SampleDetailsLineage with sample_lineage api
nafiz1001 May 17, 2022
ec20601
fetch parents
nafiz1001 May 17, 2022
d8f8bbc
reuse pairToProcess
nafiz1001 May 17, 2022
23f61cf
optimize backend
nafiz1001 May 18, 2022
027a197
show number of children
nafiz1001 May 18, 2022
fdea51a
Revert "show number of children"
nafiz1001 May 19, 2022
1420125
optimize backend even more
nafiz1001 May 19, 2022
48ecdaf
remove tkinter
nafiz1001 May 19, 2022
ffad722
move nodes and edges to top of function
nafiz1001 May 19, 2022
edfdcc7
flat values_list
nafiz1001 May 19, 2022
7f1a8bf
add space between samples and process_measurements
nafiz1001 May 19, 2022
c8202f5
process__protocol__name to protocol_name
nafiz1001 May 19, 2022
cfdc4ec
graph.js no longer needed
nafiz1001 May 19, 2022
c54a098
some refactoring and TODO
nafiz1001 May 19, 2022
41a9532
refactor sample_lineage.py
nafiz1001 May 19, 2022
dc8d64f
reformat/refactor SampleDetailsLineage.js
nafiz1001 May 19, 2022
572e8c5
iterate over graph.edges instead of g.edges
nafiz1001 May 19, 2022
8ed06b2
provide size and border for div around graph
nafiz1001 May 20, 2022
b267076
add legend for lineage
nafiz1001 May 20, 2022
cd4496b
make border thin
nafiz1001 May 20, 2022
5f49795
add instructions
nafiz1001 May 20, 2022
176528e
use antd components
nafiz1001 May 20, 2022
80e109d
graph to { data }
nafiz1001 May 20, 2022
a43a661
position current sample to the top left corner
nafiz1001 May 24, 2022
dc65246
make graph horizontal and extend legend horizontally
nafiz1001 May 24, 2022
1739eb4
redesign and use popover for legend
nafiz1001 May 24, 2022
2036524
center current sample
nafiz1001 May 24, 2022
7b4e21c
align dots
nafiz1001 May 24, 2022
b7247b3
reduce apparent whitespace
nafiz1001 May 24, 2022
f7f85c2
_End sentences with a period._
nafiz1001 May 25, 2022
8ba0d20
add d3@5.5.0
nafiz1001 May 26, 2022
dc8f4f2
fix indentation
nafiz1001 May 26, 2022
2279545
position current node to the left
nafiz1001 May 26, 2022
03bf5eb
use ref to get width and height for graph
nafiz1001 May 26, 2022
b315b8b
improve code quality
nafiz1001 May 27, 2022
f780115
add reset button
nafiz1001 May 27, 2022
15914f4
refactor
nafiz1001 May 27, 2022
37cccc4
don't fetch samples directly
nafiz1001 May 30, 2022
0f95a48
remove select_related
nafiz1001 May 31, 2022
52f800f
use divs in right places
nafiz1001 May 31, 2022
5bc6aa9
only reposition horizontally if the graph is too wide
nafiz1001 May 31, 2022
f419266
add docstrings
nafiz1001 Jun 5, 2022
290fd42
tiny tweaks
nafiz1001 Jun 6, 2022
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
2 changes: 2 additions & 0 deletions backend/fms_core/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
ProjectViewSet,
SequenceViewSet,
TaxonViewSet,
SampleLineageViewSet,
)

__all__ = ["router"]
Expand Down Expand Up @@ -56,3 +57,4 @@
router.register(r"revisions", RevisionViewSet)
router.register(r"users", UserViewSet)
router.register(r"groups", GroupViewSet)
router.register(r"sample-lineage", SampleLineageViewSet, basename="sample-lineage")
28 changes: 27 additions & 1 deletion backend/fms_core/services/sample_lineage.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.db.models import F
from django.core.exceptions import ValidationError
from fms_core.models import SampleLineage
from fms_core.models import SampleLineage, Sample, DerivedBySample, ProcessMeasurement


def create_sample_lineage(parent_sample, child_sample, process_measurement):
Expand All @@ -25,3 +26,28 @@ def create_sample_lineage(parent_sample, child_sample, process_measurement):
errors.append(str(e))

return (sample_lineage, errors, warnings)

def create_sample_lineage_graph(sampleId):
errors = []
nodes = []
edges = []

if not Sample.objects.filter(pk=sampleId).exists():
errors.append(f"Sample with id ${sampleId} does not exist")

if not errors:
derivedBySample = DerivedBySample.objects.filter(sample__id=sampleId) \
.values_list("derived_sample__biosample_id", flat=True)

sampleIds = DerivedBySample.objects.filter(derived_sample__biosample__id__in=derivedBySample) \
.values_list("sample__id", flat=True)
samples = Sample.objects.filter(id__in=sampleIds)

process_measurements = ProcessMeasurement.objects.filter(source_sample__in=sampleIds) \
.select_related("process__lineage").annotate(child_sample=F("lineage__child")) \
.select_related("process_protocol").annotate(protocol_name=F("process__protocol__name"))

nodes = list(samples.values("id", "name", "quality_flag", "quantity_flag"))
edges = list(process_measurements.values("id", "source_sample", "child_sample", "protocol_name"))

return (nodes, edges, errors)
2 changes: 2 additions & 0 deletions backend/fms_core/viewsets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from .platform import PlatformViewSet
from .library_type import LibraryTypeViewSet
from .taxon import TaxonViewSet
from .sample_lineage import SampleLineageViewSet

__all__ = [
"ContainerViewSet",
Expand Down Expand Up @@ -50,4 +51,5 @@
"PlatformViewSet",
"LibraryTypeViewSet",
"TaxonViewSet",
"SampleLineageViewSet"
]
21 changes: 21 additions & 0 deletions backend/fms_core/viewsets/sample_lineage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from fms_core.services.sample_lineage import create_sample_lineage_graph
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from django.core.exceptions import ValidationError

from fms_core.models import Sample
from fms_core.serializers import SampleSerializer, ProcessMeasurementSerializer

class SampleLineageViewSet(viewsets.ViewSet):
@action(detail=True, methods=["get"])
def graph(self, _request, pk):
nodes, edges, errors = create_sample_lineage_graph(pk)

if errors:
raise ValidationError(errors)
else:
return Response({
"nodes": nodes,
"edges": edges,
})
Loading