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

Search enhancements #13

Open
wants to merge 41 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
3a0d397
wip
billyfish Feb 2, 2024
255ae34
wip
billyfish Feb 2, 2024
ed24397
Merge branch 'master' of github.com:TGAC/grassroots_services_django_web
billyfish Feb 20, 2024
2ec56b6
wip
billyfish Feb 22, 2024
b499a12
wip
billyfish Feb 28, 2024
7dea5c2
wip on search result enhancements
billyfish Apr 4, 2024
cbb4f1f
Saved changes to gi_dynamics_web for search enhaancements branch
DOC-MEX Jun 12, 2024
a7ce941
Update footer (for old templates)
DOC-MEX Jun 12, 2024
7f7fd13
Update header (old templates)
DOC-MEX Jun 13, 2024
d9ac352
Provide missing value of study_design to modal window that display in…
DOC-MEX Jun 21, 2024
3d3723a
Test for displaying multiple images per plot in maps that includes pl…
DOC-MEX Jun 26, 2024
b10e412
Photo_receiver: Create intermediate subfolder when saving images, sub…
DOC-MEX Jun 26, 2024
e0f70eb
Function for retrieving latest photos now adds intermediate subfolder…
DOC-MEX Jun 27, 2024
2a4948a
Authentication tests
DOC-MEX Jun 27, 2024
fccf234
Merge branch 'search_enhancements' of https://github.com/TGAC/grassro…
DOC-MEX Jun 27, 2024
6cc8d29
Update url of photos retrieved, now include intermediate subfolder na…
DOC-MEX Jun 27, 2024
825d8ed
Updates to formatGPSPlot (fieldtrial_map.js) function and views.py fo…
DOC-MEX Jun 28, 2024
25c652c
Update function in views.py (fieldtrial) for single study to create i…
DOC-MEX Jun 28, 2024
145b4f7
Add paths and urls for live beta server test (wew carousel for images…
DOC-MEX Jun 28, 2024
39384ac
Updates to formatGPSPlot (fieldtrial_map.js) function and views.py fo…
DOC-MEX Jun 28, 2024
26710e3
Update function in views.py (fieldtrial) for single study to create i…
DOC-MEX Jun 28, 2024
e252a0c
Add paths and urls for live beta server test (wew carousel for images…
DOC-MEX Jun 28, 2024
82f10cd
Improve presentation of carousel of images over map of single studies
DOC-MEX Jul 1, 2024
7514bdf
correct merging conflicts
DOC-MEX Jul 1, 2024
2954384
Update create_CSV function. Use full path when working on the creatio…
DOC-MEX Jul 12, 2024
4f1e57e
solve mergeing conflict in requirements.txt file
DOC-MEX Jul 29, 2024
c56b477
Add carousel for displaying multiple images per plot to the plots page
DOC-MEX Aug 2, 2024
36c3e10
Add check in format_phenotype function to prevent reading plots with …
DOC-MEX Aug 2, 2024
3c4fd8a
Add Date as a default column in the modal tables of the plots.html t…
DOC-MEX Aug 12, 2024
1383b07
Add Date as a default column in the modal tables of the study.html t…
DOC-MEX Aug 12, 2024
b4de587
Add date (when available) of latest observation to hovering data in h…
DOC-MEX Aug 12, 2024
c60620a
Ensure correct paring of date and observation value
DOC-MEX Aug 13, 2024
0bc746f
Ensure correct paring of dates and observation values in modal table …
DOC-MEX Aug 13, 2024
52bccea
When a phenotype has multiple observation for a given plot, display t…
DOC-MEX Aug 13, 2024
65fab07
Remove links and old jquery libraries
DOC-MEX Sep 3, 2024
b9b2347
Remove links and old jquery libraries
DOC-MEX Sep 3, 2024
fce5fbb
Display date of photo in the carousel of images over the map and the …
DOC-MEX Sep 6, 2024
5fb7d29
Adjust date format of the photos in the carousel of images
DOC-MEX Sep 6, 2024
2ce2b23
function for updating limits.json. It accepts now any generic phenotype
DOC-MEX Sep 18, 2024
940cac1
added marti samples to study info
billyfish Oct 7, 2024
9cefc64
updating provider details for the treatment and measured variable sea…
billyfish Oct 19, 2024
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
7 changes: 4 additions & 3 deletions fieldtrial/grassroots_csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ def create_CSV(plot_data, phenotypes, treatment_factors, plot_id):
name = plot_id + '.csv'
path = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'filedownload/Files'))
filename = os.path.join(path, name)
data_cleaned_path = os.path.join(path, 'data_cleaned.csv')
print(filename)

# Actual order of columns given by these headers
Expand Down Expand Up @@ -294,18 +295,18 @@ def create_CSV(plot_data, phenotypes, treatment_factors, plot_id):
print(removed_columns_message)
#print(f"The following columns have been removed due to being empty: {', '.join(removed_columns)}")

with open('data_cleaned.csv', 'w', encoding='UTF8', newline='') as f:
with open(data_cleaned_path, 'w', encoding='UTF8', newline='') as f:
writer = csv.DictWriter(f, fieldnames=[col for col in headers if col in exception or col not in empty_columns])
writer.writeheader()
writer.writerows(new_rows)
else:
# no empty columns, so write the original data to the cleaned file
with open('data_cleaned.csv', 'w', encoding='UTF8', newline='') as f:
with open(data_cleaned_path, 'w', encoding='UTF8', newline='') as f:
writer = csv.DictWriter(f, fieldnames=headers)
writer.writeheader()
writer.writerows(new_rows)


# replace the original file with the cleaned data
os.remove(filename)
os.rename('data_cleaned.csv', filename)
os.rename(data_cleaned_path, filename)
126 changes: 95 additions & 31 deletions fieldtrial/grassroots_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def searchPhenotypeUnit(listPheno, value):
'''
test rendering plotly interactive heatmap
'''
def plotly_plot(numpy_matrix, accession, title, unit, IDs, treatments):
def plotly_plot(numpy_matrix, accession, title, unit, IDs, treatments, dates):

##numpy_matrix = np.flipud(numpy_matrix) # To Match order shown originally in JS code
#plotID = np.flipud(IDs)
Expand Down Expand Up @@ -116,20 +116,38 @@ def plotly_plot(numpy_matrix, accession, title, unit, IDs, treatments):
labels=dict(x="columns", y="rows", color=units),
color_continuous_scale=px.colors.sequential.Greens, height=800 )

#print(treatments)
if len(treatments)>0:
treatments = treatments.reshape(Y,X)
treatments = np.flipud(treatments)

fig.update_traces(
customdata = np.moveaxis([accession, s_matrix, plotID, treatments], 0,-1),
#hovertemplate="Accession: %{customdata[0]}<br>raw value: %{customdata[1]:.2f} <extra></extra>")
hovertemplate="Accession: %{customdata[0]}<br>Raw value: %{customdata[1]}<br>Plot ID: %{customdata[2]} (column: %{x}, row: %{y})<br>Treatment: %{customdata[3]} <extra></extra>")
if len(dates)>0: # Only include dates if they are not an empty list
dates = dates.reshape(Y, X)
dates = np.flipud(dates)
fig.update_traces(
customdata=np.moveaxis([accession, s_matrix, plotID, treatments, dates], 0, -1),
hovertemplate="Accession: %{customdata[0]}<br>Raw value: %{customdata[1]}<br>Plot ID: %{customdata[2]} (column: %{x}, row: %{y})<br>Treatment: %{customdata[3]}<br>Date: %{customdata[4]}<extra></extra>"
)
else:
fig.update_traces(
customdata=np.moveaxis([accession, s_matrix, plotID, treatments], 0, -1),
hovertemplate="Accession: %{customdata[0]}<br>Raw value: %{customdata[1]}<br>Plot ID: %{customdata[2]} (column: %{x}, row: %{y})<br>Treatment: %{customdata[3]}<extra></extra>"
)


else:
fig.update_traces(
customdata = np.moveaxis([accession, s_matrix, plotID], 0,-1),
hovertemplate="Accession: %{customdata[0]}<br>Raw value: %{customdata[1]}<br>Plot ID: %{customdata[2]} (column: %{x}, row:%{y})<extra></extra>")
if len(dates)>0: # Only include dates if they are not an empty list
dates = dates.reshape(Y, X)
dates = np.flipud(dates)
fig.update_traces(
customdata=np.moveaxis([accession, s_matrix, plotID, dates], 0, -1),
hovertemplate="Accession: %{customdata[0]}<br>Raw value: %{customdata[1]}<br>Plot ID: %{customdata[2]} (column: %{x}, row:%{y})<br>Date: %{customdata[3]}<extra></extra>"
)
else:
fig.update_traces(
customdata=np.moveaxis([accession, s_matrix, plotID], 0, -1),
hovertemplate="Accession: %{customdata[0]}<br>Raw value: %{customdata[1]}<br>Plot ID: %{customdata[2]} (column: %{x}, row:%{y})<extra></extra>"
)


fig.update_layout(font=dict(family="Courier New, monospace",size=12,color="Black"),title={
'text': title,
Expand All @@ -150,6 +168,35 @@ def plotly_plot(numpy_matrix, accession, title, unit, IDs, treatments):

return plot_div

#########################################################################################################
def observation_dates(arraysJson, rows, columns, current_name):
dt = np.dtype(('U', 80)) # Adjust dtype if date strings are longer
matrix = np.zeros((rows, columns), dtype=dt)
matrix[:] = "N/A"

for r in range(len(arraysJson)):
i = int(arraysJson[r]['row_index'])
j = int(arraysJson[r]['column_index'])
i = i - 1
j = j - 1

if 'observations' in arraysJson[r]['rows'][0]:
# Filter observations by the selected phenotype
relevant_observations = [
obs for obs in arraysJson[r]['rows'][0]['observations'] if obs['phenotype']['variable'] == current_name
]

if relevant_observations:
# Sort observations by date and select the latest one
relevant_observations.sort(key=lambda x: x.get('date', ''), reverse=True)
latest_observation = relevant_observations[0]
observation_date = latest_observation.get('date', 'N/A').split('T')[0] # Keep only the date part
matrix[i][j] = observation_date

matrix = matrix.flatten()
return matrix


############################################################################################
'''
test rendering seaborn image
Expand Down Expand Up @@ -362,18 +409,27 @@ def numpy_data(json, pheno, current_name, total_rows, total_columns):
plotsIds = np.append(plotsIds, json[j]['rows'][0]['study_index'] )

elif ( 'observations' in json[j]['rows'][0] ):
if( search_phenotype(json[j]['rows'][0]['observations'], current_name) ):
indexCurrentPhenotype = search_phenotype_index (json[j]['rows'][0]['observations'], current_name)
if 'raw_value' in json[j]['rows'][0]['observations'][indexCurrentPhenotype]:
row_raw = np.append(row_raw, json[j]['rows'][0]['observations'][indexCurrentPhenotype]['raw_value'])
if 'corrected_value' in json[j]['rows'][0]['observations'][indexCurrentPhenotype]:
row_raw = np.append(row_raw, json[j]['rows'][0]['observations'][indexCurrentPhenotype]['corrected_value'])
row_acc = np.append(row_acc, json[j]['rows'][0]['material']['accession'])
plotsIds = np.append(plotsIds, json[j]['rows'][0]['study_index'] )
if search_phenotype(json[j]['rows'][0]['observations'], current_name):
# Instead of getting the first match, we now sort the relevant observations by date
relevant_observations = [
obs for obs in json[j]['rows'][0]['observations'] if lookup_keys(obs, 'phenotype.variable') == current_name
]
relevant_observations.sort(key=lambda x: x.get('date', ''), reverse=True)
latest_observation = relevant_observations[0]
#print("latest_observations -> ", latest_observation)

if 'raw_value' in latest_observation:
row_raw = np.append(row_raw, latest_observation['raw_value'])
if 'corrected_value' in latest_observation:
row_raw = np.append(row_raw, latest_observation['corrected_value'])

row_acc = np.append(row_acc, json[j]['rows'][0]['material']['accession'])
plotsIds = np.append(plotsIds, json[j]['rows'][0]['study_index'])
else:
row_raw = np.append(row_raw, np.inf ) # use infinity for N/A data
row_acc = np.append(row_acc, json[j]['rows'][0]['material']['accession'])
plotsIds = np.append(plotsIds, json[j]['rows'][0]['study_index'] )
row_raw = np.append(row_raw, np.inf) # use infinity for N/A data
row_acc = np.append(row_acc, json[j]['rows'][0]['material']['accession'])
plotsIds = np.append(plotsIds, json[j]['rows'][0]['study_index'])

else:
if('rows' in json[j]): # when plots have rows but no observations!!
row_raw = np.append(row_raw, np.inf ) # use infinity for N/A data
Expand All @@ -398,18 +454,26 @@ def numpy_data(json, pheno, current_name, total_rows, total_columns):
plotsIds = np.append(plotsIds, json[j]['rows'][0]['study_index'] )

elif ( 'observations' in json[j]['rows'][0] ):
if( search_phenotype(json[j]['rows'][0]['observations'], current_name) ):
indexCurrentPhenotype = search_phenotype_index (json[j]['rows'][0]['observations'], current_name)
if 'raw_value' in json[j]['rows'][0]['observations'][indexCurrentPhenotype]:
row_raw = np.append(row_raw, json[j]['rows'][0]['observations'][indexCurrentPhenotype]['raw_value'])
if 'corrected_value' in json[j]['rows'][0]['observations'][indexCurrentPhenotype]:
row_raw = np.append(row_raw, json[j]['rows'][0]['observations'][indexCurrentPhenotype]['corrected_value'])
row_acc = np.append(row_acc, json[j]['rows'][0]['material']['accession'])
plotsIds = np.append(plotsIds, json[j]['rows'][0]['study_index'] )
if search_phenotype(json[j]['rows'][0]['observations'], current_name):
# Instead of getting the first match, we now sort the relevant observations by date
relevant_observations = [
obs for obs in json[j]['rows'][0]['observations'] if lookup_keys(obs, 'phenotype.variable') == current_name
]
relevant_observations.sort(key=lambda x: x.get('date', ''), reverse=True)
latest_observation = relevant_observations[0]
#print("latest_observations -> ", latest_observation)

if 'raw_value' in latest_observation:
row_raw = np.append(row_raw, latest_observation['raw_value'])
if 'corrected_value' in latest_observation:
row_raw = np.append(row_raw, latest_observation['corrected_value'])

row_acc = np.append(row_acc, json[j]['rows'][0]['material']['accession'])
plotsIds = np.append(plotsIds, json[j]['rows'][0]['study_index'])
else:
row_raw = np.append(row_raw, np.inf )
row_acc = np.append(row_acc, json[j]['rows'][0]['material']['accession'])
plotsIds = np.append(plotsIds, json[j]['rows'][0]['study_index'] )
row_raw = np.append(row_raw, np.inf) # use infinity for N/A data
row_acc = np.append(row_acc, json[j]['rows'][0]['material']['accession'])
plotsIds = np.append(plotsIds, json[j]['rows'][0]['study_index'])
else:
if('rows' in json[j]): # when plots have rows but no observations!!
row_raw = np.append(row_raw, np.inf ) # use infinity for N/A data
Expand Down
59 changes: 59 additions & 0 deletions fieldtrial/templates/fieldtrial/study.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
{% block all_styles_and_scripts %}
{{ block.super }}
<!-- ********************************************************-->
<script type="text/javascript">
var images = [
{% for url in imageUrls %}
"{{ url }}",
{% endfor %}
];
</script>
<!-- Leaflet NEWEST VERSION -->
<link rel="stylesheet" href="{% static 'fieldtrial/SCRIPTS/leaflet/leaflet.css' %}"/>
<script src="{% static 'fieldtrial/SCRIPTS/leaflet/leaflet.js' %}"></script>
Expand Down Expand Up @@ -77,6 +84,43 @@
margin: 0 auto;
text-align: left;
}

.carousel-button {
cursor: pointer;
background-color: transparent;
border: none;
font-size: 24px;
padding: 10px;
z-index: 10; /* Ensures the button is above the image */
}

.image-carousel {
display: flex;
align-items: center;
justify-content: center;
position: relative; /* Required for absolute positioning of children */
}

.image-carousel .carouselImage {
width: 300px; /* Fixed width, adjust as necessary */
height: auto; /* Maintain aspect ratio */
display: block;
}

.image-container {
max-width: 100%;
text-align: center; // Centers the text and image
position: relative; // Needed for positioning elements inside it
}

.image-title {
background-color: #fff; // White background for the text
color: #000; // Black text color
padding: 5px;
display: block;
width: 100%; // Take full width of the container
text-align: center;
}

</style>

Expand Down Expand Up @@ -284,6 +328,21 @@ <h3 class="table-title centered-title">Study details</h3>
<tr><td><strong>Handbook pdf:</strong></td><td>
<a href="{% lookup_keys study_json "handbook.so:url" %}"> {% lookup_keys study_json "handbook.name" %} </a></td></tr>
{% endif %}


{% if "marti_samples" in study_json %}
<tr><td><strong>MARTi Samples:</strong></td>
<td>
{% for sample in study_json.marti_samples %}
<ul>
<li><a href="{% lookup_keys sample "so:url" %}"> {% lookup_keys sample "so:name" %} </a></li>
</ul>
{% endfor %}
</td>
{% else %}
<tr><td><strong>No MARTi Samples:</strong></td> <td></td>
{% endif %}

</table>
</section>

Expand Down
54 changes: 54 additions & 0 deletions fieldtrial/templates/plots.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,62 @@
height: 600px;
}
}
.carousel-button {
cursor: pointer;
background-color: transparent;
border: none;
font-size: 24px;
padding: 10px;
top: 50%; /* Center vertically */
transform: translateY(-50%); /* Center vertically */
position: absolute;
}

.carousel-button.left {
left: 50px; /* Adjust as necessary */
}

.carousel-button.right {
right: 50px; /* Adjust as necessary */
}

.image-carousel {
display: flex;
align-items: center;
justify-content: center;
position: relative; /* Required for absolute positioning of children */
}

.image-carousel .carouselImage {
width: 300px; /* Fixed width, adjust as necessary */
height: auto; /* Maintain aspect ratio */
display: block;
}

.image-container {
max-width: 100%;
text-align: center; // Centers the text and image
position: relative; // Needed for positioning elements inside it
}

.image-title {
background-color: #fff; // White background for the text
color: #000; // Black text color
padding: 5px;
display: block;
width: 100%; // Take full width of the container
text-align: center;
}

</style>

<script type="text/javascript">
var images = [
{% for url in imageUrls %}
"{{ url }}",
{% endfor %}
];
</script>
<section id="services" style="padding: 100px 0px 100px 0px ! important;">
<div class="container">
<!--style="width: 1170px ! important; margin-right: auto ! important; margin-left: auto ! important;">-->
Expand Down
1 change: 1 addition & 0 deletions fieldtrial/templates/study.html
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ <h5 class="modal-title"></h5>


</table>

</section>
-->

Expand Down
Loading