[project @ Updated eland_config app to generate config file from fctracker app.]
authorBrandon King <kingb@caltech.edu>
Tue, 13 Nov 2007 02:14:12 +0000 (02:14 +0000)
committerBrandon King <kingb@caltech.edu>
Tue, 13 Nov 2007 02:14:12 +0000 (02:14 +0000)
 * WARNING DB CHANGE: Added read_length, and advanced_run to flowcell
   model in fctracker app.
 * Updated eland_config app to generate config files from db instead of form.
   * Currently regenerates the config file on every request. Simple flag will
     cause it to re-read saved copy on disk.
 * Changed URL to http://<host>/eland_config/.

bin/retrieve_eland_config.py
ga_frontend/eland_config/urls.py
ga_frontend/eland_config/views.py
ga_frontend/fctracker/models.py

index 60c0c2e84a7603adcfbcaf0958f64831d5e6fe70..3c8825ba7aa7e86c9775cd929fd16693d2356d5a 100644 (file)
@@ -106,7 +106,7 @@ def saveConfigFile(flowcell, base_host_url, output_filepath):
   retrieves the flowcell eland config file, give the base_host_url
   (i.e. http://sub.domain.edu:port)
   """
-  url = base_host_url + '/eland_config/config/%s/' % (flowcell)
+  url = base_host_url + '/eland_config/%s/' % (flowcell)
   
   f = open(output_filepath, 'w')
   try:
index 1aefca26528523c34a180fa58e62a5b8e842d34e..13d659b92a8ebb8e5bd8749c43b844c259875a76 100644 (file)
@@ -3,8 +3,8 @@ from django.conf.urls.defaults import *
 urlpatterns = patterns('',
     # Example:
     
-    (r'^config/(?P<flowcell>FC\d+)/$', 'ga_frontend.eland_config.views.config'),
-    (r'^config/$', 'ga_frontend.eland_config.views.config'),
-    (r'^$', 'ga_frontend.eland_config.views.index')
+    (r'^(?P<flowcell>FC\d+)/$', 'ga_frontend.eland_config.views.config'),
+    (r'^$', 'ga_frontend.eland_config.views.config'),
+    #(r'^$', 'ga_frontend.eland_config.views.index')
 
 )
index 8f8057775724368b835b1c2373c2103ffcd81cdb..b87fdf9386785116e4b8035d2941a819de97ea45 100644 (file)
@@ -1,5 +1,7 @@
 from django.http import HttpResponse
 from django.shortcuts import render_to_response
+from django.core.exceptions import ObjectDoesNotExist
+
 from ga_frontend.eland_config import forms
 from ga_frontend import settings
 from ga_frontend.fctracker import models
@@ -9,6 +11,10 @@ import glob
 # Create your views here.
 
 
+def _validate_input(data):
+  #if data.find('..') == -1 or data.find('/') == -1 or data.find('\\') == -1:
+  return data.replace('..', '').replace('/', '_').replace('\\', '_')
+
 #def contact(request):
 #    if request.method == 'POST':
 #        form = ContactForm(request.POST)
@@ -21,150 +27,263 @@ import glob
 
 
 
-def _saveConfigFile(form):
-  """
-  Given a valid form, save eland config to file based on flowcell number.
-  """
-  assert form.is_valid()
-  
-  clean_data = form.cleaned_data
-  flowcell = clean_data['flow_cell_number'].replace('/','_').replace('..', '__')
-  
-  file_path = os.path.join(settings.UPLOADTO_CONFIG_FILE, flowcell)
-  
-  f = open(file_path, 'w')
-  cfg = generateElandConfig(form)
-  f.write(cfg)
-  f.close()
-  
+#def _saveConfigFile(form):
+#  """
+#  Given a valid form, save eland config to file based on flowcell number.
+#  """
+#  assert form.is_valid()
+#  
+#  clean_data = form.cleaned_data
+#  flowcell = clean_data['flow_cell_number'].replace('/','_').replace('..', '__')
+#  
+#  file_path = os.path.join(settings.UPLOADTO_CONFIG_FILE, flowcell)
+#  
+#  f = open(file_path, 'w')
+#  cfg = generateElandConfig(form)
+#  f.write(cfg)
+#  f.close()
+#  
+#
+#def _saveToDb(form):
+#  """
+#  Save info to the database.
+#  """
+#  clean_data = form.cleaned_data
+#  
+#  fc_id = clean_data['flow_cell_number']
+#  
+#  try:
+#    fc = models.FlowCell.objects.get(flowcell_id=fc_id)
+#  except models.FlowCell.DoesNotExist:
+#    fc = models.FlowCell()
+#    
+#  fc.flowcell_id = fc_id
+#  fc.run_date = clean_data['run_date']
+#  
+#  #LANE 1
+#  fc.lane1_sample = clean_data['lane1_description']
+#  species_name = clean_data['lane1_species']
+#  try:
+#    specie = models.Specie.objects.get(scientific_name=species_name)
+#  except models.Specie.DoesNotExist:
+#    specie = models.Specie(scientific_name=species_name)
+#    specie.save()
+#  fc.lane1_species = specie
+#  
+#  #LANE 2
+#  fc.lane2_sample = clean_data['lane2_description']
+#  species_name = clean_data['lane2_species']
+#  try:
+#    specie = models.Specie.objects.get(scientific_name=species_name)
+#  except models.Specie.DoesNotExist:
+#    specie = models.Specie(scientific_name=species_name)
+#    specie.save()
+#  fc.lane2_species = specie
+#  
+#  #LANE 3
+#  fc.lane3_sample = clean_data['lane3_description']
+#  species_name = clean_data['lane3_species']
+#  try:
+#    specie = models.Specie.objects.get(scientific_name=species_name)
+#  except models.Specie.DoesNotExist:
+#    specie = models.Specie(scientific_name=species_name)
+#    specie.save()
+#  fc.lane3_species = specie
+#  
+#  #LANE 4
+#  fc.lane4_sample = clean_data['lane4_description']
+#  species_name = clean_data['lane4_species']
+#  try:
+#    specie = models.Specie.objects.get(scientific_name=species_name)
+#  except models.Specie.DoesNotExist:
+#    specie = models.Specie(scientific_name=species_name)
+#    specie.save()
+#  fc.lane4_species = specie
+#  
+#  #LANE 5
+#  fc.lane5_sample = clean_data['lane5_description']
+#  species_name = clean_data['lane5_species']
+#  try:
+#    specie = models.Specie.objects.get(scientific_name=species_name)
+#  except models.Specie.DoesNotExist:
+#    specie = models.Specie(scientific_name=species_name)
+#    specie.save()
+#  fc.lane5_species = specie
+#  
+#  #LANE 6
+#  fc.lane6_sample = clean_data['lane6_description']
+#  species_name = clean_data['lane6_species']
+#  try:
+#    specie = models.Specie.objects.get(scientific_name=species_name)
+#  except models.Specie.DoesNotExist:
+#    specie = models.Specie(scientific_name=species_name)
+#    specie.save()
+#  fc.lane6_species = specie
+#  
+#  #LANE 7
+#  fc.lane7_sample = clean_data['lane7_description']
+#  species_name = clean_data['lane7_species']
+#  try:
+#    specie = models.Specie.objects.get(scientific_name=species_name)
+#  except models.Specie.DoesNotExist:
+#    specie = models.Specie(scientific_name=species_name)
+#    specie.save()
+#  fc.lane7_species = specie
+#  
+#  #LANE 8
+#  fc.lane8_sample = clean_data['lane8_description']
+#  species_name = clean_data['lane8_species']
+#  try:
+#    specie = models.Specie.objects.get(scientific_name=species_name)
+#  except models.Specie.DoesNotExist:
+#    specie = models.Specie(scientific_name=species_name)
+#    specie.save()
+#  fc.lane8_species = specie
+#  
+#  fc.notes = clean_data['notes']
+#  
+#  fc.save()
+#  
+#  return fc
+#  
+#
+#def generateElandConfig(form):
+#  data = []
+#  
+#  form = form.cleaned_data
+#  
+#  BASE_DIR = '/data-store01/compbio/genomes'
+#  
+#  data.append("# FLOWCELL: %s" % (form['flow_cell_number']))
+#  data.append("#")
+#  
+#  notes = form['notes'].replace('\r\n', '\n').replace('\r', '\n')
+#  notes = notes.replace('\n', '\n#  ')
+#  data.append("# NOTES:")
+#  data.append("#  %s\n#" % (notes))
+#  
+#  #Convert all newline conventions to unix style
+#  l1d = form['lane1_description'].replace('\r\n', '\n').replace('\r', '\n')
+#  l2d = form['lane2_description'].replace('\r\n', '\n').replace('\r', '\n')
+#  l3d = form['lane3_description'].replace('\r\n', '\n').replace('\r', '\n')
+#  l4d = form['lane4_description'].replace('\r\n', '\n').replace('\r', '\n')
+#  l5d = form['lane5_description'].replace('\r\n', '\n').replace('\r', '\n')
+#  l6d = form['lane6_description'].replace('\r\n', '\n').replace('\r', '\n')
+#  l7d = form['lane7_description'].replace('\r\n', '\n').replace('\r', '\n')
+#  l8d = form['lane8_description'].replace('\r\n', '\n').replace('\r', '\n')
+#  
+#  # Turn new lines into indented commented newlines
+#  l1d = l1d.replace('\n', '\n#  ')
+#  l2d = l2d.replace('\n', '\n#  ')
+#  l3d = l3d.replace('\n', '\n#  ')
+#  l4d = l4d.replace('\n', '\n#  ')
+#  l5d = l5d.replace('\n', '\n#  ')
+#  l6d = l6d.replace('\n', '\n#  ')
+#  l7d = l7d.replace('\n', '\n#  ')
+#  l8d = l8d.replace('\n', '\n#  ')
+#  
+#  data.append("# Lane1: %s" % (l1d))
+#  data.append("# Lane2: %s" % (l2d))
+#  data.append("# Lane3: %s" % (l3d))
+#  data.append("# Lane4: %s" % (l4d))
+#  data.append("# Lane5: %s" % (l5d))
+#  data.append("# Lane6: %s" % (l6d))
+#  data.append("# Lane7: %s" % (l7d))
+#  data.append("# Lane8: %s" % (l8d))
+#  
+#  #data.append("GENOME_DIR %s" % (BASE_DIR))
+#  #data.append("CONTAM_DIR %s" % (BASE_DIR))
+#  read_length = form['read_length']
+#  data.append("READ_LENGTH %d" % (read_length))
+#  #data.append("ELAND_REPEAT")
+#  data.append("ELAND_MULTIPLE_INSTANCES 8")
+#  
+#  #Construct genome dictionary to figure out what lanes to put
+#  # in the config file.
+#  genome_dict = {}
+#  l1s = form['lane1_species']
+#  genome_dict.setdefault(l1s, []).append('1')
+#  l2s = form['lane2_species']
+#  genome_dict.setdefault(l2s, []).append('2')
+#  l3s = form['lane3_species']
+#  genome_dict.setdefault(l3s, []).append('3')
+#  l4s = form['lane4_species']
+#  genome_dict.setdefault(l4s, []).append('4')
+#  l5s = form['lane5_species']
+#  genome_dict.setdefault(l5s, []).append('5')
+#  l6s = form['lane6_species']
+#  genome_dict.setdefault(l6s, []).append('6')
+#  l7s = form['lane7_species']
+#  genome_dict.setdefault(l7s, []).append('7')
+#  l8s = form['lane8_species']
+#  genome_dict.setdefault(l8s, []).append('8')
+#  
+#  genome_list = genome_dict.keys()
+#  genome_list.sort()
+#  
+#  #Loop through and create entries for each species.
+#  for genome in genome_list:
+#    lanes = ''.join(genome_dict[genome])
+#    data.append('%s:ANALYSIS eland' % (lanes))
+#    data.append('%s:READ_LENGTH %s' % (lanes, read_length))
+#    data.append('%s:ELAND_GENOME %s' % (lanes, os.path.join(BASE_DIR, genome)))
+#    data.append('%s:USE_BASES %s' % (lanes, 'Y'*int(read_length)))
+#    
+#  data.append('SEQUENCE_FORMAT --scarf')
+#  
+#  return '\n'.join(data)
 
-def _saveToDb(form):
-  """
-  Save info to the database.
-  """
-  clean_data = form.cleaned_data
-  
-  fc_id = clean_data['flow_cell_number']
-  
-  try:
-    fc = models.FlowCell.objects.get(flowcell_id=fc_id)
-  except models.FlowCell.DoesNotExist:
-    fc = models.FlowCell()
-    
-  fc.flowcell_id = fc_id
-  fc.run_date = clean_data['run_date']
-  
-  #LANE 1
-  fc.lane1_sample = clean_data['lane1_description']
-  species_name = clean_data['lane1_species']
-  try:
-    specie = models.Specie.objects.get(scientific_name=species_name)
-  except models.Specie.DoesNotExist:
-    specie = models.Specie(scientific_name=species_name)
-    specie.save()
-  fc.lane1_species = specie
-  
-  #LANE 2
-  fc.lane2_sample = clean_data['lane2_description']
-  species_name = clean_data['lane2_species']
-  try:
-    specie = models.Specie.objects.get(scientific_name=species_name)
-  except models.Specie.DoesNotExist:
-    specie = models.Specie(scientific_name=species_name)
-    specie.save()
-  fc.lane2_species = specie
-  
-  #LANE 3
-  fc.lane3_sample = clean_data['lane3_description']
-  species_name = clean_data['lane3_species']
-  try:
-    specie = models.Specie.objects.get(scientific_name=species_name)
-  except models.Specie.DoesNotExist:
-    specie = models.Specie(scientific_name=species_name)
-    specie.save()
-  fc.lane3_species = specie
-  
-  #LANE 4
-  fc.lane4_sample = clean_data['lane4_description']
-  species_name = clean_data['lane4_species']
-  try:
-    specie = models.Specie.objects.get(scientific_name=species_name)
-  except models.Specie.DoesNotExist:
-    specie = models.Specie(scientific_name=species_name)
-    specie.save()
-  fc.lane4_species = specie
-  
-  #LANE 5
-  fc.lane5_sample = clean_data['lane5_description']
-  species_name = clean_data['lane5_species']
-  try:
-    specie = models.Specie.objects.get(scientific_name=species_name)
-  except models.Specie.DoesNotExist:
-    specie = models.Specie(scientific_name=species_name)
-    specie.save()
-  fc.lane5_species = specie
+
+def getElandConfig(flowcell, regenerate=False):
   
-  #LANE 6
-  fc.lane6_sample = clean_data['lane6_description']
-  species_name = clean_data['lane6_species']
-  try:
-    specie = models.Specie.objects.get(scientific_name=species_name)
-  except models.Specie.DoesNotExist:
-    specie = models.Specie(scientific_name=species_name)
-    specie.save()
-  fc.lane6_species = specie
+  file_path = os.path.join(settings.UPLOADTO_CONFIG_FILE, flowcell)
   
-  #LANE 7
-  fc.lane7_sample = clean_data['lane7_description']
-  species_name = clean_data['lane7_species']
-  try:
-    specie = models.Specie.objects.get(scientific_name=species_name)
-  except models.Specie.DoesNotExist:
-    specie = models.Specie(scientific_name=species_name)
-    specie.save()
-  fc.lane7_species = specie
+  #If we are regenerating the config file, skip
+  # reading of existing file. If the file doesn't
+  # exist, try to generate it form the DB.
+  if not regenerate and os.path.isfile(file_path):
+    f = open(file_path, 'r')
+    data = f.read()
+    f.close()
+    return data
   
-  #LANE 8
-  fc.lane8_sample = clean_data['lane8_description']
-  species_name = clean_data['lane8_species']
   try:
-    specie = models.Specie.objects.get(scientific_name=species_name)
-  except models.Specie.DoesNotExist:
-    specie = models.Specie(scientific_name=species_name)
-    specie.save()
-  fc.lane8_species = specie
+    fcObj = models.FlowCell.objects.get(flowcell_id=flowcell)
+  except ObjectDoesNotExist:
+    return None
   
-  fc.notes = clean_data['notes']
-  
-  fc.save()
-  
-  return fc
-  
-
-def generateElandConfig(form):
   data = []
   
-  form = form.cleaned_data
+  #form = form.cleaned_data
   
   BASE_DIR = '/data-store01/compbio/genomes'
   
-  data.append("# FLOWCELL: %s" % (form['flow_cell_number']))
+  data.append("# FLOWCELL: %s" % (fcObj.flowcell_id))
   data.append("#")
   
-  notes = form['notes'].replace('\r\n', '\n').replace('\r', '\n')
+  notes = fcObj.notes.replace('\r\n', '\n').replace('\r', '\n')
   notes = notes.replace('\n', '\n#  ')
   data.append("# NOTES:")
   data.append("#  %s\n#" % (notes))
   
   #Convert all newline conventions to unix style
-  l1d = form['lane1_description'].replace('\r\n', '\n').replace('\r', '\n')
-  l2d = form['lane2_description'].replace('\r\n', '\n').replace('\r', '\n')
-  l3d = form['lane3_description'].replace('\r\n', '\n').replace('\r', '\n')
-  l4d = form['lane4_description'].replace('\r\n', '\n').replace('\r', '\n')
-  l5d = form['lane5_description'].replace('\r\n', '\n').replace('\r', '\n')
-  l6d = form['lane6_description'].replace('\r\n', '\n').replace('\r', '\n')
-  l7d = form['lane7_description'].replace('\r\n', '\n').replace('\r', '\n')
-  l8d = form['lane8_description'].replace('\r\n', '\n').replace('\r', '\n')
+  l1d = str(fcObj.lane_1_library.library_id) + '|' \
+          + fcObj.lane_1_library.library_name.replace('\r\n', '\n').replace('\r', '\n')
+  l2d = str(fcObj.lane_2_library.library_id) + '|' \
+          + fcObj.lane_2_library.library_name.replace('\r\n', '\n').replace('\r', '\n')
+  l3d = str(fcObj.lane_3_library.library_id) + '|' \
+          + fcObj.lane_3_library.library_name.replace('\r\n', '\n').replace('\r', '\n')
+  l4d = str(fcObj.lane_4_library.library_id) + '|' \
+          + fcObj.lane_4_library.library_name.replace('\r\n', '\n').replace('\r', '\n')
+  
+  l5d = str(fcObj.lane_5_library.library_id) + '|' \
+          + fcObj.lane_5_library.library_name.replace('\r\n', '\n').replace('\r', '\n')
+  l6d = str(fcObj.lane_6_library.library_id) + '|' \
+          + fcObj.lane_6_library.library_name.replace('\r\n', '\n').replace('\r', '\n')
+  l7d = str(fcObj.lane_7_library.library_id) + '|' \
+          + fcObj.lane_7_library.library_name.replace('\r\n', '\n').replace('\r', '\n')
+  l8d = str(fcObj.lane_8_library.library_id) + '|' \
+          + fcObj.lane_8_library.library_name.replace('\r\n', '\n').replace('\r', '\n')
   
   # Turn new lines into indented commented newlines
   l1d = l1d.replace('\n', '\n#  ')
@@ -187,7 +306,7 @@ def generateElandConfig(form):
   
   #data.append("GENOME_DIR %s" % (BASE_DIR))
   #data.append("CONTAM_DIR %s" % (BASE_DIR))
-  read_length = form['read_length']
+  read_length = fcObj.read_length
   data.append("READ_LENGTH %d" % (read_length))
   #data.append("ELAND_REPEAT")
   data.append("ELAND_MULTIPLE_INSTANCES 8")
@@ -195,21 +314,23 @@ def generateElandConfig(form):
   #Construct genome dictionary to figure out what lanes to put
   # in the config file.
   genome_dict = {}
-  l1s = form['lane1_species']
+  
+  #l1s = form['lane1_species']
+  l1s = fcObj.lane_1_library.library_species.scientific_name
   genome_dict.setdefault(l1s, []).append('1')
-  l2s = form['lane2_species']
+  l2s = fcObj.lane_2_library.library_species.scientific_name
   genome_dict.setdefault(l2s, []).append('2')
-  l3s = form['lane3_species']
+  l3s = fcObj.lane_3_library.library_species.scientific_name
   genome_dict.setdefault(l3s, []).append('3')
-  l4s = form['lane4_species']
+  l4s = fcObj.lane_4_library.library_species.scientific_name
   genome_dict.setdefault(l4s, []).append('4')
-  l5s = form['lane5_species']
+  l5s = fcObj.lane_5_library.library_species.scientific_name
   genome_dict.setdefault(l5s, []).append('5')
-  l6s = form['lane6_species']
+  l6s = fcObj.lane_6_library.library_species.scientific_name
   genome_dict.setdefault(l6s, []).append('6')
-  l7s = form['lane7_species']
+  l7s = fcObj.lane_7_library.library_species.scientific_name
   genome_dict.setdefault(l7s, []).append('7')
-  l8s = form['lane8_species']
+  l8s = fcObj.lane_8_library.library_species.scientific_name
   genome_dict.setdefault(l8s, []).append('8')
   
   genome_list = genome_dict.keys()
@@ -225,7 +346,15 @@ def generateElandConfig(form):
     
   data.append('SEQUENCE_FORMAT --scarf')
   
-  return '\n'.join(data)
+  data = '\n'.join(data)
+  
+  f = open(file_path, 'w')
+  f.write(data)
+  f.close()
+  
+  return data
+
+
 
 def config(request, flowcell=None):
   """
@@ -236,40 +365,41 @@ def config(request, flowcell=None):
   # Provide INDEX of available Flowcell config files.
   if flowcell is None:
     #Find all FC* config files and report an index html file
-    fc_list = [ os.path.split(file_path)[1] for file_path in glob.glob(os.path.join(settings.UPLOADTO_CONFIG_FILE, 'FC*')) ]
+    #fc_list = [ os.path.split(file_path)[1] for file_path in glob.glob(os.path.join(settings.UPLOADTO_CONFIG_FILE, 'FC*')) ]
+    fc_list = [ fc.flowcell_id for fc in models.FlowCell.objects.all() ]
+    
     #Convert FC* list to html links
-    fc_html = [ '<a href="/elandifier/config/%s/">%s</a>' % (fc_name, fc_name) for fc_name in fc_list ]
+    fc_html = [ '<a href="/eland_config/%s/">%s</a>' % (fc_name, fc_name) for fc_name in fc_list ]
+      
     return HttpResponse('<br />'.join(fc_html))
   
   #FIXME: Should validate flowcell input before using.
-  file_path = os.path.join(settings.UPLOADTO_CONFIG_FILE, flowcell)
+  flowcell = _validate_input(flowcell)
+  cfg = getElandConfig(flowcell, regenerate=True)
   
-  if not os.path.isfile(file_path):
-    return HttpResponse("Hmm, config file for %s does not seem to exist. Maybe I don't exist either?" % (flowcell))
+  if not cfg:
+    return HttpResponse("Hmm, config file for %s does not seem to exist." % (flowcell))
   
-  f = open(file_path, 'r')
-  cfg = f.read()
-  f.close()
   
   return HttpResponse(cfg, mimetype="text/plain")
 
 
 
 
-def index(request):
-  """
-  Return a form for filling out information about the flowcell
-  """
-  if request.method == 'POST':
-    form = forms.ConfigForm(request.POST, error_class=forms.DivErrorList)
-    if form.is_valid():
-      #cfg = generateElandConfig(form)
-      _saveConfigFile(form)
-      _saveToDb(form)
-      return HttpResponse("Eland Config Saved!", mimetype="text/plain")
-    else:
-      return render_to_response('config_form.html', {'form': form })
-  
-  else:   
-    fm = forms.ConfigForm(error_class=forms.DivErrorList)
-    return render_to_response('config_form.html', {'form': fm })
+#def index(request):
+#  """
+#  Return a form for filling out information about the flowcell
+#  """
+#  if request.method == 'POST':
+#    form = forms.ConfigForm(request.POST, error_class=forms.DivErrorList)
+#    if form.is_valid():
+#      #cfg = generateElandConfig(form)
+#      _saveConfigFile(form)
+#      _saveToDb(form)
+#      return HttpResponse("Eland Config Saved!", mimetype="text/plain")
+#    else:
+#      return render_to_response('config_form.html', {'form': form })
+#  
+#  else:   
+#    fm = forms.ConfigForm(error_class=forms.DivErrorList)
+#    return render_to_response('config_form.html', {'form': fm })
index 5a0136787df68ad17abd068047936ef91ccbfcbb..e86183c3078970e64976d33aa31e4dcf1f036abd 100644 (file)
@@ -78,6 +78,8 @@ class FlowCell(models.Model):
   
   flowcell_id = models.CharField(max_length=20, unique=True, db_index=True, core=True)
   run_date = models.DateTimeField(core=True)
+  advanced_run = models.BooleanField(default=False)
+  read_length = models.IntegerField(default=32)
   
   lane_1_library = models.ForeignKey(Library, related_name="lane_1_library")
   lane_2_library = models.ForeignKey(Library, related_name="lane_2_library")
@@ -121,7 +123,7 @@ class FlowCell(models.Model):
     list_display = ('flowcell_id', 'run_date', 'lane_1_library', 'lane_2_library', 'lane_3_library', 'lane_4_library', 'lane_5_library', 'lane_6_library', 'lane_7_library', 'lane_8_library')
     fields = (
         (None, {
-            'fields': ('run_date', 'flowcell_id',)
+            'fields': ('run_date', 'flowcell_id', ('read_length', 'advanced_run'),)
         }),
         ('Lanes:', {
             'fields' : (('lane_1_library', 'lane_1_pM', 'lane_1_cluster_estimate'), ('lane_2_library', 'lane_2_pM', 'lane_2_cluster_estimate'), ('lane_3_library', 'lane_3_pM', 'lane_3_cluster_estimate'), ('lane_4_library', 'lane_4_pM', 'lane_4_cluster_estimate'), ('lane_5_library', 'lane_5_pM', 'lane_5_cluster_estimate'), ('lane_6_library', 'lane_6_pM', 'lane_6_cluster_estimate'), ('lane_7_library', 'lane_7_pM', 'lane_7_cluster_estimate'), ('lane_8_library', 'lane_8_pM', 'lane_8_cluster_estimate'),)