タグ: redmine

chem-redmine

I’m still playing with redmine.
I want to embed structure editor in redmine, and store structural information.
It’s good idea to make plugin, but it’s difficult to do ASAP.
So, I embedded javascript directory in base code.
At first, put javascript library JSME in $REDMINE_ROOT/public/javascripts/.
JSME can get from following site. http://peter-ertl.com/jsme/
Then added javascript and some html code.
Base code was $REDMINE_ROOT/app/views/issues/_form.html.erb
Before embed code, I make custom_field named smiles as text, that store smilestrings and set trucker Task.
OK let’s start.

yesterday, my code has bug.
I have mistake that form tag nested.
So I fixed the bug.
( remove tag )

<!-- added script -->
<%= javascript_include_tag "/javascripts/JSME/jsme/jsme.nocache.js" %>
<!-- added script -->

<%= labelled_fields_for :issue, @issue do |f| %>
<%= call_hook(:view_issues_form_details_top, { :issue => @issue, :form => f }) %>

<% if @issue.safe_attribute? 'is_private' %>
<p style="float:right; margin-right:1em;">
  <%= f.check_box :is_private, :no_label => true %><label class="inline" for="issue_is_private" id="issue_is_private_label"><%= l(:field_is_private) %></label>
</p>
<% end %>

<% if @issue.safe_attribute? 'project_id' %>
<p><%= f.select :project_id, project_tree_options_for_select(@issue.allowed_target_projects, :selected => @issue.project), {:required => true},
                :onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %></p>
<% end %>

<% if @issue.safe_attribute? 'tracker_id' %>
<p><%= f.select :tracker_id, @issue.project.trackers.collect {|t| [t.name, t.id]}, {:required => true},
                :onchange => "updateIssueFrom('#{escape_javascript project_issue_form_path(@project, :id => @issue, :format => 'js')}')" %></p>
<% end %>

<% if @issue.safe_attribute? 'subject' %>
<p><%= f.text_field :subject, :size => 80, :maxlength => 255, :required => true %></p>
<% end %>

<% if @issue.safe_attribute? 'description' %>
<p>
  <%= f.label_for_field :description, :required => @issue.required_attribute?('description') %>
  <%= link_to_function image_tag('edit.png'), '$(this).hide(); $("#issue_description_and_toolbar").show()' unless @issue.new_record? %>
  <%= content_tag 'span', :id => "issue_description_and_toolbar", :style => (@issue.new_record? ? nil : 'display:none') do %>
    <%= f.text_area :description,
                   :cols => 60,
                   :rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
                   :accesskey => accesskey(:edit),
                   :class => 'wiki-edit',
                   :no_label => true %>
  <% end %>

<%= call_hook(:view_issues_form_details_bottom, { :issue => @issue, :form => f }) %>
<% end %>

<!-- added script from here-->
<div name='chem_editor'>
<table border=0 width=''100%'>
<tr>
<td align=''center'>
<div code='JME.class' name='JME' archive='JME.jar' width=360 height=315>
</div>
</td>
<td>
<input type='button' value='GET SMILES' onClick='getSmiles()'>
</td>
</tr>
</table>
</div>
<p>test</p>
<!-- end -->

</p>
<%= wikitoolbar_for 'issue_description' %>
<% end %>

<div id="attributes" class="attributes">
  <%= render :partial => 'issues/attributes' %>
</div>
// this function get smiles from JME object and fill smile strings to custom_field.
<script language='javascript'>
function getSmiles(){
  var drawing = document.all.JME.smiles();
  document.all.issue_custom_field_values_1.value = drawing;
};
</script>


<% heads_for_wiki_formatter %>
<%= javascript_tag do %>
$(document).ready(function(){
  $("#issue_tracker_id, #issue_status_id").each(function(){
    $(this).val($(this).find("option[selected=selected]").val());
  });
});
<% end %>

Then restart server and click new ticket.
Then you can see…
Screen Shot 2015-02-02 at 11.16.28 PM
And push get smiles…
Screen Shot 2015-02-02 at 11.16.41 PM
Custom_field filled smiles ;-).
push submit button, smiles will be stored database.
There are no flexibility about this method, I’m studying about ruby, and redmine-plugins. So, I want to make more flexible code…
If anyone who has good advice or suggestion, please post comment here ;-).

redmine and rdkit

To think about DMTA cycle in drug discovery process, I think most important thing is ‘why you make the compound ‘.
We make hypothesis to solve problems, and think about priority what make first. And make it.
Next analyse assay data, and make next plan……
So, issue tracking system is good tool for hypothesis driven drug discovery.
Redmine is one of nice tool for ITS.
But it is not friendly for chemist, because this tool is often used for system development. There are no plug in for chemistry.

Med chem. wants to check issues with chemical structure ;-).
So, I try to very simple solution for post structure to redmine.
Redmine can use REST API. http://www.redmine.org/projects/redmine/wiki/Rest_api
So, from python, I make structure image using rdkit, and post structure as png image.
Procedure is following..

At first build redmine.(I used bitnami installer for this blogpost)
Then change setting use REST, and show thambnail.
If you check use REST for web app, you can get API key.
Then write simple python script.
I need two steps for post ticket with file.
1st, upload image and get token.
2nd post issue as xml.

# -*- coding:utf-8 -*-
import urllib2
import xml.etree.ElementTree

from rdkit import Chem
from rdkit.Chem import Draw
smiles = "CCCNCc1ccccc1"
filename = smiles+".jpg"
mol = Chem.MolFromSmiles( smiles )
Draw.MolToFile(mol, "out.png")
api_key = 'put on your API key'

f = open( "out.png", 'rb')
img = f.read()
f.close()

url = 'http://localhost:8081/redmine/uploads.xml'
request = urllib2.Request(url, data=img)
request.add_header('Content-Type', 'application/octet-stream')
request.add_header('X-Redmine-API-Key', api_key)
request.get_method = lambda: 'POST'

response = urllib2.urlopen(request)
ret = response.read()
print(ret)

doc = xml.etree.ElementTree.fromstring(ret)
token = doc.findtext('token')
print(token)

xml = """<?xml version="1.0"?>
<issue>
<project_id>1</project_id>
<subject>SytheticPlan1</subject>
<description>%s</description>
<start_date>2015-01-20</start_date>
<due_date>2015-02-10</due_date>
 <uploads type="array">
    <upload>
      <token>%s</token>
      <filename>out.png</filename>
      <description>None</description>
      <content_type>image/png</content_type>
   </upload>
 </uploads>
</issue>"""%(smiles, token)

url = 'http://localhost:8081/redmine/issues.xml'

# Content-Type:text/xml
# X-Redmine-API-Key:[API]
# method:post

request = urllib2.Request(url, data=xml)
request.add_header('Content-Type', 'text/xml')
request.add_header('X-Redmine-API-Key', api_key)
request.get_method = lambda: 'POST'

response = urllib2.urlopen(request)
ret = response.read()
print 'Response:', ret

OK, run script.

Last login: Sat Jan 24 14:10:16 on ttys000
iwatobipen$ cd Desktop/
iwatobipen$ python testapi2.py 
<?xml version="1.0" encoding="UTF-8"?><upload><token>your token</token></upload>
your token
Response: <?xml version="1.0" encoding="UTF-8"?><issue><id>1</id><project id="1" name="ChemoPj"/><tracker id="1" name="バグ"/><status id="1" name="新規"/><priority id="2" name="通常"/><author id="1" name="iwatobipen Admin"/><subject>SytheticPlan1</subject><description>CCCNCc1ccccc1</description><start_date>2015-01-20</start_date><due_date>2015-02-10</due_date><done_ratio>0</done_ratio><is_private>false</is_private><estimated_hours/><spent_hours>0.0</spent_hours><created_on>2015-01-24T05:28:27Z</created_on><updated_on>2015-01-24T05:28:27Z</updated_on><closed_on/></issue>
iwatobipen$ 

Opps, I forgot set tracker id, so tracker was bug…
Now check redmine.
Before run script, gantt chart show no ticket.
Screen Shot 2015-01-24 at 2.27.53 PM
After run script, I get one ticket…
Screen Shot 2015-01-24 at 2.29.24 PM
Click this ticket…
Screen Shot 2015-01-24 at 2.58.47 PM
I can check structure.
I want to embed structure editor in redmine, but it is hard work for me. ;-(