Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
tramyn committed Sep 28, 2020
2 parents 97fd6b3 + c8d690b commit d7180e5
Show file tree
Hide file tree
Showing 34 changed files with 1,266 additions and 215 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ This project is set up to build docker images for the server and for the Google
docker push username/repo_name:tag_name_and_version
```
4. To build and push a docker image for GAS,
- Update `current_release`(a variable) in [ip_addon_script.py](https://github.com/SD2E/experimental-intent-parser/blob/master/intent_parser/addons/ip_addon_script.py) to reflect the tool's version for release.
- Update `current_release`(a variable) in [ip_addon_script.py](https://github.com/SD2E/experimental-intent-parser/blob/master/intent_parser/addons/ip_addon_script.py) to reflect the tool's version for release.
- Update version in [setup.py](https://github.com/SD2E/experimental-intent-parser/blob/a0e3108888dfaa12e139dbb516a262dd63ddf271/intent_parser/setup.py#L5) to reflect the tool's version for release.
- Run the following dockerhub commands:
```
Expand Down
7 changes: 0 additions & 7 deletions intent_parser/accessor/google_doc_accessor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from googleapiclient.discovery import build
from intent_parser.constants.google_doc_api_constants import TextStyleFields
import intent_parser.constants.google_doc_api_constants as doc_constants
import logging
import statistics
Expand Down Expand Up @@ -111,12 +110,6 @@ def merge_table_cells(self,

return {doc_constants.REQUEST_MERGE_TABLE_CELLS: merge_properties}

def update_text_style(self, text_start_index, text_end_index):
text_style_properties = {doc_constants.TEXT_STYLE: '',
doc_constants.FIELDS: TextStyleFields.BOLD,
doc_constants.RANGE: self.create_range(text_start_index, text_end_index)}
return {doc_constants.REQUEST_UPDATE_TEXT_STYLE: text_style_properties}

def execute_batch_request(self, requests, document_id):
return self._docs_service.documents().batchUpdate(documentId=document_id,
body={'requests': requests}).execute()
54 changes: 54 additions & 0 deletions intent_parser/accessor/google_drive_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ def __init__(self, credentials):
self._service = build('drive', 'v3', credentials=credentials)
self._authed_session = AuthorizedSession(credentials)

def insert_comment_with_anchor(self, file_id, comment_text, quoted_tex, anchor_data):
body = {'content': comment_text,
'quotedFileContent': {'value': quoted_tex},
'anchor': json.dumps(anchor_data)}
results = self._service.comments.create(fileId=file_id,
fields='*',
body=body).execute()

def get_documents_from_folder(self, folder_id):
"""
Get all Google Docs from a Google Drive folder.
Expand Down Expand Up @@ -130,6 +138,52 @@ def get_file_with_revision(self, file_id, revision_id, mime_type):
response = self._authed_session.request('GET', url)
return response

def insert_comment_box(self, file_id, comment_message, quoted_text=None):
"""Insert a comment box to the desired document.
Args:
file_id: ID of a document.
comment_message: message to display in comment box
quoted_text: text in document that comment box refers to.
"""
new_comment = {'content': comment_message}
if quoted_text:
new_comment['context'] = {'value': quoted_text}
try:
response = self._service.comments().insert(fileId=file_id,
body=new_comment).execute()
except errors.HttpError as error:
self.logger.warning('Unable to insert comment box to file: %s due to %s' % (file_id, error))

def retrieve_comments(self, file_id):
"""Retrieve a list of comments.
Args:
service: Drive API service instance.
file_id: ID of the file to retrieve comments for.
Returns:
List of comments.
"""
try:
comments = self._service.comments().list(fileId=file_id).execute()
return comments.get('items', [])
except errors.HttpError as error:
self.logger.warning('Unable to retrieve comments from file: %s due to %s' % (file_id, error))

def remove_comment(self, file_id, comment_id):
"""Remove a comment.
Args:
service: Drive API service instance.
file_id: ID of the file to remove the comment for.
comment_id: ID of the comment to remove.
"""
try:
self._service.comments().delete(
fileId=file_id, commentId=comment_id).execute()
except errors.HttpError as error:
self.logger.warning('Unable to remove comment box from file: %s due to %s' % (file_id, error))

def upload_revision(self, document_name, document, folder_id, original_format, title='Untitled',
target_format='*/*'):
"""Upload file to a Google Drive folder.
Expand Down
2 changes: 1 addition & 1 deletion intent_parser/accessor/item-map.json

Large diffs are not rendered by default.

47 changes: 23 additions & 24 deletions intent_parser/accessor/sbol_dictionary_accessor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import timedelta
from intent_parser.experiment_variables.experiment_variables import ExperimentVariable
from intent_parser.accessor.google_accessor import GoogleAccessor
from intent_parser.intent_parser_exceptions import DictionaryMaintainerException
import intent_parser.table.cell_parser as cell_parser
Expand Down Expand Up @@ -370,7 +371,7 @@ def gen_row_data(self, entry, tab):

def map_common_names_and_tacc_id(self):
result = {}
attribute_tab = self.get_tab_sheet(dictionary_constants.ATTRIBUTE_TAB)
attribute_tab = self.get_tab_sheet(dictionary_constants.TAB_ATTRIBUTE)
for row in attribute_tab:
if dictionary_constants.COLUMN_COMMON_NAME in row and dictionary_constants.COLUMN_TACC_UID in row:
common_name = row[dictionary_constants.COLUMN_COMMON_NAME]
Expand All @@ -394,20 +395,34 @@ def get_mapped_strain(self, lab_name):
raise DictionaryMaintainerException(message)
lab_uid = dictionary_constants.MAPPED_LAB_UID[lab_name]

strain_tab = self.get_tab_sheet(dictionary_constants.STRAIN_TAB)
strain_tab = self.get_tab_sheet(dictionary_constants.TAB_STRAIN)
for row in strain_tab:
if dictionary_constants.COLUMN_COMMON_NAME in row \
and dictionary_constants.COLUMN_SYNBIOHUB_URI in row\
and lab_uid in row:
if (dictionary_constants.COLUMN_COMMON_NAME in row
and dictionary_constants.COLUMN_SYNBIOHUB_URI in row
and lab_uid in row):
sbh_uri = row[dictionary_constants.COLUMN_SYNBIOHUB_URI]
common_name = row[dictionary_constants.COLUMN_COMMON_NAME]
lab_strain_names = {}
if row[lab_uid]:
lab_strain_names = [name for name in cell_parser.PARSER.extract_name_value(row[lab_uid])]
mapped_strains[sbh_uri] = StrainMapping(sbh_uri, lab_name, common_name, lab_names=lab_strain_names)

mapped_strains[sbh_uri] = ExperimentVariable(sbh_uri, lab_name, common_name, lab_names=lab_strain_names)
return mapped_strains

def create_experiment_variables_from_spreadsheet_tab(self, tab):
experiment_variables ={}
for row in tab:
if (dictionary_constants.COLUMN_COMMON_NAME in row and dictionary_constants.COLUMN_SYNBIOHUB_URI in row):
sbh_uri = row[dictionary_constants.COLUMN_SYNBIOHUB_URI]
common_name = row[dictionary_constants.COLUMN_COMMON_NAME]
for lab_name, lab_uid in dictionary_constants.MAPPED_LAB_UID.items():
if lab_uid and lab_uid in row:
if row[lab_uid]:
lab_strain_names = [name for name in cell_parser.PARSER.extract_name_value(row[lab_uid])]
experiment_variables[common_name] = ExperimentVariable(sbh_uri, lab_name, common_name, lab_names=lab_strain_names)
else:
experiment_variables[common_name] = ExperimentVariable(sbh_uri, lab_name, common_name)
return experiment_variables

def get_common_name_from_transcriptic_id(self, transcriptic_id):
mappings = self.map_common_names_and_transcriptic_id()
for key, value in mappings.items():
Expand All @@ -417,7 +432,7 @@ def get_common_name_from_transcriptic_id(self, transcriptic_id):

def map_common_names_and_transcriptic_id(self):
result = {}
attribute_tab = self.get_tab_sheet(dictionary_constants.ATTRIBUTE_TAB)
attribute_tab = self.get_tab_sheet(dictionary_constants.TAB_ATTRIBUTE)
for row in attribute_tab:
if dictionary_constants.COLUMN_COMMON_NAME in row and dictionary_constants.COLUMN_TRANSCRIPT_UID in row:
common_name = row[dictionary_constants.COLUMN_COMMON_NAME]
Expand Down Expand Up @@ -492,19 +507,3 @@ def get_common_names_to_uri(self, use_cache=False):
self.logger.info('Num items in item_map: %d' % len(item_map))
return item_map

class StrainMapping(object):

def __init__(self, sbh_uri, lab_id, common_name, lab_names={}):
self._sbh_uri = sbh_uri
self._lab_id = lab_id
self._common_name = common_name
self._lab_names = lab_names

def get_common_name(self):
return self._common_name

def get_lab_id(self):
return self._lab_id

def has_lab_name(self, lab_name):
return lab_name in self._lab_names
65 changes: 63 additions & 2 deletions intent_parser/addons/Code.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var serverURL = 'http://intentparser.sd2e.org';
var versionString = '2.8';
var versionString = '2.9';

function onOpen() {
const ui = DocumentApp.getUi();
Expand All @@ -8,6 +8,15 @@ function onOpen() {
tablesMenu.addItem('Parameters', 'createParameterTable');
tablesMenu.addItem('Measurements', 'createTableMeasurements');

const tableHelpMenu = ui.createMenu('Tables');
tableHelpMenu.addItem('Controls', 'reportControlsInfo');
tableHelpMenu.addItem('Lab', 'reportLabInfo');
tableHelpMenu.addItem('Measurements', 'reportMeasurementsInfo');

const helpMenu = ui.createMenu('Help');
helpMenu.addSubMenu(tableHelpMenu);
helpMenu.addItem('About', 'showHelp');

const menu = ui.createMenu('Parse Intent');
menu.addItem('Analyze from top', 'sendAnalyzeFromTop');
menu.addItem('Analyze from cursor', 'sendAnalyzeFromCursor');
Expand All @@ -23,10 +32,62 @@ function onOpen() {
menu.addItem('Report Experiment Status', 'reportExperimentStatus');
menu.addSubMenu(tablesMenu);
menu.addItem('File Issues', 'reportIssues');
menu.addItem('Help', 'showHelp');
menu.addSubMenu(helpMenu);
menu.addToUi();
}

function reportControlsInfo(){
html_content = '<h2> Controls Table </h2>\n' +
'<p><b>Description</b>: control definition based on time, strain, contents, etc.</p>\n' +
'<b>Required fields:</b>\n' +
'<ul>\n' +
'\t<li><a href="https://schema.catalog.sd2e.org/schemas/control_type.json"> <b>Type</b></a>: an expected type for this control. <i>Example:</i> HIGH_FITC</li>\n' +
'\t<li><b>Strains</b>: a list of one or more string values representing a strain listed in the SBOL Dictionary lab name. <i>Example:</i> B_subtilis_comKS_mCherry_1x</li>\n' +
'</ul>\n' +
'<b>Optional fields:</b>\n' +
'<ul>\n' +
'\t<li><b>Channel</b>: a string value representing FCS channel. <i>Example:</i> BL1-A</li>\n' +
'\t<li><b>Contents</b>: a list of one or more string values representing the content of a control. A content can come in the form of a name or a name followed by a value, followed by a timepoint unit. <i>Example:</i> beta_estradiol or beta_estradiol 0.05 micromole</li>\n' +
'\t<li><b><a href="https://schema.catalog.sd2e.org/schemas/time_unit.json">Timepoints</a></b>: a list of one or more string values representing point in a time series. <i>Example:</i> 2, 4 hours</li>\n' +
'</ul>';
showSidebar(html_content);
}

function reportLabInfo(){
html_content = '<h2> Lab Table </h2>\n' +
'<p><b>Description</b>: information linked to a lab.</p>\n' +
'<b>Required fields:</b>\n' +
'<ul>\n' +
'\t<li><a href="https://schema.catalog.sd2e.org/schemas/lab.json"> <b>Lab</b></a>: a string value representing the lab that performed this experiment. <i>Example:</i> TACC</li>\n' +
'</ul>\n' +
'<b>Optionalfields:</b>\n' +
'<ul>\n' +
'\t<li><b>Experiment_id</b>: a string identifier, namespaced performer, for the experiment. <i>Example:</i> 123</li>\n' +
'</ul>';
showSidebar(html_content);
}

function reportMeasurementsInfo(){
html_content = '<h2> Measurements Table </h2>\n' +
'<p><b>Description</b>: measurements expected to be produced for a run, broken down by measurement type and sample conditions.</p>\n' +
'<b>Required fields:</b>\n' +
'<ul>\n' +
'\t<li><a href="https://schema.catalog.sd2e.org/schemas/measurement_type.json"> <b>Measurement Type</b></a>: an expected file type for this measurement. <i>Example:</i> RNA_SEQ</li>\n' +
'\t<li><a href="https://schema.catalog.sd2e.org/schemas/filetype_label.json"> <b>File Type</b></a>: a list of one or more expected file type for this measurement. <i>Example:</i> MSWORD, SPREADSHEET</li>\n' +
'</ul>\n' +
'<b>Optional fields:</b>\n' +
'<ul>\n' +
'\t<li><b>Batch</b>: a list of one or more numerical values representing the batches a measurement belongs to. <i>Example:</i> 1, 2, 3</li>\n' +
'\t<li><b>Controls</b>: a list of Control Table captions for representing expected control elements for this run. <i>Example:</i> Table 1, Table 2</li>\n' +
'\t<li><b>Ods</b>: a list of one or more numerical values representing expected optical densities for this measurement. <i>Example:</i> 5</li>\n' +
'\t<li><b>Replicates</b>: a list of one or more numerical values representing expected number of replicates. <i>Example:</i> 6</li>\n' +
'\t<li><b>Strains</b>: a list of one or more string values representing expected strains for this measurement. Strains listed in this field must have a hyperlink that references to a SBH URI. <i>Example:</i> UWBF_6390</li>\n' +
'\t<li><a href="https://schema.catalog.sd2e.org/schemas/temperature.json"><b>Temperatures</b></a>: a list of one or more numerical values followed by a temperature unit representing expected temperatures for this measurement. <i>Example</i>: 30 celsius</li>\n' +
'\t<li><a href="https://schema.catalog.sd2e.org/schemas/time_unit.json"><b>Timepoints</b></a>: a list of one or more numerical values followed by a timepoint unit representing expected timepoints for this run. <i>Example:</i> 0, 4, 8, 12, 16 hour</li>\n' +
'</ul>';
showSidebar(html_content);
}

function showHelp() {
var helpHTML = '\
<p>\
Expand Down
2 changes: 1 addition & 1 deletion intent_parser/addons/addon_file.json

Large diffs are not rendered by default.

18 changes: 7 additions & 11 deletions intent_parser/constants/google_doc_api_constants.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from enum import Enum

REQUEST_DELETE_CONTENT_RANGE = 'deleteContentRange'
REQUEST_DELETE_TABLE_ROW = 'deleteTableRow'
REQUEST_INSERT_TABLE = 'insertTable'
Expand All @@ -8,13 +6,9 @@
REQUEST_MERGE_TABLE_CELLS = 'mergeTableCells'
REQUEST_UPDATE_TEXT_STYLE = 'updateTextStyle'

BOLD = 'bold'
ITALIC = 'italic'
UNDERLINE = 'underline'
STRIKETHROUGH = 'strikethrough'
SMALL_CAPS = 'smallCaps'
HEADING_ID = 'headingId'

BODY = 'body'
BOLD = 'bold'
BOOKMARK_ID = 'bookmarkId'
CONTENT = 'content'
COLUMN_INDEX = 'columnIndex'
Expand All @@ -24,8 +18,10 @@
END_INDEX = 'endIndex'
END_OF_SEGMENT_LOCATION = 'endOfSegmentLocation'
FIELDS = 'fields'
HEADING_ID = 'headingId'
INDEX = 'index'
INSERT_BELOW = 'insertBelow'
ITALIC = 'italic'
LINK = 'link'
LOCATION = 'location'
NUMBER_OF_COLUMNS = 'columns'
Expand All @@ -35,7 +31,9 @@
ROW_INDEX = 'rowIndex'
ROW_SPAN = 'rowSpan'
SEGMENT_ID = 'segmentId'
SMALL_CAPS = 'smallCaps'
START_INDEX = 'startIndex'
STRIKETHROUGH = 'strikethrough'
TABLE = 'table'
TABLE_CELLS = 'tableCells'
TABLE_CELL_LOCATION = 'tableCellLocation'
Expand All @@ -45,8 +43,6 @@
TEXT = 'text'
TEXT_RUN = 'textRun'
TEXT_STYLE = 'textStyle'
UNDERLINE = 'underline'
URL = 'url'

class TextStyleFields(Enum):
BOLD = 'bold'
UNKNOWN = '*'
8 changes: 7 additions & 1 deletion intent_parser/constants/intent_parser_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@
GOOGLE_DOC_MIMETYPE = 'application/vnd.google-apps.document'
WORD_DOC_MIMETYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'

# Stateos Protocols Supported in IP
GROWTH_CURVE_PROTOCOL = 'GrowthCurve'
OBSTACLE_COURSE_PROTOCOL = 'ObstacleCourse'
TIME_SERIES_HTP_PROTOCOL = 'TimeSeriesHTP'

# Mapping protocols to human readible names
PARAMETER_PROTOCOL = 'protocol'
PROTOCOL_NAMES = {GROWTH_CURVE_PROTOCOL: 'Growth Curves',
TIME_SERIES_HTP_PROTOCOL: 'Time Series',
Expand All @@ -57,6 +59,7 @@
PARAMETER_EXPERIMENT_REFERENCE_URL_FOR_XPLAN = 'experiment_reference_url_for_xplan'
PARAMETER_TEST_MODE = 'test_mode'
PARAMETER_SUBMIT = 'submit'
PARAMETER_BASE_DIR = 'xplan_base_dir'
PARAMETER_XPLAN_REACTOR = 'xplan_reactor'
PARAMETER_PLATE_SIZE = 'plate_size'
PARAMETER_PLATE_NUMBER = 'plate_number'
Expand All @@ -66,7 +69,9 @@
PARAMETER_PROTOCOL_ID = 'protocol_id'

PARAMETER_EXP_INFO_MEDIA_WELL_STRINGS = 'exp_info.media_well_strings'
PARAMETER_INDUCTION_INFO_REAGENTS = 'induction_info.induction_reagents'
PARAMETER_INDUCTION_INFO_REAGENTS_INDUCER = 'induction_info.induction_reagents.inducer'
PARAMETER_INDUCTION_INFO_SAMPLING_INFO = 'induction_info.sampling_info'
PARAMETER_MEASUREMENT_INFO_36_HR_READ = 'measurement_info.36_hr_read'
PARAMETER_MEASUREMENT_INFO_FLOW_INFO = 'measurement_info.flow_info'
PARAMETER_MEASUREMENT_INFO_PLATE_READER_INFO = 'measurement_info.plate_reader_info'
Expand All @@ -85,7 +90,7 @@
TEST_SPREADSHEET_ID = '1wHX8etUZFMrvmsjvdhAGEVU1lYgjbuRX5mmYlKv7kdk' # Intent parser test dict
UNIT_TEST_SPREADSHEET_ID = '1r3CIyv75vV7A7ghkB0od-TM_16qSYd-byAbQ1DhRgB0' #sd2 unit test dictionary

# Header types
# Table headers
HEADER_BATCH_VALUE = 'batch'
HEADER_CHANNEL_VALUE = 'Channel'
HEADER_CONTENTS_VALUE = 'Contents'
Expand All @@ -110,6 +115,7 @@
HEADER_TEMPERATURE_VALUE = 'temperature'
HEADER_TIMEPOINT_VALUE = 'Timepoint'

# Table header types
HEADER_BATCH_TYPE = 'BATCH'
HEADER_CHANNEL_TYPE = 'CHANNEL'
HEADER_CONTENTS_TYPE = 'CONTENTS'
Expand Down
Loading

0 comments on commit d7180e5

Please sign in to comment.